global_stats_registry.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include "global_stats_registry.h"
  2. #include "../core/component.h"
  3. #include "../core/world.h"
  4. #include "../units/troop_config.h"
  5. #include "core/event_manager.h"
  6. #include "owner_registry.h"
  7. #include "units/spawn_type.h"
  8. #include <chrono>
  9. #include <unordered_map>
  10. namespace Game::Systems {
  11. auto GlobalStatsRegistry::instance() -> GlobalStatsRegistry & {
  12. static GlobalStatsRegistry inst;
  13. return inst;
  14. }
  15. void GlobalStatsRegistry::initialize() {
  16. m_unit_spawned_subscription =
  17. Engine::Core::ScopedEventSubscription<Engine::Core::UnitSpawnedEvent>(
  18. [this](const Engine::Core::UnitSpawnedEvent &e) {
  19. on_unit_spawned(e);
  20. });
  21. m_unit_died_subscription =
  22. Engine::Core::ScopedEventSubscription<Engine::Core::UnitDiedEvent>(
  23. [this](const Engine::Core::UnitDiedEvent &e) { on_unit_died(e); });
  24. m_barrack_captured_subscription =
  25. Engine::Core::ScopedEventSubscription<Engine::Core::BarrackCapturedEvent>(
  26. [this](const Engine::Core::BarrackCapturedEvent &e) {
  27. on_barrack_captured(e);
  28. });
  29. }
  30. void GlobalStatsRegistry::clear() { m_player_stats.clear(); }
  31. auto GlobalStatsRegistry::get_stats(int owner_id) const -> const PlayerStats * {
  32. auto it = m_player_stats.find(owner_id);
  33. if (it != m_player_stats.end()) {
  34. return &it->second;
  35. }
  36. return nullptr;
  37. }
  38. auto GlobalStatsRegistry::get_stats(int owner_id) -> PlayerStats * {
  39. auto it = m_player_stats.find(owner_id);
  40. if (it != m_player_stats.end()) {
  41. return &it->second;
  42. }
  43. return nullptr;
  44. }
  45. void GlobalStatsRegistry::mark_game_start(int owner_id) {
  46. auto &stats = m_player_stats[owner_id];
  47. stats.game_start_time = std::chrono::steady_clock::now();
  48. stats.game_ended = false;
  49. stats.play_time_sec = 0.0F;
  50. }
  51. void GlobalStatsRegistry::mark_game_end(int owner_id) {
  52. auto it = m_player_stats.find(owner_id);
  53. if (it != m_player_stats.end() && !it->second.game_ended) {
  54. it->second.game_end_time = std::chrono::steady_clock::now();
  55. it->second.game_ended = true;
  56. auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
  57. it->second.game_end_time - it->second.game_start_time);
  58. it->second.play_time_sec = duration.count() / 1000.0F;
  59. }
  60. }
  61. void GlobalStatsRegistry::on_unit_spawned(
  62. const Engine::Core::UnitSpawnedEvent &event) {
  63. if (event.is_initial_spawn) {
  64. if (event.spawn_type == Game::Units::SpawnType::Barracks) {
  65. auto &stats = m_player_stats[event.owner_id];
  66. stats.barracks_owned++;
  67. }
  68. return;
  69. }
  70. auto &stats = m_player_stats[event.owner_id];
  71. if (event.spawn_type == Game::Units::SpawnType::Barracks) {
  72. stats.barracks_owned++;
  73. } else if (event.spawn_type != Game::Units::SpawnType::DefenseTower &&
  74. event.spawn_type != Game::Units::SpawnType::Home) {
  75. int const production_cost =
  76. Game::Units::TroopConfig::instance().getProductionCost(
  77. event.spawn_type);
  78. stats.troops_recruited += production_cost;
  79. }
  80. }
  81. void GlobalStatsRegistry::on_unit_died(
  82. const Engine::Core::UnitDiedEvent &event) {
  83. if (event.spawn_type != Game::Units::SpawnType::Barracks &&
  84. event.spawn_type != Game::Units::SpawnType::DefenseTower &&
  85. event.spawn_type != Game::Units::SpawnType::Home) {
  86. auto it = m_player_stats.find(event.owner_id);
  87. if (it != m_player_stats.end()) {
  88. int const production_cost =
  89. Game::Units::TroopConfig::instance().getProductionCost(
  90. event.spawn_type);
  91. it->second.losses += production_cost;
  92. }
  93. }
  94. if (event.spawn_type == Game::Units::SpawnType::Barracks) {
  95. auto it = m_player_stats.find(event.owner_id);
  96. if (it != m_player_stats.end()) {
  97. it->second.barracks_owned--;
  98. if (it->second.barracks_owned < 0) {
  99. it->second.barracks_owned = 0;
  100. }
  101. }
  102. }
  103. if (event.killer_owner_id != 0 && event.killer_owner_id != event.owner_id) {
  104. auto &owner_registry = OwnerRegistry::instance();
  105. if (owner_registry.are_enemies(event.killer_owner_id, event.owner_id)) {
  106. auto &stats = m_player_stats[event.killer_owner_id];
  107. if (event.spawn_type != Game::Units::SpawnType::Barracks &&
  108. event.spawn_type != Game::Units::SpawnType::DefenseTower &&
  109. event.spawn_type != Game::Units::SpawnType::Home) {
  110. int const production_cost =
  111. Game::Units::TroopConfig::instance().getProductionCost(
  112. event.spawn_type);
  113. stats.enemies_killed += production_cost;
  114. }
  115. }
  116. }
  117. }
  118. void GlobalStatsRegistry::on_barrack_captured(
  119. const Engine::Core::BarrackCapturedEvent &event) {
  120. auto prev_it = m_player_stats.find(event.previous_owner_id);
  121. if (prev_it != m_player_stats.end() && event.previous_owner_id != -1) {
  122. prev_it->second.barracks_owned--;
  123. if (prev_it->second.barracks_owned < 0) {
  124. prev_it->second.barracks_owned = 0;
  125. }
  126. }
  127. auto &new_stats = m_player_stats[event.new_owner_id];
  128. new_stats.barracks_owned++;
  129. }
  130. void GlobalStatsRegistry::rebuild_from_world(Engine::Core::World &world) {
  131. std::unordered_map<int, std::chrono::steady_clock::time_point> start_times;
  132. std::unordered_map<int, int> troops_recruited_values;
  133. std::unordered_map<int, int> enemies_killed_values;
  134. std::unordered_map<int, int> losses_values;
  135. for (auto &[owner_id, stats] : m_player_stats) {
  136. start_times[owner_id] = stats.game_start_time;
  137. troops_recruited_values[owner_id] = stats.troops_recruited;
  138. enemies_killed_values[owner_id] = stats.enemies_killed;
  139. losses_values[owner_id] = stats.losses;
  140. }
  141. m_player_stats.clear();
  142. for (auto &[owner_id, start_time] : start_times) {
  143. m_player_stats[owner_id].game_start_time = start_time;
  144. m_player_stats[owner_id].troops_recruited =
  145. troops_recruited_values[owner_id];
  146. m_player_stats[owner_id].enemies_killed = enemies_killed_values[owner_id];
  147. m_player_stats[owner_id].losses = losses_values[owner_id];
  148. }
  149. auto entities = world.get_entities_with<Engine::Core::UnitComponent>();
  150. for (auto *e : entities) {
  151. auto *unit = e->get_component<Engine::Core::UnitComponent>();
  152. if ((unit == nullptr) || unit->health <= 0) {
  153. continue;
  154. }
  155. auto &stats = m_player_stats[unit->owner_id];
  156. if (unit->spawn_type == Game::Units::SpawnType::Barracks) {
  157. stats.barracks_owned++;
  158. }
  159. }
  160. }
  161. } // namespace Game::Systems