production_service.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include "production_service.h"
  2. #include "../core/component.h"
  3. #include "../core/world.h"
  4. #include "../game_config.h"
  5. #include "../systems/nation_registry.h"
  6. #include "../systems/troop_profile_service.h"
  7. #include "../units/troop_config.h"
  8. #include "core/entity.h"
  9. #include "units/spawn_type.h"
  10. #include "units/troop_type.h"
  11. #include <vector>
  12. namespace Game::Systems {
  13. static auto
  14. findFirstSelectedBarracks(Engine::Core::World &world,
  15. const std::vector<Engine::Core::EntityID> &selected,
  16. int owner_id) -> Engine::Core::Entity * {
  17. for (auto id : selected) {
  18. if (auto *e = world.getEntity(id)) {
  19. auto *u = e->getComponent<Engine::Core::UnitComponent>();
  20. if ((u == nullptr) || u->owner_id != owner_id) {
  21. continue;
  22. }
  23. if (u->spawn_type == Game::Units::SpawnType::Barracks) {
  24. return e;
  25. }
  26. }
  27. }
  28. return nullptr;
  29. }
  30. namespace {
  31. auto resolve_nation_id(const Engine::Core::UnitComponent *unit,
  32. int owner_id) -> std::string {
  33. if ((unit != nullptr) && !unit->nation_id.empty()) {
  34. return unit->nation_id;
  35. }
  36. auto &registry = NationRegistry::instance();
  37. if (const auto *nation = registry.getNationForPlayer(owner_id)) {
  38. return nation->id;
  39. }
  40. return registry.default_nation_id();
  41. }
  42. void apply_production_profile(Engine::Core::ProductionComponent *prod,
  43. const std::string &nation_id,
  44. Game::Units::TroopType unit_type) {
  45. if (prod == nullptr) {
  46. return;
  47. }
  48. const auto profile =
  49. TroopProfileService::instance().get_profile(nation_id, unit_type);
  50. prod->buildTime = profile.production.build_time;
  51. prod->villagerCost = profile.individuals_per_unit;
  52. }
  53. } // namespace
  54. auto ProductionService::startProductionForFirstSelectedBarracks(
  55. Engine::Core::World &world,
  56. const std::vector<Engine::Core::EntityID> &selected, int owner_id,
  57. Game::Units::TroopType unit_type) -> ProductionResult {
  58. auto *e = findFirstSelectedBarracks(world, selected, owner_id);
  59. if (e == nullptr) {
  60. return ProductionResult::NoBarracks;
  61. }
  62. auto *unit = e->getComponent<Engine::Core::UnitComponent>();
  63. const std::string nation_id = resolve_nation_id(unit, owner_id);
  64. const auto profile =
  65. TroopProfileService::instance().get_profile(nation_id, unit_type);
  66. auto *p = e->getComponent<Engine::Core::ProductionComponent>();
  67. if (p == nullptr) {
  68. p = e->addComponent<Engine::Core::ProductionComponent>();
  69. }
  70. if (p == nullptr) {
  71. return ProductionResult::NoBarracks;
  72. }
  73. int const individuals_per_unit = profile.individuals_per_unit;
  74. if (p->producedCount + individuals_per_unit > p->maxUnits) {
  75. return ProductionResult::PerBarracksLimitReached;
  76. }
  77. int const current_troops =
  78. Engine::Core::World::countTroopsForPlayer(owner_id);
  79. int const max_troops = Game::GameConfig::instance().getMaxTroopsPerPlayer();
  80. if (current_troops + individuals_per_unit > max_troops) {
  81. return ProductionResult::GlobalTroopLimitReached;
  82. }
  83. const int max_queue_size = 5;
  84. int total_in_queue = p->inProgress ? 1 : 0;
  85. total_in_queue += static_cast<int>(p->productionQueue.size());
  86. if (total_in_queue >= max_queue_size) {
  87. return ProductionResult::QueueFull;
  88. }
  89. if (p->inProgress) {
  90. p->productionQueue.push_back(unit_type);
  91. } else {
  92. p->product_type = unit_type;
  93. apply_production_profile(p, nation_id, unit_type);
  94. p->timeRemaining = p->buildTime;
  95. p->inProgress = true;
  96. }
  97. return ProductionResult::Success;
  98. }
  99. auto ProductionService::setRallyForFirstSelectedBarracks(
  100. Engine::Core::World &world,
  101. const std::vector<Engine::Core::EntityID> &selected, int owner_id, float x,
  102. float z) -> bool {
  103. auto *e = findFirstSelectedBarracks(world, selected, owner_id);
  104. if (e == nullptr) {
  105. return false;
  106. }
  107. auto *p = e->getComponent<Engine::Core::ProductionComponent>();
  108. if (p == nullptr) {
  109. p = e->addComponent<Engine::Core::ProductionComponent>();
  110. }
  111. if (p == nullptr) {
  112. return false;
  113. }
  114. p->rallyX = x;
  115. p->rallyZ = z;
  116. p->rallySet = true;
  117. return true;
  118. }
  119. auto ProductionService::getSelectedBarracksState(
  120. Engine::Core::World &world,
  121. const std::vector<Engine::Core::EntityID> &selected, int owner_id,
  122. ProductionState &outState) -> bool {
  123. auto *e = findFirstSelectedBarracks(world, selected, owner_id);
  124. if (e == nullptr) {
  125. outState = {};
  126. return false;
  127. }
  128. outState.has_barracks = true;
  129. if (auto *p = e->getComponent<Engine::Core::ProductionComponent>()) {
  130. outState.inProgress = p->inProgress;
  131. outState.product_type = p->product_type;
  132. outState.timeRemaining = p->timeRemaining;
  133. outState.buildTime = p->buildTime;
  134. outState.producedCount = p->producedCount;
  135. outState.maxUnits = p->maxUnits;
  136. outState.villagerCost = p->villagerCost;
  137. outState.queueSize = static_cast<int>(p->productionQueue.size());
  138. outState.productionQueue = p->productionQueue;
  139. }
  140. return true;
  141. }
  142. } // namespace Game::Systems