Freeciv21
Develop your civilization from humble roots to a global empire
control.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2023 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <QSet>
15 #include <QTimer>
16 #include <algorithm>
17 // utility
18 #include "bitvector.h"
19 #include "fcintl.h"
20 #include "log.h"
21 
22 // common
23 #include "combat.h"
24 #include "game.h"
25 #include "map.h"
26 #include "movement.h"
27 #include "path_finder.h"
28 #include "unitlist.h"
29 
30 /* common/aicore */
31 /* client/include */
32 #include "citydlg_g.h"
33 #include "dialogs_g.h"
34 #include "mapctrl_g.h"
35 #include "mapview_g.h"
36 #include "menu_g.h"
37 
38 // client
39 #include "audio/audio.h"
40 #include "chatline.h"
41 #include "client_main.h"
42 #include "climap.h"
43 #include "climisc.h"
44 #include "control.h"
45 #include "editor.h"
46 #include "goto.h"
47 #include "governor.h"
48 #include "options.h"
49 #include "overview_common.h"
50 #include "page_game.h"
51 #include "qtg_cxxside.h"
52 #include "tileset/tilespec.h"
53 #include "update_queue.h"
54 #include "views/view_map.h"
55 
57  int unit_id;
58  int alt;
59 };
60 
61 // Ways to disband a unit. Sorted by preference. Starts with the worst.
62 /* TODO: Should other actions that consumes the unit be considered?
63  * Join City may be an appealing alternative. Perhaps it should be a
64  * user configurable client option? */
65 static int disband_unit_alternatives[3] = {
66  ACTION_DISBAND_UNIT,
67  ACTION_RECYCLE_UNIT,
68  ACTION_HELP_WONDER,
69 };
70 
71 // current_focus points to the current unit(s) in focus
72 static auto current_focus = std::vector<unit *>();
73 
74 /* The previously focused unit(s). Focus can generally be recalled
75  * with keypad 5 (or the equivalent). */
76 static struct unit_list *previous_focus = nullptr;
77 
78 // The priority unit(s) for unit_focus_advance().
79 static struct unit_list *urgent_focus_queue = nullptr;
80 
81 // These should be set via set_hover_state()
83 enum unit_activity connect_activity;
85 
89 enum unit_orders goto_last_order; // Last order for goto
90 
91 static struct tile *hover_tile = nullptr;
92 static struct unit_list *battlegroups[MAX_NUM_BATTLEGROUPS];
93 
94 // Current moving unit.
95 static struct unit *punit_moving = nullptr;
96 
97 // units involved in current combat
98 static struct unit *punit_attacking = nullptr;
99 static struct unit *punit_defending = nullptr;
100 
101 /* The ID of the unit that currently is in the action selection process.
102  *
103  * The action selection process begins when the client asks the server what
104  * actions a unit can take. It ends when the last follow up question is
105  * answered.
106  *
107  * No common client code using client supports more than one action
108  * selection process at once. The interface between the common client code
109  * and the clients would have to change before that could happen. (See
110  * action_selection_actor_unit() etc)
111  */
113 
114 /*
115  * This variable is TRUE iff a NON-AI controlled unit was focused this
116  * turn.
117  */
119 
120 static void key_unit_clean(enum unit_activity act,
121  enum extra_rmcause rmcause);
122 
123 /*************************************************************************/
124 
125 static struct unit *quickselect(struct tile *ptile,
126  enum quickselect_type qtype);
127 
132 {
133  int i;
134 
135  previous_focus = unit_list_new();
136  urgent_focus_queue = unit_list_new();
137 
138  for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
139  battlegroups[i] = unit_list_new();
140  }
141  hover_tile = nullptr;
142 }
143 
148 {
149  int i;
150 
151  current_focus.clear();
152  unit_list_destroy(previous_focus);
153  previous_focus = nullptr;
154  unit_list_destroy(urgent_focus_queue);
155  urgent_focus_queue = nullptr;
156 
157  for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
158  unit_list_destroy(battlegroups[i]);
159  battlegroups[i] = nullptr;
160  }
161 
164 }
165 
169 std::vector<unit *> &get_units_in_focus() { return current_focus; }
170 
174 int get_num_units_in_focus() { return current_focus.size(); }
175 
180 static void store_previous_focus()
181 {
182  if (get_num_units_in_focus() > 0) {
183  unit_list_clear(previous_focus);
184  for (auto punit : get_units_in_focus()) {
185  unit_list_append(previous_focus, punit);
186  }
187  }
188 }
189 
193 void unit_focus_urgent(struct unit *punit)
194 {
195  unit_list_append(urgent_focus_queue, punit);
196 }
197 
201 static void focus_units_changed()
202 {
204  menus_update();
205  // Notify the GUI
207 }
208 
212 void control_unit_killed(struct unit *punit)
213 {
214  int i;
215 
216  goto_unit_killed(punit);
217 
218  auto &focus = get_units_in_focus();
219  focus.erase(std::remove(focus.begin(), focus.end(), punit), focus.end());
220  if (get_num_units_in_focus() < 1) {
222  }
223 
224  unit_list_remove(previous_focus, punit);
225  unit_list_remove(urgent_focus_queue, punit);
226 
227  for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
228  unit_list_remove(battlegroups[i], punit);
229  }
230 
232 }
233 
237 void unit_change_battlegroup(struct unit *punit, int battlegroup)
238 {
239  if (battlegroup < 0 || battlegroup >= MAX_NUM_BATTLEGROUPS) {
241  }
242 
243  if (punit->battlegroup != battlegroup) {
244  if (battlegroup != BATTLEGROUP_NONE) {
245  unit_list_append(battlegroups[battlegroup], punit);
246  }
247  if (punit->battlegroup != BATTLEGROUP_NONE) {
248  unit_list_remove(battlegroups[punit->battlegroup], punit);
249  }
250  punit->battlegroup = battlegroup;
251  }
252 }
253 
257 void unit_register_battlegroup(struct unit *punit)
258 {
259  if (punit->battlegroup < 0 || punit->battlegroup >= MAX_NUM_BATTLEGROUPS) {
260  punit->battlegroup = BATTLEGROUP_NONE;
261  } else {
262  unit_list_append(battlegroups[punit->battlegroup], punit);
263  }
264 }
265 
272 void set_hover_state(const std::vector<unit *> &units,
273  enum cursor_hover_state state,
274  enum unit_activity activity, struct extra_type *tgt,
275  int last_tgt, int last_sub_tgt, action_id action,
276  enum unit_orders order)
277 {
278  fc_assert_ret(!units.empty()
279  || (state == HOVER_NONE || state == HOVER_DEBUG_TILE));
280  fc_assert_ret(state == HOVER_CONNECT || activity == ACTIVITY_LAST);
281  fc_assert_ret((state == HOVER_GOTO || state == HOVER_GOTO_SEL_TGT)
282  || order == ORDER_LAST);
283  fc_assert_ret((state == HOVER_GOTO || state == HOVER_GOTO_SEL_TGT)
284  || action == ACTION_NONE);
285 
287  && (state == HOVER_GOTO || state == HOVER_GOTO_SEL_TGT))) {
288  // Exit goto unless this is a switch between goto states
289  exit_goto_state();
290  }
291 
292  hover_state = state;
294  if (tgt) {
295  connect_tgt = tgt;
296  } else {
297  connect_tgt = nullptr;
298  }
299  goto_last_order = order;
301  goto_last_tgt = last_tgt;
302  goto_last_sub_tgt = last_sub_tgt;
303 }
304 
309 {
310  set_hover_state({}, HOVER_NONE, ACTIVITY_LAST, nullptr, NO_TARGET,
312 }
313 
318 bool should_ask_server_for_actions(const struct unit *punit)
319 {
320  return (punit->action_decision_want == ACT_DEC_ACTIVE
321  /* The player is interested in getting a pop up for a mere
322  * arrival. */
323  || (punit->action_decision_want == ACT_DEC_PASSIVE
325 }
326 
332 {
333  // OK as long as no other unit already asked and aren't done yet.
336 }
337 
345 static void ask_server_for_actions(struct unit *punit)
346 {
347  fc_assert_ret(punit);
349 
350  // Only one action selection dialog at a time is supported.
352  "Unit %d started action selection before unit %d was done",
355 
356  dsend_packet_unit_get_actions(
359 }
360 
364 bool unit_is_in_focus(const struct unit *punit)
365 {
366  const auto &focus = get_units_in_focus();
367  return std::find(focus.begin(), focus.end(), punit) != focus.end();
368 }
369 
373 struct unit *get_focus_unit_on_tile(const struct tile *ptile)
374 {
375  for (const auto punit : get_units_in_focus()) {
376  if (unit_tile(punit) == ptile) {
377  return punit;
378  }
379  }
380 
381  return nullptr;
382 }
383 
388 {
389  const auto &list = get_units_in_focus();
390  return list.empty() ? nullptr : list.front();
391 }
392 
397 {
398  struct unit *punit;
399 
400  if (nullptr
402  return unit_tile(punit);
403  } else if (get_num_units_in_focus() > 0) {
405  } else {
406  return nullptr;
407  }
408 }
409 
410 namespace {
411 bool auto_center_enabled = true;
412 }
413 
417 void set_auto_center_enabled(bool enabled) { auto_center_enabled = enabled; }
418 
423 {
424  struct tile *ptile = find_a_focus_unit_tile_to_center_on();
425 
426  if (ptile && gui_options->auto_center_on_unit && auto_center_enabled
428  queen()->mapview_wdg->center_on_tile(ptile);
429  }
430 }
431 
435 static void current_focus_append(struct unit *punit)
436 {
437  get_units_in_focus().push_back(punit);
438 
439  punit->client.focus_status = FOCUS_AVAIL;
440  refresh_unit_mapcanvas(punit, unit_tile(punit), true);
441 
443  ask_server_for_actions(punit);
444  }
445 
447  clear_unit_orders(punit);
448  }
449 }
450 
454 void clear_unit_orders(struct unit *punit)
455 {
456  if (!punit) {
457  return;
458  }
459 
460  if (punit->activity != ACTIVITY_IDLE
461  || punit->ssa_controller != SSA_NONE) {
462  punit->ssa_controller = SSA_NONE;
464  request_new_unit_activity(punit, ACTIVITY_IDLE);
465  } else if (unit_has_orders(punit)) {
466  // Clear the focus unit's orders.
467  request_orders_cleared(punit);
468  }
469 }
470 
479 void unit_focus_set(struct unit *punit)
480 {
481  bool focus_changed = false;
482 
483  if (nullptr != punit && nullptr != client.conn.playing
484  && unit_owner(punit) != client.conn.playing) {
485  // Callers should make sure this never happens.
486  return;
487  }
488 
489  /* FIXME: this won't work quite right; for instance activating a
490  * battlegroup twice in a row will store the focus erronously. The only
491  * solution would be a set_units_focus() */
492  if (!(get_num_units_in_focus() == 1
493  && punit == head_of_units_in_focus())) {
495  focus_changed = true;
496  }
497 
498  // Close the action selection dialog if the actor unit lose focus.
499  for (const auto punit_old : get_units_in_focus()) {
500  if (action_selection_actor_unit() == punit_old->id) {
502  }
503  }
504 
505  /* Redraw the old focus unit (to fix blinking or remove the selection
506  * circle). */
507  for (const auto punit_old : get_units_in_focus()) {
508  refresh_unit_mapcanvas(punit_old, unit_tile(punit_old), true);
509  }
510  get_units_in_focus().clear();
511 
512  if (!can_client_change_view()) {
513  /* This function can be called to set the focus to nullptr when
514  * disconnecting. In this case we don't want any other actions! */
515  fc_assert(punit == nullptr);
516  return;
517  }
518 
519  if (nullptr != punit) {
520  current_focus_append(punit);
522  }
523 
524  if (focus_changed) {
527  }
529 }
530 
534 void unit_focus_add(struct unit *punit)
535 {
536  if (nullptr != punit && nullptr != client.conn.playing
537  && unit_owner(punit) != client.conn.playing) {
538  // Callers should make sure this never happens.
539  return;
540  }
541 
542  if (nullptr == punit || !can_client_change_view()) {
543  return;
544  }
545 
546  if (unit_is_in_focus(punit)) {
547  return;
548  }
549 
550  if (hover_state != HOVER_NONE) {
551  /* Can't continue with current goto if set of focus units
552  * change. Cancel it. */
554  }
555 
556  current_focus_append(punit);
558 }
559 
563 void unit_focus_set_and_select(struct unit *punit)
564 {
565  unit_focus_set(punit);
566  if (punit) {
568  }
569 }
570 
577 static struct unit *find_best_focus_candidate(bool accept_current)
578 {
579  struct tile *ptile = get_center_tile_mapcanvas();
580 
581  if (!get_focus_unit_on_tile(ptile)) {
582  struct unit *pfirst = head_of_units_in_focus();
583 
584  if (pfirst) {
585  ptile = unit_tile(pfirst);
586  }
587  }
588 
589  iterate_outward(&(wld.map), ptile, FC_INFINITY, ptile2)
590  {
591  unit_list_iterate(ptile2->units, punit)
592  {
593  if ((!unit_is_in_focus(punit) || accept_current)
594  && unit_owner(punit) == client.conn.playing
595  && punit->client.focus_status == FOCUS_AVAIL
596  && punit->activity == ACTIVITY_IDLE && !unit_has_orders(punit)
597  && (punit->moves_left > 0 || unit_type_get(punit)->move_rate == 0)
598  && can_unit_move_now(punit) && !punit->done_moving
599  && punit->ssa_controller == SSA_NONE) {
600  return punit;
601  }
602  }
604  }
606 
607  return nullptr;
608 }
609 
618 {
619  struct unit *candidate = nullptr;
620  const int num_units_in_old_focus = get_num_units_in_focus();
621 
622  if (nullptr == client.conn.playing
624  || !can_client_change_view()) {
625  unit_focus_set(nullptr);
626  return;
627  }
628 
630 
631  for (const auto punit : get_units_in_focus()) {
632  /*
633  * Is the unit which just lost focus a non-AI unit? If yes this
634  * enables the auto end turn.
635  */
636  if (punit->ssa_controller == SSA_NONE) {
637  non_ai_unit_focus = true;
638  break;
639  }
640  }
641 
642  if (unit_list_size(urgent_focus_queue) > 0) {
643  // Try top of the urgent list.
644  struct tile *focus_tile =
646  : nullptr);
647 
649  {
650  if ((ACTIVITY_IDLE != punit->activity || unit_has_orders(punit))
651  /* This isn't an action decision needed because of an
652  * ORDER_ACTION_MOVE located in the middle of an order. */
653  && !should_ask_server_for_actions(punit)) {
654  // We have assigned new orders to this unit since, remove it.
655  unit_list_erase(urgent_focus_queue, plink);
656  } else if (nullptr == focus_tile || focus_tile == unit_tile(punit)) {
657  // Use the first one found
658  candidate = punit;
659  break;
660  } else if (nullptr == candidate) {
661  candidate = punit;
662  }
663  }
665 
666  if (nullptr != candidate) {
667  unit_list_remove(urgent_focus_queue, candidate);
668 
669  /* Autocenter on Wakeup, regardless of the local option
670  * "auto_center_on_unit". */
672  queen()->mapview_wdg->center_on_tile(unit_tile(candidate));
673  }
674  }
675  }
676 
677  if (nullptr == candidate) {
678  candidate = find_best_focus_candidate(false);
679 
680  if (!candidate) {
681  // Try for "waiting" units.
683  {
684  if (punit->client.focus_status == FOCUS_WAIT) {
685  punit->client.focus_status = FOCUS_AVAIL;
686  }
687  }
689  candidate = find_best_focus_candidate(false);
690 
691  if (!candidate) {
692  // Accept current focus unit as last resort.
693  candidate = find_best_focus_candidate(true);
694  }
695  }
696  }
697 
698  unit_focus_set(candidate);
699 
700  /*
701  * Handle auto-turn-done mode: If a unit was in focus (did move),
702  * but now none are (no more to move) and there was at least one
703  * non-AI unit this turn which was focused, then fake a Turn Done
704  * keypress.
705  */
706  if (gui_options->auto_turn_done && num_units_in_old_focus > 0
708  key_end_turn();
709  }
710 }
711 
719 {
720  if (nullptr == client.conn.playing || !can_client_change_view()) {
721  return;
722  }
723 
726 
727  /* An actor unit is asking the player what to do. Don't steal his
728  * focus. */
729  return;
730  }
731 
732  /* iterate zero times for no units in focus,
733  * otherwise quit for any of the conditions. */
734  for (const auto punit : get_units_in_focus()) {
735  if ((punit->activity == ACTIVITY_IDLE || punit->activity == ACTIVITY_GOTO
736  || unit_has_orders(punit))
737  && punit->moves_left > 0 && !punit->done_moving
738  && punit->ssa_controller == SSA_NONE) {
739  return;
740  }
741  }
742 
744 }
745 
749 unit *find_visible_unit(const ::tile *ptile)
750 {
751  struct unit *panyowned = nullptr, *panyother = nullptr,
752  *ptptother = nullptr;
753 
754  // If no units here, return nothing.
755  if (unit_list_size(ptile->units) == 0) {
756  return nullptr;
757  }
758 
759  // If a unit is attacking we should show that on top
761  unit_list_iterate(ptile->units, punit)
762  {
763  if (punit == punit_attacking) {
764  return punit;
765  }
766  }
768  }
769 
770  // If a unit is defending we should show that on top
772  unit_list_iterate(ptile->units, punit)
773  {
774  if (punit == punit_defending) {
775  return punit;
776  }
777  }
779  }
780 
781  // If the unit in focus is at this tile, show that on top
782  for (const auto punit : get_units_in_focus()) {
783  if (punit != punit_moving && unit_tile(punit) == ptile) {
784  return punit;
785  }
786  }
787 
788  // If a city is here (and UI is drawing them), return nothing
789  // (unit hidden by city).
790  if (gui_options->draw_cities && tile_city(ptile)) {
791  return nullptr;
792  }
793 
794  /* Iterate through the units to find the best one we prioritize this way:
795  1: owned transporter.
796  2: any owned unit
797  3: any transporter
798  4: any unit
799  (always return first in stack). */
800  unit_list_iterate(ptile->units, punit)
801  {
802  if (unit_owner(punit) == client.conn.playing) {
803  if (!unit_transported(punit)) {
804  if (get_transporter_capacity(punit) > 0) {
805  return punit;
806  } else if (!panyowned) {
807  panyowned = punit;
808  }
809  }
810  } else if (!ptptother && !unit_transported(punit)) {
811  if (get_transporter_capacity(punit) > 0) {
812  ptptother = punit;
813  } else if (!panyother) {
814  panyother = punit;
815  }
816  }
817  }
819 
820  return (panyowned ? panyowned : (ptptother ? ptptother : panyother));
821 }
822 
828 {
829  static QTimer blink_timer;
830  blink_timer.setSingleShot(true);
831  const int blink_time = get_focus_unit_toggle_timeout(tileset);
832 
833  if (get_num_units_in_focus() > 0) {
834  if (!blink_timer.isActive()) {
836 
837  blink_timer.start(blink_time);
838 
839  for (const auto punit : get_units_in_focus()) {
840  /* We flush to screen directly here. This is most likely faster
841  * since these drawing operations are all small but may be spread
842  * out widely. */
843  refresh_unit_mapcanvas(punit, unit_tile(punit), false);
844  }
845  }
846 
847  return blink_time - blink_timer.remainingTime();
848  }
849 
850  return blink_time;
851 }
852 
858 {
859  static QTimer blink_timer;
860  blink_timer.setSingleShot(true);
861  const double blink_time = 500; // half-second blink interval
862 
863  if (nullptr != client.conn.playing && client.conn.playing->is_alive
866  if (!blink_timer.isActive()) {
867  int is_waiting = 0, is_moving = 0;
868  bool blocking_mode;
869  struct option *opt;
870 
871  opt = optset_option_by_name(server_optset, "turnblock");
872  if (opt != nullptr) {
873  blocking_mode = option_bool_get(opt);
874  } else {
875  blocking_mode = false;
876  }
877 
878  players_iterate_alive(pplayer)
879  {
880  if ((pplayer->is_connected || blocking_mode)
881  && is_player_phase(pplayer, game.info.phase)) {
882  if (pplayer->phase_done) {
883  is_waiting++;
884  } else {
885  is_moving++;
886  }
887  }
888  }
890 
891  if (is_moving == 1 && is_waiting > 0) {
892  update_turn_done_button(false); // stress the slow player!
893  }
894  blink_timer.start(blink_time);
895  }
896  return blink_time - blink_timer.remainingTime();
897  }
898 
899  return blink_time;
900 }
901 
905 void set_units_in_combat(struct unit *pattacker, struct unit *pdefender)
906 {
907  punit_attacking = pattacker;
908  punit_defending = pdefender;
909 
912  /* If one of the units is the focus unit, make sure hidden-focus is
913  * disabled. We don't just do this as a check later because then
914  * with a blinking unit it would just disappear again right after the
915  * battle. */
917  }
918 }
919 
924 void action_selection_no_longer_in_progress(const int old_actor_id)
925 {
926  /* IDENTITY_NUMBER_ZERO is accepted for cases where the unit is gone
927  * without a trace. */
929  || old_actor_id == IDENTITY_NUMBER_ZERO,
930  "Decision taken for %d but selection is for %d.",
931  old_actor_id, action_selection_in_progress_for);
932 
933  // Stop objecting to allowing the next unit to ask.
935 
936  // Clean up any client specific assumptions.
938 }
939 
944 void action_decision_clear_want(const int old_actor_id)
945 {
946  struct unit *old = game_unit_by_number(old_actor_id);
947 
948  if (old) {
949  // Have the server record that a decision no longer is wanted.
950  dsend_packet_unit_sscs_set(&client.conn, old_actor_id, USSDT_UNQUEUE,
952  }
953 }
954 
958 void action_selection_next_in_focus(const int old_actor_id)
959 {
960  struct unit *old;
961 
962  old = game_unit_by_number(old_actor_id);
963 
964  // Go to the next unit in focus that needs a decision.
965  for (const auto punit : get_units_in_focus()) {
966  if (old != punit && should_ask_server_for_actions(punit)) {
967  ask_server_for_actions(punit);
968  return;
969  }
970  }
971 }
972 
976 void action_decision_request(struct unit *actor_unit)
977 {
978  fc_assert_ret(actor_unit);
979  fc_assert_ret(actor_unit->action_decision_tile);
980 
981  if (!unit_is_in_focus(actor_unit)) {
982  /* Getting feed back may be urgent. A unit standing next to an enemy
983  * could be killed while waiting. */
984  unit_focus_urgent(actor_unit);
986  /* No need to wait. The actor unit is in focus. No other actor unit
987  * is currently asking about action selection. */
988  ask_server_for_actions(actor_unit);
989  }
990 }
991 
995 void request_unit_goto(enum unit_orders last_order, action_id act_id,
996  int sub_tgt_id)
997 {
998  const auto focus = get_units_in_focus();
999 
1000  fc_assert_ret(act_id == ACTION_NONE || last_order == ORDER_PERFORM_ACTION);
1001 
1002  if (focus.empty()) {
1003  return;
1004  }
1005 
1006  if (last_order == ORDER_PERFORM_ACTION) {
1007  // An action has been specified.
1009 
1010  for (const auto punit : focus) {
1011  if (!unit_can_do_action(punit, act_id)) {
1012  /* This unit can't perform the action specified in the last
1013  * order. */
1014  QString roles;
1015 
1016  if (role_units_translations(roles, action_id_get_role(act_id),
1017  true)) {
1018  // ...but other units can perform it.
1019  create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1020  /* TRANS: Only Nuclear or ICBM can do Explode
1021  * Nuclear. */
1022  _("Only %s can do %s."), qUtf8Printable(roles),
1023  qUtf8Printable(action_id_name_translation(act_id)));
1024  } else {
1025  create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1026  // TRANS: Spy can't do Explode Nuclear.
1027  _("%s can't do %s."), unit_name_translation(punit),
1028  qUtf8Printable(action_id_name_translation(act_id)));
1029  }
1030 
1031  return;
1032  }
1033  }
1034  }
1035 
1037  set_hover_state(focus, HOVER_GOTO, ACTIVITY_LAST, nullptr, NO_TARGET,
1038  sub_tgt_id, act_id, last_order);
1039  enter_goto_state(focus);
1041  update_unit_info_label(focus);
1042  control_mouse_cursor(nullptr);
1043  } else {
1045  // Adding a long range action in the middle isn't handled yet
1048  }
1049 }
1050 
1054 static bool can_units_attack_at(const std::vector<unit *> &units,
1055  const struct tile *ptile)
1056 {
1057  return std::any_of(units.begin(), units.end(), [&](const auto *unit) {
1058  return is_attack_unit(unit) && can_unit_attack_tile(unit, ptile);
1059  });
1060 }
1061 
1067 void control_mouse_cursor(struct tile *ptile)
1068 {
1069  struct unit *punit = nullptr;
1070  struct city *pcity = nullptr;
1071  const auto &active_units = get_units_in_focus();
1072  enum cursor_type mouse_cursor_type = CURSOR_DEFAULT;
1073 
1075  return;
1076  }
1077 
1078  if (C_S_RUNNING != client_state()) {
1080  return;
1081  }
1082 
1083  if (is_server_busy()) {
1084  // Server will not accept any commands.
1086  return;
1087  }
1088 
1089  if (!ptile) {
1090  if (hover_tile) {
1091  /* hover_tile is the tile that was previously under the mouse cursor.
1092  */
1093  ptile = hover_tile;
1094  } else {
1096  return;
1097  }
1098  } else {
1099  hover_tile = ptile;
1100  }
1101 
1102  punit = find_visible_unit(ptile);
1103  pcity = tile_city(ptile);
1104 
1105  switch (hover_state) {
1106  case HOVER_NONE:
1107  if (nullptr != punit && unit_owner(punit) == client_player()) {
1108  // Set mouse cursor to select a unit.
1109  mouse_cursor_type = CURSOR_SELECT;
1110  } else if (nullptr != pcity && pcity->client.full) {
1111  // Set mouse cursor to select a city.
1112  mouse_cursor_type = CURSOR_SELECT;
1113  } else {
1114  // Set default mouse cursor, because nothing selectable found.
1115  }
1116  break;
1117  case HOVER_GOTO:
1118  // Determine if the goto is valid, invalid, nuke or will attack.
1119  if (is_valid_goto_destination(ptile)) {
1120  if (action_id_has_result_safe(goto_last_action, ACTRES_NUKE_UNITS)
1121  || action_id_has_result_safe(goto_last_action, ACTRES_NUKE_CITY)
1122  || action_id_has_result_safe(goto_last_action, ACTRES_NUKE)) {
1123  // Goto results in nuclear attack.
1124  mouse_cursor_type = CURSOR_NUKE;
1125  } else if (can_units_attack_at(active_units, ptile)) {
1126  // Goto results in military attack.
1127  mouse_cursor_type = CURSOR_ATTACK;
1128  } else if (is_enemy_city_tile(ptile, client.conn.playing)) {
1129  // Goto results in attack of enemy city.
1130  mouse_cursor_type = CURSOR_ATTACK;
1131  } else {
1132  mouse_cursor_type = CURSOR_GOTO;
1133  }
1134  } else {
1135  mouse_cursor_type = CURSOR_INVALID;
1136  }
1137  break;
1138  case HOVER_PATROL:
1139  if (is_valid_goto_destination(ptile)) {
1140  mouse_cursor_type = CURSOR_PATROL;
1141  } else {
1142  mouse_cursor_type = CURSOR_INVALID;
1143  }
1144  break;
1145  case HOVER_CONNECT:
1146  if (is_valid_goto_destination(ptile)) {
1147  mouse_cursor_type = CURSOR_GOTO;
1148  } else {
1149  mouse_cursor_type = CURSOR_INVALID;
1150  }
1151  break;
1152  case HOVER_PARADROP:
1153  // FIXME: check for invalid tiles.
1154  mouse_cursor_type = CURSOR_PARADROP;
1155  break;
1156  case HOVER_ACT_SEL_TGT:
1157  case HOVER_GOTO_SEL_TGT:
1158  case HOVER_DEBUG_TILE:
1159  /* Select a tile to target / find targets on. */
1160  mouse_cursor_type = CURSOR_SELECT;
1161  break;
1162  };
1163 
1164  update_mouse_cursor(mouse_cursor_type);
1165 }
1166 
1170 static bool is_activity_on_tile(struct tile *ptile,
1171  enum unit_activity activity)
1172 {
1173  unit_list_iterate(ptile->units, punit)
1174  {
1175  if (punit->activity == activity) {
1176  return true;
1177  }
1178  }
1180 
1181  return false;
1182 }
1183 
1189  const struct extra_type *pextra,
1190  const struct unit *punit,
1191  const struct player *pplayer, int rec)
1192 {
1193  int activity_mc = 0;
1194  struct terrain *pterrain = tile_terrain(ptile);
1195 
1196  if (rec > MAX_EXTRA_TYPES) {
1197  return -1;
1198  }
1199 
1200  if (!is_extra_caused_by(pextra, EC_ROAD)) {
1201  return -1;
1202  }
1203 
1204  extra_deps_iterate(&(pextra->reqs), pdep)
1205  {
1206  if (!tile_has_extra(ptile, pdep)) {
1207  int single_mc;
1208 
1209  single_mc =
1210  check_recursive_road_connect(ptile, pdep, punit, pplayer, rec + 1);
1211 
1212  if (single_mc < 0) {
1213  return -1;
1214  }
1215 
1216  activity_mc += single_mc;
1217  }
1218  }
1220 
1221  // Can build road after that?
1222  if (punit != nullptr) {
1223  if (!can_build_road(extra_road_get(pextra), punit, ptile)) {
1224  return -1;
1225  }
1226  } else if (pplayer != nullptr) {
1227  if (!player_can_build_road(extra_road_get(pextra), pplayer, ptile)) {
1228  return -1;
1229  }
1230  }
1231 
1232  tile_add_extra(ptile, pextra);
1233 
1234  activity_mc +=
1235  terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD, pextra);
1236 
1237  return activity_mc;
1238 }
1239 
1244 static bool can_be_irrigated(const struct tile *ptile,
1245  const struct unit *punit)
1246 {
1247  struct terrain *pterrain = tile_terrain(ptile);
1248  struct universal for_unit = {
1249  .value = {.utype = unit_type_get(punit)},
1250  .kind = VUT_UTYPE,
1251  };
1252  struct universal for_tile = {
1253  .value = {.terrain = tile_terrain(ptile)},
1254  .kind = VUT_TERRAIN,
1255  };
1256 
1257  if (T_UNKNOWN == pterrain) {
1258  return false;
1259  }
1260 
1261  return action_id_univs_not_blocking(ACTION_IRRIGATE, &for_unit, &for_tile);
1262 }
1263 
1270 bool can_unit_do_connect(struct unit *punit, enum unit_activity activity,
1271  struct extra_type *tgt)
1272 {
1273  struct tile *ptile = unit_tile(punit);
1274  struct terrain *pterrain = tile_terrain(ptile);
1275  struct road_type *proad = nullptr;
1276 
1277  /* HACK: This code duplicates that in
1278  * can_unit_do_activity_targeted_at(). The general logic here is that
1279  * the connect is allowed if both:
1280  * (1) the unit can do that activity type, in general
1281  * (2) either
1282  * (a) the activity has already been completed at this tile
1283  * (b) it can be done by the unit at this tile. */
1284  switch (activity) {
1285  case ACTIVITY_GEN_ROAD: {
1286  struct tile *vtile;
1287  int build_time;
1288 
1289  fc_assert(is_extra_caused_by(tgt, EC_ROAD));
1290 
1291  proad = extra_road_get(tgt);
1292 
1293  if (tile_has_road(ptile, proad)) {
1294  // This tile has road, can unit build road to other tiles too?
1295  return are_reqs_active(nullptr, nullptr, nullptr, nullptr, nullptr,
1296  punit, unit_type_get(punit), nullptr, nullptr,
1297  nullptr, &tgt->reqs, RPT_POSSIBLE);
1298  }
1299 
1300  /* To start connect, unit must be able to build road to this
1301  * particular tile. */
1302  vtile = tile_virtual_new(ptile);
1303  build_time = check_recursive_road_connect(vtile, tgt, punit, nullptr, 0);
1304  tile_virtual_destroy(vtile);
1305 
1306  return build_time >= 0;
1307  }
1308 
1309  case ACTIVITY_IRRIGATE:
1310  /* Special case for irrigation: only irrigate to make S_IRRIGATION,
1311  * never to transform tiles. */
1312  if (!unit_has_type_flag(punit, UTYF_SETTLERS)) {
1313  return false;
1314  }
1315  if (tile_has_extra(ptile, tgt)) {
1316  return are_reqs_active(nullptr, nullptr, nullptr, nullptr, nullptr,
1317  punit, unit_type_get(punit), nullptr, nullptr,
1318  nullptr, &tgt->reqs, RPT_POSSIBLE);
1319  }
1320 
1321  return pterrain == pterrain->irrigation_result
1322  && can_be_irrigated(ptile, punit)
1323  && can_build_extra(tgt, punit, ptile)
1324  && !is_activity_on_tile(ptile, ACTIVITY_MINE);
1325  default:
1326  break;
1327  }
1328 
1329  return false;
1330 }
1331 
1336 void request_unit_connect(enum unit_activity activity,
1337  struct extra_type *tgt)
1338 {
1339  const auto &focus = get_units_in_focus();
1340 
1341  if (!can_units_do_connect(focus, activity, tgt)) {
1342  return;
1343  }
1344 
1345  if (hover_state != HOVER_CONNECT || connect_activity != activity
1346  || (connect_tgt != tgt
1347  && (activity == ACTIVITY_GEN_ROAD
1348  || activity == ACTIVITY_IRRIGATE))) {
1349  set_hover_state(focus, HOVER_CONNECT, activity, tgt, NO_TARGET,
1351  enter_goto_state(focus);
1353  update_unit_info_label(focus);
1354  control_mouse_cursor(nullptr);
1355  } else {
1358  }
1359 }
1360 
1364 struct unit *request_unit_unload_all(struct unit *punit)
1365 {
1366  struct tile *ptile = unit_tile(punit);
1367  struct unit *plast = nullptr;
1368 
1369  if (get_transporter_capacity(punit) == 0) {
1370  create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1371  _("Only transporter units can be unloaded."));
1372  return nullptr;
1373  }
1374 
1375  unit_list_iterate(ptile->units, pcargo)
1376  {
1377  if (unit_transport_get(pcargo) == punit) {
1378  request_unit_unload(pcargo);
1379 
1380  if (pcargo->activity == ACTIVITY_SENTRY) {
1381  request_new_unit_activity(pcargo, ACTIVITY_IDLE);
1382  }
1383 
1384  if (unit_owner(pcargo) == unit_owner(punit)) {
1385  plast = pcargo;
1386  }
1387  }
1388  }
1390 
1391  return plast;
1392 }
1393 
1397 void request_unit_airlift(struct unit *punit, struct city *pcity)
1398 {
1399  request_do_action(ACTION_AIRLIFT, punit->id, pcity->id, 0, "");
1400 }
1401 
1407 {
1408  for (const auto unit : get_units_in_focus()) {
1409  // Find a path to the closest city
1410  auto finder = freeciv::path_finder(unit);
1412  finder.set_constraint(
1413  std::make_unique<freeciv::tile_known_constraint>(client_player()));
1414  }
1415  if (auto path = finder.find_path(
1417  auto steps = path->steps();
1418  int hp = steps.empty() ? unit->hp : steps.back().health;
1419  // Recover full health if needed
1420  if (hp < unit_type_get(unit)->hp) {
1421  auto sentry = steps.back();
1422  sentry.order.order = ORDER_ACTIVITY;
1423  sentry.order.dir = DIR8_ORIGIN;
1424  sentry.order.activity = ACTIVITY_SENTRY;
1425  sentry.order.target = NO_TARGET;
1426  sentry.order.sub_target = NO_TARGET;
1427  sentry.order.action = ACTION_NONE;
1428  steps.push_back(sentry);
1429  }
1430 
1431  // Make a packet and send it
1432  if (!steps.empty()) {
1433  auto packet = packet_unit_orders{};
1434  packet.unit_id = unit->id;
1435  packet.dest_tile = steps.back().location->index;
1436  packet.src_tile = unit->tile->index;
1437  packet.repeat = false;
1438  packet.vigilant = false;
1439 
1440  fc_assert_ret(steps.size() < MAX_LEN_ROUTE);
1441 
1442  packet.length = steps.size();
1443  for (std::size_t i = 0; i < steps.size(); ++i) {
1444  packet.orders[i] = steps[i].order;
1445  }
1446 
1447  // Send
1448  request_unit_ssa_set(unit, SSA_NONE);
1449  send_packet_unit_orders(&client.conn, &packet);
1450  }
1451  }
1452  }
1453 }
1454 
1458 void wakeup_sentried_units(struct tile *ptile)
1459 {
1460  if (!can_client_issue_orders()) {
1461  return;
1462  }
1463  unit_list_iterate(ptile->units, punit)
1464  {
1465  if (punit->activity == ACTIVITY_SENTRY
1466  && unit_owner(punit) == client.conn.playing) {
1467  request_new_unit_activity(punit, ACTIVITY_IDLE);
1468  }
1469  }
1471 }
1472 
1476 void request_unit_wakeup(struct unit *punit)
1477 {
1479 }
1480 
1484 void request_unit_select(const std::vector<unit *> &punits,
1485  enum unit_select_type_mode seltype,
1486  enum unit_select_location_mode selloc)
1487 {
1488  const struct player *pplayer;
1489  const struct tile *ptile;
1490  QSet<const struct tile *> tile_table;
1491  QSet<const struct unit_type *> type_table;
1492  QSet<Continent_id> cont_table;
1493 
1494  if (!can_client_change_view() || punits.empty()) {
1495  return;
1496  }
1497 
1498  const auto punit_first = punits.front();
1499 
1500  if (seltype == SELTYPE_SINGLE) {
1501  unit_focus_set(punit_first);
1502  return;
1503  }
1504 
1505  pplayer = unit_owner(punit_first);
1506 
1507  for (const auto punit : punits) {
1508  if (seltype == SELTYPE_SAME) {
1509  type_table.insert(unit_type_get(punit));
1510  }
1511 
1512  ptile = unit_tile(punit);
1513  if (selloc == SELLOC_TILE) {
1514  tile_table.insert(ptile);
1515  } else if (selloc == SELLOC_CONT) {
1516  cont_table.insert(tile_continent(ptile));
1517  }
1518  }
1519 
1520  if (selloc == SELLOC_TILE) {
1521  for (const auto *hash_tile : tile_table) {
1522  unit_list_iterate(hash_tile->units, punit)
1523  {
1524  if (unit_owner(punit) != pplayer) {
1525  continue;
1526  }
1527  if (seltype == SELTYPE_SAME
1528  && !type_table.contains(unit_type_get(punit))) {
1529  continue;
1530  }
1531  unit_focus_add(punit);
1532  }
1534  }
1535  } else {
1536  unit_list_iterate(pplayer->units, punit)
1537  {
1538  ptile = unit_tile(punit);
1539  if ((seltype == SELTYPE_SAME
1540  && !type_table.contains(unit_type_get(punit)))
1541  || (selloc == SELLOC_CONT
1542  && !cont_table.contains(tile_continent(ptile)))) {
1543  continue;
1544  }
1545 
1546  unit_focus_add(punit);
1547  }
1549  }
1550 }
1551 
1563 void request_do_action(action_id action, int actor_id, int target_id,
1564  int sub_tgt, const char *name)
1565 {
1566  struct unit *actor_unit = game_unit_by_number(actor_id);
1567 
1568  // Giving an order takes back control.
1569  request_unit_ssa_set(actor_unit, SSA_NONE);
1570 
1571  dsend_packet_unit_do_action(&client.conn, actor_id, target_id, sub_tgt,
1572  name, action);
1573 }
1574 
1582 void request_action_details(action_id action, int actor_id, int target_id)
1583 {
1584  dsend_packet_unit_action_query(&client.conn, actor_id, target_id, action,
1585  /* Users that need the answer in the
1586  * background should send the packet them
1587  * self. At least for now. */
1588  true);
1589 }
1590 
1599 void request_unit_build_city(struct unit *punit)
1600 {
1601  struct city *pcity = tile_city(unit_tile(punit));
1602 
1603  if (pcity) {
1604  // Try to join the city.
1605  request_do_action(ACTION_JOIN_CITY, punit->id, pcity->id, 0, "");
1606  } else {
1607  // The reply will trigger a dialog to name the new city.
1608  dsend_packet_city_name_suggestion_req(&client.conn, punit->id);
1609  }
1610 }
1611 
1618 void request_unit_non_action_move(struct unit *punit, struct tile *dest_tile)
1619 {
1620  struct packet_unit_orders p;
1621  int dir;
1622 
1623  dir = get_direction_for_step(&(wld.map), unit_tile(punit), dest_tile);
1624 
1625  if (dir == -1) {
1626  // The unit isn't located next to the destination tile.
1627  return;
1628  }
1629 
1630  memset(&p, 0, sizeof(p));
1631 
1632  p.repeat = false;
1633  p.vigilant = false;
1634 
1635  p.unit_id = punit->id;
1636  p.src_tile = tile_index(unit_tile(punit));
1637  p.dest_tile = tile_index(dest_tile);
1638 
1639  p.length = 1;
1640  p.orders[0].order = ORDER_MOVE;
1641  p.orders[0].dir = static_cast<direction8>(dir);
1642  p.orders[0].activity = ACTIVITY_LAST;
1643  p.orders[0].target = NO_TARGET;
1644  p.orders[0].sub_target = NO_TARGET;
1645  p.orders[0].action = ACTION_NONE;
1646 
1647  request_unit_ssa_set(punit, SSA_NONE);
1648  send_packet_unit_orders(&client.conn, &p);
1649 }
1650 
1660 void request_move_unit_direction(struct unit *punit, int dir)
1661 {
1662  struct packet_unit_orders p;
1663  struct tile *dest_tile;
1664 
1665  // Catches attempts to move off map
1666  dest_tile =
1667  mapstep(&(wld.map), unit_tile(punit), static_cast<direction8>(dir));
1668  if (!dest_tile) {
1669  return;
1670  }
1671 
1672  if (!can_unit_exist_at_tile(&(wld.map), punit, dest_tile)) {
1673  if (request_transport(punit, dest_tile)) {
1674  return;
1675  }
1676  }
1677 
1678  /* The goto system isn't used to send the order because that would
1679  * prevent direction movement from overriding it.
1680  * Example of a situation when overriding the goto system is useful:
1681  * The goto system creates a longer path to make a move legal. The player
1682  * wishes to order the illegal move so the server will explain why the
1683  * short move is illegal. */
1684 
1685  memset(&p, 0, sizeof(p));
1686 
1687  p.repeat = false;
1688  p.vigilant = false;
1689 
1690  p.unit_id = punit->id;
1691  p.src_tile = tile_index(unit_tile(punit));
1692  p.dest_tile = tile_index(dest_tile);
1693 
1694  p.length = 1;
1695  p.orders[0].order =
1697  : ORDER_MOVE);
1698  p.orders[0].dir = static_cast<direction8>(dir);
1699  p.orders[0].activity = ACTIVITY_LAST;
1700  p.orders[0].target = NO_TARGET;
1701  p.orders[0].sub_target = NO_TARGET;
1702  p.orders[0].action = ACTION_NONE;
1703 
1704  request_unit_ssa_set(punit, SSA_NONE);
1705  send_packet_unit_orders(&client.conn, &p);
1706 }
1707 
1712 void request_new_unit_activity(struct unit *punit, enum unit_activity act)
1713 {
1714  request_new_unit_activity_targeted(punit, act, nullptr);
1715 }
1716 
1722  enum unit_activity act,
1723  struct extra_type *tgt)
1724 {
1725  if (!can_client_issue_orders()) {
1726  return;
1727  }
1728 
1729  // Callers rely on this to take back control from server side agents.
1730  request_unit_ssa_set(punit, SSA_NONE);
1731 
1732  if (tgt == nullptr) {
1733  dsend_packet_unit_change_activity(&client.conn, punit->id, act,
1734  EXTRA_NONE);
1735  } else {
1736  dsend_packet_unit_change_activity(&client.conn, punit->id, act,
1737  extra_index(tgt));
1738  }
1739 }
1740 
1745 {
1746  struct client_disband_unit_data *data =
1747  static_cast<client_disband_unit_data *>(p);
1748 
1749  delete data;
1750 }
1751 
1755 static void do_disband_alternative(void *p)
1756 {
1757  struct unit *punit;
1758  struct city *pcity;
1759  struct tile *ptile;
1760  int last_request_id_used;
1761  struct client_disband_unit_data *next;
1762  struct client_disband_unit_data *data =
1763  static_cast<client_disband_unit_data *>(p);
1764  int act;
1765 
1767 
1768  // Fetch the unit to get rid of.
1769  punit = player_unit_by_number(client_player(), data->unit_id);
1770 
1771  if (punit == nullptr) {
1772  // Success! It is gone.
1773  return;
1774  }
1775 
1776  if (data->alt == -1) {
1777  // All alternatives have been tried.
1778  create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1779  // TRANS: Unable to get rid of Leader.
1780  _("Unable to get rid of %s."),
1781  unit_name_translation(punit));
1782  return;
1783  }
1784 
1785  act = disband_unit_alternatives[data->alt];
1786 
1787  // Prepare the data for the next try in case this try fails.
1788  next = new client_disband_unit_data();
1789  next->unit_id = data->unit_id;
1790  next->alt = data->alt - 1;
1791 
1792  // Latest request ID before trying to send a request.
1793  last_request_id_used = client.conn.client.last_request_id_used;
1794 
1795  // Send a request to the server unless it is known to be pointless.
1796  switch (action_id_get_target_kind(act)) {
1797  case ATK_CITY:
1798  pcity = tile_city(unit_tile(punit));
1799  if (pcity
1800  && action_prob_possible(action_prob_vs_city(punit, act, pcity))) {
1801  request_do_action(act, punit->id, pcity->id, 0, "");
1802  }
1803  break;
1804  case ATK_UNIT:
1805  if (action_prob_possible(action_prob_vs_unit(punit, act, punit))) {
1806  request_do_action(act, punit->id, punit->id, 0, "");
1807  }
1808  break;
1809  case ATK_UNITS:
1810  if ((ptile = unit_tile(punit))
1811  && action_prob_possible(action_prob_vs_units(punit, act, ptile))) {
1812  request_do_action(act, punit->id, ptile->index, 0, "");
1813  }
1814  break;
1815  case ATK_TILE:
1816  if ((ptile = unit_tile(punit))
1818  action_prob_vs_tile(punit, act, ptile, nullptr))) {
1819  request_do_action(act, punit->id, ptile->index, 0, "");
1820  }
1821  break;
1822  case ATK_SELF:
1823  if (action_prob_possible(action_prob_self(punit, act))) {
1824  request_do_action(act, punit->id, punit->id, 0, "");
1825  }
1826  break;
1827  case ATK_COUNT:
1828  fc_assert(action_id_get_target_kind(act) != ATK_COUNT);
1829  break;
1830  }
1831 
1832  if (last_request_id_used != client.conn.client.last_request_id_used) {
1833  // A request was sent.
1834 
1835  // Check if it worked. Move on if it didn't.
1837  client.conn.client.last_request_id_used, do_disband_alternative,
1839  } else {
1840  // No request was sent.
1841 
1842  // Move on.
1843  do_disband_alternative(next);
1844 
1845  // Won't be freed by anyone else.
1847  }
1848 }
1849 
1853 void request_unit_disband(struct unit *punit)
1854 {
1855  struct client_disband_unit_data *data;
1856 
1857  // Set up disband data. Start at the end of the array.
1858  data = new client_disband_unit_data();
1859  data->unit_id = punit->id;
1860  data->alt = 2;
1861 
1862  // Begin.
1863  do_disband_alternative(data);
1864 
1865  // Won't be freed by anyone else.
1867 }
1868 
1873 {
1874  struct city *pcity = tile_city(unit_tile(punit));
1875 
1876  if (pcity) {
1877  request_do_action(ACTION_HOME_CITY, punit->id, pcity->id, 0, "");
1878  }
1879 }
1880 
1884 void request_unit_upgrade(struct unit *punit)
1885 {
1886  struct city *pcity = tile_city(unit_tile(punit));
1887 
1888  if (pcity) {
1889  request_do_action(ACTION_UPGRADE_UNIT, punit->id, pcity->id, 0, "");
1890  }
1891 }
1892 
1896 void request_unit_convert(struct unit *punit)
1897 {
1898  request_new_unit_activity(punit, ACTIVITY_CONVERT);
1899 }
1900 
1906 void request_unit_ssa_set(const struct unit *punit,
1907  enum server_side_agent agent)
1908 {
1909  if (punit) {
1910  dsend_packet_unit_server_side_agent_set(&client.conn, punit->id, agent);
1911  }
1912 }
1913 
1918 void request_unit_autosettlers(const struct unit *punit)
1919 {
1920  if (punit && can_unit_do_autosettlers(punit)) {
1921  request_unit_ssa_set(punit, SSA_AUTOSETTLER);
1922  } else if (punit) {
1923  create_event(unit_tile(punit), E_BAD_COMMAND, ftc_client,
1924  _("Only settler units can be put into auto mode."));
1925  }
1926 }
1927 
1934 void request_unit_load(struct unit *pcargo, struct unit *ptrans,
1935  struct tile *ptile)
1936 {
1937  if (!ptrans) {
1938  ptrans = transporter_for_unit(pcargo);
1939  }
1940 
1941  if (ptrans && can_client_issue_orders()
1942  && could_unit_load(pcargo, ptrans)) {
1943  if (same_pos(unit_tile(pcargo), ptile)) {
1944  request_do_action(ACTION_TRANSPORT_BOARD, pcargo->id, ptrans->id, 0,
1945  "");
1946  } else {
1947  request_do_action(ACTION_TRANSPORT_EMBARK, pcargo->id, ptrans->id, 0,
1948  "");
1949  }
1950 
1951  // Sentry the unit.
1952  /* FIXME: Should not sentry if above loading fails (transport moved away,
1953  * or filled already in server side) */
1954  request_new_unit_activity_targeted(pcargo, ACTIVITY_SENTRY, nullptr);
1955  }
1956 }
1957 
1962 void request_unit_unload(struct unit *pcargo)
1963 {
1964  struct unit *ptrans = unit_transport_get(pcargo);
1965 
1966  if (can_client_issue_orders() && ptrans && can_unit_unload(pcargo, ptrans)
1967  && can_unit_survive_at_tile(&(wld.map), pcargo, unit_tile(pcargo))) {
1968  if (unit_owner(pcargo) == client.conn.playing) {
1969  request_do_action(ACTION_TRANSPORT_ALIGHT, pcargo->id, ptrans->id, 0,
1970  "");
1971  } else {
1972  request_do_action(ACTION_TRANSPORT_UNLOAD, ptrans->id, pcargo->id, 0,
1973  "");
1974  }
1975 
1976  if (unit_owner(pcargo) == client.conn.playing
1977  && pcargo->activity == ACTIVITY_SENTRY) {
1978  // Activate the unit.
1979  request_new_unit_activity_targeted(pcargo, ACTIVITY_IDLE, nullptr);
1980  }
1981  }
1982 }
1983 
1989 {
1990  struct city *target_city = tile_city(unit_tile(punit));
1991 
1992  if (!target_city) {
1993  return;
1994  }
1995 
1996  if (action == ACTION_TRADE_ROUTE) {
1997  request_do_action(ACTION_TRADE_ROUTE, punit->id, target_city->id, 0, "");
1998  } else if (action == ACTION_HELP_WONDER) {
1999  request_do_action(ACTION_HELP_WONDER, punit->id, target_city->id, 0, "");
2000  } else {
2001  qCritical("request_unit_caravan_action() Bad action (%d)", action);
2002  }
2003 }
2004 
2009 void request_unit_paradrop(const std::vector<unit *> &units)
2010 {
2011  bool can = false;
2012  struct tile *offender = nullptr;
2013 
2014  if (units.empty()) {
2015  return;
2016  }
2017  for (const auto punit : units) {
2018  if (can_unit_paradrop(punit)) {
2019  can = true;
2020  break;
2021  }
2022  if (!offender) { /* Take first offender tile/unit */
2023  offender = unit_tile(punit);
2024  }
2025  }
2026  if (can) {
2027  create_event(unit_tile(units.front()), E_BEGINNER_HELP, ftc_client,
2028  // TRANS: paradrop target tile.
2029  _("Click on a tile to paradrop to it."));
2030 
2031  set_hover_state(units, HOVER_PARADROP, ACTIVITY_LAST, nullptr, NO_TARGET,
2034  } else {
2035  create_event(offender, E_BAD_COMMAND, ftc_client,
2036  _("Only paratrooper units can do this."));
2037  }
2038 }
2039 
2044 {
2045  const auto &focus = get_units_in_focus();
2046 
2047  if (focus.empty()) {
2048  return;
2049  }
2050 
2051  if (hover_state != HOVER_PATROL) {
2052  set_hover_state(focus, HOVER_PATROL, ACTIVITY_LAST, nullptr, NO_TARGET,
2054  update_unit_info_label(focus);
2055  enter_goto_state(focus);
2057  } else {
2060  }
2061 }
2062 
2066 void request_unit_sentry(struct unit *punit)
2067 {
2068  if (punit->activity != ACTIVITY_SENTRY
2069  && can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
2070  request_new_unit_activity(punit, ACTIVITY_SENTRY);
2071  }
2072 }
2073 
2077 void request_unit_fortify(struct unit *punit)
2078 {
2079  if (punit->activity != ACTIVITY_FORTIFYING
2080  && can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
2081  request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
2082  }
2083 }
2084 
2088 void request_unit_pillage(struct unit *punit)
2089 {
2090  if (!game.info.pillage_select) {
2091  // Leave choice up to the server
2092  request_new_unit_activity_targeted(punit, ACTIVITY_PILLAGE, nullptr);
2093  } else {
2094  bv_extras pspossible;
2095  int count = 0;
2096 
2097  BV_CLR_ALL(pspossible);
2098  extra_type_iterate(potential)
2099  {
2100  if (can_unit_do_activity_targeted(punit, ACTIVITY_PILLAGE,
2101  potential)) {
2102  BV_SET(pspossible, extra_index(potential));
2103  count++;
2104  }
2105  }
2107 
2108  if (count > 1) {
2109  popup_pillage_dialog(punit, pspossible);
2110  } else {
2111  // Should be only one choice...
2112  struct extra_type *target = get_preferred_pillage(pspossible);
2113 
2114  if (target != nullptr) {
2115  request_new_unit_activity_targeted(punit, ACTIVITY_PILLAGE, target);
2116  }
2117  }
2118  }
2119 }
2120 
2125 {
2126  if (!can_client_change_view()) {
2127  return;
2128  }
2129 
2132 }
2133 
2138 {
2139  if (!can_client_change_view()) {
2140  return;
2141  }
2142 
2145 }
2146 
2151 {
2152  if (!can_client_change_view()) {
2153  return;
2154  }
2155 
2156  gui_options->draw_map_grid ^= 1;
2158 }
2159 
2164 {
2165  if (!can_client_change_view()) {
2166  return;
2167  }
2168 
2169  gui_options->draw_borders ^= 1;
2171 }
2172 
2177 {
2178  if (!can_client_change_view()) {
2179  return;
2180  }
2181 
2182  gui_options->draw_native ^= 1;
2184 }
2185 
2190 {
2191  if (!can_client_change_view()) {
2192  return;
2193  }
2194 
2197 }
2198 
2203 {
2204  if (!can_client_change_view()) {
2205  return;
2206  }
2207 
2210 }
2211 
2216 {
2217  if (!can_client_change_view()) {
2218  return;
2219  }
2220 
2223 }
2224 
2229 {
2230  if (!can_client_change_view()) {
2231  return;
2232  }
2233 
2236 }
2237 
2242 {
2243  if (!can_client_change_view()) {
2244  return;
2245  }
2246 
2249 }
2250 
2255 {
2256  struct tile *ptile = find_a_focus_unit_tile_to_center_on();
2257 
2258  if (ptile) {
2259  queen()->mapview_wdg->center_on_tile(ptile);
2260  }
2261 }
2262 
2266 void request_units_wait(const std::vector<unit *> &units)
2267 {
2268  for (auto punit : units) {
2269  punit->client.focus_status = FOCUS_WAIT;
2270  }
2272 }
2273 
2278 {
2279  if (get_num_units_in_focus() > 0) {
2280  enum unit_focus_status new_status = FOCUS_DONE;
2281  for (const auto punit : get_units_in_focus()) {
2282  /* If any of the focused units are busy, keep all of them
2283  * in focus; another tap of the key will dismiss them */
2284  if (punit->activity != ACTIVITY_IDLE) {
2285  new_status = FOCUS_WAIT;
2286  }
2287  }
2288  for (const auto punit : get_units_in_focus()) {
2289  clear_unit_orders(punit);
2290  punit->client.focus_status = new_status;
2291  }
2292  if (new_status == FOCUS_DONE) {
2294  }
2295  }
2296 }
2297 
2303 void do_move_unit(struct unit *punit, struct unit *target_unit)
2304 {
2305  struct tile *src_tile = unit_tile(punit);
2306  struct tile *dst_tile = unit_tile(target_unit);
2307  bool was_teleported, do_animation;
2308  bool in_focus = unit_is_in_focus(punit);
2309 
2310  was_teleported = !is_tiles_adjacent(src_tile, dst_tile);
2311  do_animation = (!was_teleported && gui_options->smooth_move_unit_msec > 0);
2312 
2313  if (!was_teleported && punit->activity != ACTIVITY_SENTRY
2314  && !unit_transported(punit)) {
2315  audio_play_sound(unit_type_get(punit)->sound_move,
2316  unit_type_get(punit)->sound_move_alt);
2317  }
2318 
2319  if (unit_owner(punit) == client.conn.playing
2321  && punit->activity != ACTIVITY_GOTO
2322  && punit->activity != ACTIVITY_SENTRY
2324  && punit->ssa_controller != SSA_NONE)
2325  || (punit->ssa_controller == SSA_NONE))
2327  queen()->mapview_wdg->center_on_tile(dst_tile);
2328  }
2329 
2330  if (hover_state != HOVER_NONE && in_focus) {
2331  /* Cancel current goto/patrol/connect/nuke command. */
2334  }
2335 
2336  unit_list_remove(src_tile->units, punit);
2337 
2338  if (!unit_transported(punit)) {
2339  /* Mark the unit as moving unit, then find_visible_unit() won't return
2340  * it. It is especially useful to don't draw many times the unit when
2341  * refreshing the canvas. */
2342  punit_moving = punit;
2343 
2344  /* We have to refresh the tile before moving. This will draw
2345  * the tile without the unit (because it was unlinked above). */
2346  refresh_unit_mapcanvas(punit, src_tile, true);
2347 
2349  && punit->ssa_controller != SSA_NONE) {
2350  // Dont animate automatic units
2351  } else if (do_animation) {
2352  int dx, dy;
2353 
2354  /* For the duration of the animation the unit exists at neither
2355  * tile. */
2356  map_distance_vector(&dx, &dy, src_tile, dst_tile);
2357  move_unit_map_canvas(punit, src_tile, dx, dy);
2358  }
2359  }
2360 
2361  unit_tile_set(punit, dst_tile);
2362  unit_list_prepend(dst_tile->units, punit);
2363 
2364  if (!unit_transported(punit)) {
2365  // For find_visible_unit(), see above.
2366  punit_moving = nullptr;
2367 
2368  refresh_unit_mapcanvas(punit, dst_tile, true);
2369  }
2370 
2371  /* With the "full" city bar we have to update the city bar when units move
2372  * into or out of a city. For foreign cities this is handled separately,
2373  * via the occupied field of the short-city packet. */
2374  if (nullptr != tile_city(src_tile)
2376  tile_city(src_tile))) {
2378  }
2379  if (nullptr != tile_city(dst_tile)
2381  tile_city(dst_tile))) {
2383  }
2384 
2385  if (in_focus) {
2386  menus_update();
2387  }
2389 }
2390 
2395 static void do_unit_act_sel_vs(struct tile *ptile)
2396 {
2397  for (const auto punit : get_units_in_focus()) {
2398  if (utype_may_act_at_all(unit_type_get(punit))) {
2399  /* Have the server record that an action decision is wanted for
2400  * this unit against this tile. */
2401  dsend_packet_unit_sscs_set(&client.conn, punit->id, USSDT_QUEUE,
2402  tile_index(ptile));
2403  }
2404  }
2405 }
2406 
2410 void do_map_click(struct tile *ptile, enum quickselect_type qtype)
2411 {
2412  struct city *pcity = tile_city(ptile);
2413  const auto &units = get_units_in_focus();
2414  bool maybe_goto = false;
2415 
2416  if (hover_state != HOVER_NONE) {
2417  switch (hover_state) {
2418  case HOVER_NONE:
2419  break;
2420  case HOVER_GOTO:
2421  do_unit_goto(ptile);
2422  return;
2423  case HOVER_PARADROP:
2424  for (const auto punit : units) {
2425  do_unit_paradrop_to(punit, ptile);
2426  }
2427  break;
2428  case HOVER_CONNECT:
2430  break;
2431  case HOVER_PATROL:
2432  do_unit_patrol_to(ptile);
2433  break;
2434  case HOVER_ACT_SEL_TGT:
2435  do_unit_act_sel_vs(ptile);
2436  break;
2437  case HOVER_GOTO_SEL_TGT:
2439  do_unit_goto(ptile);
2440  break;
2441  case HOVER_DEBUG_TILE:
2442  // This function is called twice, once on mouse press and once on mouse
2443  // release. We get SELECT_POPUP the second time.
2444  // We don't want to do anything the first time we're called to avoid
2445  // selecting units or opening the tile dialog.
2446  if (qtype == SELECT_POPUP) {
2447  debug_tile(ptile);
2449  }
2450  return;
2451  }
2452 
2455  }
2456 
2457  auto near_pcity = is_any_city_dialog_open();
2458  int city_x, city_y;
2459  if (qtype == SELECT_FOCUS && near_pcity
2460  && !cma_is_city_under_agent(near_pcity, nullptr)
2462  && city_base_to_city_map(&city_x, &city_y, near_pcity, ptile)) {
2463  if (nullptr != tile_worked(ptile) && tile_worked(ptile) == near_pcity) {
2464  dsend_packet_city_make_specialist(&client.conn, near_pcity->id,
2465  ptile->index);
2466  } else if (city_can_work_tile(near_pcity, ptile)) {
2467  dsend_packet_city_make_worker(&client.conn, near_pcity->id,
2468  ptile->index);
2469  }
2470  city_workers_display = near_pcity;
2471  } else if (!near_pcity && qtype != SELECT_POPUP
2472  && qtype != SELECT_APPEND) {
2473  // Bypass stack or city popup if quickselect is specified.
2474  struct unit *qunit = quickselect(ptile, qtype);
2475 
2476  if (qunit) {
2478  maybe_goto = gui_options->keyboardless_goto;
2479  }
2480  } else if (qtype == SELECT_POPUP && nullptr != pcity
2481  && pcity->client.full) {
2482  // Otherwise use popups.
2483  popup_city_dialog(pcity);
2484  } else if (!near_pcity && unit_list_size(ptile->units) == 0
2485  && nullptr == pcity && get_num_units_in_focus() > 0) {
2486  maybe_goto = gui_options->keyboardless_goto;
2487  } else if (!near_pcity && unit_list_size(ptile->units) == 1
2488  && !get_transporter_occupancy(unit_list_get(ptile->units, 0))) {
2489  struct unit *punit = unit_list_get(ptile->units, 0);
2490 
2491  if (unit_owner(punit) == client.conn.playing) {
2492  if (can_unit_do_activity(punit, ACTIVITY_IDLE)) {
2493  maybe_goto = gui_options->keyboardless_goto;
2494  if (qtype == SELECT_APPEND) {
2495  unit_focus_add(punit);
2496  } else {
2498  }
2499  }
2500  } else if (pcity) {
2501  // Don't hide the unit in the city.
2502  unit_select_dialog_popup(ptile);
2503  }
2504  } else if (!near_pcity && unit_list_size(ptile->units) > 0) {
2505  /* The stack list is always popped up, even if it includes enemy units.
2506  * If the server doesn't want the player to know about them it shouldn't
2507  * tell him! The previous behavior would only pop up the stack if you
2508  * owned a unit on the tile. This gave cheating clients an advantage,
2509  * and also showed you allied units if (and only if) you had a unit on
2510  * the tile (inconsistent). */
2511  unit_select_dialog_popup(ptile);
2512  }
2513 
2514  // See mapctrl_common.c
2515  keyboardless_goto_start_tile = maybe_goto ? ptile : nullptr;
2516  keyboardless_goto_button_down = maybe_goto;
2517  keyboardless_goto_active = false;
2518 }
2519 
2525 static struct unit *quickselect(struct tile *ptile,
2526  enum quickselect_type qtype)
2527 {
2528  int listsize = unit_list_size(ptile->units);
2529  struct unit *panytransporter = nullptr, *panymovesea = nullptr,
2530  *panysea = nullptr, *panymoveland = nullptr,
2531  *panyland = nullptr, *panymoveunit = nullptr,
2532  *panyunit = nullptr;
2533 
2534  fc_assert_ret_val(qtype > SELECT_POPUP, nullptr);
2535 
2536  if (qtype == SELECT_FOCUS) {
2537  return head_of_units_in_focus();
2538  }
2539 
2540  if (listsize == 0) {
2541  return nullptr;
2542  } else if (listsize == 1) {
2543  struct unit *punit = unit_list_get(ptile->units, 0);
2544  return (unit_owner(punit) == client.conn.playing) ? punit : nullptr;
2545  }
2546 
2547  /* Quickselect priorities. Units with moves left
2548  * before exhausted. Focus unit is excluded.
2549  *
2550  * SEA: Transporter
2551  * Sea unit
2552  * Any unit
2553  *
2554  * LAND: Military land unit
2555  * Non-combatant
2556  * Sea unit
2557  * Any unit
2558  */
2559 
2560  unit_list_iterate(ptile->units, punit)
2561  {
2562  if (unit_owner(punit) != client.conn.playing
2563  || unit_is_in_focus(punit)) {
2564  continue;
2565  }
2566  if (qtype == SELECT_SEA) {
2567  // Transporter.
2568  if (get_transporter_capacity(punit)) {
2569  if (punit->moves_left > 0) {
2570  return punit;
2571  } else if (!panytransporter) {
2572  panytransporter = punit;
2573  }
2574  }
2575  // Any sea, pref. moves left.
2576  else if (utype_move_type(unit_type_get(punit)) == UMT_SEA) {
2577  if (punit->moves_left > 0) {
2578  if (!panymovesea) {
2579  panymovesea = punit;
2580  }
2581  } else if (!panysea) {
2582  panysea = punit;
2583  }
2584  }
2585  } else if (qtype == SELECT_LAND) {
2586  if (utype_move_type(unit_type_get(punit)) == UMT_LAND) {
2587  if (punit->moves_left > 0) {
2588  if (is_military_unit(punit)) {
2589  return punit;
2590  } else if (!panymoveland) {
2591  panymoveland = punit;
2592  }
2593  } else if (!panyland) {
2594  panyland = punit;
2595  }
2596  } else if (utype_move_type(unit_type_get(punit)) == UMT_SEA) {
2597  if (punit->moves_left > 0) {
2598  panymovesea = punit;
2599  } else {
2600  panysea = punit;
2601  }
2602  }
2603  }
2604  if (punit->moves_left > 0 && !panymoveunit) {
2605  panymoveunit = punit;
2606  }
2607  if (!panyunit) {
2608  panyunit = punit;
2609  }
2610  }
2612 
2613  if (qtype == SELECT_SEA) {
2614  if (panytransporter) {
2615  return panytransporter;
2616  } else if (panymovesea) {
2617  return panymovesea;
2618  } else if (panysea) {
2619  return panysea;
2620  } else if (panymoveunit) {
2621  return panymoveunit;
2622  } else if (panyunit) {
2623  return panyunit;
2624  }
2625  } else if (qtype == SELECT_LAND) {
2626  if (panymoveland) {
2627  return panymoveland;
2628  } else if (panyland) {
2629  return panyland;
2630  } else if (panymovesea) {
2631  return panymovesea;
2632  } else if (panysea) {
2633  return panysea;
2634  } else if (panymoveunit) {
2635  return panymoveunit;
2636  } else if (panyunit) {
2637  return panyunit;
2638  }
2639  }
2640  return nullptr;
2641 }
2642 
2647 void do_unit_goto(struct tile *ptile)
2648 {
2652 
2654  send_goto_route();
2655  return;
2656  }
2657 
2658  if (is_valid_goto_draw_line(ptile)) {
2659  send_goto_route();
2660  } else {
2661  create_event(ptile, E_BAD_COMMAND, ftc_client,
2662  _("Didn't find a route to the destination!"));
2663  }
2664 }
2665 
2669 void do_unit_paradrop_to(struct unit *punit, struct tile *ptile)
2670 {
2671  request_do_action(ACTION_PARADROP, punit->id, tile_index(ptile), 0, "");
2672 }
2673 
2677 void do_unit_patrol_to(struct tile *ptile)
2678 {
2679  if (is_valid_goto_draw_line(ptile)
2682  } else {
2683  create_event(ptile, E_BAD_COMMAND, ftc_client,
2684  _("Didn't find a route to the destination!"));
2685  }
2686 
2688 }
2689 
2693 void do_unit_connect(struct tile *ptile, enum unit_activity activity,
2694  struct extra_type *tgt)
2695 {
2696  if (is_valid_goto_draw_line(ptile)) {
2698  } else {
2699  create_event(ptile, E_BAD_COMMAND, ftc_client,
2700  _("Didn't find a route to the destination!"));
2701  }
2702 
2704 }
2705 
2710 {
2711  switch (hover_state) {
2712  case HOVER_GOTO_SEL_TGT:
2716  break;
2717  case HOVER_GOTO:
2718  case HOVER_PATROL:
2719  case HOVER_CONNECT:
2720  if (goto_pop_waypoint()) {
2721  break;
2722  }
2723  fc__fallthrough; // else fall through:
2724  case HOVER_PARADROP:
2725  case HOVER_ACT_SEL_TGT:
2728 
2730  keyboardless_goto_active = false;
2731  keyboardless_goto_start_tile = nullptr;
2732  break;
2733  case HOVER_DEBUG_TILE:
2735  break;
2736  case HOVER_NONE:
2737  break;
2738  };
2739 }
2740 
2746 {
2748 
2749  if (capital) {
2750  // Center on the tile, and pop up the crosshair overlay.
2753  } else {
2754  create_event(nullptr, E_BAD_COMMAND, ftc_client,
2755  _("Oh my! You seem to have no capital!"));
2756  }
2757 }
2758 
2763 
2768 {
2769  int i = 0;
2770 
2771  /* Could use unit_list_copy here instead. Just having safe genlists
2772  * wouldn't be sufficient since we don't want to skip units already
2773  * removed from focus... */
2775  {
2776  if (i == 0) {
2777  unit_focus_set(punit);
2778  } else {
2779  unit_focus_add(punit);
2780  }
2781  i++;
2782  }
2784 }
2785 
2790 void key_unit_move(enum direction8 gui_dir)
2791 {
2792  for (const auto punit : get_units_in_focus()) {
2793  enum direction8 map_dir = gui_to_map_dir(gui_dir);
2794 
2795  request_move_unit_direction(punit, map_dir);
2796  }
2797 }
2798 
2802 void key_unit_connect(enum unit_activity activity, struct extra_type *tgt)
2803 {
2804  request_unit_connect(activity, tgt);
2805 }
2806 
2811 {
2812  struct tile *ptile;
2813 
2814  if (!can_ask_server_for_actions()) {
2815  // Looks like another action selection dialog is open.
2816  return;
2817  }
2818 
2819  for (const auto punit : get_units_in_focus()) {
2820  ptile = unit_tile(punit);
2821  if (utype_may_act_at_all(unit_type_get(punit)) && ptile) {
2822  /* Have the server record that an action decision is wanted for this
2823  * unit. */
2824  dsend_packet_unit_sscs_set(&client.conn, punit->id, USSDT_QUEUE,
2825  tile_index(ptile));
2826  }
2827  }
2828 }
2829 
2838 {
2839  const auto &focus = get_units_in_focus();
2840 
2841  if (hover_state == HOVER_ACT_SEL_TGT) {
2842  /* The 2nd key press means that the actor should target its own
2843  * tile. */
2845 
2846  // Target tile selected. Clean up hover state.
2848  update_unit_info_label(focus);
2849 
2850  return;
2851  } else if (hover_state == HOVER_GOTO_SEL_TGT) {
2853 
2854  /* We don't support long range actions in the middle of orders yet so
2855  * send it at once. */
2856  send_goto_route();
2857 
2858  // Target tile selected. Clean up hover state.
2860  update_unit_info_label(focus);
2861 
2862  return;
2863  } else if (hover_state == HOVER_GOTO
2865  struct action *paction = action_by_number(goto_last_action);
2866 
2867  create_event(unit_tile(focus.front()), E_BEGINNER_HELP, ftc_client,
2868  // TRANS: Perform action inside a goto.
2869  _("Click on a tile to do %s against it."),
2870  qUtf8Printable(action_name_translation(paction)));
2871 
2874  goto_last_order);
2875 
2876  return;
2877  }
2878 
2879  create_event(unit_tile(focus.front()), E_BEGINNER_HELP, ftc_client,
2880  // TRANS: "Do..." action selection dialog target.
2881  _("Click on a tile to act against it. "
2882  "Press 'd' again to act against own tile."));
2883 
2884  set_hover_state(focus, HOVER_ACT_SEL_TGT, ACTIVITY_LAST, nullptr,
2886 }
2887 
2892 
2897 
2902 
2907 
2912 {
2913  struct unit *pnext_focus = nullptr, *plast;
2914 
2915  for (auto punit : get_units_in_focus()) {
2916  plast = request_unit_unload_all(punit);
2917  if (plast) {
2918  pnext_focus = plast;
2919  }
2920  }
2921 
2922  if (pnext_focus) {
2923  for (auto punit : get_units_in_focus()) {
2924  /* Unfocus the ships, and advance the focus to the last unloaded unit.
2925  * If there is no unit unloaded (which shouldn't happen, but could if
2926  * the caller doesn't check if the transporter is loaded), the we
2927  * don't do anything. */
2928  punit->client.focus_status = FOCUS_WAIT;
2929  }
2930  unit_focus_set(pnext_focus);
2931  }
2932 }
2933 
2938 
2943 {
2944  for (const auto punit : get_units_in_focus()) {
2945  request_unit_wakeup(punit);
2946  }
2947 }
2948 
2953 {
2954  for (const auto punit : get_units_in_focus()) {
2955  struct base_type *pbase =
2956  get_base_by_gui_type(BASE_GUI_AIRBASE, punit, unit_tile(punit));
2957 
2958  if (pbase) {
2959  struct extra_type *pextra = base_extra_get(pbase);
2960 
2961  request_new_unit_activity_targeted(punit, ACTIVITY_BASE, pextra);
2962  }
2963  }
2964 }
2965 
2970 {
2971  for (const auto punit : get_units_in_focus()) {
2972  if (can_unit_do_activity(punit, ACTIVITY_EXPLORE)) {
2973  request_unit_ssa_set(punit, SSA_AUTOEXPLORE);
2974  }
2975  }
2976 }
2977 
2983 {
2984  for (const auto punit : get_units_in_focus()) {
2985  if (can_unit_do_autosettlers(punit)) {
2987  }
2988  }
2989 }
2990 
2995 {
2996  for (const auto punit : get_units_in_focus()) {
2997  request_unit_convert(punit);
2998  }
2999 }
3000 
3005 {
3006  key_unit_clean(ACTIVITY_FALLOUT, ERM_CLEANFALLOUT);
3007 }
3008 
3013 {
3014  for (const auto punit : get_units_in_focus()) {
3015  if (can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
3016  request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
3017  }
3018  }
3019 }
3020 
3025 {
3026  for (const auto punit : get_units_in_focus()) {
3027  struct base_type *pbase =
3028  get_base_by_gui_type(BASE_GUI_FORTRESS, punit, unit_tile(punit));
3029 
3030  if (pbase) {
3031  struct extra_type *pextra = base_extra_get(pbase);
3032 
3033  request_new_unit_activity_targeted(punit, ACTIVITY_BASE, pextra);
3034  }
3035  }
3036 }
3037 
3042 {
3043  for (const auto punit : get_units_in_focus()) {
3045  }
3046 }
3047 
3051 static void key_unit_extra(enum unit_activity act, enum extra_cause cause)
3052 {
3053  for (const auto punit : get_units_in_focus()) {
3054  struct extra_type *tgt = next_extra_for_tile(unit_tile(punit), cause,
3055  unit_owner(punit), punit);
3056 
3057  if (can_unit_do_activity_targeted(punit, act, tgt)) {
3058  request_new_unit_activity_targeted(punit, act, tgt);
3059  }
3060  }
3061 }
3062 
3066 static void key_unit_clean(enum unit_activity act,
3067  enum extra_rmcause rmcause)
3068 {
3069  for (const auto punit : get_units_in_focus()) {
3070  struct extra_type *tgt = prev_extra_in_tile(unit_tile(punit), rmcause,
3071  unit_owner(punit), punit);
3072 
3073  if (tgt != nullptr && can_unit_do_activity_targeted(punit, act, tgt)) {
3074  request_new_unit_activity_targeted(punit, act, tgt);
3075  }
3076  }
3077 }
3078 
3083 {
3084  key_unit_extra(ACTIVITY_IRRIGATE, EC_IRRIGATION);
3085 }
3086 
3091 {
3092  for (const auto punit : get_units_in_focus()) {
3093  if (can_unit_do_activity(punit, ACTIVITY_CULTIVATE)) {
3094  request_new_unit_activity(punit, ACTIVITY_CULTIVATE);
3095  }
3096  }
3097 }
3098 
3102 void key_unit_mine() { key_unit_extra(ACTIVITY_MINE, EC_MINE); }
3103 
3108 {
3109  for (const auto punit : get_units_in_focus()) {
3110  if (can_unit_do_activity(punit, ACTIVITY_PLANT)) {
3111  request_new_unit_activity(punit, ACTIVITY_PLANT);
3112  }
3113  }
3114 }
3115 
3120 {
3121  for (const auto punit : get_units_in_focus()) {
3122  if (can_unit_do_activity(punit, ACTIVITY_PILLAGE)) {
3123  request_unit_pillage(punit);
3124  }
3125  }
3126 }
3127 
3132 {
3133  for (const auto punit : get_units_in_focus()) {
3134  if (can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
3135  request_new_unit_activity(punit, ACTIVITY_SENTRY);
3136  }
3137  }
3138 }
3139 
3144 {
3145  for (const auto punit : get_units_in_focus()) {
3146  if (can_unit_do_activity(punit, ACTIVITY_TRANSFORM)) {
3147  request_new_unit_activity(punit, ACTIVITY_TRANSFORM);
3148  }
3149  }
3150 }
3151 
3156 
3161 
3166 
3171 
3176 
3181 
3187 
3193 
3198 
3204 
3208 void finish_city(struct tile *ptile, const char *name)
3209 {
3210  unit_list_iterate(ptile->units, punit)
3211  {
3212  if (punit->client.asking_city_name) {
3213  /* Unit will disappear only in case city building still success.
3214  * Cancel city building status just in case something has changed
3215  * to prevent city building in the meanwhile and unit will remain
3216  * alive. */
3217  punit->client.asking_city_name = false;
3218  request_do_action(ACTION_FOUND_CITY, punit->id, ptile->index, 0, name);
3219  }
3220  }
3222 }
3223 
3228 void cancel_city(struct tile *ptile)
3229 {
3230  unit_list_iterate(ptile->units, punit)
3231  {
3232  punit->client.asking_city_name = false;
3233  }
3235 }
struct act_prob action_prob_self(const struct unit *actor_unit, const action_id act_id)
Get the actor unit's probability of successfully performing the chosen action on itself.
Definition: actions.cpp:5145
bool action_prob_possible(const struct act_prob probability)
Returns TRUE iff the given action probability belongs to an action that may be possible.
Definition: actions.cpp:5380
struct act_prob action_prob_vs_city(const struct unit *actor_unit, const action_id act_id, const struct city *target_city)
Get the actor unit's probability of successfully performing the chosen action on the target city.
Definition: actions.cpp:4809
struct act_prob action_prob_vs_unit(const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Get the actor unit's probability of successfully performing the chosen action on the target unit.
Definition: actions.cpp:4871
struct act_prob action_prob_vs_tile(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Get the actor unit's probability of successfully performing the chosen action on the target tile.
Definition: actions.cpp:5090
struct act_prob action_prob_vs_units(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Get the actor unit's probability of successfully performing the chosen action on all units at the tar...
Definition: actions.cpp:5029
const QString action_name_translation(const struct action *action)
Get the action name used when displaying the action in the UI.
Definition: actions.cpp:1353
const QString action_id_name_translation(action_id act_id)
Get the action name used when displaying the action in the UI.
Definition: actions.cpp:1373
struct action * action_by_number(action_id act_id)
Return the action with the given id.
Definition: actions.cpp:1149
bool action_id_exists(const action_id act_id)
Returns TRUE iff the specified action ID refers to a valid action.
Definition: actions.cpp:1138
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
Definition: actions.h:754
#define action_id_get_role(act_id)
Definition: actions.h:580
#define action_id_get_target_kind(act_id)
Definition: actions.h:522
#define action_id_has_result_safe(act_id, result)
Definition: actions.h:537
#define ACTION_NONE
Definition: actions.h:220
void audio_play_sound(const QString &tag, const QString &alt_tag)
Play an audio sample as suggested by sound tags.
Definition: audio.cpp:494
struct extra_type * base_extra_get(const struct base_type *pbase)
Return extra that base is.
Definition: base.cpp:144
struct base_type * get_base_by_gui_type(enum base_gui_type type, const struct unit *punit, const struct tile *ptile)
Get best gui_type base for given parameters.
Definition: base.cpp:175
#define BV_CLR_ALL(bv)
Definition: bitvector.h:62
#define BV_SET(bv, bit)
Definition: bitvector.h:44
struct city * is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Is there an enemy city on this tile?
Definition: city.cpp:1923
bool city_base_to_city_map(int *city_map_x, int *city_map_y, const struct city *const pcity, const struct tile *map_tile)
Finds the city map coordinate for a given map position and a city.
Definition: city.cpp:274
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Returns TRUE when a tile is available to be worked, or the city itself is currently working the tile ...
Definition: city.cpp:1392
struct city * is_any_city_dialog_open()
Definition: citydlg.cpp:2315
void refresh_unit_city_dialogs(struct unit *punit)
Update city dialogs when the given unit's status changes.
Definition: citydlg.cpp:2304
void popup_city_dialog(struct city *pcity)
A path finding destination that accepts any allied city.
Definition: path_finder.h:202
A path is a succession of moves and actions to go from one location to another.
Definition: path_finder.h:55
void center_on_tile(tile *tile, bool animate=true)
Centers the view on a tile.
Definition: view_map.cpp:197
map_view * mapview_wdg
Definition: page_game.h:81
static update_queue * uq()
void connect_processing_finished_full(int request_id, uq_callback_t cb, void *data, uq_free_fn_t free_func)
enum client_states client_state()
Return current client state.
bool is_server_busy()
Returns if server is considered busy at the moment.
struct player * client_player()
Either controlling or observing.
struct civclient client
bool can_client_issue_orders()
Returns TRUE iff the client can issue orders (such as giving unit commands).
void send_turn_done()
Send information about player having finished his/her turn to server.
bool can_client_change_view()
Return TRUE if the client can change the view; i.e.
@ C_S_RUNNING
Definition: client_main.h:43
enum direction8 gui_to_map_dir(enum direction8 gui_dir)
Convert the given GUI direction into a map direction.
Definition: climap.cpp:50
void create_event(struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Creates a struct packet_generic_message packet and injects it via handle_chat_msg.
Definition: climisc.cpp:952
void flush_dirty_overview()
This module contains various general - mostly highlevel - functions used throughout the client.
bool can_units_do_connect(const std::vector< unit * > &units, enum unit_activity activity, struct extra_type *tgt)
Returns TRUE if any of the units can do the connect activity.
Definition: climisc.cpp:1056
static bool can_ask_server_for_actions()
Returns TRUE iff it is OK to ask the server about what actions a unit can perform.
Definition: control.cpp:331
void request_toggle_city_productions()
Toggle display of city productions.
Definition: control.cpp:2215
void request_unit_airlift(struct unit *punit, struct city *pcity)
Send unit airlift request to server.
Definition: control.cpp:1397
void do_move_unit(struct unit *punit, struct unit *target_unit)
Called to have the client move a unit from one location to another, updating the graphics if necessar...
Definition: control.cpp:2303
void request_unit_non_action_move(struct unit *punit, struct tile *dest_tile)
Order a unit to move to a neighboring tile without performing an action.
Definition: control.cpp:1618
void request_toggle_city_output()
Toggle display of worker output of cities on the map.
Definition: control.cpp:2137
void key_unit_plant()
Handle user 'plant' input.
Definition: control.cpp:3107
bool unit_is_in_focus(const struct unit *punit)
Return TRUE iff this unit is in focus.
Definition: control.cpp:364
std::vector< unit * > & get_units_in_focus()
Returns list of units currently in focus.
Definition: control.cpp:169
void key_unit_paradrop()
Handle user 'paradrop' input.
Definition: control.cpp:2901
void key_unit_goto()
Handle user 'unit goto' input.
Definition: control.cpp:2896
void request_units_wait(const std::vector< unit * > &units)
Set units in list to waiting focus and advance focus.
Definition: control.cpp:2266
void key_unit_homecity()
Handle user 'change homecity' input.
Definition: control.cpp:3041
void request_unit_fortify(struct unit *punit)
Try to fortify unit.
Definition: control.cpp:2077
void request_unit_caravan_action(struct unit *punit, action_id action)
Send request to do caravan action - establishing traderoute or helping in wonder building - to server...
Definition: control.cpp:1988
void action_selection_no_longer_in_progress(const int old_actor_id)
The action selection process is no longer in progres for the specified unit.
Definition: control.cpp:924
enum unit_orders goto_last_order
Definition: control.cpp:89
void request_unit_wakeup(struct unit *punit)
(RP:) un-sentry all my own sentried units on punit's tile
Definition: control.cpp:1476
void key_city_names_toggle()
Handle user 'toggle city names display' input.
Definition: control.cpp:3180
void action_decision_request(struct unit *actor_unit)
Request that the player makes a decision for the specified unit.
Definition: control.cpp:976
void key_unit_fallout()
Handle user 'clean fallout' input.
Definition: control.cpp:3004
void key_unit_mine()
Handle user 'build mine' input.
Definition: control.cpp:3102
void key_unit_done()
Handle user 'unit done' input.
Definition: control.cpp:2891
void set_units_in_combat(struct unit *pattacker, struct unit *pdefender)
Adjusts way combatants are displayed suitable for combat.
Definition: control.cpp:905
int check_recursive_road_connect(struct tile *ptile, const struct extra_type *pextra, const struct unit *punit, const struct player *pplayer, int rec)
Fill orders to build recursive roads.
Definition: control.cpp:1188
void request_toggle_city_trade_routes()
Toggle display of city trade routes.
Definition: control.cpp:2241
void request_toggle_map_grid()
Toggle display of grid lines on the map.
Definition: control.cpp:2150
static int action_selection_in_progress_for
Definition: control.cpp:112
static void do_disband_alternative(void *p)
Try to disband a unit using actions ordered by preference.
Definition: control.cpp:1755
void key_unit_wait()
Handle user 'wait' input.
Definition: control.cpp:2937
void unit_focus_update()
If there is no unit currently in focus, or if the current unit in focus should not be in focus,...
Definition: control.cpp:718
unit * find_visible_unit(const ::tile *ptile)
Return a pointer to a visible unit, if there is one.
Definition: control.cpp:749
void key_unit_connect(enum unit_activity activity, struct extra_type *tgt)
Handle user pressing key for 'Connect' command.
Definition: control.cpp:2802
void request_unit_load(struct unit *pcargo, struct unit *ptrans, struct tile *ptile)
Send a request to the server that the cargo be loaded into the transporter.
Definition: control.cpp:1934
void do_map_click(struct tile *ptile, enum quickselect_type qtype)
Handles everything when the user clicked a tile.
Definition: control.cpp:2410
static void key_unit_extra(enum unit_activity act, enum extra_cause cause)
Handle user extra building input of given type.
Definition: control.cpp:3051
void key_unit_auto_settle()
Call to request (from the server) that the focus unit is put into autosettler mode.
Definition: control.cpp:2982
void control_init()
Called only by client_game_init() in client/client_main.c.
Definition: control.cpp:131
static struct unit * punit_attacking
Definition: control.cpp:98
void key_unit_irrigate()
Handle user 'irrigate' input.
Definition: control.cpp:3082
void unit_focus_add(struct unit *punit)
Adds this unit to the list of units in focus.
Definition: control.cpp:534
void key_city_trade_routes_toggle()
Handle client request to toggle drawing of trade route information by the city name for cities visibl...
Definition: control.cpp:3203
void key_unit_wakeup_others()
Handle user 'wakeup others' input.
Definition: control.cpp:2942
void unit_focus_set(struct unit *punit)
Sets the focus unit directly.
Definition: control.cpp:479
struct unit * request_unit_unload_all(struct unit *punit)
Returns one of the unit of the transporter which can have focus next.
Definition: control.cpp:1364
static void do_unit_act_sel_vs(struct tile *ptile)
An action selection dialog for the selected units against the specified tile is wanted.
Definition: control.cpp:2395
void request_unit_goto(enum unit_orders last_order, action_id act_id, int sub_tgt_id)
Do a goto with an order at the end (or ORDER_LAST).
Definition: control.cpp:995
void key_center_capital()
Center the mapview on the player's named capital, or print a failure message.
Definition: control.cpp:2745
void do_unit_paradrop_to(struct unit *punit, struct tile *ptile)
Paradrop to a location.
Definition: control.cpp:2669
bool should_ask_server_for_actions(const struct unit *punit)
Returns TRUE iff the client should ask the server about what actions a unit can perform.
Definition: control.cpp:318
int goto_last_tgt
Definition: control.cpp:87
struct extra_type * connect_tgt
Definition: control.cpp:84
void request_do_action(action_id action, int actor_id, int target_id, int sub_tgt, const char *name)
Request an actor unit to do a specific action.
Definition: control.cpp:1563
void key_map_native_toggle()
Toggle native tiles on the mapview on/off based on a keypress.
Definition: control.cpp:3175
void request_unit_disband(struct unit *punit)
Send request to disband unit to server.
Definition: control.cpp:1853
static struct unit_list * previous_focus
Definition: control.cpp:76
void request_unit_autosettlers(const struct unit *punit)
Call to request (from the server) that the settler unit is put into autosettler mode.
Definition: control.cpp:1918
void request_unit_pillage(struct unit *punit)
Send pillage request to server.
Definition: control.cpp:2088
void unit_focus_urgent(struct unit *punit)
Store a priority focus unit.
Definition: control.cpp:193
bool can_unit_do_connect(struct unit *punit, enum unit_activity activity, struct extra_type *tgt)
Return whether the unit can connect with given activity (or with any activity if activity arg is set ...
Definition: control.cpp:1270
void request_unit_change_homecity(struct unit *punit)
Send request to change unit homecity to server.
Definition: control.cpp:1872
void request_unit_patrol()
Either start new patrol route planning, or add waypoint to current one.
Definition: control.cpp:2043
void key_unit_transform()
Handle user 'transform unit' input.
Definition: control.cpp:3143
void request_unit_move_done()
Set focus units to FOCUS_DONE state.
Definition: control.cpp:2277
void request_toggle_map_native()
Toggle display of native tiles on the map.
Definition: control.cpp:2176
void key_unit_unload_all()
Handle user 'unload all' input.
Definition: control.cpp:2911
void request_unit_unload(struct unit *pcargo)
Send a request to the server that the cargo be unloaded from its current transporter.
Definition: control.cpp:1962
void key_unit_sentry()
Handle user 'sentry' input.
Definition: control.cpp:3131
static auto current_focus
Definition: control.cpp:72
static void client_disband_unit_data_destroy(void *p)
Destroy the client disband unit data.
Definition: control.cpp:1744
void request_unit_ssa_set(const struct unit *punit, enum server_side_agent agent)
Call to request (from the server) that the unit is put under the control of the specified server side...
Definition: control.cpp:1906
void request_action_details(action_id action, int actor_id, int target_id)
Request data for follow up questions about an action the unit can perform.
Definition: control.cpp:1582
static struct unit * quickselect(struct tile *ptile, enum quickselect_type qtype)
Quickselecting a unit is normally done with [control] left, right click, for the current tile.
Definition: control.cpp:2525
void request_unit_paradrop(const std::vector< unit * > &units)
Have the player select what tile to paradrop to.
Definition: control.cpp:2009
enum unit_activity connect_activity
Definition: control.cpp:83
void request_toggle_city_growth()
Toggle display of city growth (turns-to-grow)
Definition: control.cpp:2202
void request_new_unit_activity_targeted(struct unit *punit, enum unit_activity act, struct extra_type *tgt)
Send request for unit activity changing to server.
Definition: control.cpp:1721
void key_city_productions_toggle()
Handle user 'toggle city production display' input.
Definition: control.cpp:3197
void set_auto_center_enabled(bool enabled)
Allows disabling automatic map recentering.
Definition: control.cpp:417
void request_unit_build_city(struct unit *punit)
Player pressed 'b' or otherwise instructed unit to build or add to city.
Definition: control.cpp:1599
void unit_change_battlegroup(struct unit *punit, int battlegroup)
Change the battlegroup for this unit.
Definition: control.cpp:237
void key_unit_auto_explore()
Handle user 'autoexplore' input.
Definition: control.cpp:2969
static struct unit_list * urgent_focus_queue
Definition: control.cpp:79
void key_map_grid_toggle()
Handle user 'toggle map grid' input.
Definition: control.cpp:3165
void key_cancel_action()
The 'Escape' key.
Definition: control.cpp:2709
void key_city_buycost_toggle()
Toggles the showing of the buy cost of the current production in the city descriptions.
Definition: control.cpp:3192
void key_unit_convert()
Unit convert key pressed or respective menu entry selected.
Definition: control.cpp:2994
void control_free()
Called only by client_game_free() in client/client_main.c.
Definition: control.cpp:147
void key_unit_move(enum direction8 gui_dir)
Move the focus unit in the given direction.
Definition: control.cpp:2790
static int disband_unit_alternatives[3]
Definition: control.cpp:65
void request_unit_select(const std::vector< unit * > &punits, enum unit_select_type_mode seltype, enum unit_select_location_mode selloc)
Select all units based on the given list of units and the selection modes.
Definition: control.cpp:1484
void key_unit_action_select()
Handle user 'Do...' input.
Definition: control.cpp:2810
int get_num_units_in_focus()
Return the number of units currently in focus (0 or more).
Definition: control.cpp:174
void key_recall_previous_focus_unit()
Recall the previous focus unit(s).
Definition: control.cpp:2767
void request_center_focus_unit()
Center to focus unit.
Definition: control.cpp:2254
void key_unit_patrol()
Handle user 'patrol' input.
Definition: control.cpp:2906
void key_city_output_toggle()
Toggle drawing of city output produced by workers of the city.
Definition: control.cpp:3160
int blink_turn_done_button()
Blink the turn done button (if necessary).
Definition: control.cpp:857
void request_unit_sentry(struct unit *punit)
Try to sentry unit.
Definition: control.cpp:2066
bool non_ai_unit_focus
Definition: control.cpp:118
static struct unit * punit_defending
Definition: control.cpp:99
static bool can_units_attack_at(const std::vector< unit * > &units, const struct tile *ptile)
Return TRUE if at least one of the units can do an attack at the tile.
Definition: control.cpp:1054
void key_unit_fortify()
Handle user 'fortify' input.
Definition: control.cpp:3012
enum cursor_hover_state hover_state
Definition: control.cpp:82
void request_unit_connect(enum unit_activity activity, struct extra_type *tgt)
Prompt player for entering destination point for unit connect (e.g.
Definition: control.cpp:1336
void clear_unit_orders(struct unit *punit)
Clear all orders for the given unit.
Definition: control.cpp:454
static void key_unit_clean(enum unit_activity act, enum extra_rmcause rmcause)
Handle user extra cleaning input of given type.
Definition: control.cpp:3066
void key_unit_cultivate()
Handle user 'cultivate' input.
Definition: control.cpp:3090
void action_decision_clear_want(const int old_actor_id)
Have the server record that a decision no longer is wanted for the specified unit.
Definition: control.cpp:944
void do_unit_connect(struct tile *ptile, enum unit_activity activity, struct extra_type *tgt)
"Connect" to the given location.
Definition: control.cpp:2693
int goto_last_sub_tgt
Definition: control.cpp:88
struct unit * get_focus_unit_on_tile(const struct tile *ptile)
Return TRUE iff a unit on this tile is in focus.
Definition: control.cpp:373
void key_end_turn()
Handle user 'end turn' input.
Definition: control.cpp:2762
void do_unit_patrol_to(struct tile *ptile)
Patrol to a location.
Definition: control.cpp:2677
void request_toggle_city_buycost()
Toggle display of city buycost.
Definition: control.cpp:2228
void finish_city(struct tile *ptile, const char *name)
All units ready to build city to the tile should now proceed.
Definition: control.cpp:3208
static struct unit * punit_moving
Definition: control.cpp:95
static bool is_activity_on_tile(struct tile *ptile, enum unit_activity activity)
Return TRUE if there are any units doing the activity on the tile.
Definition: control.cpp:1170
static bool can_be_irrigated(const struct tile *ptile, const struct unit *punit)
Can tile be irrigated by given unit? Unit can be nullptr to check if any settler type unit of any pla...
Definition: control.cpp:1244
void key_city_outlines_toggle()
Toggle drawing of city outlines.
Definition: control.cpp:3155
void set_hover_state(const std::vector< unit * > &units, enum cursor_hover_state state, enum unit_activity activity, struct extra_type *tgt, int last_tgt, int last_sub_tgt, action_id action, enum unit_orders order)
Enter the given hover state.
Definition: control.cpp:272
static struct unit_list * battlegroups[MAX_NUM_BATTLEGROUPS]
Definition: control.cpp:92
void unit_focus_advance()
This function may be called from packhand.c, via unit_focus_update(), as a result of packets indicati...
Definition: control.cpp:617
void key_unit_action_select_tgt()
Have the user select what action the unit(s) in focus should perform to the targets at the tile the u...
Definition: control.cpp:2837
void request_move_unit_direction(struct unit *punit, int dir)
This function is called whenever the player pressed an arrow key.
Definition: control.cpp:1660
static void current_focus_append(struct unit *punit)
Add unit to list of units currently in focus.
Definition: control.cpp:435
void request_toggle_city_outlines()
Toggle display of city outlines on the map.
Definition: control.cpp:2124
static struct tile * find_a_focus_unit_tile_to_center_on()
Finds a single focus unit that we can center on.
Definition: control.cpp:396
static struct tile * hover_tile
Definition: control.cpp:91
void unit_focus_set_and_select(struct unit *punit)
The only difference is that here we draw the "cross".
Definition: control.cpp:563
void request_unit_convert(struct unit *punit)
Sends unit convert packet.
Definition: control.cpp:1896
void clear_hover_state()
Clear current hover state (go to HOVER_NONE).
Definition: control.cpp:308
void unit_register_battlegroup(struct unit *punit)
Call this on new units to enter them in the battlegroup lists.
Definition: control.cpp:257
void request_units_return()
Return-and-recover for a particular unit.
Definition: control.cpp:1406
static void focus_units_changed()
Do various updates required when the set of units in focus changes.
Definition: control.cpp:201
void control_mouse_cursor(struct tile *ptile)
Determines which mouse cursor should be used, according to hover_state, and the information gathered ...
Definition: control.cpp:1067
void request_toggle_map_borders()
Toggle display of national borders on the map.
Definition: control.cpp:2163
void wakeup_sentried_units(struct tile *ptile)
Wakes all owned sentried units on tile.
Definition: control.cpp:1458
void auto_center_on_focus_unit()
Center on the focus unit, if off-screen and auto_center_on_unit is true.
Definition: control.cpp:422
void key_unit_pillage()
Handle user 'pillage' input.
Definition: control.cpp:3119
void key_unit_fortress()
Handle user 'build base of class fortress' input.
Definition: control.cpp:3024
static void store_previous_focus()
Store the focus unit(s).
Definition: control.cpp:180
void request_unit_upgrade(struct unit *punit)
Send request to upgrade unit to server.
Definition: control.cpp:1884
void control_unit_killed(struct unit *punit)
Called when a unit is killed; this removes it from the control lists.
Definition: control.cpp:212
void request_toggle_city_names()
Toggle display of city names.
Definition: control.cpp:2189
void cancel_city(struct tile *ptile)
Do not build city after all.
Definition: control.cpp:3228
static void ask_server_for_actions(struct unit *punit)
Ask the server about what actions punit may be able to perform against it's stored target tile.
Definition: control.cpp:345
struct unit * head_of_units_in_focus()
Return head of focus units list.
Definition: control.cpp:387
void request_new_unit_activity(struct unit *punit, enum unit_activity act)
Send request for unit activity changing to server.
Definition: control.cpp:1712
static struct unit * find_best_focus_candidate(bool accept_current)
Find the nearest available unit for focus, excluding any current unit in focus unless "accept_current...
Definition: control.cpp:577
action_id goto_last_action
Definition: control.cpp:86
void key_map_borders_toggle()
Toggle map borders on the mapview on/off based on a keypress.
Definition: control.cpp:3170
void do_unit_goto(struct tile *ptile)
Finish the goto mode and let the units stored in goto_map_list move to a given location.
Definition: control.cpp:2647
void key_city_growth_toggle()
Toggles the "show city growth turns" option by passing off the request to another function....
Definition: control.cpp:3186
void action_selection_next_in_focus(const int old_actor_id)
Move on to the next unit in focus that needs an action decision.
Definition: control.cpp:958
void key_unit_airbase()
Handle user 'build base of class airbase' input.
Definition: control.cpp:2952
int blink_active_unit()
Blink the active unit (if necessary).
Definition: control.cpp:827
unit_select_location_mode
Definition: control.h:116
@ SELLOC_CONT
Definition: control.h:118
@ SELLOC_TILE
Definition: control.h:117
quickselect_type
Definition: control.h:30
@ SELECT_LAND
Definition: control.h:33
@ SELECT_APPEND
Definition: control.h:34
@ SELECT_SEA
Definition: control.h:32
@ SELECT_POPUP
Definition: control.h:31
@ SELECT_FOCUS
Definition: control.h:35
cursor_hover_state
Definition: control.h:18
@ HOVER_GOTO
Definition: control.h:20
@ HOVER_PARADROP
Definition: control.h:21
@ HOVER_ACT_SEL_TGT
Definition: control.h:24
@ HOVER_NONE
Definition: control.h:19
@ HOVER_CONNECT
Definition: control.h:22
@ HOVER_DEBUG_TILE
Definition: control.h:26
@ HOVER_PATROL
Definition: control.h:23
@ HOVER_GOTO_SEL_TGT
Definition: control.h:25
unit_select_type_mode
Definition: control.h:114
@ SELTYPE_SINGLE
Definition: control.h:114
@ SELTYPE_SAME
Definition: control.h:114
int action_selection_actor_unit(void)
Returns the id of the actor unit currently handled in action selection dialog when the action selecti...
Definition: dialogs.cpp:3528
void unit_select_dialog_popup(struct tile *ptile)
Popup a dialog window to select units on a particular tile.
Definition: dialogs.cpp:1022
void action_selection_close(void)
Closes the action selection dialog.
Definition: dialogs.cpp:3740
void action_selection_no_longer_in_progress_gui_specific(int actor_id)
Let the non shared client code know that the action selection process no longer is in progress for th...
Definition: dialogs.cpp:1697
void popup_pillage_dialog(struct unit *punit, bv_extras extras)
Popup a dialog asking the unit which improvement they would like to pillage.
Definition: dialogs.cpp:3321
bool request_transport(struct unit *pcargo, struct tile *ptile)
Unit wants to get into some transport on given tile.
Definition: dialogs.cpp:3827
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Returns prev extra by cause that unit or player can remove from tile.
Definition: extras.cpp:732
bool can_build_extra(const struct extra_type *pextra, const struct unit *punit, const struct tile *ptile)
Tells if unit can build extra on tile.
Definition: extras.cpp:475
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Returns next extra by cause that unit or player can build to tile.
Definition: extras.cpp:687
#define extra_type_iterate(_p)
Definition: extras.h:279
#define extra_deps_iterate(_reqs, _dep)
Definition: extras.h:335
#define extra_type_iterate_end
Definition: extras.h:285
#define is_extra_caused_by(e, c)
Definition: extras.h:182
#define extra_index(_e_)
Definition: extras.h:163
#define extra_deps_iterate_end
Definition: extras.h:343
#define EXTRA_NONE
Definition: extras.h:72
#define extra_road_get(_e_)
Definition: extras.h:171
#define NO_TARGET
Definition: fc_types.h:271
@ RPT_POSSIBLE
Definition: fc_types.h:567
#define DIR8_ORIGIN
Definition: fc_types.h:372
int action_id
Definition: fc_types.h:306
#define MAX_EXTRA_TYPES
Definition: fc_types.h:42
#define IDENTITY_NUMBER_ZERO
Definition: fc_types.h:76
#define _(String)
Definition: fcintl.h:50
const struct ft_color ftc_client
struct unit * game_unit_by_number(int id)
Find unit out of all units in game: now uses fast idex method, instead of looking through all units o...
Definition: game.cpp:112
struct civ_game game
Definition: game.cpp:47
bool is_player_phase(const struct player *pplayer, int phase)
Return TRUE if it is this player's phase.
Definition: game.cpp:672
struct world wld
Definition: game.cpp:48
bool goto_pop_waypoint()
Returns whether there were any waypoint popped (we don't remove the initial position)
Definition: goto.cpp:126
void send_patrol_route()
Send the current patrol route (i.e., the one generated via HOVER_STATE) to the server.
Definition: goto.cpp:718
void enter_goto_state(const std::vector< unit * > &units)
Enter the goto state: activate, prepare PF-template and add the initial part.
Definition: goto.cpp:247
bool goto_is_active()
Is goto state active?
Definition: goto.cpp:302
void send_goto_route()
Send the current goto route (i.e., the one generated via HOVER_STATE) to the server.
Definition: goto.cpp:836
void goto_add_waypoint()
Inserts a waypoint at the end of the current goto line.
Definition: goto.cpp:104
bool is_valid_goto_draw_line(struct tile *dest_tile)
Puts a line to dest_tile on the map according to the current goto_map.
Definition: goto.cpp:383
bool can_unit_move_now(const struct unit *punit)
Returns if unit can move now.
Definition: goto.cpp:56
void send_connect_route(enum unit_activity activity, struct extra_type *tgt)
Send the current connect route (i.e., the one generated via HOVER_STATE) to the server.
Definition: goto.cpp:724
void goto_unit_killed(struct unit *punit)
Called from control_unit_killed() in client/control.c.
Definition: goto.cpp:284
bool is_valid_goto_destination(const struct tile *ptile)
Determines if a goto to the destination tile is allowed.
Definition: goto.cpp:96
void exit_goto_state()
Tidy up and deactivate goto state.
Definition: goto.cpp:269
void request_orders_cleared(struct unit *punit)
Send a packet to the server to request that the current orders be cleared.
Definition: goto.cpp:442
void free_client_goto()
Called above, and by control_done() in client/control.c.
Definition: goto.cpp:87
bool cma_is_city_under_agent(const struct city *pcity, struct cm_parameter *parameter)
Check whether city is under governor control, and fill parameter if it is.
Definition: governor.cpp:632
void real_focus_units_changed()
Called when the set of units in focus (get_units_in_focus()) changes.
Definition: gui_main.cpp:155
const char * name
Definition: inputfile.cpp:118
#define fc_assert_msg(condition, message,...)
Definition: log.h:96
#define fc_assert_ret(condition)
Definition: log.h:112
#define fc_assert(condition)
Definition: log.h:89
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
int get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile)
Return the direction which is needed for a step on the map from (start_x, start_y) to (end_x,...
Definition: map.cpp:1288
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Are two tiles adjacent to each other.
Definition: map.cpp:878
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Are (x1,y1) and (x2,y2) really the same when adjusted? This function might be necessary ALOT of place...
Definition: map.cpp:887
void map_distance_vector(int *dx, int *dy, const struct tile *tile0, const struct tile *tile1)
Topology function to find the vector which has the minimum "real" distance between the map positions ...
Definition: map.cpp:1012
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Step from the given tile in the given direction.
Definition: map.cpp:342
#define iterate_outward(nmap, start_tile, max_dist, itr_tile)
Definition: map.h:288
#define iterate_outward_end
Definition: map.h:291
struct city * city_workers_display
bool keyboardless_goto_button_down
bool keyboardless_goto_active
struct tile * keyboardless_goto_start_tile
void create_line_at_mouse_pos()
Draw a goto or patrol line at the current mouse position.
Definition: mapctrl.cpp:68
void debug_tile(tile *t)
Callback to set the tile being debugged.
Definition: view_map.cpp:757
void update_turn_done_button(bool do_restore)
If do_restore is false it should change the turn button style (to draw the user's attention to it).
Definition: view_map.cpp:468
void put_cross_overlay_tile(struct tile *ptile)
Draw a cross-hair overlay on a tile.
Definition: view_map.cpp:533
void update_unit_info_label(const std::vector< unit * > &unit_list)
Update the information label which gives info on the current unit and the tile under the current unit...
Definition: view_map.cpp:446
void update_mouse_cursor(enum cursor_type new_cursor_type)
Update the mouse cursor.
Definition: view_map.cpp:457
void menus_update()
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Return TRUE iff the unit can "exist" at this location.
Definition: movement.cpp:267
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Return TRUE iff the unit can "survive" at this location.
Definition: movement.cpp:452
const struct option_set * server_optset
Definition: options.cpp:2430
client_options * gui_options
Definition: options.cpp:74
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Returns the option corresponding of the name in this option set.
Definition: options.cpp:110
bool option_bool_get(const struct option *poption)
Returns the current value of this boolean option.
Definition: options.cpp:457
#define MAX_LEN_ROUTE
Definition: packets.h:38
pageGame * queen()
Return game instandce.
Definition: page_game.cpp:557
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
If the specified player owns the unit with the specified id, return pointer to the unit struct.
Definition: player.cpp:1139
struct city * player_primary_capital(const struct player *pplayer)
Locate the player's primary capital city, (nullptr Otherwise)
Definition: player.cpp:1247
bool can_player_see_units_in_city(const struct player *pplayer, const struct city *pcity)
Return TRUE iff the player can see units in the city.
Definition: player.cpp:1045
#define players_iterate_alive_end
Definition: player.h:532
#define players_iterate_alive(_pplayer)
Definition: player.h:526
bool are_reqs_active(const struct player *target_player, const struct player *other_player, const struct city *target_city, const struct impr_type *target_building, const struct tile *target_tile, const struct unit *target_unit, const struct unit_type *target_unittype, const struct output_type *target_output, const struct specialist *target_specialist, const struct action *target_action, const struct requirement_vector *reqs, const enum req_problem_type prob_type, const enum vision_layer vision_layer, const enum national_intelligence nintel)
Checks the requirement(s) to see if they are active on the given target.
bool player_can_build_road(const struct road_type *proad, const struct player *pplayer, const struct tile *ptile)
Tells if player can build road to tile with suitable unit.
Definition: road.cpp:261
bool can_build_road(struct road_type *proad, const struct unit *punit, const struct tile *ptile)
Tells if unit can build road on tile.
Definition: road.cpp:275
#define FC_INFINITY
Definition: shared.h:32
Definition: base.h:43
Definition: city.h:291
struct city::@15::@18 client
int id
Definition: city.h:296
enum capital_type capital
Definition: city.h:298
struct packet_game_info info
Definition: game.h:80
struct connection conn
Definition: client_main.h:89
bool draw_native
Definition: options.h:141
bool enable_cursor_changes
Definition: options.h:101
bool auto_turn_done
Definition: options.h:94
bool draw_city_output
Definition: options.h:121
bool draw_city_names
Definition: options.h:123
bool draw_city_productions
Definition: options.h:125
int smooth_move_unit_msec
Definition: options.h:81
bool goto_into_unknown
Definition: options.h:90
bool draw_borders
Definition: options.h:140
bool draw_city_buycost
Definition: options.h:126
bool auto_center_on_automated
Definition: options.h:86
bool draw_city_trade_routes
Definition: options.h:127
bool unit_selection_clears_orders
Definition: options.h:103
bool draw_cities
Definition: options.h:136
bool draw_map_grid
Definition: options.h:122
bool draw_city_growth
Definition: options.h:124
bool draw_city_outlines
Definition: options.h:120
bool popup_actor_arrival
Definition: options.h:97
bool auto_center_on_unit
Definition: options.h:85
bool popup_last_move_to_allied
Definition: options.h:99
bool keyboardless_goto
Definition: options.h:100
struct player * playing
Definition: connection.h:142
struct connection::@55::@60 client
struct requirement_vector reqs
Definition: extras.h:90
The base class for options.
Definition: options.cpp:209
Definition: player.h:231
struct player::@65::@68 client
struct unit_list * units
Definition: player.h:264
bool is_alive
Definition: player.h:250
bool phase_done
Definition: player.h:245
Definition: road.h:54
struct terrain * irrigation_result
Definition: terrain.h:200
Definition: tile.h:42
int index
Definition: tile.h:43
struct unit_list * units
Definition: tile.h:50
Definition: unit.h:134
enum action_decision action_decision_want
Definition: unit.h:199
int battlegroup
Definition: unit.h:188
enum unit_activity activity
Definition: unit.h:154
struct unit::@76::@78 client
int id
Definition: unit.h:141
int hp
Definition: unit.h:148
struct tile * tile
Definition: unit.h:136
struct unit_order * list
Definition: unit.h:195
struct tile * action_decision_tile
Definition: unit.h:200
struct player * owner
Definition: unit.h:139
enum server_side_agent ssa_controller
Definition: unit.h:169
universals_u value
Definition: fc_types.h:739
struct civ_map map
Definition: world_object.h:21
#define fc__fallthrough
Definition: support.h:49
struct extra_type * get_preferred_pillage(bv_extras extras)
Returns the highest-priority (best) extra to be pillaged from the terrain set.
Definition: terrain.cpp:439
int terrain_extra_build_time(const struct terrain *pterrain, enum unit_activity activity, const struct extra_type *tgt)
Time to complete the extra building activity on the given terrain.
Definition: terrain.cpp:579
#define T_UNKNOWN
Definition: terrain.h:51
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Adds extra to tile.
Definition: tile.cpp:974
void tile_virtual_destroy(struct tile *vtile)
Frees all memory used by the virtual tile, including freeing virtual units in the tile's unit list an...
Definition: tile.cpp:1051
bool tile_has_road(const struct tile *ptile, const struct road_type *proad)
Returns TRUE if the given tile has a road of given type on it.
Definition: tile.cpp:868
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
struct tile * tile_virtual_new(const struct tile *ptile)
Returns a virtual tile.
Definition: tile.cpp:997
#define tile_index(_pt_)
Definition: tile.h:70
#define tile_worked(_tile)
Definition: tile.h:97
#define tile_terrain(_tile)
Definition: tile.h:93
#define tile_continent(_tile)
Definition: tile.h:74
#define tile_has_extra(ptile, pextra)
Definition: tile.h:130
int get_focus_unit_toggle_timeout(const struct tileset *t)
Return the amount of time between calls to toggle_focus_unit_state.
Definition: tilespec.cpp:3200
void toggle_focus_unit_state(struct tileset *t)
Toggle/increment the focus unit state.
Definition: tilespec.cpp:3232
void focus_unit_in_combat(struct tileset *t)
Setup tileset for showing combat where focus unit participates.
Definition: tilespec.cpp:3221
cursor_type
Definition: tilespec.h:154
@ CURSOR_GOTO
Definition: tilespec.h:155
@ CURSOR_INVALID
Definition: tilespec.h:160
@ CURSOR_PATROL
Definition: tilespec.h:156
@ CURSOR_WAIT
Definition: tilespec.h:164
@ CURSOR_SELECT
Definition: tilespec.h:159
@ CURSOR_DEFAULT
Definition: tilespec.h:166
@ CURSOR_PARADROP
Definition: tilespec.h:157
@ CURSOR_NUKE
Definition: tilespec.h:158
@ CURSOR_ATTACK
Definition: tilespec.h:161
const struct unit_type * utype
Definition: fc_types.h:585
struct terrain * terrain
Definition: fc_types.h:583
int get_transporter_occupancy(const struct unit *ptrans)
Return how many units are in the transport.
Definition: unit.cpp:1647
struct unit * transporter_for_unit(const struct unit *pcargo)
Find the best transporter at the given location for the unit.
Definition: unit.cpp:1779
bool can_unit_paradrop(const struct unit *punit)
Return whether the unit can be paradropped - that is, if the unit is in a friendly city or on an airb...
Definition: unit.cpp:772
struct unit * is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Is there an non-allied unit on this tile?
Definition: unit.cpp:1252
struct unit * unit_transport_get(const struct unit *pcargo)
Returns the transporter of the unit or nullptr if it is not transported.
Definition: unit.cpp:2189
bool is_military_unit(const struct unit *punit)
Military units are capable of enforcing martial law.
Definition: unit.cpp:300
bool could_unit_load(const struct unit *pcargo, const struct unit *ptrans)
Return TRUE iff the given unit could be loaded into the transporter if we moved there.
Definition: unit.cpp:646
bool can_unit_do_autosettlers(const struct unit *punit)
Return whether the unit can be put in auto-settler mode.
Definition: unit.cpp:548
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Return TRUE iff this unit can do the specified generalized (ruleset defined) action enabler controlle...
Definition: unit.cpp:309
bool can_unit_do_activity_targeted(const struct unit *punit, enum unit_activity activity, struct extra_type *target)
Return whether the unit can do the targeted activity at its current location.
Definition: unit.cpp:842
int get_transporter_capacity(const struct unit *punit)
Return the number of units the transporter can hold (or 0).
Definition: unit.cpp:280
bool can_unit_do_activity(const struct unit *punit, enum unit_activity activity)
Return TRUE iff the unit can do the given untargeted activity at its current location.
Definition: unit.cpp:806
void unit_tile_set(struct unit *punit, struct tile *ptile)
Set the tile location of the unit.
Definition: unit.cpp:1200
bool unit_transported(const struct unit *pcargo)
Returns TRUE iff the unit is transported.
Definition: unit.cpp:2176
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Return TRUE iff the given unit can be unloaded from its current transporter.
Definition: unit.cpp:720
bool unit_has_orders(const struct unit *punit)
Return TRUE iff the unit is following client-side orders.
Definition: unit.cpp:195
#define unit_tile(_pu)
Definition: unit.h:371
unit_focus_status
Definition: unit.h:46
@ FOCUS_AVAIL
Definition: unit.h:46
@ FOCUS_DONE
Definition: unit.h:46
@ FOCUS_WAIT
Definition: unit.h:46
#define BATTLEGROUP_NONE
Definition: unit.h:187
unit_orders
Definition: unit.h:31
@ ORDER_ACTION_MOVE
Definition: unit.h:39
@ ORDER_ACTIVITY
Definition: unit.h:35
@ ORDER_MOVE
Definition: unit.h:33
@ ORDER_LAST
Definition: unit.h:43
@ ORDER_PERFORM_ACTION
Definition: unit.h:41
#define unit_owner(_pu)
Definition: unit.h:370
#define MAX_NUM_BATTLEGROUPS
Definition: unit.h:186
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_safe(unitlist, _unit)
Definition: unitlist.h:33
#define unit_list_iterate_end
Definition: unitlist.h:27
#define unit_list_both_iterate_end
Definition: unitlist.h:31
#define unit_list_both_iterate(unitlist, plink, punit)
Definition: unitlist.h:28
#define unit_list_iterate_safe_end
Definition: unitlist.h:54
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
enum unit_move_type utype_move_type(const struct unit_type *punittype)
Return move type of the unit type.
Definition: unittype.cpp:1247
bool utype_may_act_at_all(const struct unit_type *putype)
Return TRUE iff units of this type can do actions controlled by generalized (ruleset defined) action ...
Definition: unittype.cpp:374
bool role_units_translations(QString &astr, int flag, bool alts)
Return a string with all the names of units with this flag.
Definition: unittype.cpp:1343
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Return whether the unit has the given flag.
Definition: unittype.cpp:176
const char * unit_name_translation(const struct unit *punit)
Return the (translated) name of the unit.
Definition: unittype.cpp:1265
struct tile * get_center_tile_mapcanvas()
Finds the current center tile of the mapcanvas.
void move_unit_map_canvas(struct unit *punit, struct tile *src_tile, int dx, int dy)
Animates punit's "smooth" move from (x0, y0) to (x0+dx, y0+dy).
void update_city_description(struct city *pcity)
Update the city description for the given city.
void refresh_unit_mapcanvas(struct unit *punit, struct tile *ptile, bool full_refresh)
Refreshes a single unit on the map canvas.
bool tile_visible_and_not_on_border_mapcanvas(struct tile *ptile)
Return TRUE iff the given map position has a tile visible within the interior of the map canvas.
void update_map_canvas_visible()
Schedules an update of (only) the visible part of the map at the next unqueue_mapview_update().