BattleManager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Copyright (C) 2022 The V-Gears Team
  3. *
  4. * This file is part of V-Gears
  5. *
  6. * V-Gears is free software: you can redistribute it and/or modify it under
  7. * terms of the GNU General Public License as published by the Free Software
  8. * Foundation, version 3.0 (GPLv3) of the License.
  9. *
  10. * V-Gears is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <algorithm>
  16. #include <iostream>
  17. #include <cmath>
  18. #include <OgreEntity.h>
  19. #include <OgreRoot.h>
  20. #include <OgreViewport.h>
  21. #include "FF7Character.h"
  22. #include "core/AudioManager.h"
  23. #include "core/BattleManager.h"
  24. #include "core/CameraManager.h"
  25. #include "core/Console.h"
  26. #include "core/DialogsManager.h"
  27. #include "core/Enemy.h"
  28. #include "core/EntityManager.h"
  29. #include "core/ConfigVar.h"
  30. #include "core/InputManager.h"
  31. #include "core/Logger.h"
  32. #include "core/ScriptManager.h"
  33. #include "core/TextHandler.h"
  34. #include "core/UiManager.h"
  35. #include "core/XmlFormationFile.h"
  36. /**
  37. * Battle manager singleton.
  38. */
  39. template<>BattleManager *Ogre::Singleton<BattleManager>::msSingleton = nullptr;
  40. ConfigVar cv_debug_battle_grid("debug_battle_grid", "Draw debug battle grid", "false");
  41. ConfigVar cv_debug_battle_axis("debug_battle_axis", "Draw debug battle axis", "false");
  42. const float BattleManager::ENEMY_SCALE = 0.0032f;
  43. const float BattleManager::ATTACK_SCALE = 0.0032f;
  44. const float BattleManager::PARTY_SCALE = 0.0039f;
  45. const float BattleManager::SCENE_SCALE = 0.0012f;
  46. BattleManager::BattleManager(){
  47. LOG_TRIVIAL("BattleManager created.");
  48. scene_node_ = Ogre::Root::getSingleton().getSceneManager("Scene")
  49. ->getRootSceneNode()->createChildSceneNode("BattleManager");
  50. // Build scene model map.
  51. scene_model_map_ = XmlBattleScenesFile("./data/models/battle/scenes.xml").GetScenes();
  52. // Build character model map.
  53. character_model_map_
  54. = XmlBattleCharactersFile("./data/models/battle/characters.xml").GetCharacters();
  55. }
  56. BattleManager::~BattleManager(){
  57. Clear();
  58. Ogre::Root::getSingleton().getSceneManager("Scene")->getRootSceneNode()->removeAndDestroyChild(
  59. "BattleManager"
  60. );
  61. LOG_TRIVIAL("BattleManager destroyed.");
  62. }
  63. void BattleManager::Input(const VGears::Event& event){}
  64. void BattleManager::UpdateDebug(){}
  65. void BattleManager::OnResize(){}
  66. void BattleManager::ClearField(){
  67. LOG_TRIVIAL("Called empty method BattleManager::ClearField()");
  68. }
  69. void BattleManager::ClearBattle(){
  70. formation_id_ = -1;
  71. next_formation_id_ = -1;
  72. // TODO location_ = null;
  73. camera_.clear();
  74. initial_camera_ = 0;
  75. layout_ = LAYOUT::NORMAL;
  76. escape_difficulty_ = 0.0f;
  77. arena_battle_ = false;
  78. show_victory_pose_ = true;
  79. show_spoils_ = true;
  80. preemptive_ = true;
  81. money_ = 0;
  82. spoil_.clear();
  83. enemies_.clear();
  84. // TODO party_.clear();
  85. }
  86. void BattleManager::ClearWorld(){
  87. LOG_TRIVIAL("Called empty method BattleManager::ClearWorld()");
  88. }
  89. void BattleManager::StartBattle(const unsigned int id){
  90. if (module_ == Module::BATTLE){
  91. LOG_ERROR("Started battle in BattleManager, but the manager was already in battle mode.");
  92. return;
  93. }
  94. SetBattleModule();
  95. AudioManager::getSingleton().SetBattleModule();
  96. CameraManager::getSingleton().SetBattleModule();
  97. DialogsManager::getSingleton().SetBattleModule();
  98. EntityManager::getSingleton().SetBattleModule();
  99. EntityManager::getSingleton().GetBackground2D()->Hide();
  100. InputManager::getSingleton().SetBattleModule();
  101. ScriptManager::getSingleton().SetBattleModule();
  102. UiManager::getSingleton().SetBattleModule();
  103. SetFormationId(id);
  104. // Load the formation XML file (name is dddd.xml)
  105. std::string filename = std::to_string(formation_id_);
  106. while (filename.length() < 4) filename = "0" + filename;
  107. filename = "./data/gamedata/formation/" + filename + ".xml";
  108. // This sets the data in the battle manager singleton.
  109. XmlFormationFile(filename).LoadFormation();
  110. // TODO: Music
  111. if (camera_.size() == 0)
  112. LOG_ERROR("Unable to start battle camera. No cameras defined in the BattleManager.");
  113. else if (initial_camera_ > camera_.size()){
  114. LOG_ERROR(
  115. "Unable to set initial battle camera. Default camera is set to "
  116. + std::to_string(initial_camera_) + " but only " + std::to_string(camera_.size())
  117. + " cameras are defined in the CameraManager. Defaulting to first camera.");
  118. CameraManager::getSingleton().StartBattleCamera(
  119. camera_.at(0).location, camera_.at(0).orientation
  120. );
  121. }
  122. else
  123. CameraManager::getSingleton().StartBattleCamera(
  124. camera_.at(initial_camera_).location, camera_.at(initial_camera_).orientation
  125. );
  126. LoadParty();
  127. //EndBattle();// TODO: Debug
  128. }
  129. void BattleManager::EndBattle(){
  130. if (module_ != Module::BATTLE){
  131. LOG_ERROR("Ended battle in BattleManager, but the manager was not in battle mode.");
  132. return;
  133. }
  134. SetPreviousModule();
  135. ClearBattle();
  136. CameraManager::getSingleton().EndBattleCamera();
  137. AudioManager::getSingleton().SetPreviousModule();
  138. CameraManager::getSingleton().SetPreviousModule();
  139. DialogsManager::getSingleton().SetPreviousModule();
  140. ScriptManager::getSingleton().ClearBattle();
  141. EntityManager::getSingleton().ClearBattle();
  142. EntityManager::getSingleton().GetBackground2D()->Show();
  143. EntityManager::getSingleton().SetPreviousModule();
  144. InputManager::getSingleton().SetPreviousModule();
  145. ScriptManager::getSingleton().ClearBattle();
  146. ScriptManager::getSingleton().SetPreviousModule();
  147. UiManager::getSingleton().SetPreviousModule();
  148. }
  149. std::vector<Enemy> BattleManager::GetEnemies() const{return enemies_;}
  150. void BattleManager::AddEnemy(
  151. const unsigned int id, const Ogre::Vector3 pos, const bool front, const bool visible,
  152. const bool targeteable, const bool active, const std::string cover
  153. ){
  154. if (module_ != Module::BATTLE){
  155. LOG_ERROR(
  156. "Tried to add an enemy to the BattleManager, but the manager was not in battle mode."
  157. );
  158. return;
  159. }
  160. Enemy* enemy = new Enemy(id, pos, front, visible, targeteable, active, cover);
  161. enemies_.push_back(*enemy);
  162. EntityManager::getSingleton().AddEntity(
  163. enemy->GetName() + "_" + std::to_string(enemies_.size() - 1),
  164. "enemies/" + enemy->GetModel() + ".mesh", enemy->GetPos(), Ogre::Degree(1),
  165. Ogre::Vector3(ENEMY_SCALE, ENEMY_SCALE, ENEMY_SCALE), Ogre::Quaternion(1, 1, 0, 0), id
  166. );
  167. EntityManager::getSingleton().GetEntity(
  168. enemy->GetName() + "_" + std::to_string(enemies_.size() - 1)
  169. )->SetRotation(Ogre::Degree(180));
  170. }
  171. unsigned int BattleManager::ScriptGetEnemyCount() const{return enemies_.size();}
  172. Enemy* BattleManager::ScriptGetEnemy(const unsigned int index){
  173. if (index >= enemies_.size()) return nullptr;
  174. return &enemies_[index];
  175. }
  176. void BattleManager::AddAttackModel(
  177. const unsigned int id, const std::string model, const Ogre::Vector3 pos,
  178. const Ogre::Degree orientation, const std::string animation
  179. ){
  180. if (module_ != Module::BATTLE){
  181. LOG_ERROR(
  182. "Tried to add an attack model to the BattleManager,"
  183. + " but the manager was not in battle mode."
  184. );
  185. return;
  186. }
  187. //Enemy* enemy = new Enemy(id, pos, front, visible, targeteable, active, cover);
  188. //enemies_.push_back(*enemy);
  189. EntityManager::getSingleton().AddEntity(
  190. model + "_" + std::to_string(id), "attacks/" + model + ".mesh", pos, orientation,
  191. Ogre::Vector3(ENEMY_SCALE, ENEMY_SCALE, ENEMY_SCALE), Ogre::Quaternion(1, 1, 0, 0), id
  192. );
  193. EntityManager::getSingleton().GetEntity(model + "_" + std::to_string(id))
  194. ->SetRotation(orientation);
  195. EntityManager::getSingleton().GetEntity(model + "_" + std::to_string(id))
  196. ->ScriptSetDefaultAnimation(animation.c_str());
  197. }
  198. void BattleManager::ScriptAddAttackModel(
  199. const unsigned int id, const char* model, const float x, const float y, const float z,
  200. const int orientation, const char* animation
  201. ){
  202. AddAttackModel(
  203. id, std::string(model), Ogre::Vector3(x, y, z),
  204. Ogre::Degree(orientation), std::string(animation)
  205. );
  206. }
  207. void BattleManager::AddCamera(
  208. const unsigned int id, const Ogre::Vector3 pos, const Ogre::Vector3 dir
  209. ){
  210. if (module_ != Module::BATTLE){
  211. LOG_ERROR(
  212. "Tried to add a camera to the BattleManager, but the manager was not in battle mode."
  213. );
  214. return;
  215. }
  216. BattleCamera camera;
  217. camera.id = id;
  218. camera.location = pos;
  219. camera.orientation = dir;
  220. camera_.push_back(camera);
  221. }
  222. void BattleManager::SetLayout(const LAYOUT layout){
  223. if (module_ != Module::BATTLE){
  224. LOG_ERROR("Tried to set a layout the BattleManager, but it's not in battle mode.");
  225. return;
  226. }
  227. if (layout == LAYOUT::UNKNOWN_0 || layout == LAYOUT::UNKNOWN_1) layout_ = LAYOUT::NORMAL;
  228. else layout_ = layout;
  229. }
  230. void BattleManager::SetFormationId(const int id){
  231. if (module_ != Module::BATTLE){
  232. LOG_ERROR("Tried to set formation int the BattleManager, but it's not in battle mode.");
  233. return;
  234. }
  235. if (id < 0) formation_id_ = -1;
  236. else formation_id_ = id;
  237. }
  238. void BattleManager::SetNextFormationId(const int id){
  239. if (module_ != Module::BATTLE){
  240. LOG_ERROR("Tried to set next formation in the BattleManager, but it's not in battle mode.");
  241. return;
  242. }
  243. if (id < 0) next_formation_id_ = -1;
  244. else next_formation_id_ = id;
  245. }
  246. void BattleManager::SetEscapeability(const float difficulty){
  247. if (module_ != Module::BATTLE){
  248. LOG_ERROR("Tried to set escapability in the BattleManager, but it's not in battle mode.");
  249. return;
  250. }
  251. if (difficulty < 0.0f || difficulty > 1.0f) escape_difficulty_ = -1.0f;
  252. else escape_difficulty_ = difficulty;
  253. }
  254. void BattleManager::SetSkipVictoryPose(const bool skip){
  255. if (module_ != Module::BATTLE){
  256. LOG_ERROR("Tried to set pose mode in the BattleManager, but it's not in battle mode.");
  257. return;
  258. }
  259. show_victory_pose_ = !skip;
  260. }
  261. void BattleManager::SetSkipSpoils(const bool skip){
  262. if (module_ != Module::BATTLE){
  263. LOG_ERROR("Tried to set spoils mode in the BattleManager, but it's not in battle mode.");
  264. return;
  265. }
  266. show_spoils_ = !skip;
  267. }
  268. void BattleManager::SetLocation(const int id, const Ogre::String name){
  269. if (module_ != Module::BATTLE){
  270. LOG_ERROR("Tried to set a location in the BattleManager, but it's not in battle mode.");
  271. return;
  272. }
  273. std::string model = "";
  274. for (XmlBattleScenesFile::BattleScene scene : scene_model_map_){
  275. if (scene.id == id){
  276. model = "scenes/" + scene.model;
  277. break;
  278. }
  279. }
  280. if (model == ""){
  281. LOG_ERROR("No 3D model assigned to battle location " + std::to_string(id));
  282. return;
  283. }
  284. EntityManager::getSingleton().SetBackground3D(name, model);
  285. }
  286. void BattleManager::SetArenaBattle(const bool arena){
  287. if (module_ != Module::BATTLE){
  288. LOG_ERROR("Tried to set arena info in the BattleManager, but it's not in battle mode.");
  289. return;
  290. }
  291. arena_battle_ = arena;
  292. }
  293. void BattleManager::SetInitialCamera(const unsigned int id){
  294. if (module_ != Module::BATTLE){
  295. LOG_ERROR("Tried to set the camera in the BattleManager, but it's not in battle mode.");
  296. return;
  297. }
  298. initial_camera_ = id;
  299. }
  300. void BattleManager::LoadParty(){
  301. if (module_ != Module::BATTLE){
  302. LOG_ERROR("Tried to load party in the BattleManager, but it's not in battle mode.");
  303. return;
  304. }
  305. std::vector<int> party = TextHandler::getSingleton().GetParty();
  306. std::vector<int> positions {};
  307. for (int i = 0; i < party.size(); i ++) positions.push_back(i);
  308. Ogre::Vector3 position = Ogre::Vector3(0, 5, 0);
  309. // Randomize party member positions.
  310. std::random_shuffle(positions.begin(), positions.end());
  311. // TODO: Read this from data/gamedata/characters.xml
  312. for (int i = 0; i < positions.size(); i ++){
  313. if (party.at(positions.at(i)) == - 1) continue;
  314. std::string name = "";
  315. std::string model = "";
  316. for (XmlBattleCharactersFile::BattleCharacter character : character_model_map_){
  317. if (character.id == party.at(positions.at(i))){
  318. model = "characters/" + character.models.at(0).model;
  319. name = "party_" + character.models.at(0).name;
  320. break;
  321. }
  322. }
  323. if (model == ""){
  324. LOG_ERROR(
  325. "No 3D model assigned to battle character "
  326. + std::to_string(party.at(positions.at(i)))
  327. );
  328. return;
  329. }
  330. EntityManager::getSingleton().AddEntity(
  331. name, model, position, Ogre::Degree(0),
  332. Ogre::Vector3(PARTY_SCALE, PARTY_SCALE, PARTY_SCALE),
  333. Ogre::Quaternion(1, 1, 0, 0), 100 + i
  334. );
  335. // Next position in Y axis
  336. position.x += ((i + 1) * (i % 2 == 0 ? 5 : -5));
  337. }
  338. }
  339. void BattleManager::UpdateField(){}
  340. void BattleManager::UpdateBattle(){
  341. ScriptManager::getSingleton().RunString("UiContainer.BattleUi:tick()");
  342. }
  343. void BattleManager::UpdateWorld(){}