input_command_handler.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #include "input_command_handler.h"
  2. #include "../controllers/action_vfx.h"
  3. #include "../controllers/command_controller.h"
  4. #include "../models/cursor_manager.h"
  5. #include "../models/cursor_mode.h"
  6. #include "../models/hover_tracker.h"
  7. #include "../utils/movement_utils.h"
  8. #include "game/core/component.h"
  9. #include "game/core/world.h"
  10. #include "game/game_config.h"
  11. #include "game/systems/command_service.h"
  12. #include "game/systems/formation_planner.h"
  13. #include "game/systems/picking_service.h"
  14. #include "game/systems/selection_system.h"
  15. #include "render/gl/camera.h"
  16. InputCommandHandler::InputCommandHandler(
  17. Engine::Core::World *world,
  18. Game::Systems::SelectionController *selection_controller,
  19. App::Controllers::CommandController *command_controller,
  20. CursorManager *cursor_manager, HoverTracker *hover_tracker,
  21. Game::Systems::PickingService *picking_service, Render::GL::Camera *camera)
  22. : m_world(world), m_selection_controller(selection_controller),
  23. m_command_controller(command_controller),
  24. m_cursor_manager(cursor_manager), m_hover_tracker(hover_tracker),
  25. m_picking_service(picking_service), m_camera(camera) {}
  26. void InputCommandHandler::on_map_clicked(qreal sx, qreal sy, int local_owner_id,
  27. const ViewportState &viewport) {
  28. if (m_selection_controller && m_camera) {
  29. m_selection_controller->on_click_select(sx, sy, false, viewport.width,
  30. viewport.height, m_camera,
  31. local_owner_id);
  32. }
  33. }
  34. void InputCommandHandler::on_right_click(qreal sx, qreal sy, int local_owner_id,
  35. const ViewportState &viewport) {
  36. if (!m_world) {
  37. return;
  38. }
  39. auto *selection_system =
  40. m_world->get_system<Game::Systems::SelectionSystem>();
  41. if (selection_system == nullptr) {
  42. return;
  43. }
  44. if (m_cursor_manager->mode() == CursorMode::Patrol ||
  45. m_cursor_manager->mode() == CursorMode::Attack) {
  46. m_cursor_manager->setMode(CursorMode::Normal);
  47. return;
  48. }
  49. const auto &sel = selection_system->get_selected_units();
  50. if (sel.empty()) {
  51. return;
  52. }
  53. if (m_picking_service && m_camera) {
  54. Engine::Core::EntityID const target_id = m_picking_service->pick_unit_first(
  55. float(sx), float(sy), *m_world, *m_camera, viewport.width,
  56. viewport.height, 0);
  57. if (target_id != 0U) {
  58. auto *target_entity = m_world->get_entity(target_id);
  59. if (target_entity != nullptr) {
  60. auto *target_unit =
  61. target_entity->get_component<Engine::Core::UnitComponent>();
  62. if (target_unit != nullptr) {
  63. bool const is_enemy = (target_unit->owner_id != local_owner_id);
  64. if (is_enemy) {
  65. Game::Systems::CommandService::attack_target(*m_world, sel,
  66. target_id, true);
  67. return;
  68. }
  69. }
  70. }
  71. }
  72. }
  73. if (m_picking_service && m_camera) {
  74. QVector3D hit;
  75. if (m_picking_service->screen_to_ground(
  76. QPointF(sx, sy), *m_camera, viewport.width, viewport.height, hit)) {
  77. auto targets = Game::Systems::FormationPlanner::spreadFormation(
  78. int(sel.size()), hit,
  79. Game::GameConfig::instance().gameplay().formation_spacing_default);
  80. Game::Systems::CommandService::MoveOptions opts;
  81. opts.group_move = sel.size() > 1;
  82. Game::Systems::CommandService::moveUnits(*m_world, sel, targets, opts);
  83. }
  84. }
  85. }
  86. void InputCommandHandler::on_attack_click(qreal sx, qreal sy,
  87. const ViewportState &viewport) {
  88. if (!m_command_controller || !m_camera) {
  89. return;
  90. }
  91. auto result = m_command_controller->onAttackClick(sx, sy, viewport.width,
  92. viewport.height, m_camera);
  93. auto *selection_system =
  94. m_world->get_system<Game::Systems::SelectionSystem>();
  95. if ((selection_system == nullptr) || !m_picking_service || !m_camera ||
  96. !m_world) {
  97. return;
  98. }
  99. const auto &selected = selection_system->get_selected_units();
  100. if (!selected.empty()) {
  101. Engine::Core::EntityID const target_id = m_picking_service->pick_unit_first(
  102. float(sx), float(sy), *m_world, *m_camera, viewport.width,
  103. viewport.height, 0);
  104. if (target_id != 0) {
  105. auto *target_entity = m_world->get_entity(target_id);
  106. if (target_entity != nullptr) {
  107. auto *target_unit =
  108. target_entity->get_component<Engine::Core::UnitComponent>();
  109. if ((target_unit != nullptr)) {
  110. App::Controllers::ActionVFX::spawnAttackArrow(m_world, target_id);
  111. }
  112. }
  113. }
  114. }
  115. if (result.resetCursorToNormal) {
  116. m_cursor_manager->setMode(CursorMode::Normal);
  117. }
  118. }
  119. void InputCommandHandler::reset_movement(Engine::Core::Entity *entity) {
  120. App::Utils::reset_movement(entity);
  121. }
  122. void InputCommandHandler::on_stop_command() {
  123. if (!m_command_controller) {
  124. return;
  125. }
  126. auto result = m_command_controller->onStopCommand();
  127. if (result.resetCursorToNormal) {
  128. m_cursor_manager->setMode(CursorMode::Normal);
  129. }
  130. }
  131. void InputCommandHandler::on_hold_command() {
  132. if (!m_command_controller) {
  133. return;
  134. }
  135. auto result = m_command_controller->onHoldCommand();
  136. if (result.resetCursorToNormal) {
  137. m_cursor_manager->setMode(CursorMode::Normal);
  138. }
  139. }
  140. auto InputCommandHandler::any_selected_in_hold_mode() const -> bool {
  141. if (!m_command_controller) {
  142. return false;
  143. }
  144. return m_command_controller->anySelectedInHoldMode();
  145. }
  146. void InputCommandHandler::on_patrol_click(qreal sx, qreal sy,
  147. const ViewportState &viewport) {
  148. if (!m_command_controller || !m_camera) {
  149. return;
  150. }
  151. auto result = m_command_controller->onPatrolClick(sx, sy, viewport.width,
  152. viewport.height, m_camera);
  153. if (result.resetCursorToNormal) {
  154. m_cursor_manager->setMode(CursorMode::Normal);
  155. }
  156. }
  157. void InputCommandHandler::on_click_select(qreal sx, qreal sy, bool additive,
  158. int local_owner_id,
  159. const ViewportState &viewport) {
  160. if (m_selection_controller && m_camera) {
  161. m_selection_controller->on_click_select(sx, sy, additive, viewport.width,
  162. viewport.height, m_camera,
  163. local_owner_id);
  164. }
  165. }
  166. void InputCommandHandler::on_area_selected(qreal x1, qreal y1, qreal x2,
  167. qreal y2, bool additive,
  168. int local_owner_id,
  169. const ViewportState &viewport) {
  170. if (m_selection_controller && m_camera) {
  171. m_selection_controller->on_area_selected(x1, y1, x2, y2, additive,
  172. viewport.width, viewport.height,
  173. m_camera, local_owner_id);
  174. }
  175. }
  176. void InputCommandHandler::select_all_troops(int local_owner_id) {
  177. if (m_selection_controller) {
  178. m_selection_controller->select_all_player_troops(local_owner_id);
  179. }
  180. }
  181. void InputCommandHandler::select_unit_by_id(int unit_id, int local_owner_id) {
  182. if (!m_selection_controller || (unit_id <= 0)) {
  183. return;
  184. }
  185. m_selection_controller->select_single_unit(
  186. static_cast<Engine::Core::EntityID>(unit_id), local_owner_id);
  187. }
  188. void InputCommandHandler::set_hover_at_screen(qreal sx, qreal sy,
  189. const ViewportState &viewport) {
  190. if (!m_hover_tracker || !m_camera || !m_world) {
  191. return;
  192. }
  193. m_cursor_manager->updateCursorShape(nullptr);
  194. m_hover_tracker->update_hover(float(sx), float(sy), *m_world, *m_camera,
  195. viewport.width, viewport.height);
  196. }