input_command_handler.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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_is_spectator_mode) {
  29. return;
  30. }
  31. if (m_selection_controller && m_camera) {
  32. m_selection_controller->on_click_select(sx, sy, false, viewport.width,
  33. viewport.height, m_camera,
  34. local_owner_id);
  35. }
  36. }
  37. void InputCommandHandler::on_right_click(qreal sx, qreal sy, int local_owner_id,
  38. const ViewportState &viewport) {
  39. if (m_is_spectator_mode) {
  40. return;
  41. }
  42. if (!m_world) {
  43. return;
  44. }
  45. auto *selection_system =
  46. m_world->get_system<Game::Systems::SelectionSystem>();
  47. if (selection_system == nullptr) {
  48. return;
  49. }
  50. if (m_cursor_manager->mode() == CursorMode::Patrol ||
  51. m_cursor_manager->mode() == CursorMode::Attack ||
  52. m_cursor_manager->mode() == CursorMode::Guard) {
  53. m_cursor_manager->set_mode(CursorMode::Normal);
  54. return;
  55. }
  56. const auto &sel = selection_system->get_selected_units();
  57. if (sel.empty()) {
  58. return;
  59. }
  60. if (m_picking_service && m_camera) {
  61. Engine::Core::EntityID const target_id = m_picking_service->pick_unit_first(
  62. float(sx), float(sy), *m_world, *m_camera, viewport.width,
  63. viewport.height, 0);
  64. if (target_id != 0U) {
  65. auto *target_entity = m_world->get_entity(target_id);
  66. if (target_entity != nullptr) {
  67. auto *target_unit =
  68. target_entity->get_component<Engine::Core::UnitComponent>();
  69. if (target_unit != nullptr) {
  70. bool const is_enemy = (target_unit->owner_id != local_owner_id);
  71. if (is_enemy) {
  72. Game::Systems::CommandService::attack_target(*m_world, sel,
  73. target_id, true);
  74. return;
  75. }
  76. }
  77. }
  78. }
  79. }
  80. if (m_picking_service && m_camera) {
  81. QVector3D hit;
  82. if (m_picking_service->screen_to_ground(
  83. QPointF(sx, sy), *m_camera, viewport.width, viewport.height, hit)) {
  84. auto targets = Game::Systems::FormationPlanner::spreadFormation(
  85. int(sel.size()), hit,
  86. Game::GameConfig::instance().gameplay().formation_spacing_default);
  87. Game::Systems::CommandService::MoveOptions opts;
  88. opts.group_move = sel.size() > 1;
  89. Game::Systems::CommandService::moveUnits(*m_world, sel, targets, opts);
  90. }
  91. }
  92. }
  93. void InputCommandHandler::on_attack_click(qreal sx, qreal sy,
  94. const ViewportState &viewport) {
  95. if (m_is_spectator_mode) {
  96. return;
  97. }
  98. if (!m_command_controller || !m_camera) {
  99. return;
  100. }
  101. auto result = m_command_controller->on_attack_click(
  102. sx, sy, viewport.width, viewport.height, m_camera);
  103. auto *selection_system =
  104. m_world->get_system<Game::Systems::SelectionSystem>();
  105. if ((selection_system == nullptr) || !m_picking_service || !m_camera ||
  106. !m_world) {
  107. return;
  108. }
  109. const auto &selected = selection_system->get_selected_units();
  110. if (!selected.empty()) {
  111. Engine::Core::EntityID const target_id = m_picking_service->pick_unit_first(
  112. float(sx), float(sy), *m_world, *m_camera, viewport.width,
  113. viewport.height, 0);
  114. if (target_id != 0) {
  115. auto *target_entity = m_world->get_entity(target_id);
  116. if (target_entity != nullptr) {
  117. auto *target_unit =
  118. target_entity->get_component<Engine::Core::UnitComponent>();
  119. if ((target_unit != nullptr)) {
  120. App::Controllers::ActionVFX::spawnAttackArrow(m_world, target_id);
  121. }
  122. }
  123. }
  124. }
  125. if (result.reset_cursor_to_normal) {
  126. m_cursor_manager->set_mode(CursorMode::Normal);
  127. }
  128. }
  129. void InputCommandHandler::reset_movement(Engine::Core::Entity *entity) {
  130. App::Utils::reset_movement(entity);
  131. }
  132. void InputCommandHandler::on_stop_command() {
  133. if (m_is_spectator_mode) {
  134. return;
  135. }
  136. if (!m_command_controller) {
  137. return;
  138. }
  139. auto result = m_command_controller->on_stop_command();
  140. if (result.reset_cursor_to_normal) {
  141. m_cursor_manager->set_mode(CursorMode::Normal);
  142. }
  143. }
  144. void InputCommandHandler::on_hold_command() {
  145. if (m_is_spectator_mode) {
  146. return;
  147. }
  148. if (!m_command_controller) {
  149. return;
  150. }
  151. auto result = m_command_controller->on_hold_command();
  152. if (result.reset_cursor_to_normal) {
  153. m_cursor_manager->set_mode(CursorMode::Normal);
  154. }
  155. }
  156. void InputCommandHandler::on_guard_command() {
  157. if (m_is_spectator_mode) {
  158. return;
  159. }
  160. if (!m_command_controller) {
  161. return;
  162. }
  163. auto result = m_command_controller->on_guard_command();
  164. if (result.reset_cursor_to_normal) {
  165. m_cursor_manager->set_mode(CursorMode::Normal);
  166. }
  167. }
  168. void InputCommandHandler::on_guard_click(qreal sx, qreal sy,
  169. const ViewportState &viewport) {
  170. if (m_is_spectator_mode) {
  171. return;
  172. }
  173. if (!m_command_controller || !m_camera) {
  174. return;
  175. }
  176. auto result = m_command_controller->on_guard_click(sx, sy, viewport.width,
  177. viewport.height, m_camera);
  178. if (result.reset_cursor_to_normal) {
  179. m_cursor_manager->set_mode(CursorMode::Normal);
  180. }
  181. }
  182. auto InputCommandHandler::any_selected_in_hold_mode() const -> bool {
  183. if (!m_command_controller) {
  184. return false;
  185. }
  186. return m_command_controller->any_selected_in_hold_mode();
  187. }
  188. auto InputCommandHandler::any_selected_in_guard_mode() const -> bool {
  189. if (!m_command_controller) {
  190. return false;
  191. }
  192. return m_command_controller->any_selected_in_guard_mode();
  193. }
  194. void InputCommandHandler::on_patrol_click(qreal sx, qreal sy,
  195. const ViewportState &viewport) {
  196. if (m_is_spectator_mode) {
  197. return;
  198. }
  199. if (!m_command_controller || !m_camera) {
  200. return;
  201. }
  202. auto result = m_command_controller->on_patrol_click(
  203. sx, sy, viewport.width, viewport.height, m_camera);
  204. if (result.reset_cursor_to_normal) {
  205. m_cursor_manager->set_mode(CursorMode::Normal);
  206. }
  207. }
  208. void InputCommandHandler::on_click_select(qreal sx, qreal sy, bool additive,
  209. int local_owner_id,
  210. const ViewportState &viewport) {
  211. if (m_is_spectator_mode) {
  212. return;
  213. }
  214. if (m_selection_controller && m_camera) {
  215. m_selection_controller->on_click_select(sx, sy, additive, viewport.width,
  216. viewport.height, m_camera,
  217. local_owner_id);
  218. }
  219. }
  220. void InputCommandHandler::on_area_selected(qreal x1, qreal y1, qreal x2,
  221. qreal y2, bool additive,
  222. int local_owner_id,
  223. const ViewportState &viewport) {
  224. if (m_is_spectator_mode) {
  225. return;
  226. }
  227. if (m_selection_controller && m_camera) {
  228. m_selection_controller->on_area_selected(x1, y1, x2, y2, additive,
  229. viewport.width, viewport.height,
  230. m_camera, local_owner_id);
  231. }
  232. }
  233. void InputCommandHandler::select_all_troops(int local_owner_id) {
  234. if (m_is_spectator_mode) {
  235. return;
  236. }
  237. if (m_selection_controller) {
  238. m_selection_controller->select_all_player_troops(local_owner_id);
  239. }
  240. }
  241. void InputCommandHandler::select_unit_by_id(int unit_id, int local_owner_id) {
  242. if (m_is_spectator_mode) {
  243. return;
  244. }
  245. if (!m_selection_controller || (unit_id <= 0)) {
  246. return;
  247. }
  248. m_selection_controller->select_single_unit(
  249. static_cast<Engine::Core::EntityID>(unit_id), local_owner_id);
  250. }
  251. void InputCommandHandler::set_hover_at_screen(qreal sx, qreal sy,
  252. const ViewportState &viewport) {
  253. if (!m_hover_tracker || !m_camera || !m_world) {
  254. return;
  255. }
  256. m_hover_tracker->update_hover(float(sx), float(sy), *m_world, *m_camera,
  257. viewport.width, viewport.height);
  258. }