BattleManager.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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::PARTY_SCALE = 0.0039f;
  44. const float BattleManager::SCENE_SCALE = 0.0012f;
  45. BattleManager::BattleManager(){
  46. LOG_TRIVIAL("BattleManager created.");
  47. scene_node_ = Ogre::Root::getSingleton().getSceneManager("Scene")
  48. ->getRootSceneNode()->createChildSceneNode("BattleManager");
  49. // Build scene model map.
  50. scene_model_map_ = XmlBattleScenesFile("./data/models/battle/scenes.xml").GetScenes();
  51. // Build character model map.
  52. character_model_map_
  53. = XmlBattleCharactersFile("./data/models/battle/characters.xml").GetCharacters();
  54. }
  55. BattleManager::~BattleManager(){
  56. Clear();
  57. Ogre::Root::getSingleton().getSceneManager("Scene")->getRootSceneNode()->removeAndDestroyChild(
  58. "BattleManager"
  59. );
  60. LOG_TRIVIAL("BattleManager destroyed.");
  61. }
  62. void BattleManager::Input(const VGears::Event& event){}
  63. void BattleManager::UpdateDebug(){}
  64. void BattleManager::OnResize(){}
  65. void BattleManager::ClearField(){
  66. LOG_TRIVIAL("Called empty method BattleManager::ClearField()");
  67. }
  68. void BattleManager::ClearBattle(){
  69. formation_id_ = -1;
  70. next_formation_id_ = -1;
  71. // TODO location_ = null;
  72. camera_.clear();
  73. initial_camera_ = 0;
  74. layout_ = LAYOUT::NORMAL;
  75. escape_difficulty_ = 0.0f;
  76. arena_battle_ = false;
  77. show_victory_pose_ = true;
  78. show_spoils_ = true;
  79. preemptive_ = true;
  80. money_ = 0;
  81. spoil_.clear();
  82. enemies_.clear();
  83. // TODO party_.clear();
  84. }
  85. void BattleManager::ClearWorld(){
  86. LOG_TRIVIAL("Called empty method BattleManager::ClearWorld()");
  87. }
  88. void BattleManager::StartBattle(const unsigned int id){
  89. if (module_ == Module::BATTLE){
  90. LOG_ERROR("Started battle in BattleManager, but the manager was already in battle mode.");
  91. return;
  92. }
  93. SetBattleModule();
  94. AudioManager::getSingleton().SetBattleModule();
  95. CameraManager::getSingleton().SetBattleModule();
  96. DialogsManager::getSingleton().SetBattleModule();
  97. EntityManager::getSingleton().SetBattleModule();
  98. EntityManager::getSingleton().GetBackground2D()->Hide();
  99. InputManager::getSingleton().SetBattleModule();
  100. ScriptManager::getSingleton().SetBattleModule();
  101. UiManager::getSingleton().SetBattleModule();
  102. SetFormationId(id);
  103. // Load the formation XML file (name is dddd.xml)
  104. std::string filename = std::to_string(formation_id_);
  105. while (filename.length() < 4) filename = "0" + filename;
  106. filename = "./data/gamedata/formation/" + filename + ".xml";
  107. // This sets the data in the battle manager singleton.
  108. XmlFormationFile(filename).LoadFormation();
  109. // TODO: Music
  110. if (camera_.size() == 0)
  111. LOG_ERROR("Unable to start battle camera. No cameras defined in the BattleManager.");
  112. else if (initial_camera_ > camera_.size()){
  113. LOG_ERROR(
  114. "Unable to set initial battle camera. Default camera is set to "
  115. + std::to_string(initial_camera_) + " but only " + std::to_string(camera_.size())
  116. + " cameras are defined in the CameraManager. Defaulting to first camera.");
  117. CameraManager::getSingleton().StartBattleCamera(
  118. camera_.at(0).location, camera_.at(0).orientation
  119. );
  120. }
  121. else
  122. CameraManager::getSingleton().StartBattleCamera(
  123. camera_.at(initial_camera_).location, camera_.at(initial_camera_).orientation
  124. );
  125. LoadParty();
  126. //EndBattle();// TODO: Debug
  127. }
  128. void BattleManager::EndBattle(){
  129. if (module_ != Module::BATTLE){
  130. LOG_ERROR("Ended battle in BattleManager, but the manager was not in battle mode.");
  131. return;
  132. }
  133. SetPreviousModule();
  134. ClearBattle();
  135. CameraManager::getSingleton().EndBattleCamera();
  136. AudioManager::getSingleton().SetPreviousModule();
  137. CameraManager::getSingleton().SetPreviousModule();
  138. DialogsManager::getSingleton().SetPreviousModule();
  139. ScriptManager::getSingleton().ClearBattle();
  140. EntityManager::getSingleton().ClearBattle();
  141. EntityManager::getSingleton().GetBackground2D()->Show();
  142. EntityManager::getSingleton().SetPreviousModule();
  143. InputManager::getSingleton().SetPreviousModule();
  144. ScriptManager::getSingleton().ClearBattle();
  145. ScriptManager::getSingleton().SetPreviousModule();
  146. UiManager::getSingleton().SetPreviousModule();
  147. }
  148. std::vector<Enemy> BattleManager::GetEnemies() const{return enemies_;}
  149. void BattleManager::AddEnemy(
  150. const unsigned int id, const Ogre::Vector3 pos, const bool front, const bool visible,
  151. const bool targeteable, const bool active, const std::string cover
  152. ){
  153. if (module_ != Module::BATTLE){
  154. LOG_ERROR(
  155. "Tried to add an enemy to the BattleManager, but the manager was not in battle mode."
  156. );
  157. return;
  158. }
  159. Enemy* enemy = new Enemy(id, pos, front, visible, targeteable, active, cover);
  160. enemies_.push_back(*enemy);
  161. EntityManager::getSingleton().AddEntity(
  162. enemy->GetName() + "_" + std::to_string(enemies_.size() - 1),
  163. "enemies/" + enemy->GetModel() + ".mesh", enemy->GetPos(), Ogre::Degree(1),
  164. Ogre::Vector3(ENEMY_SCALE, ENEMY_SCALE, ENEMY_SCALE), Ogre::Quaternion(1, 1, 0, 0), id
  165. );
  166. EntityManager::getSingleton().GetEntity(
  167. enemy->GetName() + "_" + std::to_string(enemies_.size() - 1)
  168. )->SetRotation(Ogre::Degree(180));
  169. }
  170. unsigned int BattleManager::ScriptGetEnemyCount() const{return enemies_.size();}
  171. Enemy* BattleManager::ScriptGetEnemy(const unsigned int index){
  172. if (index >= enemies_.size()) return nullptr;
  173. return &enemies_[index];
  174. }
  175. void BattleManager::AddCamera(
  176. const unsigned int id, const Ogre::Vector3 pos, const Ogre::Vector3 dir
  177. ){
  178. if (module_ != Module::BATTLE){
  179. LOG_ERROR(
  180. "Tried to add a camera to the BattleManager, but the manager was not in battle mode."
  181. );
  182. return;
  183. }
  184. BattleCamera camera;
  185. camera.id = id;
  186. camera.location = pos;
  187. camera.orientation = dir;
  188. camera_.push_back(camera);
  189. }
  190. void BattleManager::SetLayout(const LAYOUT layout){
  191. if (module_ != Module::BATTLE){
  192. LOG_ERROR("Tried to set a layout the BattleManager, but it's not in battle mode.");
  193. return;
  194. }
  195. if (layout == LAYOUT::UNKNOWN_0 || layout == LAYOUT::UNKNOWN_1) layout_ = LAYOUT::NORMAL;
  196. else layout_ = layout;
  197. }
  198. void BattleManager::SetFormationId(const int id){
  199. if (module_ != Module::BATTLE){
  200. LOG_ERROR("Tried to set formation int the BattleManager, but it's not in battle mode.");
  201. return;
  202. }
  203. if (id < 0) formation_id_ = -1;
  204. else formation_id_ = id;
  205. }
  206. void BattleManager::SetNextFormationId(const int id){
  207. if (module_ != Module::BATTLE){
  208. LOG_ERROR("Tried to set next formation in the BattleManager, but it's not in battle mode.");
  209. return;
  210. }
  211. if (id < 0) next_formation_id_ = -1;
  212. else next_formation_id_ = id;
  213. }
  214. void BattleManager::SetEscapeability(const float difficulty){
  215. if (module_ != Module::BATTLE){
  216. LOG_ERROR("Tried to set escapability in the BattleManager, but it's not in battle mode.");
  217. return;
  218. }
  219. if (difficulty < 0.0f || difficulty > 1.0f) escape_difficulty_ = -1.0f;
  220. else escape_difficulty_ = difficulty;
  221. }
  222. void BattleManager::SetSkipVictoryPose(const bool skip){
  223. if (module_ != Module::BATTLE){
  224. LOG_ERROR("Tried to set pose mode in the BattleManager, but it's not in battle mode.");
  225. return;
  226. }
  227. show_victory_pose_ = !skip;
  228. }
  229. void BattleManager::SetSkipSpoils(const bool skip){
  230. if (module_ != Module::BATTLE){
  231. LOG_ERROR("Tried to set spoils mode in the BattleManager, but it's not in battle mode.");
  232. return;
  233. }
  234. show_spoils_ = !skip;
  235. }
  236. void BattleManager::SetLocation(const int id, const Ogre::String name){
  237. if (module_ != Module::BATTLE){
  238. LOG_ERROR("Tried to set a location in the BattleManager, but it's not in battle mode.");
  239. return;
  240. }
  241. std::string model = "";
  242. for (XmlBattleScenesFile::BattleScene scene : scene_model_map_){
  243. if (scene.id == id){
  244. model = "scenes/" + scene.model;
  245. break;
  246. }
  247. }
  248. if (model == ""){
  249. LOG_ERROR("No 3D model assigned to battle location " + std::to_string(id));
  250. return;
  251. }
  252. EntityManager::getSingleton().SetBackground3D(name, model);
  253. }
  254. void BattleManager::SetArenaBattle(const bool arena){
  255. if (module_ != Module::BATTLE){
  256. LOG_ERROR("Tried to set arena info in the BattleManager, but it's not in battle mode.");
  257. return;
  258. }
  259. arena_battle_ = arena;
  260. }
  261. void BattleManager::SetInitialCamera(const unsigned int id){
  262. if (module_ != Module::BATTLE){
  263. LOG_ERROR("Tried to set the camera in the BattleManager, but it's not in battle mode.");
  264. return;
  265. }
  266. initial_camera_ = id;
  267. }
  268. void BattleManager::LoadParty(){
  269. if (module_ != Module::BATTLE){
  270. LOG_ERROR("Tried to load party in the BattleManager, but it's not in battle mode.");
  271. return;
  272. }
  273. std::vector<int> party = TextHandler::getSingleton().GetParty();
  274. std::vector<int> positions {};
  275. for (int i = 0; i < party.size(); i ++) positions.push_back(i);
  276. Ogre::Vector3 position = Ogre::Vector3(0, 5, 0);
  277. // Randomize party member positions.
  278. std::random_shuffle(positions.begin(), positions.end());
  279. // TODO: Read this from data/gamedata/characters.xml
  280. for (int i = 0; i < positions.size(); i ++){
  281. if (party.at(positions.at(i)) == - 1) continue;
  282. std::string name = "";
  283. std::string model = "";
  284. for (XmlBattleCharactersFile::BattleCharacter character : character_model_map_){
  285. if (character.id == party.at(positions.at(i))){
  286. model = "characters/" + character.models.at(0).model;
  287. name = "party_" + character.models.at(0).name;
  288. break;
  289. }
  290. }
  291. if (model == ""){
  292. LOG_ERROR(
  293. "No 3D model assigned to battle character "
  294. + std::to_string(party.at(positions.at(i)))
  295. );
  296. return;
  297. }
  298. EntityManager::getSingleton().AddEntity(
  299. name, model, position, Ogre::Degree(0),
  300. Ogre::Vector3(PARTY_SCALE, PARTY_SCALE, PARTY_SCALE),
  301. Ogre::Quaternion(1, 1, 0, 0), 100 + i
  302. );
  303. // Next position in Y axis
  304. position.x += ((i + 1) * (i % 2 == 0 ? 5 : -5));
  305. }
  306. }
  307. void BattleManager::UpdateField(){}
  308. void BattleManager::UpdateBattle(){
  309. ScriptManager::getSingleton().RunString("UiContainer.BattleUi:tick()");
  310. }
  311. void BattleManager::UpdateWorld(){}