Procházet zdrojové kódy

Some progress on the battle manager, behind the scenes.

Iñigo Valentin před 3 roky
rodič
revize
7c6cce5ce0

+ 38 - 14
src/core/BattleManager.cpp

@@ -19,8 +19,11 @@
 #include <OgreRoot.h>
 #include <OgreViewport.h>
 #include "core/BattleManager.h"
+#include "core/Enemy.h"
+#include "core/EntityManager.h"
 #include "core/ConfigVar.h"
 #include "core/Logger.h"
+#include "core/XmlFormationFile.h"
 
 /**
  * Battle manager singleton.
@@ -44,6 +47,41 @@ BattleManager::~BattleManager(){
     LOG_TRIVIAL("BattleManager destroyed.");
 }
 
+void BattleManager::StartBattle(const unsigned int id){
+    formation_id_ = id;
+    EntityManager::getSingleton().SetBattleModule();
+    // Load the formation XML file (name is dddd.xml)
+    std::string filename = std::to_string(formation_id_);
+    while (filename.length() < 4) filename = "0" + filename;
+    filename = "./data/game/formation/" + filename + ".xml";
+    // This sets the data in the battle manager singleton.
+    XmlFormationFile(filename).LoadFormation();
+    // TODO: Read formation file, enemy files...
+    // TODO: Music
+    // TODO: Camera
+}
+
+void BattleManager::EndBattle(){
+    formation_id_ = -1;
+    EntityManager::getSingleton().SetPreviousModule();
+}
+
+std::vector<Enemy> BattleManager::GetEnemies() const{return enemies_;}
+
+void BattleManager::AddEnemy(
+  const unsigned int id, const Ogre::Vector3 pos, const bool front, const bool visible,
+  const bool targeteable, const bool active, const std::string cover
+){
+    Enemy* enemy = new Enemy(id, pos, front, visible, targeteable, active, cover);
+    enemies_.push_back(*enemy);
+}
+
+void BattleManager::AddCamera(
+  const unsigned int id, const Ogre::Vector3 pos, const Ogre::Vector3 dir
+){
+    // TODO implrement
+}
+
 void BattleManager::Input(const VGears::Event& event){
     // TODO: Change to battle input commands.
     //background_2d_.InputDebug(event);
@@ -122,18 +160,4 @@ void BattleManager::SetLocation(const int id, const Ogre::String name){
 
 void BattleManager::SetArenaBattle(const bool arena){arena_battle_ = arena;}
 
-void BattleManager::AddCamera(
-  const unsigned int id, const int x, const int y, const int z,
-  const int direction_x, const int direction_y, const int direction_z
-){
-    // TODO
-}
-
 void BattleManager::SetInitialCamera(const unsigned int id){initial_camera_ = id;}
-
-void BattleManager::AddEnemy(
-  const unsigned int id, const int x, const int y, const int z, const bool front_row,
-  const Ogre::String cover, const bool visible, const bool target, const int script
-){
-    // TODO
-}

+ 44 - 36
src/core/BattleManager.h

@@ -16,11 +16,8 @@
 #pragma once
 
 #include <OgreSingleton.h>
-#include "Entity.h"
-#include "EntityPoint.h"
-#include "EntityTrigger.h"
+#include "Enemy.h"
 #include "Event.h"
-#include "Walkmesh.h"
 
 /**
  * The battle manager.
@@ -136,6 +133,41 @@ class BattleManager : public Ogre::Singleton<BattleManager>{
          */
         virtual ~BattleManager();
 
+        /**
+         * Starts a battle.
+         *
+         * @param id Battle ID.
+         */
+        void StartBattle(const unsigned int id);
+
+        /**
+         * Ends the current battle.
+         */
+        void EndBattle();
+
+        /**
+         * Retrieves the list of enemies.
+         *
+         * @return The list of enemies.
+         */
+        std::vector<Enemy> GetEnemies() const;
+
+        /**
+         * Adds an enemy to the manager for the next battle.
+         *
+         * @param[in] id Enemy ID.
+         * @param[in] pos Enemy position (x, y, z).
+         * @param[in] front True to set the enemy in the front row, false for back row.
+         * @param[in] visible Indicates enemy visibility.
+         * @param[in] targeteable Indicates if the enemy can be targeted.
+         * @param[in] active Indicates whether the enemy main script is active or not.
+         * @param[in] cover Cover binary flags string.
+         */
+        void AddEnemy(
+          const unsigned int id, const Ogre::Vector3 pos, const bool front, const bool visible,
+          const bool targeteable, const bool active, const std::string cover
+        );
+
         /**
          * Handles an input event.
          *
@@ -231,49 +263,25 @@ class BattleManager : public Ogre::Singleton<BattleManager>{
          */
         void SetArenaBattle(const bool arena);
 
-        /**
-         * Adds an camera for the battle.
-         *
-         * @param[in] id The camera ID.
-         * @param[in] x X coordinate for the camera.
-         * @param[in] y Y coordinate for the camera.
-         * @param[in] z Z coordinate for the camera.
-         * @param[in] direction_x X rotation for the camera.
-         * @param[in] direction_y Y rotation for the camera.
-         * @param[in] direction_z Z rotation for the camera.
-         */
-        void AddCamera(
-          const unsigned int id, const int x, const int y, const int z,
-          const int direction_x, const int direction_y, const int direction_z
-        );
-
         /**
          * Sets the initial camera.
          *
          * Can be set before configuring the camera, but if the battle starts and this index is
          * invalid, it's undefined behavior.
          *
-         * @param[in] ID of the initial camera.
+         * @param[in] id ID of the initial camera.
          */
         void SetInitialCamera(const unsigned int id);
 
         /**
-         * Adds an enemy to the enemy formation.
+         * Adds a camera for the next battle.
          *
-         * @param[in] id The enemy ID.
-         * @param[in] x X coordinate for the enemy (center, cursor position).
-         * @param[in] y Y coordinate for the enemy (center, cursor position).
-         * @param[in] z Z coordinate for the enemy (center, cursor position).
-         * @param[in] front_row True to set the enemy in the front row, fals efor the back row.
-         * @param[in] cover Binary cover flags. {@see
-         * https://wiki.ffrtt.ru/index.php/FF7/Battle/Battle_Scenes#Binary_.22Cover_Flags.22}.
-         * @param[in] visible Enemy visibility.
-         * @param[in] target Indicates if the enemy can be targeted.
-         * @param[in] script Indicates the main script for the enemy.
+         * @param[in] id Camera ID.
+         * @param[in] pos Camera position (x, y, z).
+         * @param[in] dir Camera orientation (x, y, z).
          */
