ai_command_applier.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "ai_command_applier.h"
  2. #include "../../core/component.h"
  3. #include "../../core/world.h"
  4. #include "../../game_config.h"
  5. #include "../../units/troop_config.h"
  6. #include "../command_service.h"
  7. #include "ai_utils.h"
  8. #include "systems/ai_system/ai_types.h"
  9. #include "units/troop_type.h"
  10. #include <QVector3D>
  11. #include <cstddef>
  12. #include <qvectornd.h>
  13. #include <vector>
  14. namespace Game::Systems::AI {
  15. void AICommandApplier::apply(Engine::Core::World &world, int aiOwnerId,
  16. const std::vector<AICommand> &commands) {
  17. for (const auto &command : commands) {
  18. switch (command.type) {
  19. case AICommandType::MoveUnits: {
  20. if (command.units.empty()) {
  21. break;
  22. }
  23. std::vector<float> expanded_x;
  24. std::vector<float> expanded_y;
  25. std::vector<float> expanded_z;
  26. if (command.moveTargetX.size() != command.units.size()) {
  27. replicateLastTargetIfNeeded(command.moveTargetX, command.moveTargetY,
  28. command.moveTargetZ, command.units.size(),
  29. expanded_x, expanded_y, expanded_z);
  30. } else {
  31. expanded_x = command.moveTargetX;
  32. expanded_y = command.moveTargetY;
  33. expanded_z = command.moveTargetZ;
  34. }
  35. if (expanded_x.empty()) {
  36. break;
  37. }
  38. std::vector<Engine::Core::EntityID> owned_units;
  39. std::vector<QVector3D> owned_targets;
  40. owned_units.reserve(command.units.size());
  41. owned_targets.reserve(command.units.size());
  42. for (std::size_t idx = 0; idx < command.units.size(); ++idx) {
  43. auto entity_id = command.units[idx];
  44. auto *entity = world.get_entity(entity_id);
  45. if (entity == nullptr) {
  46. continue;
  47. }
  48. auto *unit = entity->get_component<Engine::Core::UnitComponent>();
  49. if ((unit == nullptr) || unit->owner_id != aiOwnerId) {
  50. continue;
  51. }
  52. owned_units.push_back(entity_id);
  53. owned_targets.emplace_back(expanded_x[idx], expanded_y[idx],
  54. expanded_z[idx]);
  55. }
  56. if (owned_units.empty()) {
  57. break;
  58. }
  59. CommandService::MoveOptions opts;
  60. opts.allow_direct_fallback = true;
  61. opts.clear_attack_intent = false;
  62. opts.group_move = owned_units.size() > 1;
  63. CommandService::moveUnits(world, owned_units, owned_targets, opts);
  64. break;
  65. }
  66. case AICommandType::AttackTarget: {
  67. if (command.units.empty() || command.target_id == 0) {
  68. break;
  69. }
  70. std::vector<Engine::Core::EntityID> owned_units;
  71. owned_units.reserve(command.units.size());
  72. for (auto entity_id : command.units) {
  73. auto *entity = world.get_entity(entity_id);
  74. if (entity == nullptr) {
  75. continue;
  76. }
  77. auto *unit = entity->get_component<Engine::Core::UnitComponent>();
  78. if ((unit == nullptr) || unit->owner_id != aiOwnerId) {
  79. continue;
  80. }
  81. owned_units.push_back(entity_id);
  82. }
  83. if (owned_units.empty()) {
  84. break;
  85. }
  86. CommandService::attack_target(world, owned_units, command.target_id,
  87. command.should_chase);
  88. break;
  89. }
  90. case AICommandType::StartProduction: {
  91. auto *entity = world.get_entity(command.buildingId);
  92. if (entity == nullptr) {
  93. break;
  94. }
  95. auto *production =
  96. entity->get_component<Engine::Core::ProductionComponent>();
  97. if (production == nullptr) {
  98. break;
  99. }
  100. if (production->in_progress) {
  101. break;
  102. }
  103. auto *unit = entity->get_component<Engine::Core::UnitComponent>();
  104. if ((unit != nullptr) && unit->owner_id != aiOwnerId) {
  105. break;
  106. }
  107. int const current_troops =
  108. Engine::Core::World::count_troops_for_player(aiOwnerId);
  109. int const max_troops =
  110. Game::GameConfig::instance().getMaxTroopsPerPlayer();
  111. Game::Units::TroopType const product_type = production->product_type;
  112. int const individuals_per_unit =
  113. Game::Units::TroopConfig::instance().getIndividualsPerUnit(
  114. product_type);
  115. if (current_troops + individuals_per_unit > max_troops) {
  116. break;
  117. }
  118. production->product_type = command.product_type;
  119. production->time_remaining = production->build_time;
  120. production->in_progress = true;
  121. break;
  122. }
  123. }
  124. }
  125. }
  126. } // namespace Game::Systems::AI