unit.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #include "unit.h"
  2. #include "../core/component.h"
  3. #include "../core/world.h"
  4. #include "../systems/nation_id.h"
  5. #include "../systems/nation_registry.h"
  6. #include "../systems/troop_profile_service.h"
  7. #include "units/troop_type.h"
  8. #include <qvectornd.h>
  9. #include <string>
  10. #include <utility>
  11. namespace Game::Units {
  12. Unit::Unit(Engine::Core::World &world, TroopType type)
  13. : m_world(&world), m_type_string(troop_typeToString(type)) {}
  14. Unit::Unit(Engine::Core::World &world, std::string type)
  15. : m_world(&world), m_type_string(std::move(type)) {}
  16. auto Unit::entity() const -> Engine::Core::Entity * {
  17. return (m_world != nullptr) ? m_world->get_entity(m_id) : nullptr;
  18. }
  19. auto Unit::resolve_nation_id(const SpawnParams &params)
  20. -> Game::Systems::NationID {
  21. return params.nation_id;
  22. }
  23. void Unit::ensureCoreComponents() {
  24. if (m_world == nullptr) {
  25. return;
  26. }
  27. if (auto *e = entity()) {
  28. if (m_t == nullptr) {
  29. m_t = e->get_component<Engine::Core::TransformComponent>();
  30. }
  31. if (m_r == nullptr) {
  32. m_r = e->get_component<Engine::Core::RenderableComponent>();
  33. }
  34. if (m_u == nullptr) {
  35. m_u = e->get_component<Engine::Core::UnitComponent>();
  36. }
  37. if (m_mv == nullptr) {
  38. m_mv = e->get_component<Engine::Core::MovementComponent>();
  39. }
  40. if (m_atk == nullptr) {
  41. m_atk = e->get_component<Engine::Core::AttackComponent>();
  42. }
  43. }
  44. }
  45. void Unit::move_to(float x, float z) {
  46. ensureCoreComponents();
  47. if (m_mv == nullptr) {
  48. if (auto *e = entity()) {
  49. m_mv = e->add_component<Engine::Core::MovementComponent>();
  50. }
  51. }
  52. if (m_mv != nullptr) {
  53. m_mv->target_x = x;
  54. m_mv->target_y = z;
  55. m_mv->has_target = true;
  56. m_mv->goal_x = x;
  57. m_mv->goal_y = z;
  58. m_mv->clear_path();
  59. m_mv->path_pending = false;
  60. m_mv->pending_request_id = 0;
  61. }
  62. if (auto *e = entity()) {
  63. auto *hold_comp = e->get_component<Engine::Core::HoldModeComponent>();
  64. if (hold_comp != nullptr) {
  65. hold_comp->active = false;
  66. }
  67. auto *guard_comp = e->get_component<Engine::Core::GuardModeComponent>();
  68. if (guard_comp != nullptr) {
  69. guard_comp->active = false;
  70. }
  71. }
  72. }
  73. auto Unit::is_alive() const -> bool {
  74. if (auto *e = entity()) {
  75. if (auto *u = e->get_component<Engine::Core::UnitComponent>()) {
  76. return u->health > 0;
  77. }
  78. }
  79. return false;
  80. }
  81. auto Unit::position() const -> QVector3D {
  82. if (auto *e = entity()) {
  83. if (auto *t = e->get_component<Engine::Core::TransformComponent>()) {
  84. return {t->position.x, t->position.y, t->position.z};
  85. }
  86. }
  87. return {};
  88. }
  89. void Unit::set_hold_mode(bool enabled) {
  90. auto *e = entity();
  91. if (e == nullptr) {
  92. return;
  93. }
  94. auto *hold_comp = e->get_component<Engine::Core::HoldModeComponent>();
  95. if (enabled) {
  96. if (hold_comp == nullptr) {
  97. hold_comp = e->add_component<Engine::Core::HoldModeComponent>();
  98. }
  99. hold_comp->active = true;
  100. hold_comp->exit_cooldown = 0.0F;
  101. auto *guard_comp = e->get_component<Engine::Core::GuardModeComponent>();
  102. if (guard_comp != nullptr) {
  103. guard_comp->active = false;
  104. }
  105. auto *mv = e->get_component<Engine::Core::MovementComponent>();
  106. if (mv != nullptr) {
  107. mv->has_target = false;
  108. mv->clear_path();
  109. mv->path_pending = false;
  110. }
  111. } else {
  112. if (hold_comp != nullptr) {
  113. hold_comp->active = false;
  114. hold_comp->exit_cooldown = hold_comp->stand_up_duration;
  115. }
  116. }
  117. }
  118. auto Unit::is_in_hold_mode() const -> bool {
  119. auto *e = entity();
  120. if (e == nullptr) {
  121. return false;
  122. }
  123. auto *hold_comp = e->get_component<Engine::Core::HoldModeComponent>();
  124. return (hold_comp != nullptr) && hold_comp->active;
  125. }
  126. void Unit::set_guard_mode(bool enabled) {
  127. auto *e = entity();
  128. if (e == nullptr) {
  129. return;
  130. }
  131. auto *guard_comp = e->get_component<Engine::Core::GuardModeComponent>();
  132. if (enabled) {
  133. if (guard_comp == nullptr) {
  134. guard_comp = e->add_component<Engine::Core::GuardModeComponent>();
  135. }
  136. guard_comp->active = true;
  137. guard_comp->returning_to_guard_position = false;
  138. auto *hold_comp = e->get_component<Engine::Core::HoldModeComponent>();
  139. if (hold_comp != nullptr) {
  140. hold_comp->active = false;
  141. }
  142. if (!guard_comp->has_guard_target) {
  143. auto *transform = e->get_component<Engine::Core::TransformComponent>();
  144. if (transform != nullptr) {
  145. guard_comp->guard_position_x = transform->position.x;
  146. guard_comp->guard_position_z = transform->position.z;
  147. guard_comp->has_guard_target = true;
  148. }
  149. }
  150. } else {
  151. if (guard_comp != nullptr) {
  152. guard_comp->active = false;
  153. }
  154. }
  155. }
  156. void Unit::set_guard_target(Engine::Core::EntityID target_id) {
  157. auto *e = entity();
  158. if (e == nullptr) {
  159. return;
  160. }
  161. auto *guard_comp = e->get_component<Engine::Core::GuardModeComponent>();
  162. if (guard_comp == nullptr) {
  163. guard_comp = e->add_component<Engine::Core::GuardModeComponent>();
  164. }
  165. guard_comp->guarded_entity_id = target_id;
  166. guard_comp->guard_position_x = 0.0F;
  167. guard_comp->guard_position_z = 0.0F;
  168. guard_comp->active = true;
  169. guard_comp->returning_to_guard_position = false;
  170. guard_comp->has_guard_target = true;
  171. auto *hold_comp = e->get_component<Engine::Core::HoldModeComponent>();
  172. if (hold_comp != nullptr) {
  173. hold_comp->active = false;
  174. }
  175. }
  176. void Unit::set_guard_position(float x, float z) {
  177. auto *e = entity();
  178. if (e == nullptr) {
  179. return;
  180. }
  181. auto *guard_comp = e->get_component<Engine::Core::GuardModeComponent>();
  182. if (guard_comp == nullptr) {
  183. guard_comp = e->add_component<Engine::Core::GuardModeComponent>();
  184. }
  185. guard_comp->guarded_entity_id = 0;
  186. guard_comp->guard_position_x = x;
  187. guard_comp->guard_position_z = z;
  188. guard_comp->active = true;
  189. guard_comp->returning_to_guard_position = false;
  190. guard_comp->has_guard_target = true;
  191. auto *hold_comp = e->get_component<Engine::Core::HoldModeComponent>();
  192. if (hold_comp != nullptr) {
  193. hold_comp->active = false;
  194. }
  195. }
  196. auto Unit::is_in_guard_mode() const -> bool {
  197. auto *e = entity();
  198. if (e == nullptr) {
  199. return false;
  200. }
  201. auto *guard_comp = e->get_component<Engine::Core::GuardModeComponent>();
  202. return (guard_comp != nullptr) && guard_comp->active;
  203. }
  204. void Unit::clear_guard_mode() {
  205. auto *e = entity();
  206. if (e == nullptr) {
  207. return;
  208. }
  209. auto *guard_comp = e->get_component<Engine::Core::GuardModeComponent>();
  210. if (guard_comp != nullptr) {
  211. guard_comp->active = false;
  212. guard_comp->guarded_entity_id = 0;
  213. guard_comp->guard_position_x = 0.0F;
  214. guard_comp->guard_position_z = 0.0F;
  215. guard_comp->returning_to_guard_position = false;
  216. guard_comp->has_guard_target = false;
  217. }
  218. }
  219. void Unit::set_run_mode(bool enabled) {
  220. auto *e = entity();
  221. if (e == nullptr) {
  222. return;
  223. }
  224. const auto *unit_comp = e->get_component<Engine::Core::UnitComponent>();
  225. if (unit_comp == nullptr ||
  226. !Game::Units::can_use_run_mode(unit_comp->spawn_type)) {
  227. return;
  228. }
  229. auto *stamina_comp = e->get_component<Engine::Core::StaminaComponent>();
  230. if (stamina_comp == nullptr) {
  231. if (!enabled) {
  232. return;
  233. }
  234. stamina_comp = e->add_component<Engine::Core::StaminaComponent>();
  235. const auto troop_type =
  236. Game::Units::spawn_typeToTroopType(unit_comp->spawn_type);
  237. if (troop_type.has_value()) {
  238. const auto profile =
  239. Game::Systems::TroopProfileService::instance().get_profile(
  240. unit_comp->nation_id, *troop_type);
  241. stamina_comp->initialize_from_stats(
  242. profile.combat.max_stamina, profile.combat.stamina_regen_rate,
  243. profile.combat.stamina_depletion_rate);
  244. }
  245. }
  246. stamina_comp->run_requested = enabled;
  247. }
  248. auto Unit::is_running() const -> bool {
  249. const auto *e = entity();
  250. if (e == nullptr) {
  251. return false;
  252. }
  253. const auto *stamina_comp = e->get_component<Engine::Core::StaminaComponent>();
  254. return stamina_comp != nullptr && stamina_comp->is_running;
  255. }
  256. auto Unit::can_run() const -> bool {
  257. const auto *e = entity();
  258. if (e == nullptr) {
  259. return false;
  260. }
  261. const auto *unit_comp = e->get_component<Engine::Core::UnitComponent>();
  262. return unit_comp != nullptr &&
  263. Game::Units::can_use_run_mode(unit_comp->spawn_type);
  264. }
  265. } // namespace Game::Units