-        void AddEnemy(
-          const unsigned int id, const int x, const int y, const int z, const bool front_row,
-          const Ogre::String cover, const bool visible, const bool target, const int script
+        void AddCamera(
+          const unsigned int id, const Ogre::Vector3 pos, const Ogre::Vector3 dir
         );
 
     private:
@@ -352,7 +360,7 @@ class BattleManager : public Ogre::Singleton<BattleManager>{
         /**
          * List of enemies for the battle.
          */
-        // TODO std::vector<Enemy> enemy_;
+        std::vector<Enemy> enemies_;
 
         /**
          * List of party members in the battle.

+ 117 - 303
src/core/Enemy.cpp

@@ -13,70 +13,87 @@
  * GNU General Public License for more details.
  */
 
-#include <cmath>
 #include <OgreSceneNode.h>
 #include <OgreMaterialManager.h>
 #include "core/Enemy.h"
 #include "core/ConfigVar.h"
 #include "core/DebugDraw.h"
 #include "core/Logger.h"
+#include "core/XmlEnemyFile.h"
 
-ConfigVar cv_debug_enemy("debug_enemy", "Draw enemy debug info", "0");
+Enemy::Enemy(const unsigned int id):
+  id_(id),
+  name_("UNKNOWN"),
+  level_(1),
+  exp_(0),
+  ap_(0),
+  money_(0),
+  morph_(-1),
+  back_damage_(1.5f),
+  str_(0),
+  mag_(0),
+  def_(0),
+  spr_(0),
+  dex_(0),
+  lck_(0),
+  eva_(0),
+  meva_(0),
+  hp_(1),
+  mp_(0),
+  hp_max_(1),
+  mp_max_(0),
+  pos_(Ogre::Vector3(0, 0, 0)),
+  front_(false),
+  visible_(false),
+  active_(false),
+  cover_("00000")
+{
+    ReadFromXml();
+    LOG_TRIVIAL("Enemy " + std::to_string(id_) + " '" + name_ + "' created.");
+}
 
-Enemy::Enemy(const int enemy_id, Ogre::SceneNode* node):
-  enemy_id_(enemy_id),
+Enemy::Enemy(
+  const unsigned int id, const Ogre::Vector3 pos, const bool front, const bool visible,
+  const bool targeteable, const bool active, const std::string cover
+):
+  id_(id),
   name_("UNKNOWN"),
-  scene_node_(node),
-  height_(1.0f),
-  move_position_(Ogre::Vector3(0, 0, 0)),
-  move_auto_rotation_(true),
-  offset_position_start_(0.0f, 0.0f, 0.0f),
-  offset_position_end_(0.0f, 0.0f, 0.0f),
-  offset_type_(AT_NONE),
-  offset_seconds_(0.0f),
-  offset_current_seconds_(0.0f),
-  turn_direction_(TD_CLOSEST),
-  turn_direction_start_(0),
-  turn_direction_end_(0),
-  turn_type_(AT_NONE),
-  turn_seconds_(0.0f),
-  turn_current_seconds_(0.0f),
-  animation_speed_(1.0f),
-  animation_default_("Idle"),
-  animation_current_name_(""),
-  animation_auto_play_(true)
+  level_(1),
+  exp_(0),
+  ap_(0),
+  money_(0),
+  morph_(-1),
+  back_damage_(1.5f),
+  str_(0),
+  mag_(0),
+  def_(0),
+  spr_(0),
+  dex_(0),
+  lck_(0),
+  eva_(0),
+  meva_(0),
+  hp_(1),
+  mp_(0),
+  hp_max_(1),
+  mp_max_(0),
+  pos_(pos),
+  front_(front),
+  visible_(visible),
+  active_(active),
+  cover_(cover)
 {
-    model_root_node_ = scene_node_->createChildSceneNode();
-    model_node_ = model_root_node_->createChildSceneNode();
-    model_root_node_->setPosition(Ogre::Vector3::ZERO);
-    model_node_->setPosition(Ogre::Vector3::ZERO);
-    scene_node_->setPosition(Ogre::Vector3::ZERO);
-    LOG_TRIVIAL("Enemy " + std::to_string(enemy_id_) + " '" + name_ + "' created.");
+    ReadFromXml();
+    LOG_TRIVIAL("Enemy " + std::to_string(id_) + " '" + name_ + "' created.");
 }
 
 Enemy::~Enemy(){
-    scene_node_->removeAndDestroyAllChildren();
-    LOG_TRIVIAL("Enemy " + std::to_string(enemy_id_) + " '" + name_ + "' destroyed.");
+    LOG_TRIVIAL("Enemy " + std::to_string(id_) + " '" + name_ + "' destroyed.");
 }
 
-void Enemy::Update(){}
-
-void Enemy::UpdateDebug(){
-    int debug = cv_debug_enemy.GetI();
-    if (debug > 0){
-        DEBUG_DRAW.SetColour(Ogre::ColourValue::White);
-        DEBUG_DRAW.SetScreenSpace(true);
-        DEBUG_DRAW.SetTextAlignment(DEBUG_DRAW.CENTER);
-        DEBUG_DRAW.SetFadeDistance(40, 50);
-        Ogre::Vector3 enemy_pos = GetPosition();
-        DEBUG_DRAW.Text(enemy_pos, 0, 0, name_);
-        DEBUG_DRAW.Text(enemy_pos, 0, 12, animation_current_name_);
-    }
-}
 
-const int Enemy::GetEnemyId() const{return enemy_id_;}
+const int Enemy::GetId() const{return id_;}
 
-void Enemy::SetEnemyId(const int id){enemy_id_ = id;}
+void Enemy::SetId(const int id){id_ = id;}
 
 const Ogre::String& Enemy::GetName() const{return name_;}
 
@@ -98,6 +115,34 @@ unsigned int Enemy::GetMoney() const{return money_;}
 
 void Enemy::SetMoney(const unsigned int money){money_ = money;}
 
+std::vector<unsigned int> Enemy::GetAnimations() const{return animations_;}
+
+void Enemy::AddAnimation(const unsigned int animation){animations_.push_back(animation);}
+
+std::vector<Enemy::Attack> Enemy::GetAttacks() const{return attacks_;}
+
+void Enemy::AddAttack(const Attack attack){attacks_.push_back(attack);}
+
+std::vector<Enemy::Item> Enemy::GetDrop() const{return drop_;}
+
+void Enemy::AddDrop(const Item item){drop_.push_back(item);}
+
+std::vector<Enemy::Element> Enemy::GetElements() const{return elements_;}
+
+void Enemy::AddElement(const Element element){elements_.push_back(element);}
+
+std::vector<Enemy::Immunity> Enemy::GetImmunities() const{return immunities_;}
+
+void Enemy::AddImmunity(const Immunity immunity){immunities_.push_back(immunity);}
+
+std::vector<unsigned int> Enemy::GetManipulateAttacks() const{return manipulate_attacks_;}
+
+void Enemy::AddManipulateAttack(const unsigned int attack){manipulate_attacks_.push_back(attack);}
+
+std::vector<Enemy::Item> Enemy::GetSteal() const{return steal_;}
+
+void Enemy::AddSteal(const Item item){steal_.push_back(item);}
+
 unsigned int Enemy::GetMorph() const{return morph_;}
 
 void Enemy::SetMorph(const int morph){morph_ = std::max(-1, morph);}
@@ -133,6 +178,14 @@ unsigned int Enemy::GetLck() const{return lck_;}
 
 void Enemy::SetLck(const unsigned int lck){lck_ = lck;}
 
+unsigned int Enemy::GetEva() const{return eva_;}
+
+void Enemy::SetEva(const unsigned int eva){eva_ = eva;}
+
+unsigned int Enemy::GetMeva() const{return meva_;}
+
+void Enemy::SetMeva(const unsigned int meva){meva_ = meva;}
+
 unsigned int Enemy::GetHp() const{return hp_;}
 
 void Enemy::SetHp(const unsigned int hp){hp_ = std::min(hp, hp_max_);}
@@ -155,276 +208,37 @@ void Enemy::SetMpMax(const unsigned int mp_max){
     mp_ = std::min(mp_, mp_max_);
 }
 
-void Enemy::SetPosition(const Ogre::Vector3& position){scene_node_->setPosition(position);}
+Ogre::Vector3& Enemy::GetPos(){return pos_;}
 
-void Enemy::ScriptSetPosition(const float x, const float y, const float z){
-    SetPosition(Ogre::Vector3(x, y, z));
-    // Make the entity visible. TODO: Check if necessary.
-    SetVisible(true);
-}
+void Enemy::SetPos(const Ogre::Vector3 &pos){pos_ = pos;}
 
-const Ogre::Vector3 Enemy::GetPosition() const{return scene_node_->getPosition();}
+bool Enemy::IsFront() const{return front_;}
 
-void Enemy::ScriptGetPosition() const{
-    Ogre::Vector3 position = scene_node_->getPosition();
-    ScriptManager::getSingleton().AddValueToStack(position.x);
-    ScriptManager::getSingleton().AddValueToStack(position.y);
-    ScriptManager::getSingleton().AddValueToStack(position.z);
-}
+void Enemy::SetFront(bool front){front_ = front;}
 
-void Enemy::SetOffset(const Ogre::Vector3& position){
-    assert(model_root_node_);
-    model_root_node_->setPosition(position);
-}
+bool Enemy::IsVisible() const{return visible_;}
 
-const Ogre::Vector3 Enemy::GetOffset() const{
-    assert(model_root_node_);
-    return model_root_node_->getPosition();
-}
+void Enemy::SetVisible(bool visible){visible_ = visible;}
 
-void Enemy::SetRotation(const Ogre::Degree& rotation){
-    assert(model_root_node_);
-    float angle
-      = rotation.valueDegrees() - Ogre::Math::Floor(rotation.valueDegrees() / 360.0f) * 360.0f;
-    if (angle < 0) angle = 360 + angle;
-    Ogre::Quaternion q;
-    Ogre::Vector3 vec = Ogre::Vector3::UNIT_Z;
-    q.FromAngleAxis(Ogre::Radian(Ogre::Degree(angle)), vec);
-    model_root_node_->setOrientation(q);
-}
+bool Enemy::IsTargeteable() const{return targeteable_;}
 
-void Enemy::ScriptSetRotation(const float rotation){SetRotation(Ogre::Degree(rotation));}
+void Enemy::SetTargeteable(bool targeteable){targeteable_ = targeteable;}
 
-Ogre::Degree Enemy::GetRotation() const{
-    assert(model_root_node_);
-    Ogre::Quaternion q = model_root_node_->getOrientation();
-    Ogre::Degree temp;
-    Ogre::Vector3 vec = Ogre::Vector3::UNIT_Z;
-    q.ToAngleAxis(temp, vec);
-    return temp;
-}
+bool Enemy::IsActive() const{return active_;}
 
-float Enemy::ScriptGetRotation() const{return GetRotation().valueDegrees();}
+void Enemy::SetActive(bool active){active_ = active;}
 
-void Enemy::setScale(const Ogre::Vector3 &scale) {
-    assert(model_root_node_);
-    model_root_node_->setScale(scale);
-}
+std::string Enemy::GetCover() const{return cover_;}
 
-void Enemy::SetIndex(const int index){
-    assert(model_root_node_);
-    index_ = index;
-}
+void Enemy::SetCover(std::string cover){cover_ = cover;}
 
-int Enemy::GetIndex(){return index_;}
-
-void Enemy::setRootOrientation(const Ogre::Quaternion &root_orientation){
-    assert(model_node_);
-    model_node_->setOrientation(root_orientation);
+void Enemy::ReadFromXml(){
+    std::string filename = std::to_string(id_);
+    while (filename.length() < 4) filename = "0" + filename;
+    filename = "./data/game/enemy/" + filename + ".xml";
+    XmlEnemyFile(filename).LoadEnemy(*this);
 }
 
-float Enemy::GetHeight() const{return height_;}
-
-void Enemy::SetMoveSpeed(const float speed){move_speed_ = speed;}
 
-float Enemy::GetMoveSpeed() const{return move_speed_;}
 
-void Enemy::SetMovePosition(const Ogre::Vector3& target){move_position_ = target;}
-
-const Ogre::Vector3& Enemy::GetMovePosition() const{return move_position_;}
-
-float Enemy::GetMoveStopDistance() const{return move_stop_distance_;}
-
-void Enemy::ScriptMoveToPosition(const float x, const float y){
-    move_position_ = Ogre::Vector3(x, y, 0);
-    move_stop_distance_ = 0;
-    LOG_TRIVIAL(
-      "Enemy " + std::to_string(enemy_id_) + " '" + name_ + "' set move to position '"
-      + Ogre::StringConverter::toString(move_position_) + "'."
-    );
-}
-
-void Enemy::UnsetMove(){
-    move_stop_distance_ = 0;
-    sync_.clear();
-}
-
-void Enemy::ScriptOffsetToPosition(
-  const float x, const float y, const float z, const ActionType type, const float seconds
-){
-    LOG_TRIVIAL(
-      "Enemy " + std::to_string(enemy_id_) +" '" + name_ + "' set offset to position '"
-      + Ogre::StringConverter::toString(Ogre::Vector3(x, y, z)) + "'."
-    );
-    Ogre::Vector3 position = Ogre::Vector3(x, y, z);
-    if (type == AT_NONE){
-        this->SetOffset(position);
-        return;
-    }
-    offset_position_start_ = GetOffset();
-    offset_position_end_ = position;
-    offset_type_ = type;
-    offset_seconds_ = seconds;
-    offset_current_seconds_ = 0;
-}
-
-int Enemy::ScriptOffsetSync(){
-    // TODO
-    /*ScriptId script = ScriptManager::getSingleton().GetCurrentScriptId();
-    LOG_TRIVIAL(
-      "Wait entity '" + name_ + "' offset for function '"
-      + script.function + "' in script entity '" + script.entity + "'."
-    );
-    offset_sync_.push_back(script);
-    return -1;*/
-}
 
-void Enemy::UnsetOffset(){
-    // TODO
-    /*offset_type_ = AT_NONE;
-    for (unsigned int i = 0; i < offset_sync_.size(); ++ i)
-        ScriptManager::getSingleton().ContinueScriptExecution(offset_sync_[i]);
-    offset_sync_.clear();*/
-}
-
-const Ogre::Vector3& Enemy::GetOffsetPositionStart() const{return offset_position_start_;}
-
-const Ogre::Vector3& Enemy::GetOffsetPositionEnd() const{return offset_position_end_;}
-
-Enemy::ActionType Enemy::GetOffsetType() const{return offset_type_;}
-
-float Enemy::GetOffsetSeconds() const{return offset_seconds_;}
-
-void Enemy::SetOffsetCurrentSeconds(const float seconds){offset_current_seconds_ = seconds;}
-
-float Enemy::GetOffsetCurrentSeconds() const{return offset_current_seconds_;}
-
-void Enemy::ScriptTurnToDirection(
-  const float direction, const TurnDirection turn_direction,
-  const ActionType turn_type, const float seconds
-){
-    SetTurn(Ogre::Degree(direction), turn_direction, turn_type, seconds);
-    LOG_TRIVIAL(
-      "Enemy " + std::to_string(enemy_id_) + " '" + name_ + "' turn to angle '"
-      + Ogre::StringConverter::toString(direction) + "'."
-    );
-}
-
-int Enemy::ScriptTurnSync(){
-    // TODO
-    /*ScriptId script = ScriptManager::getSingleton().GetCurrentScriptId();
-    LOG_TRIVIAL(
-      "Wait enemy " + std::to_string(enemy_id_) + " '" + name_ + "' turn for function '"
-      + script.function + "' in script entity '" + script.entity + "'."
-    );
-    turn_sync_.push_back(script);
-    return -1;*/
-}
-
-void Enemy::SetTurn(
-  const Ogre::Degree& direction_to, const TurnDirection turn_direction,
-  const ActionType turn_type, const float seconds
-){
-    if (turn_type == AT_NONE){
-        SetRotation(direction_to);
-        return;
-    }
-    turn_direction_ = turn_direction;
-    Ogre::Degree angle_start = GetRotation();
-    Ogre::Degree angle_end = CalculateTurnAngle(angle_start, direction_to);
-    turn_direction_start_ = angle_start;
-    turn_direction_end_ = angle_end;
-    turn_type_ = turn_type;
-    turn_seconds_ = seconds;
-    turn_current_seconds_ = 0;
-}
-
-void Enemy::UnsetTurn(){
-    turn_type_ = AT_NONE;
-    //for (unsigned int i = 0; i < turn_sync_.size(); ++ i)
-    //    ScriptManager::getSingleton().ContinueScriptExecution(turn_sync_[i]);
-    turn_sync_.clear();
-}
-
-Ogre::Degree Enemy::CalculateTurnAngle(const Ogre::Degree& start, const Ogre::Degree& end) const{
-    Ogre::Degree ret = end;
-    switch(turn_direction_){
-        case TD_CLOCKWISE:
-            if (end <= start) ret = end + Ogre::Degree(360);
-            break;
-        case TD_ANTICLOCKWISE:
-            if (end >= start) ret = end - Ogre::Degree(360);
-            break;
-        case TD_CLOSEST:
-            Ogre::Degree delta = end - start;
-            delta = (delta < Ogre::Degree(0)) ? -delta : delta;
-            if (delta > Ogre::Degree(180)){
-                if (start < end) ret = end - Ogre::Degree(360);
-                else ret = end + Ogre::Degree(360);
-            }
-        break;
-    }
-    return ret;
-}
-
-Ogre::Degree Enemy::GetTurnDirectionStart() const{return turn_direction_start_;}
-
-Ogre::Degree Enemy::GetTurnDirectionEnd() const{return turn_direction_end_;}
-
-Enemy::ActionType Enemy::GetTurnType() const{return turn_type_;}
-
-float Enemy::GetTurnSeconds() const{return turn_seconds_;}
-
-void Enemy::SetTurnCurrentSeconds(const float seconds){turn_current_seconds_ = seconds;}
-
-float Enemy::GetTurnCurrentSeconds() const{return turn_current_seconds_;}
-
-void Enemy::ScriptSetAnimationSpeed(const float speed){animation_speed_ = speed;}
-
-const Ogre::String& Enemy::GetDefaultAnimationName() const{return animation_default_;}
-
-const Ogre::String& Enemy::GetCurrentAnimationName() const{return animation_current_name_;}
-
-Enemy::AnimationState Enemy::GetAnimationState() const{return animation_state_;}
-
-void Enemy::ScriptPlayAnimation(const char* name){
-    PlayAnimation(Ogre::String(name), Enemy::REQUESTED_ANIMATION, Enemy::PLAY_DEFAULT, 0, -1);
-}
-
-void Enemy::ScriptPlayAnimationStop(const char* name){
-    PlayAnimation(Ogre::String(name), Enemy::REQUESTED_ANIMATION, Enemy::PLAY_ONCE, 0, -1);
-}
-
-void Enemy::ScriptPlayAnimation(const char* name, const float start, const float end){
-    PlayAnimation(
-      Ogre::String(name), Enemy::REQUESTED_ANIMATION, Enemy::PLAY_DEFAULT, start, end
-    );
-}
-
-void Enemy::ScriptPlayAnimationStop(const char* name, const float start, const float end){
-    PlayAnimation(Ogre::String(name), Enemy::REQUESTED_ANIMATION, Enemy::PLAY_ONCE, start, end);
-}
-
-void Enemy::ScriptSetDefaultAnimation(const char* animation){
-    animation_default_ = Ogre::String(animation);
-}
-
-int Enemy::ScriptAnimationSync(){
-    // TODO
-    /*ScriptId script = ScriptManager::getSingleton().GetCurrentScriptId();
-    LOG_TRIVIAL(
-      "Wait entity '" + name_ + "' animation for function '"
-      + script.function + "' in script entity '" + script.entity + "'."
-    );
-    animation_sync_.push_back(script);*/
-    return -1;
-}
-
-Ogre::Degree Enemy::GetDirectionToPoint(Ogre::Vector2 point) const{
-    Ogre::Vector3 current_point = GetPosition();
-    Ogre::Vector2 up(0.0f, -1.0f);
-    Ogre::Vector2 dir(point.x - current_point.x, point.y - current_point.y);
-    // Angle between vectors
-    Ogre::Degree angle(Ogre::Radian(acosf(dir.dotProduct(up) / (dir.length() * up.length()))));
-    return (dir.x < 0) ? Ogre::Degree(360) - angle : angle;
-}

+ 278 - 632
src/core/Enemy.h

@@ -25,131 +25,121 @@ class Enemy{
 
     public:
 
-        /**
-         * Enemy animation states.
-         */
-        enum AnimationState{
+        struct Element{
 
             /**
-             * An animation has been requested.
+             * The element ID.
              */
-            REQUESTED_ANIMATION,
+            unsigned int id;
 
             /**
-             * An animation is set to play automatically.
+             * Damage modification factor when attacked by the element.
+             *
+             * 1 means normal damage taken.
+             * 0 means no damage taken.
+             * [0-1] means reduced damage.
+             * [1-10) means extended damage.
+             * (-10-0) means recovery
+             * >10 means death.
+             * <-10 means full recovery.
              */
-            AUTO_ANIMATION
+            float factor;
         };
 
         /**
-         * Types of animations.
+         * Enemy attack data.
          */
-        enum AnimationPlayType{
-
-            /**
-             * Default animation mode.
-             *
-             * @todo Same as PLAY_ONCE?
-             */
-            PLAY_DEFAULT,
+        struct Attack{
 
             /**
-             * Play the animation once, then stop.
+             * Attack ID.
              */
-            PLAY_ONCE,
+            unsigned int id;
 
             /**
-             * Play an animation in a continous loop.
+             * Camera ID to use during the attack.
+             *
+             * -1 to not move the camera.
              */
-            PLAY_LOOPED
+            int camera;
         };
 
-
         /**
-         * Action types.
+         * Data for drop and steal items.
          */
-        enum ActionType{
+        struct Item{
 
             /**
-             * No action.
+             * Item ID.
              */
-            AT_NONE,
+            unsigned int id;
 
             /**
-             * Linear action.
-             *
-             * It starts and ends at full speed.
+             * Steal or drop rate.
              */
-            AT_LINEAR,
-
-            /**
-             * Smooth action.
-             *
-             * The action speed steadily increases when started, and it steadily
-             * decreases before the end.
-             */
-            AT_SMOOTH
+            float rate;
         };
 
         /**
-         * The direction for an entity turn.
+         * Status immunity.
          */
-        enum TurnDirection{
-
-            /**
-             * Turn clockwise.
-             */
-            TD_CLOCKWISE,
+        struct Immunity{
 
             /**
-             * Turn anticlockwise.
+             * Status ID.
              */
-            TD_ANTICLOCKWISE,
+            unsigned int status;
 
             /**
-             * Choose direction automatically.
+             * Immunity rate.
              *
-             * The direction in which the turn is shorter will be selected.
+             * 0 or lower means no immunity, 1 or higher completely immune. Values between 0 and 1
+             * indicate resistance.
              */
-            TD_CLOSEST
+            float rate;
         };
 
         /**
          * Constructor.
          *
-         * @param[in] name Enemy ID.
-         * @param[in] node Scene node to which the enemy should be attached.
-         */
-        Enemy(const int enemy_id, Ogre::SceneNode* node);
-
-        /**
-         * Destructor.
+         * @param[in] id Enemy ID.
          */
-        virtual ~Enemy();
+        Enemy(const unsigned int id);
 
         /**
-         * Updates the enemy status.
-         */
-        virtual void Update();
+         * Constructor.
+         *
+         * @param[in] id Enemy ID.
+         * @param[in] pos Enemy position (x, y, z).
+         * @param[in] front True to set the enemy in the front row, false for back row.
+         * @param[in] visible Indicates enemy visibility.
+         * @param[in] targeteable Indicates if the enemy can be targeted.
+         * @param[in] active Indicates whether the enemy main script is active or not.
+         * @param[in] cover Cover binary flags string.
+         */
+        Enemy(
+          const unsigned int id, const Ogre::Vector3 pos, const bool front, const bool visible,
+          const bool targeteable, const bool active, const std::string cover
+        );
 
         /**
-         * Updates the enemy status with debug information.
+         * Destructor.
          */
-        virtual void UpdateDebug();
+        virtual ~Enemy();
 
         /**
          * Retrieves the enemy ID.
          *
          * @return The enemy ID, or -1 if it's not loaded.
          */
-        const int GetEnemyId() const;
+        const int GetId() const;
 
         /**
          * Sets the enemy ID.
          *
          * @param[in] id The enemy ID.
          */
-        void SetEnemyId(const int id);
+        void SetId(const int id);
 
         /**
          * Retrieves the enemy name.
@@ -221,6 +211,107 @@ class Enemy{
          */
         void SetMoney(const unsigned int money);
 
+        /**
+         * Retrieves the enemy animation IDs.
+         *
+         * @return The list of animation IDs
+         */
+        std::vector<unsigned int> GetAnimations() const;
+
+        /**
+         * Adds an animation for the enemy.
+         *
+         * @param[in] Animation ID.
+         */
+        void AddAnimation(const unsigned int animation);
+
+        /**
+         * Retrieves the enemy attacks.
+         *
+         * @return The list of attacks.
+         */
+        std::vector<Attack> GetAttacks() const;
+
+        /**
+         * Adds an attack for the enemy.
+         *
+         * @param[in] Attack to add.
+         */
+        void AddAttack(const Attack attack);
+
+        /**
+         * Retrieves the enemy possible item drops.
+         *
+         * @return List of items that can be droped by the enemy.
+         */
+        std::vector<Item> GetDrop() const;
+
+        /**
+         * Adds an item drop for the enemy.
+         *
+         * @param[in] item The dropable item.
+         */
+        void AddDrop(const Item item);
+
+        /**
+         * Retrieves the list of the enemy elemental affinities.
+         *
+         * @return The list of elemental affinities.
+         */
+        std::vector<Element> GetElements() const;
+
+        /**
+         * Adds an elemental affinity to the monster.
+         *
+         * @param[in] element Elemental affinity.
+         */
+        void AddElement(const Element element);
+
+        /**
+         * Retrieves the list of status immunities.
+         *
+         * @return The list of status immunities.
+         */
+        std::vector<Immunity> GetImmunities() const;
+
+        /**
+         * Adds an immunity to the monster.
+         *
+         * @param[in] immunity The immunity to add.
+         */
+        void AddImmunity(const Immunity immunity);
+
+        /**
+         * Retrieves the list of attacks that can be used during the manipulated state.
+         *
+         * The first attack of the list is also the attack the enemy will use when in berserkr
+         * state. If the list is empty, the enemy can't be manipulated or berserkred.
+         *
+         * @return List of IDs of attacks usable during manipulation
+         */
+        std::vector<unsigned int> GetManipulateAttacks() const;
+
+        /**
+         * Adds an attack usable during manipulation.
+         *
+         * @param[in] attack ID of the attack.
+         */
+        void AddManipulateAttack(const unsigned int attack);
+
+        /**
+         * Retrieves the enemy possible item stelas.
+         *
+         * @return List of items that can be stolen from the enemy.
+         */
+        std::vector<Item> GetSteal() const;
+
+        /**
+         * Adds an item steal to the enemy.
+         *
+         * @param[in] item The stealableitem.
+         */
+        void AddSteal(const Item item);
+
         /**
          * Retrieves the ID of the item the monster can be morphed into.
          *
@@ -333,6 +424,34 @@ class Enemy{
          */
         void SetLck(const unsigned int lck);
 
+        /**
+         * Retrieves the enemy's evasion stat.
+         *
+         * @return The evasion stat.
+         */
+        unsigned int GetEva() const;
+
+        /**
+         * Sets the enemy's evasion stat.
+         *
+         * @param[in] eva The evasion stat.
+         */
+        void SetEva(const unsigned int eva);
+
+        /**
+         * Retrieves the enemy's magic evasion stat.
+         *
+         * @return The magic evasion stat.
+         */
+        unsigned int GetMeva() const;
+
+        /**
+         * Sets the enemy's magic evasion stat.
+         *
+         * @param[in] meva The magic evasion stat.
+         */
+        void SetMeva(const unsigned int meva);
+
         /**
          * Retrieves the enemy's current HP.
          *
@@ -402,507 +521,169 @@ class Enemy{
         void SetMpMax(const unsigned int mp_max);
 
         /**
-         * Sets the enemy position.
-         *
-         * @param[in] position Enemy's new position.
-         */
-        void SetPosition(const Ogre::Vector3& position);
-
-        /**
-         * Sets the enemy position.
-         *
-         * @param[in] x Enemy's new position X coordinate.
-         * @param[in] y Enemy's new position Y coordinate.
-         * @param[in] z Enemy's new position Z coordinate.
-         */
-        void ScriptSetPosition(const float x, const float y, const float z);
-
-        /**
-         * Retrieves the enemy position.
-         *
-         * @return The enemy position.
-         */
-        const Ogre::Vector3 GetPosition() const;
-
-        /**
-         * Informs the script manager of the enemy position.
-         */
-        void ScriptGetPosition() const;
-
-        /**
-         * Sets the enemy offset.
-         *
-         * The offset is relative to it's defined position.
-         *
-         * @param[in] position The enemy's offset.
-         */
-        void SetOffset(const Ogre::Vector3& position);
-
-        /**
-         * Retrieves the enemy offset.
-         *
-         * The offset is relative to it's defined position.
+         * Retrieves the enemy position in the battlefield.
          *
-         * @return The enemy's offset.
+         * @return The enemy position (x, y, z).
          */
-        const Ogre::Vector3 GetOffset() const;
+        Ogre::Vector3& GetPos();
 
         /**
-         * Sets the enemy rotation.
+         * Sets the enemy position in the battlefield.
          *
-         * @param[in] rotation The enemy rotation.
+         * @param[in] pos The enemy position (x, y, z).
          */
-        void SetRotation(const Ogre::Degree& rotation);
+        void SetPos(const Ogre::Vector3 &pos);
 
         /**
-         * Sets the enemy rotation.
+         * Checks if the enemy is in the front row.
          *
-         * @param[in] rotation The enemy rotation, in degrees (0-360).
+         * @return True if the enemy is in the front row. false if not.
          */
-        void ScriptSetRotation(const float rotation);
+        bool IsFront() const;
 
         /**
-         * Retrieves the enemy rotation.
+         * Sets the enemy in or out the front row.
          *
-         * @return The enemy rotation, in degrees.
+         * @param[in] front True to set the enemy in the front row, false for the back row.
          */
-        Ogre::Degree GetRotation() const;
+        void SetFront(bool front);
 
         /**
-         * Retrieves the enemy rotation.
+         * Checks the enemy visibility.
          *
-         * @return The enemy rotation (0-360).
+         * @return True if the enemy is visible, false if not.
          */
-        float ScriptGetRotation() const;
+        bool IsVisible() const;
 
         /**
-         * Sets the enemy scale.
+         * Toggles the enemy visibility.
          *
-         * @param[in] scale Three dimensional scale.
+         * @param[in] visible True to make the enemy visible, false to make it invisible.
          */
-        virtual void setScale(const Ogre::Vector3 &scale);
+        void SetVisible(bool visible);
 
         /**
-         * Sets the enemy index in the field.
+         * Checks whether the enemy can be targeted.
          *
-         * @param[in] index Index of the enemy.
+         * @return True if the enemy can be targeted, false if not.
          */
-        void SetIndex(const int index);
+        bool IsTargeteable() const;
 
         /**
-         * Retrieves the enemy index in the field.
+         * Determines whether the enemy can be targeted.
          *
-         * @return Index of the enemy.
+         * @param[in] targeteable True to allow targeting the enemy false to prevent it.
          */
-        int GetIndex();
+        void SetTargeteable(bool targeteable);
 
         /**
-         * Sets the enemy's absolute orientation.
+         * Checks whether the enemy's main script is active.
          *
-         * @param[in] root_orientation The enemy's new orientation.
+         * @return True if the script is active, false if not.
          */
-        virtual void setRootOrientation(const Ogre::Quaternion &root_orientation);
+        bool IsActive() const;
 
         /**
-         * Retrieves the enemy's height.
+         * Activates or deactivates the enemy main script.
          *
-         * @return The enemy's height.
+         * @param[in] active True to activate the script, false to deactivate it.
          */
-        float GetHeight() const;
+        void SetActive(bool active);
 
         /**
-         * Makes the enemy visible or invisible.
+         * Retrieves the flags for enemy covering.
          *
-         * Invisible entities can't be interacted with.
+         * {@see https://wiki.ffrtt.ru/index.php/FF7/Battle/Battle_Scenes#Binary_.22Cover_Flags.22}
+         * for more info about cover flags.
          *
-         * @param[in] visible True to make the unit visible, false to make it invisible.
+         * @return A string with five 0s or 1s indicating the cover flags.
          */
-        virtual void SetVisible(const bool visible) = 0;
+        std::string GetCover() const;
 
         /**
-         * Checks if the enemy is visible or invisible.
+         * Sets the flags for enemy covering.
          *
-         * Invisible entities can't be interacted with.
+         * {@see https://wiki.ffrtt.ru/index.php/FF7/Battle/Battle_Scenes#Binary_.22Cover_Flags.22}
+         * for more info about cover flags.
          *
-         * @return True if the unit is visible, false if it's invisible.
+         * @param[in] A string with five 0s or 1s indicating the cover flags.
          */
-        virtual bool IsVisible() const = 0;
+        void SetCover(std::string cover);
 
-        /**
-         * Sets the enemy's movement destination position.
-         *
-         * @param[in] target The destination position.
-         */
-        void SetMovePosition(const Ogre::Vector3& target);
-
-        /**
-         * Sets the enemy's model movement speed.
-         *
-         * @param[in] speed Movement speed.
-         */
-        void SetMoveSpeed(const float speed);
-
-        /**
-         * Retrieves the enemy's automatic movement speed.
-         *
-         * @return The movement speed.
-         */
-        float GetMoveSpeed() const;
-
-        /**
-         * Retrieves the enemy's movement destination position.
-         *
-         * @return The destination position.
-         */
-        const Ogre::Vector3& GetMovePosition() const;
-
-        /**
-         * Retrieves the distance to destination.
-         *
-         * It's the distance between the enemy's current position and it's current movement
-         * destination point.
-         *
-         * @return The distance to destination.
-         */
-        float GetMoveStopDistance() const;
-
-        /**
-         * Makes the enemy move to a point in the map.
-         *
-         * @param[in] x X coordinate of the destination point.
-         * @param[in] y Y coordinate of the destination point.
-         */
-        void ScriptMoveToPosition(const float x, const float y);
-
-        /**
-         * Waits for enemy's movement to end.
-         *
-         * @return Always -1.
-         */
-        int ScriptMoveSync();
-
-        /**
-         * Cancels the enemy's current movement.
-         *
-         * It also clears the movement sync queue.
-         */
-        void UnsetMove();
-
-        /**
-         * @todo Understand and document.
-         *
-         * @param[in] x X coordinate of the destination point.
-         * @param[in] y Y coordinate of the destination point.
-         * @param[in] z Z coordinate of the destination point.
-         * @param[in] type Type of action.
-         * @param[in] seconds Duration of the action, in seconds.
-         */
-        void ScriptOffsetToPosition(
-          const float x, const float y, const float z,
-          const ActionType type, const float seconds
-        );
-
-        /**
-         * @todo Understand and document.
-         *
-         * @return Always -1.
-         */
-        int ScriptOffsetSync();
-
-        /**
-         * @todo Understand and document.
-         */
-        void UnsetOffset();
-
-        /**
-         * @todo Understand and document.
-         *
-         * @return Starting position.
-         */
-        const Ogre::Vector3& GetOffsetPositionStart() const;
-
-        /**
-         * @todo Understand and document.
-         *
-         * @return Ending position.
-         */
-        const Ogre::Vector3& GetOffsetPositionEnd() const;
-
-        /**
-         * @todo Understand and document.
-         *
-         * @return The action type.
-         */
-        ActionType GetOffsetType() const;
-
-        /**
-         * @todo Understand and document.
-         *
-         * @return Action total duration in seconds.
-         */
-        float GetOffsetSeconds() const;
-
-        /**
-         * @todo Understand and document.
-         *
-         * @param[in] seconds Action current duration in seconds.
-         */
-        void SetOffsetCurrentSeconds(const float seconds);
-
-        /**
-         * @todo Understand and document.
-         *
-         * @return Action current duration in seconds.
-         */
-        float GetOffsetCurrentSeconds() const;
-
-        /**
-         * Makes the enemy turn to a fixed direction.
-         *
-         * @param[in] direction Final direction to turn the enemy's to.
-         * @param[in] turn_direction Direction of the turn.
-         * @param[in] turn_type Turn mode.
-         * @param[in] seconds Total turn duration, in seconds.
-         */
-        void ScriptTurnToDirection(
-          const float direction, const TurnDirection turn_direction,
-          const ActionType turn_type, const float seconds
-        );
-
-        /**
-         * Makes the enemy turn to a fixed point.
-         *
-         * @param[in] x X coordinate of the point to turn to.
-         * @param[in] y Y coordinate of the point to turn to.
-         * @param[in] turn_direction Direction of the turn.
-         * @param[in] turn_type Turn mode.
-         * @param[in] seconds Total turn duration, in seconds.
-         */
-        void ScriptTurnToPosition(
-          const int x, const int y, const TurnDirection turn_direction,
-          const ActionType turn_type, const float seconds
-        );
-
-        /**
-         * Adds the enemy's turn to the sync queue.
-         *
-         * @return Always -1.
-         * @todo Properly describe this.
-         */
-        int ScriptTurnSync();
-
-        /**
-         * Makes the enemy turn towards a point or another enemy.
-         *
-         * @param[in] direction_to Final direction to turn the enemy's to.
-         * @param[in] turn_direction Direction of the turn.
-         * @param[in] turn_type Turn mode.
-         * @param[in] seconds Total turn duration, in seconds.
-         * @todo What if the point
-         */
-        void SetTurn(
-          const Ogre::Degree& direction_to, const TurnDirection turn_direction,
-          const ActionType turn_type, const float seconds
-        );
-
-        /**
-         * Cancels the enemy's current turn.
-         *
-         * It also clears the movement sync queue.
-         */
-        void UnsetTurn();
-
-        /**
-         * Calculates the turn angle.
-         *
-         * If the turn direction is {@see TD_CLOSEST}, the result is the
-         * smallest angle between the two orientations. Otherwise, is the angle
-         * in the specified turn direction.
-         *
-         * @param[in] start Starting angle.
-         * @param[in] end Ending angle.
-         * @return[in] Calculated turn angle.
-         */
-        Ogre::Degree CalculateTurnAngle(const Ogre::Degree& start, const Ogre::Degree& end) const;
-
-        /**
-         * Retrieves the turn staring orientation.
-         *
-         * @return The turn starting orientation.
-         */
-        Ogre::Degree GetTurnDirectionStart() const;
-
-        /**
-         * Retrieves the turn ending orientation.
-         *
-         * @return The turn ending orientation.
-         */
-        Ogre::Degree GetTurnDirectionEnd() const;
-
-        /**
-         * Retrieves the turn type.
-         *
-         * @return The turn type.
-         */
-        ActionType GetTurnType() const;
-
-        /**
-         * Retrieves the turn total duration.
-         *
-         * @return The turn total duration, in seconds.
-         */
-        float GetTurnSeconds() const;
-
-        /**
-         * Sets the turn current duration.
-         *
-         * @param[in] seconds The turn current duration, in seconds.
-         */
-        void SetTurnCurrentSeconds(const float seconds);
-
-        /**
-         * Retrieves the turn current duration.
-         *
-         * @return The turn current duration, in seconds.
-         */
-        float GetTurnCurrentSeconds() const;
-
-        /**
-         * Sets the animation speed.
-         *
-         * @param[in] speed The animation speed.
-         * @todo Indicate units, max and mins, or references.
-         */
-        void ScriptSetAnimationSpeed(const float speed);
+    private:
 
         /**
-         * Retrieves the enemy's default animation name.
-         *
-         * @return The default animation name.
+         * Reads enemy data from the xml file.
          */
-        const Ogre::String& GetDefaultAnimationName() const;
+        void ReadFromXml();
 
         /**
-         * Retrieves the enemy's current animation name.
-         *
-         * @return The current animation name.
+         * The enemy ID.
          */
-        const Ogre::String& GetCurrentAnimationName() const;
+        int id_;
 
         /**
-         * Retrieves the enemy's current animation state.
-         *
-         * @return The current animation state.
+         * The name of the enemy.
          */
-        AnimationState GetAnimationState() const;
+        Ogre::String name_;
 
         /**
-         * Plays one of the enemy's animations.
-         *
-         * @param[in] animation Name of the animation to play.
-         * @param[in] state The animation initial state.
-         * @param[in] play_type The animation play type, to play it once or in
-         * a loop.
-         * @param[in] start Animation starting point in time, in seconds.
-         * @param[in] end Animation ending point in time, in seconds.
+         * The enemy level.
          */
-        virtual void PlayAnimation(
-          const Ogre::String& animation, AnimationState state,
-          AnimationPlayType play_type, const float start, const float end
-        ) = 0;
+        unsigned int level_;
 
         /**
-         * Resumes an animation.
-         *
-         * @param[in] animation Name of the animation to resume.
+         * EXP given upon defeating the enemy.
          */
-        virtual void PlayAnimationContinue(const Ogre::String& animation) = 0;
+        unsigned int exp_;
 
         /**
-         * Updates the animation state.
-         *
-         * @param[in] delta The animation delta.
+         * AP given upon defeating the enemy.
          */
-        virtual void UpdateAnimation(const float delta) = 0;
+        unsigned int ap_;
 
         /**
-         * Plays one of the enemy's animations.
-         *
-         * @param[in] name Name of the animation to play.
+         * Money given upon defeating the enemy.
          */
-        void ScriptPlayAnimation(const char* name);
+        unsigned int money_;
 
         /**
-         * Stops one of the enemy's animations.
-         *
-         * @param[in] name Name of the animation to stop.
+         * List of animations.
          */
-        void ScriptPlayAnimationStop(const char* name);
+        std::vector<unsigned int> animations_;
 
         /**
-         * Plays one of the enemy's animations.
-         *
-         * @param[in] name Name of the animation to play.
-         * @param[in] start Animation starting point in time, in seconds.
-         * @param[in] end Animation ending point in time, in seconds.
+         * Elemental affinities.
          */
-        void ScriptPlayAnimation(const char* name, const float start, const float end);
+        std::vector<Element> elements_;
 
         /**
-         * Stops one of the enemy's animations.
-         *
-         * @param[in] name Name of the animation to stop.
-         * @param[in] start Animation starting point in time, in seconds.
-         * @param[in] end Animation ending point in time, in seconds.
+         * Status immunities and resistances.
          */
-        void ScriptPlayAnimationStop(const char* name, const float start, const float end);
+        std::vector<Immunity> immunities_;
 
         /**
-         * Sets the default animation of the enemy.
-         *
-         * @param[in] animation Name of the default animation.
+         * Enemy attacks.
          */
-        void ScriptSetDefaultAnimation(const char* animation);
+        std::vector<Attack> attacks_;
 
         /**
-         * Adds the enemy's animation to the sync queue.
+         * List of attacks that can be used while manipulated.
          *
-         * @return Always -1.
-         * @todo Properly describe this.
-         */
-        int ScriptAnimationSync();
-
-    protected:
-
-        /**
-         * The enemy ID.
-         */
-        int enemy_id_;
-
-        /**
-         * The name of the enemy.
-         */
-        Ogre::String name_;
-
-        /**
-         * The enemy level.
+         * The first one is also the one used in berserkr. If empty, it means the enemy can't be
+         * manipulated or berserkd.
          */
-        unsigned int level_;
+        std::vector<unsigned int> manipulate_attacks_;
 
         /**
-         * EXP given upon defeating the enemy.
+         * List of the items that can be stolen from the enemy.
          */
-        unsigned int exp_;
+        std::vector<Item> steal_;
 
         /**
-         * AP given upon defeating the enemy.
+         * List of the items that can be dropped from the enemy.
          */
-        unsigned int ap_;
-
-        /**
-         * Money given upon defeating the enemy.
-         */
-        unsigned int money_;
+        std::vector<Item> drop_;
 
         /**
          * ID of the item the enemy can be morphed into. -1 if none..
@@ -940,10 +721,20 @@ class Enemy{
         unsigned int dex_;
 
         /**
-         * Enemy luck stat
+         * Enemy luck stat.
          */
         unsigned int lck_;
 
+        /**
+         * Enemy evasion stat.
+         */
+        unsigned int eva_;
+
+        /**
+         * Enemy magic evasion stat.
+         */
+        unsigned int meva_;
+
         /**
          * Enemy's current HP.
          */
@@ -965,179 +756,34 @@ class Enemy{
         unsigned int mp_max_;
 
         /**
-         * The scene node the enemy is attached to.
-         */
-        Ogre::SceneNode* scene_node_;
-
-        /**
-         * The enemy's model.
-         */
-        Ogre::SceneNode* model_node_;
-
-        /**
-         * The enemy's root node.
-         */
-        Ogre::SceneNode* model_root_node_;
-
-        /**
-         * The enemy's height.
-         */
-        float height_;
-
-        /**
-         * Enemy's movement sync queue.
-         */
-        std::vector<ScriptId> sync_;
-
-        /**
-         * The speed of the models movements.
-         */
-        float move_speed_;
-
-        /**
-         * The enemy's movement destination point.
-         */
-        Ogre::Vector3 move_position_;
-
-        /**
-         * Distance between the enemy and it's movement destination point.
-         */
-        float move_stop_distance_;
-
-        /**
-         * Indicates if the enemy can rotate while moving.
-         */
-        bool move_auto_rotation_;
-
-        /**
-         * Indicates if the enemy can animate while moving.
-         */
-        bool move_auto_animation_;
-
-        /**
-         * @todo Understand and document.
-         */
-        Ogre::Vector3 offset_position_start_;
-
-        /**
-         * @todo Understand and document.
-         */
-        Ogre::Vector3 offset_position_end_;
-
-        /**
-         * @todo Understand and document.
-         */
-        ActionType offset_type_;
-
-        /**
-         * @todo Understand and document.
-         */
-        float offset_seconds_;
-
-        /**
-         * @todo Understand and document.
-         */
-        float offset_current_seconds_;
-
-        /**
-         * @todo Understand and document.
-         */
-        std::vector<ScriptId> offset_sync_;
-
-        /**
-         * Turn movement direction.
-         */
-        TurnDirection turn_direction_;
-
-        /**
-         * Turn initial orientation.
-         */
-        Ogre::Degree turn_direction_start_;
-
-        /**
-         * Turn final orientation.
-         */
-        Ogre::Degree turn_direction_end_;
-
-        /**
-         * The turn type.
-         */
-        ActionType turn_type_;
-
-        /**
-         * Total turn duration.
-         */
-        float turn_seconds_;
-
-        /**
-         * Current turn duration.
-         */
-        float turn_current_seconds_;
-
-        /**
-         * Enemy's turning sync queue.
-         */
-        std::vector<ScriptId> turn_sync_;
-
-        /**
-         * The animation speed.
-         */
-        float animation_speed_;
-
-        /**
-         * The enemy's current animation name.
-         */
-        Ogre::String animation_current_name_;
-
-        /**
-         * Enemy's animation sync queue.
-         */
-        std::vector<ScriptId> animation_sync_;
-
-        /**
-         * The enemy's current animation state.
-         */
-        AnimationState animation_state_;
-
-        /**
-         * The enemy's current animation type.
-         */
-        AnimationPlayType animation_play_type_;
-
-        /**
-         * The name of the enemy's default name.
+         * Enemy position in the battlefield (x, y, z).
          */
-        Ogre::String animation_default_;
+        Ogre::Vector3 pos_;
 
         /**
-         * @todo Understand and document.
+         * Indicates if the enmy is in the frontline.
          */
-        float animation_end_time_;
+        bool front_;
 
         /**
-         * Indicates if an automation must be played automatically.
+         * Indicates if the enemy is visible.
          */
-        bool animation_auto_play_;
-
-    private:
+        bool visible_;
 
         /**
-         * Constructor.
+         * Indicates if the enemy can be targeted.
          */
-        Enemy();
+        bool targeteable_;
 
         /**
-         * Calculates the angular distance to a point.
-         *
-         * @param[in] point Point to calculate the angular distance to.
-         * @return Angular distance to the specified point.
+         * Indicates if the enemy's main script is active.
          */
-        Ogre::Degree GetDirectionToPoint(Ogre::Vector2 point) const;
+        bool active_;
 
         /**
-         * Index of the enemy on the battle.
+         * Cover binary flags.
          */
-        int index_;
+        std::string cover_;
 
 };
 

+ 111 - 6
src/core/EntityManager.cpp

@@ -95,6 +95,7 @@ Ogre::Degree EntityManager::GetDirectionToPoint(
 }
 
 EntityManager::EntityManager():
+  module_(MODULE::FIELD),
   paused_(false),
   player_entity_(nullptr),
   player_move_(Ogre::Vector3::ZERO),
@@ -128,6 +129,50 @@ EntityManager::~EntityManager(){
     LOG_TRIVIAL("EntityManager destroyed.");
 }
 
+EntityManager::MODULE EntityManager::GetModule(){return module_;}
+
+bool EntityManager::IsModule(EntityManager::MODULE module){return (module_ == module);}
+
+bool EntityManager::IsFieldModule(){return (module_ == MODULE::FIELD);}
+
+bool EntityManager::IsBattleModule(){return (module_ == MODULE::BATTLE);}
+
+bool EntityManager::IsWorldModule(){return (module_ == MODULE::WORLD);}
+
+void EntityManager::SetModule(EntityManager::MODULE module){
+    if (module == MODULE::FIELD){
+        ClearBattle();
+        ClearWorld();
+    }
+    else if (module == MODULE::WORLD){
+        ClearBattle();
+        ClearField();
+    }
+    else if (module == MODULE::BATTLE) prev_module_ = module_;
+    module_ = module;
+}
+
+void EntityManager::SetFieldModule(){SetModule(MODULE::FIELD);}
+
+void EntityManager::SetBattleModule(){SetModule(MODULE::BATTLE);}
+
+void EntityManager::SetWorldModule(){SetModule(MODULE::WORLD);}
+
+void EntityManager::SetPreviousModule(){
+    if (module_ != MODULE::BATTLE)
+        LOG_WARNING(
+          "Called EntityManager::SetPreviousModule without battle module active. Doing nothing"
+          + "Current module is " + std::to_string(module_)
+        );
+    else if(module_ = prev_module_)
+        LOG_WARNING(
+          "Called EntityManager::SetPreviousModule but there is no previous module. Doing nothing"
+          + "Current module is " + std::to_string(module_)
+        );
+    else module_ = prev_module_;
+    return;
+}
+
 void EntityManager::Input(const VGears::Event& event){
     background_2d_.InputDebug(event);
     if (paused_ == true) return;
@@ -171,7 +216,24 @@ void EntityManager::Input(const VGears::Event& event){
 void EntityManager::Update(){
     UpdateDebug();
     if (paused_ == true) return;
+    Update(module_);
+}
 
+void EntityManager::Update(MODULE module){
+    switch (module){
+        case MODULE::FIELD:
+            UpdateField();
+            break;
+        case MODULE::BATTLE:
+            UpdateBattle();
+            break;
+        case MODULE::WORLD:
+            UpdateWorld();
+            break;
+    }
+}
+
+void EntityManager::UpdateField(){
     // Update all entity scripts
     ScriptManager::getSingleton().Update(ScriptManager::ENTITY);
 
@@ -289,19 +351,47 @@ void EntityManager::Update(){
     background_2d_.Update();
 }
 
+void EntityManager::UpdateBattle(){
+    // TODO: Implement
+}
+
+void EntityManager::UpdateWorld(){
+    // TODO: Implement
+}
+
 void EntityManager::UpdateDebug(){
     grid_->setVisible(cv_debug_grid.GetB());
     axis_->setVisible(cv_debug_axis.GetB());
-    for (unsigned int i = 0; i < entity_.size(); ++ i) entity_[i]->UpdateDebug();
-    for (unsigned int i = 0; i < entity_triggers_.size(); ++ i) entity_triggers_[i]->UpdateDebug();
-    for (unsigned int i = 0; i < entity_points_.size(); ++ i) entity_points_[i]->UpdateDebug();
-    walkmesh_.UpdateDebug();
+    if (module_ == MODULE::BATTLE)
+        for (unsigned int i = 0; i < battle_entity_.size(); ++ i) battle_entity_[i]->UpdateDebug();
+    else{
+        for (unsigned int i = 0; i < entity_.size(); ++ i) entity_[i]->UpdateDebug();
+        for (unsigned int i = 0; i < entity_triggers_.size(); ++ i) entity_triggers_[i]->UpdateDebug();
+        for (unsigned int i = 0; i < entity_points_.size(); ++ i) entity_points_[i]->UpdateDebug();
+        walkmesh_.UpdateDebug();
+    }
     background_2d_.UpdateDebug();
 }
 
 void EntityManager::OnResize(){background_2d_.OnResize();}
 
-void EntityManager::Clear(){
+void EntityManager::Clear(){Clear(module_);}
+
+void EntityManager::Clear(MODULE module){
+    switch (module){
+        case MODULE::FIELD:
+            ClearField();
+            break;
+        case MODULE::BATTLE:
+            ClearBattle();
+            break;
+        case MODULE::WORLD:
+            ClearWorld();
+            break;
+    }
+}
+
+void EntityManager::ClearField(){
     walkmesh_.Clear();
     background_2d_.Clear();
     DialogsManager::getSingleton().Clear();
@@ -328,6 +418,20 @@ void EntityManager::Clear(){
     scene_node_->removeAndDestroyAllChildren();
 }
 
+void EntityManager::ClearBattle(){
+    // TODO implement
+}
+
+void EntityManager::ClearWorld(){
+    // TODO implement
+}
+
+void EntityManager::ClearAll(){
+    ClearField();
+    ClearBattle();
+    ClearWorld();
+}
+
 void EntityManager::ScriptSetPaused(const bool paused){paused_ = paused;}
 
 Walkmesh* EntityManager::GetWalkmesh(){return &walkmesh_;}
@@ -356,7 +460,8 @@ void EntityManager::AddEntity(
     entity->setScale(scale);
     entity->SetIndex(index);
     entity->setRootOrientation(root_orientation);
-    entity_.push_back(entity);
+    if (module_ == MODULE::BATTLE) battle_entity_.push_back(entity);
+    else entity_.push_back(entity);
     ScriptManager::getSingleton().AddEntity(ScriptManager::ENTITY, entity->GetName(), entity);
 }
 

+ 195 - 1
src/core/EntityManager.h

@@ -29,6 +29,34 @@
 class EntityManager : public Ogre::Singleton<EntityManager>{
 
     public:
+
+        /**
+         * The modules the entity manager can handle.
+         */
+        enum MODULE{
+
+            /**
+             * Field module.
+             *
+             * Used in field maps. It has background, walkmesh, entities...
+             */
+            FIELD = 0,
+
+            /**
+             * Battle module.
+             *
+             * Used in battles. During battles there is no walkmesh.
+             */
+            BATTLE = 1,
+
+            /**
+             * World map module.
+             *
+             * Used in the world map. It has background, walkmesh, entities...
+             */
+            WORLD = 2
+        };
+
         /**
          * Constructor.
          */
@@ -39,6 +67,88 @@ class EntityManager : public Ogre::Singleton<EntityManager>{
          */
         virtual ~EntityManager();
 
+        /**
+         * Retrieves the currently selected module.
+         *
+         * @return The currently selected module.
+         */
+        MODULE GetModule();
+
+        /**
+         * Checks the currently selected module.
+         *
+         * @param[in] module The module to check.
+         * @return True if the currently selected module matches the module to check, false
+         * otherwise.
+         */
+        bool IsModule(MODULE module);
+
+        /**
+         * Checks if the currently selected module is the field module.
+         *
+         * @return True if the currently selected module is the field module, false otherwise.
+         */
+        bool IsFieldModule();
+
+        /**
+         * Checks if the currently selected module is the battle module.
+         *
+         * @return True if the currently selected module is the battle module, false otherwise.
+         */
+        bool IsBattleModule();
+
+        /**
+         * Checks if the currently selected module is the world module.
+         *
+         * @return True if the currently selected module is the world module, false otherwise.
+         */
+        bool IsWorldModule();
+
+        /**
+         * Sets the current module for the entity manager.
+         *
+         * Operation availability and entity visibility will depend on the loaded module. Check
+         * {@see SetFieldModule()}, {@see SetBattleModule()} and {@see SetWorldModule()} for
+         * information about what changing modules implies.
+         */
+        void SetModule(MODULE module);
+
+        /**
+         * Sets the current module to the field mode.
+         *
+         * While the field module is active. All field entities are present and updated each frame,
+         * and the walkmesh is active. Setting the field module will clear all the information
+         * stored in the battle and world modules.
+         */
+        void SetFieldModule();
+
+        /**
+         * Sets the current module to the battle mode.
+         *
+         * While the battle module is active. Battle entities are present and updated each frame.
+         * Setting the field module will not clear the information stored in the field and world
+         * modules.
+         */
+        void SetBattleModule();
+
+        /**
+         * Sets the current module to the world map mode.
+         *
+         * While the world module is active. All world entities are present and updated each frame,
+         * and the walkmesh is active. Setting the world module will clear all the information
+         * stored in the battle and field modeules.
+         */
+        void SetWorldModule();
+
+        /**
+         * Sets the module that was loaded before a battle.
+         *
+         * Calling this will call either {@see SetFieldModule()} or {@see SetWorldModule},
+         * depending on which module was loaded before. Calling this while not in the battle module
+         * will do nothing.
+         */
+        void SetPreviousModule();
+
         /**
          * Handles an input event.
          *
@@ -48,6 +158,8 @@ class EntityManager : public Ogre::Singleton<EntityManager>{
 
         /**
          * Updates the entities in the manager.
+         *
+         * It only updates the entities of the currenly selected module.
          */
         void Update();
 
@@ -65,9 +177,54 @@ class EntityManager : public Ogre::Singleton<EntityManager>{
 
         /**
          * Clears the entity manager.
+         *
+         * Clears the entity manager for the currently loaded module. Check {@see ClearField()},
+         * {@see ClearBattle()}, {@see ClearWorld()} for information about what this does
+         * depending on the currently loaded module.
          */
         void Clear();
 
+        /**
+         * Clears the entity manager.
+         *
+         * Clears the entity manager for the selected module. Check {@see ClearField()},
+         * {@see ClearBattle()}, {@see ClearWorld()} for information about what this does
+         * depending on the currently loaded module.
+         *
+         * @param[in] module The module to clear.
+         */
+        void Clear(MODULE module);
+
+        /**
+         * Clear all field information in the entity manager.
+         *
+         * It clears the background, the walkmesh, any pending actions and all the field entities.
+         */
+        void ClearField();
+
+        /**
+         * Clear all battle information in the entity manager.
+         *
+         * It clears any pending actions and all the battle entities.
+         */
+        void ClearBattle();
+
+        /**
+         * Clear all world map information in the entity manager.
+         *
+         * It clears the background, the walkmesh, any pending actions and all the world entities.
+         */
+        void ClearWorld();
+
+        /**
+         * Clears the entity manager.
+         *
+         * Clears the entity manager for every module. Check {@see ClearField()},
+         * {@see ClearBattle()}, {@see ClearWorld()} for information about what this does
+         * depending on the currently loaded module.
+         */
+        void ClearAll();
+
         /**
          * Pauses or resumes an entity scripts.
          *
@@ -399,6 +556,28 @@ class EntityManager : public Ogre::Singleton<EntityManager>{
           const Ogre::Vector3& current_point, const Ogre::Vector3& direction_point
         );
 
+        /**
+         * Updates the field entities in the manager.
+         */
+        void UpdateField();
+
+        /**
+         * Updates the battle entities in the manager.
+         */
+        void UpdateBattle();
+
+        /**
+         * Updates the world map entities in the manager.
+         */
+        void UpdateWorld();
+
+        /**
+         * Updates the entities of one module in the manager.
+         *
+         * @param[in] module The module whose entities to update.
+         */
+        void Update(MODULE module);
+
         /**
          * Attaches an entity to the walkmesh.
          *
@@ -505,6 +684,16 @@ class EntityManager : public Ogre::Singleton<EntityManager>{
          */
         void SetNextScrollStep();
 
+        /**
+         * The currently selected module.
+         */
+        MODULE module_;
+
+        /**
+         * The previous module.
+         */
+        MODULE prev_module_;
+
         /**
          * Indicates if the script execution is paused.
          */
@@ -526,10 +715,15 @@ class EntityManager : public Ogre::Singleton<EntityManager>{
         Ogre::String entity_table_name_;
 
         /**
-         * The list of entities.
+         * The list of field or world entities.
          */
         std::vector<Entity*> entity_;
 
+        /**
+         * The list of battle entities.
+         */
+        std::vector<Entity*> battle_entity_;
+
         /**
          * The player controlled entity.
          */

+ 17 - 6
src/core/ScriptManagerBinds.h

@@ -20,6 +20,7 @@
 #include "Logger.h"
 #include "Entity.h"
 #include "EntityManager.h"
+#include "BattleManager.h"
 #include "AudioManager.h"
 #include "SavemapManager.h"
 #include "Timer.h"
@@ -268,6 +269,15 @@ void ScriptManager::InitBinds(){
           .def("get_track_id", (int(EntityManager::*)(int)) &EntityManager::GetTrack)
     ];
 
+    // Commands for the battle manager.
+    luabind::module(lua_state_)[
+        luabind::class_<BattleManager>("BattleManager")
+          .def(
+            "start_battle", (void(BattleManager::*)(const unsigned int)) &BattleManager::StartBattle
+          )
+          .def("end_battle", (void(BattleManager::*)()) &BattleManager::EndBattle)
+    ];
+
     // Commands for the audio manager.
     luabind::module(lua_state_)[
         luabind::class_<AudioManager>("AudioManager")
@@ -779,12 +789,11 @@ void ScriptManager::InitBinds(){
             luabind::value("NONE", MSL_NONE)
           ]
           .def(
-              "set_map_name",
-              (void(DialogsManager::*)(const char*)) &DialogsManager::ScriptSetMapName
-            )
-            .def(
-              "get_map_name", (std::string(DialogsManager::*)()) &DialogsManager::GetMapName
-            )
+            "set_map_name", (void(DialogsManager::*)(const char*)) &DialogsManager::ScriptSetMapName
+          )
+          .def(
+            "get_map_name", (std::string(DialogsManager::*)()) &DialogsManager::GetMapName
+          )
     ];
 
     // UI widget commands
@@ -886,6 +895,8 @@ void ScriptManager::InitBinds(){
     //auto b = luabind::globals(lua_state_)["entity_manager"];
     luabind::globals(lua_state_)["entity_manager"]
       = boost::ref(*(EntityManager::getSingletonPtr()));
+    luabind::globals(lua_state_)["battle_manager"]
+      = boost::ref(*(BattleManager::getSingletonPtr()));
     luabind::globals(lua_state_)["audio_manager"] = boost::ref(*(AudioManager::getSingletonPtr()));
     luabind::globals(lua_state_)["savemap_manager"]
       = boost::ref(*(SavemapManager::getSingletonPtr()));

+ 48 - 18
src/core/XmlEnemyFile.cpp

@@ -27,7 +27,7 @@ void XmlEnemyFile::LoadEnemy(Enemy& enemy){
         LOG_ERROR(file_.ValueStr() + " is not a valid enemy map file! No <enemy> in root.");
         return;
     }
-    enemy.SetEnemyId(GetInt(node, "id"));
+    enemy.SetId(GetInt(node, "id"));
     enemy.SetName(GetString(node, "name"));
     enemy.SetLevel(GetInt(node, "level"));
     enemy.SetExp(GetInt(node, "exp"));
@@ -37,28 +37,58 @@ void XmlEnemyFile::LoadEnemy(Enemy& enemy){
     enemy.SetBackDamage(GetFloat(node, "back_damage"));
     node = node->FirstChild();
     while (node != nullptr){
-        /*// Location data.
-        if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "location"){
-            int id = GetInt(node, "id");
-            Ogre::String name(GetString(node, "name"));
-            BattleManager::getSingleton().SetLocation(id, name);
+        // Location data.
+        if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "stats"){
+            TiXmlNode* node_stat = node->FirstChild();
+            while (node_stat != nullptr){
+                int value = GetInt(node_stat, "value");
+                if (GetString(node_stat, "id") == "str") enemy.SetStr(value);
+                else if (GetString(node_stat, "id") == "mag") enemy.SetMag(value);
+                else if (GetString(node_stat, "id") == "def") enemy.SetDef(value);
+                else if (GetString(node_stat, "id") == "mdef") enemy.SetSpr(value);
+                else if (GetString(node_stat, "id") == "spd") enemy.SetDex(value);
+                else if (GetString(node_stat, "id") == "lck") enemy.SetLck(value);
+                else if (GetString(node_stat, "id") == "eva") enemy.SetEva(value);
+                node_stat = node_stat->NextSibling();
+            }
+        }
+        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "elements"){
+            TiXmlNode* node_elm = node->FirstChild();
+            while (node_elm != nullptr && node->ValueStr() == "element"){
+                Enemy::Element elm;
+                elm.id = GetInt(node_elm, "element");
+                elm.factor = GetFloat(node_elm, "factor");
+                enemy.AddElement(elm);
+                node_elm = node_elm->NextSibling();
+            }
+        }
+        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "immunities"){
+            TiXmlNode* node_imm = node->FirstChild();
+            while (node_imm != nullptr && node->ValueStr() == "element"){
+                Enemy::Immunity imm;
+                imm.status = GetInt(node_imm, "immunity");
+                imm.rate = GetFloat(node_imm, "rate");
+                enemy.AddImmunity(imm);
+                node_imm = node_imm->NextSibling();
+            }
+        }
+        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "attacks"){
+            // TODO
         }
         else if (
-          node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "arena"
+          node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "manipulate"
         ){
-            bool is_arena = GetInt(node, "is_arena") == 1;
-            BattleManager::getSingleton().SetArenaBattle(is_arena);
-            if (is_arena){
-                // TODO: Read more info for arena battles
-            }
+            // TODO
+        }
+        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "steal"){
+            // TODO
+        }
+        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "drops"){
+            // TODO
         }
-        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "camera"){
-            BattleManager::getSingleton().SetInitialCamera(GetInt(node, "initial"));
-            // TODO: Loop cameras
+        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "animations"){
+            // TODO
         }
-        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "enemies"){
-            // TODO: Loop enemies
-        }*/
         node = node->NextSibling();
     }
 }

+ 30 - 5
src/core/XmlFormationFile.cpp

@@ -42,9 +42,7 @@ void XmlFormationFile::LoadFormation(){
             Ogre::String name(GetString(node, "name"));
             BattleManager::getSingleton().SetLocation(id, name);
         }
-        else if (
-          node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "arena"
-        ){
+        else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "arena"){
             bool is_arena = GetInt(node, "is_arena") == 1;
             BattleManager::getSingleton().SetArenaBattle(is_arena);
             if (is_arena){
@@ -53,10 +51,37 @@ void XmlFormationFile::LoadFormation(){
         }
         else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "camera"){
             BattleManager::getSingleton().SetInitialCamera(GetInt(node, "initial"));
-            // TODO: Loop cameras
+            TiXmlNode* camera_node = node->FirstChild();
+            while (camera_node != nullptr){
+                int id = GetInt(camera_node, "id");
+                Ogre::Vector3 pos = Ogre::Vector3(
+                  GetInt(camera_node, "x"), GetInt(camera_node, "y"), GetInt(camera_node, "z")
+                );
+                Ogre::Vector3 dir = Ogre::Vector3(
+                  GetInt(camera_node, "direction_x"), GetInt(camera_node, "direction_y"),
+                  GetInt(camera_node, "direction_z")
+                );
+                BattleManager::getSingleton().AddCamera(id, pos, dir);
+                camera_node = camera_node->NextSibling();
+            }
         }
         else if (node->Type() == TiXmlNode::TINYXML_ELEMENT && node->ValueStr() == "enemies"){
-            // TODO: Loop enemies
+            TiXmlNode* enemy_node = node->FirstChild();
+            while (enemy_node != nullptr){
+                int id = GetInt(enemy_node, "id");
+                Ogre::Vector3 pos = Ogre::Vector3(
+                  GetInt(enemy_node, "x"), GetInt(enemy_node, "y"), GetInt(enemy_node, "z")
+                );
+                bool front = GetInt(enemy_node, "row") == 1;
+                bool visible = GetInt(enemy_node, "visible") == 1;
+                bool targeteable = GetInt(enemy_node, "targeteable") == 1;
+                bool active = GetInt(enemy_node, "main_script_active") == 1;
+                std::string cover = GetString(enemy_node, "cover");
+                BattleManager::getSingleton().AddEnemy(
+                  id, pos, front, visible, targeteable, active, cover
+                );
+                enemy_node = enemy_node->NextSibling();
+            }
         }
         node = node->NextSibling();
     }

+ 27 - 26
src/installer/BattleDataInstaller.cpp

@@ -327,7 +327,7 @@ unsigned int BattleDataInstaller::ConvertModel(){
 void BattleDataInstaller::WriteEnemies(){
     for (Enemy enemy : enemies_){
         TiXmlDocument xml;
-        std::unique_ptr<TiXmlElement> container(new TiXmlElement("Enemy"));
+        std::unique_ptr<TiXmlElement> container(new TiXmlElement("enemy"));
         container->SetAttribute("id", enemy.id);
         container->SetAttribute("name", enemy.name);
         container->SetAttribute("level", enemy.level);
@@ -336,86 +336,87 @@ void BattleDataInstaller::WriteEnemies(){
         container->SetAttribute("money", enemy.money);
         container->SetAttribute("morph", enemy.morph);
         container->SetDoubleAttribute("back_damage", enemy.back_damage);
-        std::unique_ptr<TiXmlElement> stats(new TiXmlElement("Stats"));
-        std::unique_ptr<TiXmlElement> stat_str(new TiXmlElement("Stat"));
+        std::unique_ptr<TiXmlElement> stats(new TiXmlElement("stats"));
+        std::unique_ptr<TiXmlElement> stat_str(new TiXmlElement("stat"));
         stat_str->SetAttribute("id", "str");
         stat_str->SetAttribute("value", enemy.str);
         stats->LinkEndChild(stat_str.release());
-        std::unique_ptr<TiXmlElement> stat_mag(new TiXmlElement("Stat"));
+        std::unique_ptr<TiXmlElement> stat_mag(new TiXmlElement("stat"));
         stat_mag->SetAttribute("id", "mag");
         stat_mag->SetAttribute("value", enemy.mag);
         stats->LinkEndChild(stat_mag.release());
-        std::unique_ptr<TiXmlElement> stat_def(new TiXmlElement("Stat"));
+        std::unique_ptr<TiXmlElement> stat_def(new TiXmlElement("stat"));
         stat_def->SetAttribute("id", "def");
         stat_def->SetAttribute("value", enemy.def);
         stats->LinkEndChild(stat_def.release());
-        std::unique_ptr<TiXmlElement> stat_mdef(new TiXmlElement("Stat"));
+        std::unique_ptr<TiXmlElement> stat_mdef(new TiXmlElement("stat"));
         stat_mdef->SetAttribute("id", "mdef");
         stat_mdef->SetAttribute("value", enemy.mdef);
         stats->LinkEndChild(stat_mdef.release());
-        std::unique_ptr<TiXmlElement> stat_spd(new TiXmlElement("Stat"));
+        std::unique_ptr<TiXmlElement> stat_spd(new TiXmlElement("stat"));
         stat_spd->SetAttribute("id", "spd");
         stat_spd->SetAttribute("value", enemy.spd);
         stats->LinkEndChild(stat_spd.release());
-        std::unique_ptr<TiXmlElement> stat_lck(new TiXmlElement("Stat"));
+        std::unique_ptr<TiXmlElement> stat_lck(new TiXmlElement("stat"));
         stat_lck->SetAttribute("id", "lck");
         stat_lck->SetAttribute("value", enemy.lck);
         stats->LinkEndChild(stat_lck.release());
-        std::unique_ptr<TiXmlElement> stat_eva(new TiXmlElement("Stat"));
+        std::unique_ptr<TiXmlElement> stat_eva(new TiXmlElement("stat"));
         stat_eva->SetAttribute("id", "eva");
         stat_eva->SetAttribute("value", enemy.eva);
         stats->LinkEndChild(stat_eva.release());
         container->LinkEndChild(stats.release());
-        std::unique_ptr<TiXmlElement> elements(new TiXmlElement("Elements"));
+        std::unique_ptr<TiXmlElement> elements(new TiXmlElement("elements"));
         for (Enemy::Element element : enemy.elements){
-            std::unique_ptr<TiXmlElement> xml_element(new TiXmlElement("Element"));
+            std::unique_ptr<TiXmlElement> xml_element(new TiXmlElement("element"));
             xml_element->SetAttribute("id", element.id);
             xml_element->SetDoubleAttribute("factor", element.factor);
             elements->LinkEndChild(xml_element.release());
         }
         container->LinkEndChild(elements.release());
-        std::unique_ptr<TiXmlElement> immunities(new TiXmlElement("Immunities"));
+        std::unique_ptr<TiXmlElement> immunities(new TiXmlElement("immunities"));
         for (Enemy::Immunity immunity : enemy.immunities){
-            std::unique_ptr<TiXmlElement> xml_immunity(new TiXmlElement("Immunity"));
+            std::unique_ptr<TiXmlElement> xml_immunity(new TiXmlElement("immunity"));
             xml_immunity->SetAttribute("status", immunity.status);
             xml_immunity->SetDoubleAttribute("rate", immunity.rate);
             immunities->LinkEndChild(xml_immunity.release());
         }
         container->LinkEndChild(immunities.release());
-        std::unique_ptr<TiXmlElement> attacks(new TiXmlElement("Attacks"));
+        std::unique_ptr<TiXmlElement> attacks(new TiXmlElement("attacks"));
         for (Enemy::Attack attack : enemy.attacks){
-            std::unique_ptr<TiXmlElement> xml_attack(new TiXmlElement("Attack"));
+            std::unique_ptr<TiXmlElement> xml_attack(new TiXmlElement("attack"));
             xml_attack->SetAttribute("status", attack.id);
             xml_attack->SetAttribute("camera", attack.camera);
             attacks->LinkEndChild(xml_attack.release());
         }
         container->LinkEndChild(attacks.release());
-        std::unique_ptr<TiXmlElement> manip_attacks(new TiXmlElement("ManipulateAttacks"));
+        std::unique_ptr<TiXmlElement> manip_attacks(new TiXmlElement("manipulate"));
+        manip_attacks->SetAttribute("manipulable", enemy.manipulate_attacks.size() > 0 ? 1 : 0);
         for (u16 attack : enemy.manipulate_attacks){
-            std::unique_ptr<TiXmlElement> xml_manip_attack(new TiXmlElement("Attack"));
+            std::unique_ptr<TiXmlElement> xml_manip_attack(new TiXmlElement("attack"));
             xml_manip_attack->SetAttribute("id", attack);
             manip_attacks->LinkEndChild(xml_manip_attack.release());
         }
         container->LinkEndChild(manip_attacks.release());
-        std::unique_ptr<TiXmlElement> steals(new TiXmlElement("Steal"));
+        std::unique_ptr<TiXmlElement> steals(new TiXmlElement("steal"));
         for (Enemy::Item item : enemy.steal){
-            std::unique_ptr<TiXmlElement> xml_steal(new TiXmlElement("Item"));
+            std::unique_ptr<TiXmlElement> xml_steal(new TiXmlElement("item"));
             xml_steal->SetAttribute("id", item.id);
             xml_steal->SetDoubleAttribute("rate", item.rate);
             steals->LinkEndChild(xml_steal.release());
         }
         container->LinkEndChild(steals.release());
-        std::unique_ptr<TiXmlElement> drops(new TiXmlElement("Drops"));
+        std::unique_ptr<TiXmlElement> drops(new TiXmlElement("drop"));
         for (Enemy::Item item : enemy.drop){
-            std::unique_ptr<TiXmlElement> xml_drop(new TiXmlElement("Item"));
+            std::unique_ptr<TiXmlElement> xml_drop(new TiXmlElement("item"));
             xml_drop->SetAttribute("id", item.id);
             xml_drop->SetDoubleAttribute("rate", item.rate);
             drops->LinkEndChild(xml_drop.release());
         }
         container->LinkEndChild(drops.release());
-        std::unique_ptr<TiXmlElement> animations(new TiXmlElement("Animations"));
+        std::unique_ptr<TiXmlElement> animations(new TiXmlElement("animations"));
         for (unsigned int animation : enemy.animations){
-            std::unique_ptr<TiXmlElement> xml_animation(new TiXmlElement("Animation"));
+            std::unique_ptr<TiXmlElement> xml_animation(new TiXmlElement("animation"));
             xml_animation->SetAttribute("id", animation);
             animations->LinkEndChild(xml_animation.release());
         }
@@ -645,7 +646,7 @@ std::string BattleDataInstaller::BuildEnemyFileName(Enemy enemy){
     std::string file_name = "game/enemy/";
     std::string id = std::to_string(enemy.id);
     while (id.size() < 4) id = "0" + id;
-    file_name += (id + "_");
+    /*file_name += (id + "_");
     for (int n = 0; n < enemy.name.size(); n ++){
         if (
           (enemy.name[n] >= '0' && enemy.name[n] <= '9')
@@ -654,8 +655,8 @@ std::string BattleDataInstaller::BuildEnemyFileName(Enemy enemy){
         ){
             file_name += enemy.name[n];
         }
-    }
-    file_name += ".xml";
+    }*/
+    file_name += id + ".xml";
     return file_name;
 }
 

+ 26 - 8
src/installer/data/BattleSceneFile.cpp

@@ -48,9 +48,18 @@ void BattleSceneFile::Read(File file){
     }
     for (int c = 0; c < 4; c ++){
         for (int p = 0; p < 3; p ++){
-            scene_.camera[c].camera[p].x = file.readU16LE();
-            scene_.camera[c].camera[p].y = file.readU16LE();
-            scene_.camera[c].camera[p].x = file.readU16LE();
+            // Camera positions are stored as 16 bit floats.
+            // Here, ideally, 16 bits would be read, and then turned to float values, but...
+            // since the rounding is not really important, this is just reading the most
+            // significative byte as an integer, and skipping the other byte. Also, it's being
+            // multiplied by 10 to use bigger numbers in the XML.
+            scene_.camera[c].camera[p].x = file.readU8();
+            file.readU8();
+            // Y and Z are inverted in original data.
+            scene_.camera[c].camera[p].z = file.readU8();
+            file.readU8();
+            scene_.camera[c].camera[p].y = file.readU8();
+            file.readU8();
             scene_.camera[c].camera[p].d_x = file.readU16LE();
             scene_.camera[c].camera[p].d_y = file.readU16LE();
             scene_.camera[c].camera[p].d_x = file.readU16LE();
@@ -60,9 +69,18 @@ void BattleSceneFile::Read(File file){
     for (int f = 0; f < 4; f ++){
         for (int e = 0; e < 6; e ++){
             scene_.formation[f][e].id = file.readU16LE();
-            scene_.formation[f][e].x = file.readU16LE();
-            scene_.formation[f][e].y = file.readU16LE();
-            scene_.formation[f][e].z = file.readU16LE();
+            // Enemy positions are stored as 16 bit floats.
+            // Here, ideally, 16 bits would be read, and then turned to float values, but...
+            // since the rounding is not really important, this is just reading the most
+            // significative byte as an integer, and skipping the other byte. Also, it's being
+            // multiplied by 10 to use bigger numbers in the XML.
+            scene_.formation[f][e].x = file.readU8();
+            file.readU8();
+            // Y and Z are inverted in original data.
+            scene_.formation[f][e].z = file.readU8();
+            file.readU8();
+            scene_.formation[f][e].y = file.readU8();
+            file.readU8();
             scene_.formation[f][e].row = file.readU16LE();
             scene_.formation[f][e].cover_flags = file.readU16LE();
             scene_.formation[f][e].flags = file.readU32LE();
@@ -804,10 +822,10 @@ void BattleSceneFile::Read(File file){
             Formation::Camera camera;
             camera.x = scene_.camera[f].camera[c].x;
             camera.y = scene_.camera[f].camera[c].y;
-            camera.y = scene_.camera[f].camera[c].z;
+            camera.z = scene_.camera[f].camera[c].z;
             camera.d_x = scene_.camera[f].camera[c].d_x;
             camera.d_y = scene_.camera[f].camera[c].d_y;
-            camera.d_y = scene_.camera[f].camera[c].d_z;
+            camera.d_z = scene_.camera[f].camera[c].d_z;
             formation.camera_positions.push_back(camera);
         }
         if (scene_.setup[f].camera < formation.camera_positions.size())

+ 1 - 1
src/installer/decompiler/field/instruction/FieldModuleInstruction.cpp

@@ -107,7 +107,7 @@ void FieldModuleInstruction::ProcessBATTLE(CodeGenerator* code_gen){
     const auto& battle_id = FieldCodeGenerator::FormatValueOrVariable(
       cg->GetFormatter(), params_[0]->GetUnsigned(), params_[1]->GetUnsigned()
     );
-    code_gen->AddOutputLine((boost::format("entity_manager:battle_run(%1%)") % battle_id).str());
+    code_gen->AddOutputLine((boost::format("attle_manager:start_battle(%1%)") % battle_id).str());
 }
 
 void FieldModuleInstruction::ProcessBTLON(CodeGenerator* code_gen){

+ 3 - 0
src/main.cpp

@@ -23,6 +23,7 @@
 #include "VGearsGameState.h"
 #include "common/VGearsApplication.h"
 #include "core/AudioManager.h"
+#include "core/BattleManager.h"
 #include "core/CameraManager.h"
 #include "core/ConfigCmdManager.h"
 #include "core/ConfigFile.h"
@@ -112,6 +113,7 @@ int main(int argc, char *argv[]){
         auto ui_manager = std::make_unique<UiManager>();
         auto dialogs_manager = std::make_unique<DialogsManager>();
         auto entity_manager = std::make_unique<EntityManager>();
+        auto battle_manager = std::make_unique<BattleManager>();
         auto console = std::make_unique<Console>();
         auto worldMapModule = std::make_unique<VGears::WorldmapModule>();
 
@@ -141,6 +143,7 @@ int main(int argc, char *argv[]){
 
         // Must be destroyed before the script manager.
         entity_manager.reset();
+        battle_manager.reset();
         ui_manager.reset();
         script_manager.reset();
     }