[Freeciv-Dev] Re: (PR#14365) battlegroups...
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=14365 >
This patch:
1. Is updated.
2. Adds a new order "select same type", y, which selects all units of
the same type as the focus unit.
#2 is based on the warclient behavior, as explained to me by Pille.
Eventually we should have a separate select menu:
- Select:
- Same type as focus unit
- ---separator---
- Military land units
- Diplomat land units
- Caravan land units
- Settler land units
- Worker land units
- Military sea units
- Sea transporter units
- Air units
- Helicoptor units
- Missiles
- ---separator---
- (x) Same continent
- (x) Full hit points
- ( ) Injured
- ( ) Full move points
-jason
Index: server/unittools.c
===================================================================
--- server/unittools.c (revision 11154)
+++ server/unittools.c (working copy)
@@ -1766,6 +1766,7 @@
packet->transported_by = punit->transported_by;
}
packet->occupy = get_transporter_occupancy(punit);
+ packet->battlegroup = punit->battlegroup;
packet->has_orders = punit->has_orders;
if (punit->has_orders) {
int i;
Index: server/unithand.c
===================================================================
--- server/unithand.c (revision 11154)
+++ server/unithand.c (working copy)
@@ -1418,6 +1418,22 @@
}
/**************************************************************************
+ Assign the unit to the battlegroup.
+
+ Battlegroups are handled entirely by the client, so all we have to
+ do here is save the battlegroup ID so that it'll be persistent.
+**************************************************************************/
+void handle_unit_battlegroup(struct player *pplayer,
+ int unit_id, int battlegroup)
+{
+ struct unit *punit = player_find_unit_by_id(pplayer, unit_id);
+
+ if (punit) {
+ punit->battlegroup = CLIP(-1, battlegroup, MAX_NUM_BATTLEGROUPS);
+ }
+}
+
+/**************************************************************************
...
**************************************************************************/
void handle_unit_autosettlers(struct player *pplayer, int unit_id)
Index: server/savegame.c
===================================================================
--- server/savegame.c (revision 11154)
+++ server/savegame.c (working copy)
@@ -1468,6 +1468,10 @@
punit->done_moving = secfile_lookup_bool_default(file,
(punit->moves_left == 0), "player%d.u%d.done_moving", plrno, i);
+ punit->battlegroup
+ = secfile_lookup_bool_default(file, BATTLEGROUP_NONE,
+ "player%d.u%d.battlegroup", plrno, i);
+
/* Load the goto information. Older savegames will not have the
* "go" field, so we just load the goto destination by default. */
if (secfile_lookup_bool_default(file, TRUE,
@@ -2637,6 +2641,8 @@
plrno, i);
secfile_insert_int(file, punit->fuel, "player%d.u%d.fuel",
plrno, i);
+ secfile_insert_int(file, punit->battlegroup,
+ "player%d.u%d.battlegroup", plrno, i);
if (punit->goto_tile) {
secfile_insert_bool(file, TRUE, "player%d.u%d.go", plrno, i);
Index: common/unit.c
===================================================================
--- common/unit.c (revision 11154)
+++ common/unit.c (working copy)
@@ -1498,6 +1498,7 @@
punit->ord_city = 0;
set_unit_activity(punit, ACTIVITY_IDLE);
punit->occupy = 0;
+ punit->battlegroup = BATTLEGROUP_NONE;
punit->client.colored = FALSE;
punit->server.vision = NULL; /* No vision. */
punit->has_orders = FALSE;
Index: common/unit.h
===================================================================
--- common/unit.h (revision 11154)
+++ common/unit.h (working copy)
@@ -164,6 +164,12 @@
int transported_by;
int occupy; /* number of units that occupy transporter */
+
+ /* The battlegroup ID: defined by the client but stored by the server. */
+#define MAX_NUM_BATTLEGROUPS (4)
+#define BATTLEGROUP_NONE (-1)
+ int battlegroup;
+
struct {
/* Equivalent to pcity->client.color. Only for F_CITIES units. */
bool colored;
Index: common/packets.def
===================================================================
--- common/packets.def (revision 11154)
+++ common/packets.def (working copy)
@@ -241,7 +241,7 @@
Spaceship
Ruleset
-The last used packet number is 116.
+The last used packet number is 117.
****************************************************/
@@ -727,6 +727,8 @@
ACTIVITY activity;
SPECIAL activity_target;
+ SINT8 battlegroup;
+
BOOL has_orders;
UINT16 orders_length, orders_index;
BOOL orders_repeat, orders_vigilant;
@@ -786,6 +788,11 @@
UNIT unit_id;
end
+PACKET_UNIT_BATTLEGROUP=117;cs,dsend
+ UNIT unit_id;
+ SINT8 battlegroup;
+end
+
PACKET_UNIT_HELP_BUILD_WONDER=57;cs,dsend
UNIT unit_id;
end
Index: client/control.c
===================================================================
--- client/control.c (revision 11154)
+++ client/control.c (working copy)
@@ -47,7 +47,7 @@
int num_units_below = MAX_NUM_UNITS_BELOW;
/* unit_focus points to the current unit in focus */
-static struct unit *punit_focus = NULL;
+static struct unit_list *pfocus_units;
/* The previously focused unit. Focus can generally be recalled on this
* unit with keypad 5. FIXME: this is not reset when the client
@@ -55,11 +55,13 @@
static int previous_focus_id = -1;
/* These should be set via set_hover_state() */
-int hover_unit = 0; /* id of unit hover_state applies to */
+struct unit_list *hover_units;
enum cursor_hover_state hover_state = HOVER_NONE;
enum unit_activity connect_activity;
enum unit_orders goto_last_order; /* Last order for goto */
+struct unit_list *battlegroups[MAX_NUM_BATTLEGROUPS];
+
/* units involved in current combat */
static struct unit *punit_attacking = NULL;
static struct unit *punit_defending = NULL;
@@ -86,8 +88,15 @@
**************************************************************************/
void control_init(void)
{
+ int i;
+
caravan_arrival_queue = genlist_new();
diplomat_arrival_queue = genlist_new();
+ hover_units = unit_list_new();
+ pfocus_units = unit_list_new();
+ for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
+ battlegroups[i] = unit_list_new();
+ }
}
/**************************************************************************
@@ -95,8 +104,15 @@
**************************************************************************/
void control_done(void)
{
+ int i;
+
genlist_free(caravan_arrival_queue);
genlist_free(diplomat_arrival_queue);
+ unit_list_free(hover_units);
+ unit_list_free(pfocus_units);
+ for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
+ unit_list_free(battlegroups[i]);
+ }
}
/**************************************************************************
@@ -105,28 +121,54 @@
activity => The connect activity (ACTIVITY_ROAD, etc.)
order => The last order (ORDER_BUILD_CITY, ORDER_LAST, etc.)
**************************************************************************/
-void set_hover_state(struct unit *punit, enum cursor_hover_state state,
+void set_hover_state(struct unit_list *punits, enum cursor_hover_state state,
enum unit_activity activity,
enum unit_orders order)
{
- assert(punit != NULL || state == HOVER_NONE);
+ assert((punits && unit_list_size(punits) > 0) || state == HOVER_NONE);
assert(state == HOVER_CONNECT || activity == ACTIVITY_LAST);
assert(state == HOVER_GOTO || order == ORDER_LAST);
- if (punit)
- hover_unit = punit->id;
- else
- hover_unit = 0;
+ unit_list_unlink_all(hover_units);
+ if (punits) {
+ unit_list_iterate(punits, punit) {
+ unit_list_append(hover_units, punit);
+ } unit_list_iterate_end;
+ }
hover_state = state;
connect_activity = activity;
goto_last_order = order;
exit_goto_state();
}
+/****************************************************************************
+ Return TRUE iff this unit is in focus.
+****************************************************************************/
+bool unit_is_in_focus(const struct unit *punit)
+{
+ return unit_list_search(get_units_in_focus(), punit);
+}
+
+/****************************************************************************
+ Return TRUE iff a unit on this tile is in focus.
+****************************************************************************/
+struct unit *get_focus_unit_on_tile(const struct tile *ptile)
+{
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (punit->tile == ptile) {
+ return punit;
+ }
+ } unit_list_iterate_end;
+
+ return NULL;
+}
+
/**************************************************************************
Center on the focus unit, if off-screen and auto_center_on_unit is true.
**************************************************************************/
void auto_center_on_focus_unit(void)
{
+ struct unit *punit_focus = get_first_unit_in_focus();
+
if (punit_focus && auto_center_on_unit &&
!tile_visible_and_not_on_border_mapcanvas(punit_focus->tile)) {
center_tile_mapcanvas(punit_focus->tile);
@@ -143,21 +185,27 @@
**************************************************************************/
void set_unit_focus(struct unit *punit)
{
- struct unit *punit_old_focus = punit_focus;
+ struct unit *punit_old_focus = get_first_unit_in_focus();
if (punit && game.player_ptr && punit->owner != game.player_ptr) {
/* Callers should make sure this never happens. */
return;
}
- if (punit != punit_focus) {
+ if (punit != punit_old_focus) {
store_focus();
}
/*
- * This should be the ONLY place we _modify_ punit_focus.
+ * This should be the ONLY place we _modify_ pfocus_units.
*/
- punit_focus = punit;
+ unit_list_iterate(pfocus_units, punit_old) {
+ refresh_unit_mapcanvas(punit_old, punit_old->tile, TRUE, FALSE);
+ } unit_list_iterate_end;
+ unit_list_unlink_all(pfocus_units);
+ if (punit) {
+ unit_list_append(pfocus_units, punit);
+ }
if (!can_client_change_view()) {
/* This function can be called to set the focus to NULL when
@@ -191,10 +239,35 @@
TRUE, FALSE);
}
- update_unit_info_label(punit);
+ update_unit_info_label(pfocus_units);
update_menus();
}
+void add_unit_focus(struct unit *punit)
+{
+ if (punit && game.player_ptr && punit->owner != game.player_ptr) {
+ /* Callers should make sure this never happens. */
+ return;
+ }
+ if (!punit || !can_client_change_view()) {
+ return;
+ }
+
+ unit_list_append(pfocus_units, punit);
+ punit->focus_status = FOCUS_AVAIL;
+ refresh_unit_mapcanvas(punit, punit->tile, TRUE, FALSE);
+ if (unit_has_orders(punit)) {
+ /* Clear the focus unit's orders. */
+ request_orders_cleared(punit);
+ }
+ if (punit->activity != ACTIVITY_IDLE || punit->ai.control) {
+ punit->ai.control = FALSE;
+ refresh_unit_city_dialogs(punit);
+ request_new_unit_activity(punit, ACTIVITY_IDLE);
+ }
+ update_menus();
+}
+
/**************************************************************************
The only difference is that here we draw the "cross".
**************************************************************************/
@@ -212,6 +285,8 @@
**************************************************************************/
static void store_focus(void)
{
+ struct unit *punit_focus = get_first_unit_in_focus();
+
if (punit_focus) {
previous_focus_id = punit_focus->id;
}
@@ -228,25 +303,61 @@
if (!game.player_ptr || !can_client_change_view()) {
return;
}
- if (!punit_focus
- || (punit_focus->activity != ACTIVITY_IDLE
- && !unit_has_orders(punit_focus)
- && punit_focus->activity != ACTIVITY_GOTO)
- || punit_focus->done_moving
- || punit_focus->moves_left == 0
- || punit_focus->ai.control) {
+ if (get_num_units_in_focus() == 0) {
advance_unit_focus();
+ } else {
+ bool alldone = TRUE;
+
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if ((punit->activity != ACTIVITY_IDLE
+ && !unit_has_orders(punit)
+ && punit->activity != ACTIVITY_GOTO)
+ || punit->done_moving
+ || punit->moves_left == 0
+ || punit->ai.control) {
+
+ } else {
+ alldone = FALSE;
+ break;
+ }
+ } unit_list_iterate_end;
+ if (alldone) {
+ advance_unit_focus();
+ }
}
}
/**************************************************************************
+ Returns the first unit in the focus list, or NULL.
+
+ This function is a hack; anybody that uses it probably needs to be
+ redesigned to treat all focus units equally.
+**************************************************************************/
+struct unit *get_first_unit_in_focus(void)
+{
+ if (unit_list_size(pfocus_units) > 0) {
+ return unit_list_get(pfocus_units, 0);
+ } else {
+ return NULL;
+ }
+}
+
+/**************************************************************************
...
**************************************************************************/
-struct unit *get_unit_in_focus(void)
+struct unit_list *get_units_in_focus(void)
{
- return punit_focus;
+ return pfocus_units;
}
+/****************************************************************************
+ Return the number of units currently in focus (0 or more).
+****************************************************************************/
+int get_num_units_in_focus(void)
+{
+ return unit_list_size(pfocus_units);
+}
+
/**************************************************************************
This function may be called from packhand.c, via update_unit_focus(),
as a result of packets indicating change in activity for a unit. Also
@@ -256,7 +367,7 @@
**************************************************************************/
void advance_unit_focus(void)
{
- struct unit *punit_old_focus = punit_focus;
+ const int num_units_in_old_focus = get_num_units_in_focus();
struct unit *candidate = find_best_focus_candidate(FALSE);
if (!game.player_ptr || !can_client_change_view()) {
@@ -269,6 +380,16 @@
return;
}
+ unit_list_iterate(get_units_in_focus(), punit) {
+ /*
+ * Is the unit which just lost focus a non-AI unit? If yes this
+ * enables the auto end turn.
+ */
+ if (!punit->ai.control) {
+ non_ai_unit_focus = TRUE;
+ }
+ } unit_list_iterate_end;
+
if(!candidate) {
/* First try for "waiting" units. */
unit_list_iterate(game.player_ptr->units, punit) {
@@ -287,20 +408,15 @@
set_unit_focus(candidate);
/*
- * Is the unit which just lost focus a non-AI unit? If yes this
- * enables the auto end turn.
- */
- if (punit_old_focus && !punit_old_focus->ai.control) {
- non_ai_unit_focus = TRUE;
- }
-
- /*
* Handle auto-turn-done mode: If a unit was in focus (did move),
* but now none are (no more to move) and there was at least one
* non-AI unit this turn which was focused, then fake a Turn Done
* keypress.
*/
- if (auto_turn_done && punit_old_focus && !punit_focus && non_ai_unit_focus) {
+ if (auto_turn_done
+ && num_units_in_old_focus > 0
+ && get_num_units_in_focus() == 0
+ && non_ai_unit_focus) {
key_end_turn();
}
}
@@ -312,9 +428,8 @@
**************************************************************************/
static struct unit *find_best_focus_candidate(bool accept_current)
{
- struct unit *best_candidate;
- int best_dist = 99999;
struct tile *ptile;
+ struct unit *pfirst;
if (!game.player_ptr
|| !is_player_phase(game.player_ptr, game.info.phase)) {
@@ -322,29 +437,27 @@
return NULL;
}
- if (punit_focus) {
- ptile = punit_focus->tile;
+ if ((pfirst = get_first_unit_in_focus())) {
+ ptile = pfirst->tile;
} else {
ptile = get_center_tile_mapcanvas();
}
- best_candidate = NULL;
- unit_list_iterate(game.player_ptr->units, punit) {
- if ((punit != punit_focus || accept_current)
- && punit->focus_status == FOCUS_AVAIL
- && punit->activity == ACTIVITY_IDLE
- && !unit_has_orders(punit)
- && punit->moves_left > 0
- && !punit->done_moving
- && !punit->ai.control) {
- int d = sq_map_distance(punit->tile, ptile);
- if (d < best_dist) {
- best_candidate = punit;
- best_dist = d;
- }
- }
- } unit_list_iterate_end;
- return best_candidate;
+ iterate_outward(ptile, FC_INFINITY, ptile2) {
+ unit_list_iterate(ptile2->units, punit) {
+ if ((!unit_is_in_focus(punit) || accept_current)
+ && punit->focus_status == FOCUS_AVAIL
+ && punit->activity == ACTIVITY_IDLE
+ && !unit_has_orders(punit)
+ && punit->moves_left > 0
+ && !punit->done_moving
+ && !punit->ai.control) {
+ return punit;
+ }
+ } unit_list_iterate_end;
+ } iterate_outward_end;
+
+ return NULL;
}
/**************************************************************************
@@ -353,6 +466,7 @@
struct unit *find_visible_unit(struct tile *ptile)
{
struct unit *panyowned = NULL, *panyother = NULL, *ptptother = NULL;
+ struct unit *pfocus;
/* If no units here, return nothing. */
if (unit_list_size(ptile->units)==0) {
@@ -374,10 +488,8 @@
}
/* If the unit in focus is at this tile, show that on top */
- if (punit_focus && same_pos(punit_focus->tile, ptile)) {
- unit_list_iterate(ptile->units, punit)
- if(punit == punit_focus) return punit;
- unit_list_iterate_end;
+ if ((pfocus = get_focus_unit_on_tile(ptile))) {
+ return pfocus;
}
/* If a city is here, return nothing (unit hidden by city). */
@@ -418,30 +530,20 @@
**************************************************************************/
double blink_active_unit(void)
{
- static struct unit *pblinking_unit;
static struct timer *blink_timer = NULL;
-
const double blink_time = get_focus_unit_toggle_timeout(tileset);
- struct unit *punit = punit_focus;
- bool need_update = FALSE;
- if (punit) {
- if (punit != pblinking_unit) {
- pblinking_unit = punit;
- reset_focus_unit_state(tileset);
- need_update = TRUE;
- } else {
- if (read_timer_seconds(blink_timer) > blink_time) {
- toggle_focus_unit_state(tileset);
- need_update = TRUE;
- }
- }
- if (need_update) {
+ if (get_num_units_in_focus() > 0) {
+ if (!blink_timer || read_timer_seconds(blink_timer) > blink_time) {
+ toggle_focus_unit_state(tileset);
+
/* If we lag, we don't try to catch up. Instead we just start a
* new blink_time on every update. */
blink_timer = renew_timer_start(blink_timer, TIMER_USER, TIMER_ACTIVE);
- refresh_unit_mapcanvas(punit, punit->tile, FALSE, TRUE);
+ unit_list_iterate(get_units_in_focus(), punit) {
+ refresh_unit_mapcanvas(punit, punit->tile, FALSE, TRUE);
+ } unit_list_iterate_end;
}
return blink_time - read_timer_seconds(blink_timer);
@@ -501,18 +603,21 @@
be enough information to know whether to redraw -- instead redraw every
time. (Could store enough info to know, but is it worth it?)
**************************************************************************/
-void update_unit_pix_label(struct unit *punit)
+void update_unit_pix_label(struct unit_list *punitlist)
{
int i;
/* Check for any change in the unit's state. This assumes that a unit's
* orders cannot be changed directly but must be removed and then reset. */
- if (punit && get_client_state() != CLIENT_GAME_OVER_STATE) {
+ if (unit_list_size(punitlist) > 0
+ && get_client_state() != CLIENT_GAME_OVER_STATE) {
/* There used to be a complicated and bug-prone check here to see if
* the unit had actually changed. This was misguided since the stacked
* units (below) are redrawn in any case. Unless we write a general
* system for unit updates here we might as well just redraw it every
* time. */
+ struct unit *punit = unit_list_get(punitlist, 0);
+
set_unit_icon(-1, punit);
i = 0; /* index into unit_below_canvas */
@@ -550,7 +655,8 @@
punit_attacking = pattacker;
punit_defending = pdefender;
- if (punit_attacking == punit_focus || punit_defending == punit_focus) {
+ if (unit_is_in_focus(punit_attacking)
+ || unit_is_in_focus(punit_defending)) {
/* If one of the units is the focus unit, make sure hidden-focus is
* disabled. We don't just do this as a check later because then
* with a blinking unit it would just disappear again right after the
@@ -675,15 +781,15 @@
**************************************************************************/
void request_unit_goto(enum unit_orders last_order)
{
- struct unit *punit = punit_focus;
+ struct unit_list *punits = get_units_in_focus();
- if (!punit)
+ if (unit_list_size(punits) == 0)
return;
if (hover_state != HOVER_GOTO) {
- set_hover_state(punit, HOVER_GOTO, ACTIVITY_LAST, last_order);
- update_unit_info_label(punit);
- enter_goto_state(punit);
+ set_hover_state(punits, HOVER_GOTO, ACTIVITY_LAST, last_order);
+ update_unit_info_label(punits);
+ enter_goto_state(punits);
create_line_at_mouse_pos();
} else {
assert(goto_is_active());
@@ -761,16 +867,18 @@
**************************************************************************/
void request_unit_connect(enum unit_activity activity)
{
- if (!punit_focus || !can_unit_do_connect(punit_focus, activity)) {
+ if (get_num_units_in_focus() == 0
+ || !can_unit_do_connect(get_first_unit_in_focus(), activity)) {
return;
}
if (hover_state != HOVER_CONNECT || connect_activity != activity) {
/* Enter or change the hover connect state. */
- set_hover_state(punit_focus, HOVER_CONNECT, activity, ORDER_LAST);
- update_unit_info_label(punit_focus);
+ set_hover_state(get_units_in_focus(), HOVER_CONNECT,
+ activity, ORDER_LAST);
+ update_unit_info_label(get_units_in_focus());
- enter_goto_state(punit_focus);
+ enter_goto_state(get_units_in_focus());
create_line_at_mouse_pos();
} else {
assert(goto_is_active());
@@ -857,6 +965,23 @@
wakeup_sentried_units(punit->tile);
}
+/****************************************************************************
+ Select all units of the same type as the given unit.
+****************************************************************************/
+void request_unit_select_same_type(struct unit_list *punits)
+{
+ if (can_client_change_view()) {
+ unit_list_iterate(punits, punit) {
+ unit_list_iterate(unit_owner(punit)->units, punit2) {
+ if (punit2->type == punit->type
+ && !unit_list_search(punits, punit2)) {
+ add_unit_focus(punit2);
+ }
+ } unit_list_iterate_end;
+ } unit_list_iterate_end;
+ }
+}
+
/**************************************************************************
Request a diplomat to do a specific action.
- action : The action to be requested.
@@ -1065,36 +1190,59 @@
/**************************************************************************
Explode nuclear at a tile without enemy units
**************************************************************************/
-void request_unit_nuke(struct unit *punit)
+void request_unit_nuke(struct unit_list *punits)
{
- if(!unit_flag(punit, F_NUCLEAR)) {
- create_event(punit->tile, E_BAD_COMMAND,
- _("Only nuclear units can do this."));
+ bool can = FALSE;
+ struct tile *offender = NULL;
+
+ if (unit_list_size(punits) == 0) {
return;
}
- if(punit->moves_left == 0)
- do_unit_nuke(punit);
- else {
- set_hover_state(punit, HOVER_NUKE, ACTIVITY_LAST, ORDER_LAST);
- update_unit_info_label(punit);
+ unit_list_iterate(punits, punit) {
+ if (unit_flag(punit, F_NUCLEAR)) {
+ can = TRUE;
+ break;
+ }
+ if (!offender) { /* Take first offender tile/unit */
+ offender = punit->tile;
+ }
+ } unit_list_iterate_end;
+ if (can) {
+ set_hover_state(punits, HOVER_NUKE, ACTIVITY_LAST, ORDER_LAST);
+ update_unit_info_label(punits);
+ } else {
+ create_event(offender, E_BAD_COMMAND,
+ _("Only nuclear units can do this."));
}
}
/**************************************************************************
...
**************************************************************************/
-void request_unit_paradrop(struct unit *punit)
+void request_unit_paradrop(struct unit_list *punits)
{
- if(!unit_flag(punit, F_PARATROOPERS)) {
- create_event(punit->tile, E_BAD_COMMAND,
- _("Only paratrooper units can do this."));
+ bool can = FALSE;
+ struct tile *offender = NULL;
+
+ if (unit_list_size(punits) == 0) {
return;
}
- if(!can_unit_paradrop(punit))
- return;
-
- set_hover_state(punit, HOVER_PARADROP, ACTIVITY_LAST, ORDER_LAST);
- update_unit_info_label(punit);
+ unit_list_iterate(punits, punit) {
+ if (can_unit_paradrop(punit)) {
+ can = TRUE;
+ break;
+ }
+ if (!offender) { /* Take first offender tile/unit */
+ offender = punit->tile;
+ }
+ } unit_list_iterate_end;
+ if (can) {
+ set_hover_state(punits, HOVER_PARADROP, ACTIVITY_LAST, ORDER_LAST);
+ update_unit_info_label(punits);
+ } else {
+ create_event(offender, E_BAD_COMMAND,
+ _("Only paratrooper units can do this."));
+ }
}
/**************************************************************************
@@ -1102,15 +1250,16 @@
**************************************************************************/
void request_unit_patrol(void)
{
- struct unit *punit = punit_focus;
+ struct unit_list *punits = get_units_in_focus();
- if (!punit)
+ if (unit_list_size(punits) == 0) {
return;
+ }
if (hover_state != HOVER_PATROL) {
- set_hover_state(punit, HOVER_PATROL, ACTIVITY_LAST, ORDER_LAST);
- update_unit_info_label(punit);
- enter_goto_state(punit);
+ set_hover_state(punits, HOVER_PATROL, ACTIVITY_LAST, ORDER_LAST);
+ update_unit_info_label(punits);
+ enter_goto_state(punits);
create_line_at_mouse_pos();
} else {
assert(goto_is_active());
@@ -1407,8 +1556,10 @@
**************************************************************************/
void request_center_focus_unit(void)
{
- if (punit_focus) {
- center_tile_mapcanvas(punit_focus->tile);
+ struct unit *punit = get_first_unit_in_focus();
+
+ if (punit) {
+ center_tile_mapcanvas(punit->tile);
}
}
@@ -1418,9 +1569,8 @@
void request_unit_wait(struct unit *punit)
{
punit->focus_status=FOCUS_WAIT;
- if (punit == punit_focus) {
+ if (unit_is_in_focus(punit)) {
advance_unit_focus();
- /* set_unit_focus(punit_focus); */ /* done in advance_unit_focus */
}
}
@@ -1429,10 +1579,11 @@
**************************************************************************/
void request_unit_move_done(void)
{
- if (punit_focus) {
- punit_focus->focus_status = FOCUS_DONE;
+ if (get_num_units_in_focus() > 0) {
+ unit_list_iterate(get_units_in_focus(), punit) {
+ punit->focus_status = FOCUS_DONE;
+ } unit_list_iterate_end;
advance_unit_focus();
- /* set_unit_focus(punit_focus); */ /* done in advance_unit_focus */
}
}
@@ -1504,7 +1655,9 @@
update_city_description(dst_tile->city);
}
- if (punit_focus == punit) update_menus();
+ if (unit_is_in_focus(punit)) {
+ update_menus();
+ }
}
/**************************************************************************
@@ -1513,10 +1666,12 @@
void do_map_click(struct tile *ptile, enum quickselect_type qtype)
{
struct city *pcity = tile_get_city(ptile);
- struct unit *punit = player_find_unit_by_id(game.player_ptr, hover_unit);
+ struct unit_list *punits = hover_units;
bool maybe_goto = FALSE;
+ bool possible = FALSE;
+ struct tile *offender = NULL;
- if (punit && hover_state != HOVER_NONE) {
+ if (unit_list_size(punits) > 0 && hover_state != HOVER_NONE) {
switch (hover_state) {
case HOVER_NONE:
die("well; shouldn't get here :)");
@@ -1524,32 +1679,44 @@
do_unit_goto(ptile);
break;
case HOVER_NUKE:
- if (SINGLE_MOVE * real_map_distance(punit->tile, ptile)
- > punit->moves_left) {
- create_event(punit->tile, E_BAD_COMMAND, _("Too far for this unit."));
+ unit_list_iterate(punits, punit) {
+ if (SINGLE_MOVE * real_map_distance(punit->tile, ptile)
+ <= punit->moves_left) {
+ possible = TRUE;
+ break;
+ }
+ offender = punit->tile;
+ } unit_list_iterate_end;
+ if (!possible) {
+ create_event(offender, E_BAD_COMMAND, _("Too far for this unit."));
} else {
do_unit_goto(ptile);
- /* note that this will be executed by the server after the goto */
- if (!pcity)
- do_unit_nuke(punit);
+ if (!pcity) {
+ unit_list_iterate(punits, punit) {
+ /* note that this will be executed by the server after the goto */
+ do_unit_nuke(punit);
+ } unit_list_iterate_end;
+ }
}
break;
case HOVER_PARADROP:
- do_unit_paradrop_to(punit, ptile);
+ unit_list_iterate(punits, punit) {
+ do_unit_paradrop_to(punit, ptile);
+ } unit_list_iterate_end;
break;
case HOVER_CONNECT:
- do_unit_connect(punit, ptile, connect_activity);
+ do_unit_connect(ptile, connect_activity);
break;
case HOVER_PATROL:
- do_unit_patrol_to(punit, ptile);
+ do_unit_patrol_to(ptile);
break;
}
set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
- update_unit_info_label(punit);
+ update_unit_info_label(get_units_in_focus());
}
/* Bypass stack or city popup if quickselect is specified. */
- else if (qtype) {
+ else if (qtype != SELECT_POPUP && qtype != SELECT_APPEND) {
struct unit *qunit = quickselect(ptile, qtype);
if (qunit) {
set_unit_focus_and_select(qunit);
@@ -1561,7 +1728,7 @@
popup_city_dialog(pcity);
}
else if (unit_list_size(ptile->units) == 0 && !pcity
- && punit_focus) {
+ && get_num_units_in_focus() > 0) {
maybe_goto = keyboardless_goto;
}
else if (unit_list_size(ptile->units) == 1
@@ -1571,7 +1738,11 @@
if (game.player_ptr == punit->owner) {
if(can_unit_do_activity(punit, ACTIVITY_IDLE)) {
maybe_goto = keyboardless_goto;
- set_unit_focus_and_select(punit);
+ if (qtype == SELECT_APPEND) {
+ add_unit_focus(punit);
+ } else {
+ set_unit_focus_and_select(punit);
+ }
}
} else if (pcity) {
/* Don't hide the unit in the city. */
@@ -1630,10 +1801,10 @@
* Any unit
*/
- unit_list_iterate(ptile->units, punit) {
- if (game.player_ptr != punit->owner || punit == punit_focus) {
- continue;
- }
+ unit_list_iterate(ptile->units, punit) {
+ if (game.player_ptr != punit->owner || unit_is_in_focus(punit)) {
+ continue;
+ }
if (qtype == SELECT_SEA) {
/* Transporter. */
if (get_transporter_capacity(punit)) {
@@ -1718,22 +1889,19 @@
**************************************************************************/
void do_unit_goto(struct tile *ptile)
{
- struct unit *punit = player_find_unit_by_id(game.player_ptr, hover_unit);
+ struct tile *dest_tile;
- if (hover_unit == 0 || hover_state != HOVER_GOTO)
+ if (hover_state != HOVER_GOTO) {
return;
+ }
- if (punit) {
- struct tile *dest_tile;
-
- draw_line(ptile);
- dest_tile = get_line_dest();
- if (ptile == dest_tile) {
- send_goto_route(punit);
- } else {
- create_event(punit->tile, E_BAD_COMMAND,
- _("Didn't find a route to the destination!"));
- }
+ draw_line(ptile);
+ dest_tile = get_line_dest();
+ if (ptile == dest_tile) {
+ send_goto_route();
+ } else {
+ create_event(ptile, E_BAD_COMMAND,
+ _("Didn't find a route to the destination!"));
}
set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
@@ -1758,17 +1926,17 @@
/**************************************************************************
Patrol to a location.
**************************************************************************/
-void do_unit_patrol_to(struct unit *punit, struct tile *ptile)
+void do_unit_patrol_to(struct tile *ptile)
{
struct tile *dest_tile;
draw_line(ptile);
dest_tile = get_line_dest();
if (ptile == dest_tile
- && !is_non_allied_unit_tile(ptile, unit_owner(punit))) {
- send_patrol_route(punit);
+ && !is_non_allied_unit_tile(ptile, game.player_ptr)) {
+ send_patrol_route();
} else {
- create_event(punit->tile, E_BAD_COMMAND,
+ create_event(dest_tile, E_BAD_COMMAND,
_("Didn't find a route to the destination!"));
}
@@ -1778,23 +1946,18 @@
/**************************************************************************
"Connect" to the given location.
**************************************************************************/
-void do_unit_connect(struct unit *punit, struct tile *ptile,
+void do_unit_connect(struct tile *ptile,
enum unit_activity activity)
{
- if (is_air_unit(punit)) {
- create_event(punit->tile, E_BAD_COMMAND,
- _("Sorry, airunit connect not yet implemented."));
+ struct tile *dest_tile;
+
+ draw_line(ptile);
+ dest_tile = get_line_dest();
+ if (same_pos(dest_tile, ptile)) {
+ send_connect_route(activity);
} else {
- struct tile *dest_tile;
-
- draw_line(ptile);
- dest_tile = get_line_dest();
- if (same_pos(dest_tile, ptile)) {
- send_connect_route(punit, activity);
- } else {
- create_event(punit->tile, E_BAD_COMMAND,
- _("Didn't find a route to the destination!"));
- }
+ create_event(ptile, E_BAD_COMMAND,
+ _("Didn't find a route to the destination!"));
}
set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
@@ -1814,10 +1977,8 @@
}
if (hover_state != HOVER_NONE && !popped) {
- struct unit *punit = player_find_unit_by_id(game.player_ptr, hover_unit);
-
set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
- update_unit_info_label(punit);
+ update_unit_info_label(hover_units);
keyboardless_goto_button_down = FALSE;
keyboardless_goto_active = FALSE;
@@ -1868,10 +2029,11 @@
**************************************************************************/
void key_unit_move(enum direction8 gui_dir)
{
- if (punit_focus) {
+ unit_list_iterate(get_units_in_focus(), punit) {
enum direction8 map_dir = gui_to_map_dir(gui_dir);
- request_move_unit_direction(punit_focus, map_dir);
- }
+
+ request_move_unit_direction(punit, map_dir);
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -1879,9 +2041,9 @@
**************************************************************************/
void key_unit_build_city(void)
{
- if (punit_focus) {
- request_unit_build_city(punit_focus);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_build_city(punit);
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -1889,9 +2051,11 @@
**************************************************************************/
void key_unit_build_wonder(void)
{
- if (punit_focus && unit_flag(punit_focus, F_HELP_WONDER)) {
- request_unit_caravan_action(punit_focus, PACKET_UNIT_HELP_BUILD_WONDER);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (unit_flag(punit, F_HELP_WONDER)) {
+ request_unit_caravan_action(punit, PACKET_UNIT_HELP_BUILD_WONDER);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -1899,9 +2063,7 @@
**************************************************************************/
void key_unit_connect(enum unit_activity activity)
{
- if (punit_focus) {
- request_unit_connect(activity);
- }
+ request_unit_connect(activity);
}
/**************************************************************************
@@ -1910,13 +2072,17 @@
void key_unit_diplomat_actions(void)
{
struct city *pcity; /* need pcity->id */
- if (punit_focus
- && is_diplomat_unit(punit_focus)
- && (pcity = tile_get_city(punit_focus->tile))
- && diplomat_handled_in_diplomat_dialog() != -1 /* confusing otherwise?
*/
- && diplomat_can_do_action(punit_focus, DIPLOMAT_ANY_ACTION,
- punit_focus->tile))
- process_diplomat_arrival(punit_focus, pcity->id);
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (is_diplomat_unit(punit)
+ && (pcity = tile_get_city(punit->tile))
+ && diplomat_handled_in_diplomat_dialog() != -1 /* confusing
otherwise? */
+ && diplomat_can_do_action(punit, DIPLOMAT_ANY_ACTION,
+ punit->tile)) {
+ process_diplomat_arrival(punit, pcity->id);
+ return;
+ /* FIXME: diplomat dialog for more than one unit at a time. */
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -1924,9 +2090,7 @@
**************************************************************************/
void key_unit_done(void)
{
- if (punit_focus) {
- request_unit_move_done();
- }
+ request_unit_move_done();
}
/**************************************************************************
@@ -1934,9 +2098,7 @@
**************************************************************************/
void key_unit_goto(void)
{
- if (punit_focus) {
- request_unit_goto(ORDER_LAST);
- }
+ request_unit_goto(ORDER_LAST);
}
/**************************************************************************
@@ -1944,9 +2106,7 @@
**************************************************************************/
void key_unit_nuke(void)
{
- if (punit_focus) {
- request_unit_nuke(punit_focus);
- }
+ request_unit_nuke(get_units_in_focus());
}
/**************************************************************************
@@ -1954,9 +2114,7 @@
**************************************************************************/
void key_unit_paradrop(void)
{
- if (punit_focus && can_unit_paradrop(punit_focus)) {
- request_unit_paradrop(punit_focus);
- }
+ request_unit_paradrop(get_units_in_focus());
}
/**************************************************************************
@@ -1964,9 +2122,7 @@
**************************************************************************/
void key_unit_patrol(void)
{
- if (punit_focus) {
- request_unit_patrol();
- }
+ request_unit_patrol();
}
/**************************************************************************
@@ -1974,9 +2130,11 @@
**************************************************************************/
void key_unit_traderoute(void)
{
- if (punit_focus && unit_flag(punit_focus, F_TRADE_ROUTE)) {
- request_unit_caravan_action(punit_focus, PACKET_UNIT_ESTABLISH_TRADE);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (unit_flag(punit, F_TRADE_ROUTE)) {
+ request_unit_caravan_action(punit, PACKET_UNIT_ESTABLISH_TRADE);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -1984,9 +2142,9 @@
**************************************************************************/
void key_unit_unload_all(void)
{
- if (punit_focus) {
- request_unit_unload_all(punit_focus);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_unload_all(punit);
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -1994,9 +2152,9 @@
**************************************************************************/
void key_unit_wait(void)
{
- if (punit_focus) {
- request_unit_wait(punit_focus);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_wait(punit);
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2004,9 +2162,9 @@
***************************************************************************/
void key_unit_wakeup_others(void)
{
- if (punit_focus) {
- request_unit_wakeup(punit_focus);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_wakeup(punit);
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2014,10 +2172,11 @@
**************************************************************************/
void key_unit_airbase(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_AIRBASE)) {
- request_new_unit_activity(punit_focus, ACTIVITY_AIRBASE);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_AIRBASE)) {
+ request_new_unit_activity(punit, ACTIVITY_AIRBASE);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2025,10 +2184,11 @@
**************************************************************************/
void key_unit_auto_explore(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_EXPLORE)) {
- request_new_unit_activity(punit_focus, ACTIVITY_EXPLORE);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_EXPLORE)) {
+ request_new_unit_activity(punit, ACTIVITY_EXPLORE);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2037,9 +2197,11 @@
**************************************************************************/
void key_unit_auto_settle(void)
{
- if (punit_focus && can_unit_do_autosettlers(punit_focus)) {
- request_unit_autosettlers(punit_focus);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_autosettlers(punit)) {
+ request_unit_autosettlers(punit);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2047,9 +2209,9 @@
**************************************************************************/
void key_unit_disband(void)
{
- if (punit_focus) {
- request_unit_disband(punit_focus);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_disband(punit);
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2057,10 +2219,11 @@
**************************************************************************/
void key_unit_fallout(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_FALLOUT)) {
- request_new_unit_activity(punit_focus, ACTIVITY_FALLOUT);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_FALLOUT)) {
+ request_new_unit_activity(punit, ACTIVITY_FALLOUT);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2068,10 +2231,11 @@
**************************************************************************/
void key_unit_fortify(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_FORTIFYING)) {
- request_new_unit_activity(punit_focus, ACTIVITY_FORTIFYING);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
+ request_new_unit_activity(punit, ACTIVITY_FORTIFYING);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2079,10 +2243,11 @@
**************************************************************************/
void key_unit_fortress(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_FORTRESS)) {
- request_new_unit_activity(punit_focus, ACTIVITY_FORTRESS);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_FORTRESS)) {
+ request_new_unit_activity(punit, ACTIVITY_FORTRESS);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2090,9 +2255,9 @@
**************************************************************************/
void key_unit_homecity(void)
{
- if (punit_focus) {
- request_unit_change_homecity(punit_focus);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_change_homecity(punit);
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2100,10 +2265,11 @@
**************************************************************************/
void key_unit_irrigate(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_IRRIGATE)) {
- request_new_unit_activity(punit_focus, ACTIVITY_IRRIGATE);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_IRRIGATE)) {
+ request_new_unit_activity(punit, ACTIVITY_IRRIGATE);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2111,10 +2277,11 @@
**************************************************************************/
void key_unit_mine(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_MINE)) {
- request_new_unit_activity(punit_focus, ACTIVITY_MINE);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_MINE)) {
+ request_new_unit_activity(punit, ACTIVITY_MINE);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2122,10 +2289,11 @@
**************************************************************************/
void key_unit_pillage(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_PILLAGE)) {
- request_unit_pillage(punit_focus);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_PILLAGE)) {
+ request_unit_pillage(punit);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2133,10 +2301,11 @@
**************************************************************************/
void key_unit_pollution(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_POLLUTION)) {
- request_new_unit_activity(punit_focus, ACTIVITY_POLLUTION);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_POLLUTION)) {
+ request_new_unit_activity(punit, ACTIVITY_POLLUTION);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2144,12 +2313,13 @@
**************************************************************************/
void key_unit_road(void)
{
- if (punit_focus) {
- if(can_unit_do_activity(punit_focus, ACTIVITY_ROAD))
- request_new_unit_activity(punit_focus, ACTIVITY_ROAD);
- else if(can_unit_do_activity(punit_focus, ACTIVITY_RAILROAD))
- request_new_unit_activity(punit_focus, ACTIVITY_RAILROAD);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_ROAD)) {
+ request_new_unit_activity(punit, ACTIVITY_ROAD);
+ } else if (can_unit_do_activity(punit, ACTIVITY_RAILROAD)) {
+ request_new_unit_activity(punit, ACTIVITY_RAILROAD);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2157,10 +2327,11 @@
**************************************************************************/
void key_unit_sentry(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_SENTRY)) {
- request_new_unit_activity(punit_focus, ACTIVITY_SENTRY);
- }
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
+ request_new_unit_activity(punit, ACTIVITY_SENTRY);
+ }
+ } unit_list_iterate_end;
}
/**************************************************************************
@@ -2168,12 +2339,67 @@
**************************************************************************/
void key_unit_transform(void)
{
- if (punit_focus &&
- can_unit_do_activity(punit_focus, ACTIVITY_TRANSFORM)) {
- request_new_unit_activity(punit_focus, ACTIVITY_TRANSFORM);
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (can_unit_do_activity(punit, ACTIVITY_TRANSFORM)) {
+ request_new_unit_activity(punit, ACTIVITY_TRANSFORM);
+ }
+ } unit_list_iterate_end;
+}
+
+/****************************************************************************
+ Assign all focus units to this battlegroup.
+****************************************************************************/
+void key_unit_assign_battlegroup(int battlegroup)
+{
+ if (game.player_ptr && can_client_issue_orders()
+ && battlegroups >= 0 && battlegroup < MAX_NUM_BATTLEGROUPS) {
+ /* FIXME: this is moderately inefficient since usually we just keep
+ * the same units in the battlegroup. */
+ unit_list_iterate(battlegroups[battlegroup], punit) {
+ punit->battlegroup = BATTLEGROUP_NONE;
+ dsend_packet_unit_battlegroup(&aconnection,
+ punit->id, BATTLEGROUP_NONE);
+ } unit_list_iterate_end;
+ unit_list_unlink_all(battlegroups[battlegroup]);
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (punit->battlegroup >= 0
+ && punit->battlegroup < MAX_NUM_BATTLEGROUPS) {
+ unit_list_unlink(battlegroups[punit->battlegroup], punit);
+ }
+ punit->battlegroup = battlegroup;
+ dsend_packet_unit_battlegroup(&aconnection,
+ punit->id, battlegroup);
+ unit_list_append(battlegroups[battlegroup], punit);
+ } unit_list_iterate_end;
}
}
+/****************************************************************************
+ Bring this battlegroup into focus.
+****************************************************************************/
+void key_unit_select_battlegroup(int battlegroup)
+{
+ if (game.player_ptr && can_client_change_view()
+ && battlegroups >= 0 && battlegroup < MAX_NUM_BATTLEGROUPS) {
+ int i = 0;
+
+ if (unit_list_size(battlegroups[battlegroup]) == 0) {
+ set_unit_focus(NULL);
+ return;
+ }
+
+ /* FIXME: this is very inefficient and can be improved. */
+ unit_list_iterate(battlegroups[battlegroup], punit) {
+ if (i == 0) {
+ set_unit_focus(punit);
+ } else {
+ add_unit_focus(punit);
+ }
+ i++;
+ } unit_list_iterate_end;
+ }
+}
+
/**************************************************************************
Toggle drawing of city outlines.
**************************************************************************/
@@ -2324,10 +2550,9 @@
**************************************************************************/
void key_quickselect(enum quickselect_type qtype)
{
- struct unit *punit;
+ unit_list_iterate(get_units_in_focus(), punit) {
+ struct unit *punit2 = quickselect(punit->tile, qtype);
- if(punit_focus) {
- punit = quickselect(punit_focus->tile, qtype);
- set_unit_focus_and_select(punit);
- }
+ set_unit_focus_and_select(punit2);
+ } unit_list_iterate_end;
}
Index: client/gui-gtk-2.0/gotodlg.c
===================================================================
--- client/gui-gtk-2.0/gotodlg.c (revision 11154)
+++ client/gui-gtk-2.0/gotodlg.c (working copy)
@@ -82,11 +82,9 @@
struct city *pdestcity = get_selected_city();
if (pdestcity) {
- struct unit *punit = get_unit_in_focus();
-
- if (punit) {
+ unit_list_iterate(get_units_in_focus(), punit) {
request_unit_airlift(punit, pdestcity);
- }
+ } unit_list_iterate_end;
}
}
break;
@@ -96,11 +94,9 @@
struct city *pdestcity = get_selected_city();
if (pdestcity) {
- struct unit *punit = get_unit_in_focus();
-
- if (punit) {
+ unit_list_iterate(get_units_in_focus(), punit) {
send_goto_tile(punit, pdestcity->tile);
- }
+ } unit_list_iterate_end;
}
}
break;
@@ -206,7 +202,7 @@
*****************************************************************/
void popup_goto_dialog(void)
{
- if (!can_client_issue_orders() || !get_unit_in_focus()) {
+ if (!can_client_issue_orders() || get_num_units_in_focus() == 0) {
return;
}
@@ -270,9 +266,17 @@
struct city *pdestcity;
if((pdestcity = get_selected_city())) {
- struct unit *punit = get_unit_in_focus();
+ bool can_airlift = FALSE;
+
+ unit_list_iterate(get_units_in_focus(), punit) {
+ if (unit_can_airlift_to(punit, pdestcity)) {
+ can_airlift = TRUE;
+ break;
+ }
+ } unit_list_iterate_end;
+
center_tile_mapcanvas(pdestcity->tile);
- if(punit && unit_can_airlift_to(punit, pdestcity)) {
+ if (can_airlift) {
gtk_dialog_set_response_sensitive(GTK_DIALOG(dshell), CMD_AIRLIFT, TRUE);
return;
}
Index: client/gui-gtk-2.0/mapview.c
===================================================================
--- client/gui-gtk-2.0/mapview.c (revision 11154)
+++ client/gui-gtk-2.0/mapview.c (working copy)
@@ -166,9 +166,11 @@
Also calls update_unit_pix_label() to update the icons for units on this
square.
**************************************************************************/
-void update_unit_info_label(struct unit *punit)
+void update_unit_info_label(struct unit_list *punitlist)
{
GtkWidget *label;
+ struct unit *punit = (unit_list_size(punitlist) > 0
+ ? unit_list_get(punitlist, 0) : NULL);
label = gtk_frame_get_label_widget(GTK_FRAME(unit_info_frame));
gtk_label_set_text(GTK_LABEL(label),
@@ -178,9 +180,21 @@
get_unit_info_label_text2(punit));
if(punit) {
- if (hover_unit != punit->id)
- set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
+ if (unit_list_size(hover_units) > 0) {
+ bool is_hover = FALSE;
+ unit_list_iterate(hover_units, punit2) {
+ if (punit2 == punit) {
+ is_hover = TRUE;
+ break;
+ }
+ } unit_list_iterate_end;
+
+ if (!is_hover) {
+ set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
+ }
+ }
+
switch (hover_state) {
case HOVER_NONE:
gdk_window_set_cursor (root_window, NULL);
@@ -202,7 +216,7 @@
} else {
gdk_window_set_cursor(root_window, NULL);
}
- update_unit_pix_label(punit);
+ update_unit_pix_label(punitlist);
}
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
--- client/gui-gtk-2.0/gui_main.c (revision 11154)
+++ client/gui-gtk-2.0/gui_main.c (working copy)
@@ -440,7 +440,40 @@
}
}
+ assert(MAX_NUM_BATTLEGROUPS == 4);
switch (ev->keyval) {
+ case GDK_1:
+ if (ev->state & GDK_CONTROL_MASK) {
+ key_unit_assign_battlegroup(0);
+ } else {
+ key_unit_select_battlegroup(0);
+ }
+ break;
+
+ case GDK_2:
+ if (ev->state & GDK_CONTROL_MASK) {
+ key_unit_assign_battlegroup(1);
+ } else {
+ key_unit_select_battlegroup(1);
+ }
+ break;
+
+ case GDK_3:
+ if (ev->state & GDK_CONTROL_MASK) {
+ key_unit_assign_battlegroup(2);
+ } else {
+ key_unit_select_battlegroup(2);
+ }
+ break;
+
+ case GDK_4:
+ if (ev->state & GDK_CONTROL_MASK) {
+ key_unit_assign_battlegroup(3);
+ } else {
+ key_unit_select_battlegroup(3);
+ }
+ break;
+
case GDK_KP_Up:
case GDK_8:
case GDK_KP_8:
@@ -460,25 +493,21 @@
break;
case GDK_KP_Page_Down:
- case GDK_3:
case GDK_KP_3:
key_unit_move(DIR8_SOUTHEAST);
break;
case GDK_KP_Down:
- case GDK_2:
case GDK_KP_2:
key_unit_move(DIR8_SOUTH);
break;
case GDK_KP_End:
- case GDK_1:
case GDK_KP_1:
key_unit_move(DIR8_SOUTHWEST);
break;
case GDK_KP_Left:
- case GDK_4:
case GDK_KP_4:
key_unit_move(DIR8_WEST);
break;
@@ -691,8 +720,8 @@
* but we have to make the *internal* state consistent). */
gtk_widget_hide(more_arrow_pixmap);
set_unit_icons_more_arrow(FALSE);
- set_unit_icon(-1, get_unit_in_focus());
- update_unit_pix_label(get_unit_in_focus());
+ set_unit_icon(-1, get_first_unit_in_focus());
+ update_unit_pix_label(get_units_in_focus());
}
/**************************************************************************
@@ -1488,7 +1517,7 @@
struct unit *punit;
if (i == -1) {
- if ((punit = get_unit_in_focus())) {
+ if ((punit = get_first_unit_in_focus())) {
/* Clicking on the currently selected unit will center it. */
center_tile_mapcanvas(punit->tile);
}
Index: client/gui-gtk-2.0/menu.c
===================================================================
--- client/gui-gtk-2.0/menu.c (revision 11154)
+++ client/gui-gtk-2.0/menu.c (working copy)
@@ -143,6 +143,7 @@
MENU_ORDER_DISBAND,
MENU_ORDER_DIPLOMAT_DLG,
MENU_ORDER_NUKE,
+ MENU_ORDER_SELECT_SAME_TYPE,
MENU_ORDER_WAIT,
MENU_ORDER_DONE,
@@ -395,25 +396,31 @@
guint callback_action, GtkWidget *widget)
{
switch(callback_action) {
- case MENU_ORDER_BUILD_CITY:
- if (get_unit_in_focus()) {
- struct unit *punit = get_unit_in_focus();
+ case MENU_ORDER_SELECT_SAME_TYPE:
+ request_unit_select_same_type(get_units_in_focus());
+ break;
+ case MENU_ORDER_BUILD_CITY:
+ unit_list_iterate(get_units_in_focus(), punit) {
+ /* FIXME: this can provide different actions for different units...
+ * not good! */
/* Enable the button for adding to a city in all cases, so we
get an eventual error message from the server if we try. */
if (can_unit_add_or_build_city(punit)) {
- key_unit_build_city();
+ request_unit_build_city(punit);
} else {
- key_unit_build_wonder();
+ request_unit_caravan_action(punit, PACKET_UNIT_HELP_BUILD_WONDER);
}
- }
+ } unit_list_iterate_end;
break;
- case MENU_ORDER_ROAD:
- if (get_unit_in_focus()) {
- if (unit_can_est_traderoute_here(get_unit_in_focus()))
+ case MENU_ORDER_ROAD:
+ unit_list_iterate(get_units_in_focus(), punit) {
+ /* FIXME: this can provide different actions for different units...
+ * not good! */
+ if (unit_can_est_traderoute_here(punit))
key_unit_traderoute();
else
key_unit_road();
- }
+ } unit_list_iterate_end;
break;
case MENU_ORDER_IRRIGATE:
key_unit_irrigate();
@@ -424,24 +431,28 @@
case MENU_ORDER_TRANSFORM:
key_unit_transform();
break;
- case MENU_ORDER_FORTRESS:
- if (get_unit_in_focus()) {
- if (can_unit_do_activity(get_unit_in_focus(), ACTIVITY_FORTRESS))
+ case MENU_ORDER_FORTRESS:
+ unit_list_iterate(get_units_in_focus(), punit) {
+ /* FIXME: this can provide different actions for different units...
+ * not good! */
+ if (can_unit_do_activity(punit, ACTIVITY_FORTRESS))
key_unit_fortress();
else
key_unit_fortify();
- }
+ } unit_list_iterate_end;
break;
case MENU_ORDER_AIRBASE:
key_unit_airbase();
break;
case MENU_ORDER_POLLUTION:
- if (get_unit_in_focus()) {
- if (can_unit_paradrop(get_unit_in_focus()))
+ unit_list_iterate(get_units_in_focus(), punit) {
+ /* FIXME: this can provide different actions for different units...
+ * not good! */
+ if (can_unit_paradrop(punit))
key_unit_paradrop();
else
key_unit_pollution();
- }
+ } unit_list_iterate_end;
break;
case MENU_ORDER_FALLOUT:
key_unit_fallout();
@@ -459,16 +470,22 @@
key_unit_unload_all();
break;
case MENU_ORDER_LOAD:
- request_unit_load(get_unit_in_focus(), NULL);
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_load(punit, NULL);
+ } unit_list_iterate_end;
break;
case MENU_ORDER_UNLOAD:
- request_unit_unload(get_unit_in_focus());
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_unload(punit);
+ } unit_list_iterate_end;
break;
case MENU_ORDER_WAKEUP_OTHERS:
key_unit_wakeup_others();
break;
- case MENU_ORDER_AUTO_SETTLER:
- request_unit_autosettlers(get_unit_in_focus());
+ case MENU_ORDER_AUTO_SETTLER:
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_autosettlers(punit);
+ } unit_list_iterate_end;
break;
case MENU_ORDER_AUTO_EXPLORE:
key_unit_auto_explore();
@@ -491,15 +508,16 @@
case MENU_ORDER_GOTO:
key_unit_goto();
break;
- case MENU_ORDER_GOTO_CITY:
- if(get_unit_in_focus())
+ case MENU_ORDER_GOTO_CITY:
+ if (get_num_units_in_focus() > 0) {
popup_goto_dialog();
- break;
- case MENU_ORDER_RETURN:
- if (get_unit_in_focus()) {
- request_unit_return(get_unit_in_focus());
}
break;
+ case MENU_ORDER_RETURN:
+ unit_list_iterate(get_units_in_focus(), punit) {
+ request_unit_return(punit);
+ } unit_list_iterate_end;
+ break;
case MENU_ORDER_DISBAND:
key_unit_disband();
break;
@@ -853,6 +871,8 @@
orders_menu_callback, MENU_ORDER_NUKE
},
{ "/" N_("Orders") "/sep5", NULL,
NULL, 0,
"<Separator>" },
+ { "/" N_("Orders") "/" N_("Select same type"), "y",
+ orders_menu_callback, MENU_ORDER_SELECT_SAME_TYPE },
{ "/" N_("Orders") "/" N_("_Wait"), "w",
orders_menu_callback, MENU_ORDER_WAIT
},
{ "/" N_("Orders") "/" N_("Done"), "space",
@@ -1282,7 +1302,7 @@
return;
}
- if((punit=get_unit_in_focus())) {
+ if((punit=get_first_unit_in_focus())) {
const char *irrfmt = _("Change to %s (_I)");
const char *minfmt = _("Change to %s (_M)");
const char *transfmt = _("Transf_orm to %s");
Index: client/gui-gtk-2.0/dialogs.c
===================================================================
--- client/gui-gtk-2.0/dialogs.c (revision 11154)
+++ client/gui-gtk-2.0/dialogs.c (working copy)
@@ -628,7 +628,7 @@
-1);
g_object_unref(pix);
- if (punit == get_unit_in_focus()) {
+ if (unit_is_in_focus(punit)) {
unit_select_path =
gtk_tree_model_get_path(GTK_TREE_MODEL(unit_select_store), it);
}
Index: client/gui-gtk-2.0/mapctrl.c
===================================================================
--- client/gui-gtk-2.0/mapctrl.c (revision 11154)
+++ client/gui-gtk-2.0/mapctrl.c (working copy)
@@ -253,9 +253,9 @@
else if (ev->state & GDK_CONTROL_MASK) {
action_button_pressed(ev->x, ev->y, SELECT_SEA);
}
- /* <SHIFT> + LMB: Copy Production. */
+ /* <SHIFT> + LMB: Append focus unit Production. */
else if (ptile && (ev->state & GDK_SHIFT_MASK)) {
- clipboard_copy_production(ptile);
+ action_button_pressed(ev->x, ev->y, SELECT_APPEND);
}
/* <ALT> + LMB: popit (same as middle-click) */
/* FIXME: we need a general mechanism for letting freeciv work with
@@ -403,7 +403,8 @@
if (can_client_change_view() && (ev->button == 3)) {
center_tile_mapcanvas(map_pos_to_tile(xtile, ytile));
} else if (can_client_issue_orders() && (ev->button == 1)) {
- do_map_click(map_pos_to_tile(xtile, ytile), SELECT_POPUP);
+ do_map_click(map_pos_to_tile(xtile, ytile),
+ (ev->state & GDK_SHIFT_MASK) ? SELECT_POPUP : SELECT_APPEND);
}
return TRUE;
Index: client/text.c
===================================================================
--- client/text.c (revision 11154)
+++ client/text.c (working copy)
@@ -73,7 +73,7 @@
const char *activity_text;
struct city *pcity = ptile->city;
struct unit *punit = find_visible_unit(ptile);
- struct unit *pfocus_unit = get_unit_in_focus();
+ struct unit *pfocus_unit = get_first_unit_in_focus(); /* FIXME */
const char *diplo_nation_plural_adjectives[DS_LAST] =
{Q_("?nation:Neutral"), Q_("?nation:Hostile"),
"" /* unused, DS_CEASEFIRE*/,
@@ -657,7 +657,7 @@
bv_special infrastructure =
get_tile_infrastructure_set(punit->tile, &infracount);
- if (hover_unit == punit->id) {
+ if (unit_list_search(hover_units, punit)) {
astr_add_line(&str, _("Turns to target: %d"), get_goto_turns());
} else {
astr_add_line(&str, "%s", unit_activity_text(punit));
Index: client/control.h
===================================================================
--- client/control.h (revision 11154)
+++ client/control.h (working copy)
@@ -26,30 +26,32 @@
/* Selecting unit from a stack without popup. */
enum quickselect_type {
- SELECT_POPUP = 0, SELECT_SEA, SELECT_LAND
+ SELECT_POPUP = 0, SELECT_SEA, SELECT_LAND, SELECT_APPEND
};
void control_init(void);
void control_done(void);
-extern int hover_unit; /* unit hover_state applies to */
+extern struct unit_list *hover_units; /* unit hover_state applies to */
extern enum cursor_hover_state hover_state;
extern enum unit_activity connect_activity;
extern enum unit_orders goto_last_order;
extern bool non_ai_unit_focus;
+extern struct unit_list *battlegroups[MAX_NUM_BATTLEGROUPS];
+
bool can_unit_do_connect(struct unit *punit, enum unit_activity activity);
void do_move_unit(struct unit *punit, struct unit *target_unit);
void do_unit_goto(struct tile *ptile);
void do_unit_nuke(struct unit *punit);
void do_unit_paradrop_to(struct unit *punit, struct tile *ptile);
-void do_unit_patrol_to(struct unit *punit, struct tile *ptile);
-void do_unit_connect(struct unit *punit, struct tile *ptile,
+void do_unit_patrol_to(struct tile *ptile);
+void do_unit_connect(struct tile *ptile,
enum unit_activity activity);
void do_map_click(struct tile *ptile, enum quickselect_type qtype);
-void set_hover_state(struct unit *punit, enum cursor_hover_state state,
+void set_hover_state(struct unit_list *punits, enum cursor_hover_state state,
enum unit_activity connect_activity,
enum unit_orders goto_last_order);
void request_center_focus_unit(void);
@@ -69,8 +71,8 @@
void request_unit_fortify(struct unit *punit);
void request_unit_goto(enum unit_orders last_order);
void request_unit_move_done(void);
-void request_unit_nuke(struct unit *punit);
-void request_unit_paradrop(struct unit *punit);
+void request_unit_nuke(struct unit_list *punits);
+void request_unit_paradrop(struct unit_list *punits);
void request_unit_patrol(void);
void request_unit_pillage(struct unit *punit);
void request_unit_sentry(struct unit *punit);
@@ -80,6 +82,7 @@
void request_unit_upgrade(struct unit *punit);
void request_unit_wait(struct unit *punit);
void request_unit_wakeup(struct unit *punit);
+void request_unit_select_same_type(struct unit_list *punits);
void request_diplomat_action(enum diplomat_actions action, int dipl_id,
int target_id, int value);
void request_toggle_city_outlines(void);
@@ -103,17 +106,22 @@
void wakeup_sentried_units(struct tile *ptile);
+bool unit_is_in_focus(const struct unit *punit);
+struct unit *get_focus_unit_on_tile(const struct tile *ptile);
void auto_center_on_focus_unit(void);
void advance_unit_focus(void);
-struct unit *get_unit_in_focus(void);
+struct unit *get_first_unit_in_focus(void); /* HACK: do not use if possible. */
+struct unit_list *get_units_in_focus(void);
+int get_num_units_in_focus(void);
void set_unit_focus(struct unit *punit);
+void add_unit_focus(struct unit *punit);
void set_unit_focus_and_select(struct unit *punit);
void update_unit_focus(void);
struct unit *find_visible_unit(struct tile *ptile);
void set_units_in_combat(struct unit *pattacker, struct unit *pdefender);
double blink_active_unit(void);
double blink_turn_done_button(void);
-void update_unit_pix_label(struct unit *punit);
+void update_unit_pix_label(struct unit_list *punitlist);
void process_caravan_arrival(struct unit *punit);
void process_diplomat_arrival(struct unit *pdiplomat, int victim_id);
@@ -170,6 +178,8 @@
void key_unit_unload_all(void);
void key_unit_wait(void);
void key_unit_wakeup_others(void);
+void key_unit_assign_battlegroup(int battlegroup);
+void key_unit_select_battlegroup(int battlegroup);
/* don't change this unless you also put more entries in data/Freeciv */
#define MAX_NUM_UNITS_BELOW 4
Index: client/include/mapview_g.h
===================================================================
--- client/include/mapview_g.h (revision 11154)
+++ client/include/mapview_g.h (working copy)
@@ -22,7 +22,7 @@
#include "mapview_common.h"
void update_info_label(void);
-void update_unit_info_label(struct unit *punit);
+void update_unit_info_label(struct unit_list *punitlist);
void update_timeout_label(void);
void update_turn_done_button(bool do_restore);
void update_city_descriptions(void);
Index: client/goto.c
===================================================================
--- client/goto.c (revision 11154)
+++ client/goto.c (working copy)
@@ -49,31 +49,57 @@
struct pf_map *map;
};
+/* For each tile and each direction we store the number of lines going out
+ * of the tile in this direction. Since each line is undirected, we only
+ * store the 4 lower-numbered directions for each tile; the 4 upper-numbered
+ * directions are stored as reverses from the target tile.
+ * Notes: 1. This assumes that
+ * - there are 8 directions
+ * - out of every two opposite directions (like NORTH and SOUTH) one and
+ * only one has number less than 4
+ * 2. There _can_ be more than one line drawn between two tiles, because of
+ * the waypoints. */
static struct {
- /* For each tile and each direction we store the number of lines going out
- * of the tile in this direction. Since each line is undirected, we only
- * store the 4 lower-numbered directions for each tile; the 4 upper-numbered
- * directions are stored as reverses from the target tile.
- * Notes: 1. This assumes that
- * - there are 8 directions
- * - out of every two opposite directions (like NORTH and SOUTH) one and
- * only one has number less than 4
- * 2. There _can_ be more than one line drawn between two tiles, because of
- * the waypoints. */
- struct {
- unsigned char drawn[4];
- } *tiles;
+ unsigned char drawn[4];
+} *tiles;
+
+struct goto_map {
int unit_id; /* The unit of the goto map */
struct part *parts;
int num_parts;
struct pf_parameter template;
-} goto_map;
+};
-#define DRAWN(ptile, dir) (goto_map.tiles[(ptile)->index].drawn[dir])
+/* get 'struct goto_map_list' and related functions: */
+#define SPECLIST_TAG goto_map
+#define SPECLIST_TYPE struct goto_map
+#include "speclist.h"
+#define goto_map_list_iterate(gotolist, pgoto) \
+ TYPED_LIST_ITERATE(struct goto_map, gotolist, pgoto)
+#define goto_map_list_iterate_end \
+ LIST_ITERATE_END
+/* Iterate over goto maps, filtering out dead units. */
+#define goto_map_iterate(gotolist, pgoto, punit) \
+ goto_map_list_iterate(gotolist, pgoto) { \
+ struct unit *punit = find_unit_by_id(pgoto->unit_id); \
+ \
+ if (punit) { \
+ assert(unit_is_in_focus(punit)); \
+ {
+
+#define goto_map_iterate_end \
+ }
\
+ } \
+ } goto_map_list_iterate_end;
+
+static struct goto_map_list *goto_maps;
+
+#define DRAWN(ptile, dir) (tiles[(ptile)->index].drawn[dir])
+
static void increment_drawn(struct tile *src_tile, enum direction8 dir);
static void decrement_drawn(struct tile *src_tile, enum direction8 dir);
-static void reset_last_part(void);
+static void reset_last_part(struct goto_map *goto_map);
/**************************************************************************
@@ -83,6 +109,31 @@
static bool is_init = FALSE;
static int connect_initial;
+/****************************************************************************
+ Create a new goto map.
+****************************************************************************/
+static struct goto_map *goto_map_new(void)
+{
+ struct goto_map *goto_map = fc_malloc(sizeof(*goto_map));
+
+ goto_map->unit_id = -1;
+ goto_map->parts = NULL;
+ goto_map->num_parts = 0;
+
+ return goto_map;
+}
+
+/****************************************************************************
+ Free an existing goto map.
+****************************************************************************/
+static void goto_map_free(struct goto_map *goto_map)
+{
+ if (goto_map->parts) {
+ free(goto_map->parts);
+ }
+ free(goto_map);
+}
+
/**********************************************************************
Called once per game.
***********************************************************************/
@@ -92,12 +143,12 @@
free_client_goto();
}
- goto_map.tiles = fc_malloc(MAP_INDEX_SIZE * sizeof(*goto_map.tiles));
- goto_map.parts = NULL;
- goto_map.num_parts = 0;
- goto_map.unit_id = -1;
+ goto_maps = goto_map_list_new();
+
+ tiles = fc_malloc(MAP_INDEX_SIZE * sizeof(*tiles));
whole_map_iterate(ptile) {
int dir;
+
for (dir = 0; dir < 4; dir++) {
DRAWN(ptile, dir) = 0;
}
@@ -112,12 +163,13 @@
void free_client_goto(void)
{
if (is_init) {
- free(goto_map.tiles);
- if (goto_map.parts) {
- free(goto_map.parts);
- }
+ goto_map_list_iterate(goto_maps, goto_map) {
+ goto_map_free(goto_map);
+ } goto_map_list_iterate_end;
+ goto_map_list_unlink_all(goto_maps);
+ goto_map_list_free(goto_maps);
- memset(&goto_map, 0, sizeof(goto_map));
+ free(tiles);
is_init = FALSE;
}
@@ -127,20 +179,20 @@
Change the destination of the last part to the given position if a
path can be found. If not the destination is set to the start.
***********************************************************************/
-static void update_last_part(struct tile *ptile)
+static void update_last_part(struct goto_map *goto_map, struct tile *ptile)
{
- struct part *p = &goto_map.parts[goto_map.num_parts - 1];
+ struct part *p = &goto_map->parts[goto_map->num_parts - 1];
struct pf_path *new_path;
struct tile *old_tile = p->start_tile;
int i, start_index = 0;
freelog(LOG_DEBUG, "update_last_part(%d,%d) old (%d,%d)-(%d,%d)",
- TILE_XY(ptile), TILE_XY(p->start_tile), TILE_XY(p->end_tile));
+ TILE_XY(ptile), TILE_XY(p->start_tile), TILE_XY(p->end_tile));
new_path = pf_get_path(p->map, ptile);
if (!new_path) {
freelog(PATH_LOG_LEVEL, " no path found");
- reset_last_part();
+ reset_last_part(goto_map);
return;
}
@@ -155,8 +207,8 @@
struct pf_position *b = &new_path->positions[i];
if (a->dir_to_next_pos != b->dir_to_next_pos
- || !same_pos(a->tile, b->tile)) {
- break;
+ || !same_pos(a->tile, b->tile)) {
+ break;
}
}
start_index = i;
@@ -195,7 +247,7 @@
p->end_fuel_left = pf_last_position(p->path)->fuel_left;
if (hover_state == HOVER_CONNECT) {
- int move_rate = goto_map.template.move_rate;
+ int move_rate = goto_map->template.move_rate;
int moves = pf_last_position(p->path)->total_MC;
p->time = moves / move_rate;
@@ -203,8 +255,7 @@
p->time += connect_initial;
}
freelog(PATH_LOG_LEVEL, "To (%d,%d) MC: %d, connect_initial: %d",
- TILE_XY(ptile), moves, connect_initial);
-
+ TILE_XY(ptile), moves, connect_initial);
} else {
p->time = pf_last_position(p->path)->turn;
}
@@ -218,13 +269,13 @@
Change the drawn path to a size of 0 steps by setting it to the
start position.
***********************************************************************/
-static void reset_last_part(void)
+static void reset_last_part(struct goto_map *goto_map)
{
- struct part *p = &goto_map.parts[goto_map.num_parts - 1];
+ struct part *p = &goto_map->parts[goto_map->num_parts - 1];
if (!same_pos(p->start_tile, p->end_tile)) {
/* Otherwise no need to update */
- update_last_part(p->start_tile);
+ update_last_part(goto_map, p->start_tile);
}
}
@@ -233,26 +284,29 @@
of the new part is either the unit position (for the first part) or
the destination of the last part (not the first part).
***********************************************************************/
-static void add_part(void)
+static void add_part(struct goto_map *goto_map)
{
struct part *p;
- struct pf_parameter parameter = goto_map.template;
+ struct pf_parameter parameter = goto_map->template;
+ struct unit *punit = find_unit_by_id(goto_map->unit_id);
- goto_map.num_parts++;
- goto_map.parts =
- fc_realloc(goto_map.parts,
- goto_map.num_parts * sizeof(*goto_map.parts));
- p = &goto_map.parts[goto_map.num_parts - 1];
+ if (!punit) {
+ return;
+ }
- if (goto_map.num_parts == 1) {
+ goto_map->num_parts++;
+ goto_map->parts =
+ fc_realloc(goto_map->parts,
+ goto_map->num_parts * sizeof(*goto_map->parts));
+ p = &goto_map->parts[goto_map->num_parts - 1];
+
+ if (goto_map->num_parts == 1) {
/* first part */
- struct unit *punit = find_unit_by_id(goto_map.unit_id);
-
p->start_tile = punit->tile;
p->start_moves_left = parameter.moves_left_initially;
p->start_fuel_left = parameter.fuel_left_initially;
} else {
- struct part *prev = &goto_map.parts[goto_map.num_parts - 2];
+ struct part *prev = &goto_map->parts[goto_map->num_parts - 2];
p->start_tile = prev->end_tile;
p->start_moves_left = prev->end_moves_left;
@@ -270,19 +324,19 @@
/**********************************************************************
Remove the last part, erasing the corresponding path segment.
***********************************************************************/
-static void remove_last_part(void)
+static void remove_last_part(struct goto_map *goto_map)
{
- struct part *p = &goto_map.parts[goto_map.num_parts - 1];
+ struct part *p = &goto_map->parts[goto_map->num_parts - 1];
- assert(goto_map.num_parts >= 1);
+ assert(goto_map->num_parts >= 1);
- reset_last_part();
+ reset_last_part(goto_map);
if (p->path) {
/* We do not always have a path */
pf_destroy_path(p->path);
}
pf_destroy_map(p->map);
- goto_map.num_parts--;
+ goto_map->num_parts--;
}
/**********************************************************************
@@ -290,16 +344,15 @@
***********************************************************************/
void goto_add_waypoint(void)
{
- struct part *p = &goto_map.parts[goto_map.num_parts - 1];
-
assert(is_active);
- assert(find_unit_by_id(goto_map.unit_id)
- && find_unit_by_id(goto_map.unit_id) == get_unit_in_focus());
+ goto_map_iterate(goto_maps, goto_map, punit) {
+ struct part *p = &goto_map->parts[goto_map->num_parts - 1];
- if (!same_pos(p->start_tile, p->end_tile)) {
- /* Otherwise the last part has zero length. */
- add_part();
- }
+ if (!same_pos(p->start_tile, p->end_tile)) {
+ /* Otherwise the last part has zero length. */
+ add_part(goto_map);
+ }
+ } goto_map_iterate_end;
}
/**********************************************************************
@@ -308,27 +361,29 @@
***********************************************************************/
bool goto_pop_waypoint(void)
{
- struct part *p = &goto_map.parts[goto_map.num_parts - 1];
- struct tile *end_tile = p->end_tile;
+ bool popped = FALSE;
assert(is_active);
- assert(find_unit_by_id(goto_map.unit_id)
- && find_unit_by_id(goto_map.unit_id) == get_unit_in_focus());
+ goto_map_iterate(goto_maps, goto_map, punit) {
+ struct part *p = &goto_map->parts[goto_map->num_parts - 1];
+ struct tile *end_tile = p->end_tile;
- if (goto_map.num_parts == 1) {
- /* we don't have any waypoint but the start pos. */
- return FALSE;
- }
+ if (goto_map->num_parts == 1) {
+ /* we don't have any waypoint but the start pos. */
+ continue;
+ }
+ popped = TRUE;
- remove_last_part();
+ remove_last_part(goto_map);
- /*
- * Set the end position of the previous part (now the last) to the
- * end position of the last part (now gone). I.e. redraw a line to
- * the mouse position.
- */
- update_last_part(end_tile);
- return TRUE;
+ /*
+ * Set the end position of the previous part (now the last) to the
+ * end position of the last part (now gone). I.e. redraw a line to
+ * the mouse position.
+ */
+ update_last_part(goto_map, end_tile);
+ } goto_map_iterate_end;
+ return popped;
}
/**********************************************************************
@@ -710,16 +765,23 @@
Enter the goto state: activate, prepare PF-template and add the
initial part.
***********************************************************************/
-void enter_goto_state(struct unit *punit)
+void enter_goto_state(struct unit_list *punits)
{
assert(!is_active);
+ assert(goto_map_list_size(goto_maps) == 0);
- goto_map.unit_id = punit->id;
- assert(goto_map.num_parts == 0);
+ unit_list_iterate(punits, punit) {
+ struct goto_map *goto_map = goto_map_new();
- fill_client_goto_parameter(punit, &goto_map.template);
+ goto_map->unit_id = punit->id;
+ assert(goto_map->num_parts == 0);
- add_part();
+ fill_client_goto_parameter(punit, &goto_map->template);
+
+ add_part(goto_map);
+
+ goto_map_list_append(goto_maps, goto_map);
+ } unit_list_iterate_end;
is_active = TRUE;
}
@@ -732,11 +794,13 @@
return;
}
- while (goto_map.num_parts > 0) {
- remove_last_part();
- }
- free(goto_map.parts);
- goto_map.parts = NULL;
+ goto_map_list_iterate(goto_maps, goto_map) {
+ while (goto_map->num_parts > 0) {
+ remove_last_part(goto_map);
+ }
+ goto_map_free(goto_map);
+ } goto_map_list_iterate_end;
+ goto_map_list_unlink_all(goto_maps);
is_active = FALSE;
}
@@ -754,11 +818,14 @@
***********************************************************************/
struct tile *get_line_dest(void)
{
- struct part *p = &goto_map.parts[goto_map.num_parts - 1];
+ if (is_active) {
+ struct goto_map *goto_map = goto_map_list_get(goto_maps, 0);
+ struct part *p = &goto_map->parts[goto_map->num_parts - 1];
- assert(is_active);
-
- return p->end_tile;
+ return p->end_tile;
+ } else {
+ return NULL;
+ }
}
/**************************************************************************
@@ -766,13 +833,18 @@
***************************************************************************/
int get_goto_turns(void)
{
- int time = 0, i;
+ if (is_active) {
+ struct goto_map *goto_map = goto_map_list_get(goto_maps, 0);
+ int time = 0, i;
- for(i = 0; i < goto_map.num_parts; i++) {
- time += goto_map.parts[i].time;
+ for (i = 0; i < goto_map->num_parts; i++) {
+ time += goto_map->parts[i].time;
+ }
+
+ return time;
+ } else {
+ return -1;
}
-
- return time;
}
/**********************************************************************
@@ -784,10 +856,12 @@
{
assert(is_active);
- update_last_part(dest_tile);
+ goto_map_iterate(goto_maps, goto_map, punit) {
+ update_last_part(goto_map, dest_tile);
+ } goto_map_iterate_end;
/* Update goto data in info label. */
- update_unit_info_label(get_unit_in_focus());
+ update_unit_info_label(get_units_in_focus());
}
/****************************************************************************
@@ -918,118 +992,118 @@
Send the current patrol route (i.e., the one generated via HOVER_STATE)
to the server.
**************************************************************************/
-void send_patrol_route(struct unit *punit)
+void send_patrol_route(void)
{
- int i;
- struct pf_path *path = NULL, *return_path;
- struct pf_parameter parameter = goto_map.template;
- struct pf_map *map;
-
assert(is_active);
- assert(punit->id == goto_map.unit_id);
+ goto_map_iterate(goto_maps, goto_map, punit) {
+ int i;
+ struct pf_path *path = NULL, *return_path;
+ struct pf_parameter parameter = goto_map->template;
+ struct pf_map *map;
- parameter.start_tile = goto_map.parts[goto_map.num_parts - 1].end_tile;
- parameter.moves_left_initially
- = goto_map.parts[goto_map.num_parts - 1].end_moves_left;
- parameter.fuel_left_initially
- = goto_map.parts[goto_map.num_parts - 1].end_fuel_left;
- map = pf_create_map(¶meter);
- return_path = pf_get_path(map, goto_map.parts[0].start_tile);
- if (!return_path) {
- die("No return path found!");
- }
+ parameter.start_tile = goto_map->parts[goto_map->num_parts - 1].end_tile;
+ parameter.moves_left_initially
+ = goto_map->parts[goto_map->num_parts - 1].end_moves_left;
+ parameter.fuel_left_initially
+ = goto_map->parts[goto_map->num_parts - 1].end_fuel_left;
+ map = pf_create_map(¶meter);
+ return_path = pf_get_path(map, goto_map->parts[0].start_tile);
+ if (!return_path) {
+ die("No return path found!");
+ }
- for (i = 0; i < goto_map.num_parts; i++) {
- path = pft_concat(path, goto_map.parts[i].path);
- }
- path = pft_concat(path, return_path);
+ for (i = 0; i < goto_map->num_parts; i++) {
+ path = pft_concat(path, goto_map->parts[i].path);
+ }
+ path = pft_concat(path, return_path);
- pf_destroy_map(map);
- pf_destroy_path(return_path);
+ pf_destroy_map(map);
+ pf_destroy_path(return_path);
- send_path_orders(punit, path, TRUE, TRUE, NULL);
+ send_path_orders(punit, path, TRUE, TRUE, NULL);
- pf_destroy_path(path);
+ pf_destroy_path(path);
+ } goto_map_iterate_end;
}
/**************************************************************************
Send the current connect route (i.e., the one generated via HOVER_STATE)
to the server.
**************************************************************************/
-void send_connect_route(struct unit *punit, enum unit_activity activity)
+void send_connect_route(enum unit_activity activity)
{
- struct pf_path *path = NULL;
- int i;
- struct packet_unit_orders p;
- struct tile *old_tile;
-
assert(is_active);
- assert(punit->id == goto_map.unit_id);
+ goto_map_iterate(goto_maps, goto_map, punit) {
+ struct pf_path *path = NULL;
+ int i;
+ struct packet_unit_orders p;
+ struct tile *old_tile;
- memset(&p, 0, sizeof(p));
+ memset(&p, 0, sizeof(p));
- for (i = 0; i < goto_map.num_parts; i++) {
- path = pft_concat(path, goto_map.parts[i].path);
- }
+ for (i = 0; i < goto_map->num_parts; i++) {
+ path = pft_concat(path, goto_map->parts[i].path);
+ }
- p.unit_id = punit->id;
- p.src_x = punit->tile->x;
- p.src_y = punit->tile->y;
- p.repeat = FALSE;
- p.vigilant = FALSE; /* Should be TRUE? */
+ p.unit_id = punit->id;
+ p.src_x = punit->tile->x;
+ p.src_y = punit->tile->y;
+ p.repeat = FALSE;
+ p.vigilant = FALSE; /* Should be TRUE? */
- p.length = 0;
- old_tile = path->positions[0].tile;
+ p.length = 0;
+ old_tile = path->positions[0].tile;
- for (i = 0; i < path->length; i++) {
- switch (activity) {
- case ACTIVITY_IRRIGATE:
- if (!tile_has_special(old_tile, S_IRRIGATION)) {
- /* Assume the unit can irrigate or we wouldn't be here. */
- p.orders[p.length] = ORDER_ACTIVITY;
- p.activity[p.length] = ACTIVITY_IRRIGATE;
- p.length++;
- }
- break;
- case ACTIVITY_ROAD:
- case ACTIVITY_RAILROAD:
- if (!tile_has_special(old_tile, S_ROAD)) {
- /* Assume the unit can build the road or we wouldn't be here. */
- p.orders[p.length] = ORDER_ACTIVITY;
- p.activity[p.length] = ACTIVITY_ROAD;
- p.length++;
- }
- if (activity == ACTIVITY_RAILROAD) {
- if (!tile_has_special(old_tile, S_RAILROAD)) {
- /* Assume the unit can build the rail or we wouldn't be here. */
+ for (i = 0; i < path->length; i++) {
+ switch (activity) {
+ case ACTIVITY_IRRIGATE:
+ if (!tile_has_special(old_tile, S_IRRIGATION)) {
+ /* Assume the unit can irrigate or we wouldn't be here. */
p.orders[p.length] = ORDER_ACTIVITY;
- p.activity[p.length] = ACTIVITY_RAILROAD;
+ p.activity[p.length] = ACTIVITY_IRRIGATE;
p.length++;
}
+ break;
+ case ACTIVITY_ROAD:
+ case ACTIVITY_RAILROAD:
+ if (!tile_has_special(old_tile, S_ROAD)) {
+ /* Assume the unit can build the road or we wouldn't be here. */
+ p.orders[p.length] = ORDER_ACTIVITY;
+ p.activity[p.length] = ACTIVITY_ROAD;
+ p.length++;
+ }
+ if (activity == ACTIVITY_RAILROAD) {
+ if (!tile_has_special(old_tile, S_RAILROAD)) {
+ /* Assume the unit can build the rail or we wouldn't be here. */
+ p.orders[p.length] = ORDER_ACTIVITY;
+ p.activity[p.length] = ACTIVITY_RAILROAD;
+ p.length++;
+ }
+ }
+ break;
+ default:
+ die("Invalid connect activity.");
+ break;
}
- break;
- default:
- die("Invalid connect activity.");
- break;
- }
- if (i != path->length - 1) {
- struct tile *new_tile = path->positions[i + 1].tile;
+ if (i != path->length - 1) {
+ struct tile *new_tile = path->positions[i + 1].tile;
- assert(!same_pos(new_tile, old_tile));
+ assert(!same_pos(new_tile, old_tile));
- p.orders[p.length] = ORDER_MOVE;
- p.dir[p.length] = get_direction_for_step(old_tile, new_tile);
- p.length++;
+ p.orders[p.length] = ORDER_MOVE;
+ p.dir[p.length] = get_direction_for_step(old_tile, new_tile);
+ p.length++;
- old_tile = new_tile;
+ old_tile = new_tile;
+ }
}
- }
- p.dest_x = old_tile->x;
- p.dest_y = old_tile->y;
+ p.dest_x = old_tile->x;
+ p.dest_y = old_tile->y;
- send_packet_unit_orders(&aconnection, &p);
+ send_packet_unit_orders(&aconnection, &p);
+ } goto_map_iterate_end;
}
/**************************************************************************
@@ -1037,27 +1111,27 @@
HOVER_STATE) to the server. The route might involve more than one
part if waypoints were used. FIXME: danger paths are not supported.
**************************************************************************/
-void send_goto_route(struct unit *punit)
+void send_goto_route(void)
{
- struct pf_path *path = NULL;
- int i;
-
assert(is_active);
- assert(punit->id == goto_map.unit_id);
+ goto_map_iterate(goto_maps, goto_map, punit) {
+ struct pf_path *path = NULL;
+ int i;
- for (i = 0; i < goto_map.num_parts; i++) {
- path = pft_concat(path, goto_map.parts[i].path);
- }
+ for (i = 0; i < goto_map->num_parts; i++) {
+ path = pft_concat(path, goto_map->parts[i].path);
+ }
- if (goto_last_order == ORDER_LAST) {
- send_goto_path(punit, path, NULL);
- } else {
- struct unit_order order;
+ if (goto_last_order == ORDER_LAST) {
+ send_goto_path(punit, path, NULL);
+ } else {
+ struct unit_order order;
- order.order = goto_last_order;
- send_goto_path(punit, path, &order);
- }
- pf_destroy_path(path);
+ order.order = goto_last_order;
+ send_goto_path(punit, path, &order);
+ }
+ pf_destroy_path(path);
+ } goto_map_iterate_end;
}
/* ================= drawn functions ============================ */
Index: client/packhand.c
===================================================================
--- client/packhand.c (revision 11154)
+++ client/packhand.c (working copy)
@@ -115,6 +115,7 @@
} else {
punit->transported_by = -1;
}
+ punit->battlegroup = packet->battlegroup;
punit->has_orders = packet->has_orders;
punit->orders.length = packet->orders_length;
punit->orders.index = packet->orders_index;
@@ -227,7 +228,7 @@
client_remove_city(pcity);
/* update menus if the focus unit is on the tile. */
- if (get_unit_in_focus()) {
+ if (get_num_units_in_focus() > 0) {
update_menus();
}
}
@@ -360,7 +361,7 @@
update_info_label(); /* get initial population right */
update_unit_focus();
- update_unit_info_label(get_unit_in_focus());
+ update_unit_info_label(get_units_in_focus());
/* Find something sensible to display instead of the intro gfx. */
center_on_something();
@@ -392,7 +393,7 @@
bool need_units_dialog_update = FALSE;
struct city *pcity;
bool popup, update_descriptions = FALSE, name_changed = FALSE;
- struct unit *pfocus_unit = get_unit_in_focus();
+ struct unit_list *pfocus_units = get_units_in_focus();
pcity=find_city_by_id(packet->id);
@@ -554,8 +555,13 @@
}
/* Update focus unit info label if necessary. */
- if (name_changed && pfocus_unit && pfocus_unit->homecity == pcity->id) {
- update_unit_info_label(pfocus_unit);
+ if (name_changed) {
+ unit_list_iterate(pfocus_units, pfocus_unit) {
+ if (pfocus_unit->homecity == pcity->id) {
+ update_unit_info_label(pfocus_units);
+ break;
+ }
+ } unit_list_iterate_end;
}
/* Update the units dialog if necessary. */
@@ -622,11 +628,8 @@
}
/* update menus if the focus unit is on the tile. */
- {
- struct unit *punit = get_unit_in_focus();
- if (punit && same_pos(punit->tile, pcity->tile)) {
- update_menus();
- }
+ if (get_focus_unit_on_tile(pcity->tile)) {
+ update_menus();
}
if(is_new) {
@@ -775,7 +778,7 @@
update_unit_focus();
auto_center_on_focus_unit();
- update_unit_info_label(get_unit_in_focus());
+ update_unit_info_label(get_units_in_focus());
update_menus();
set_seconds_to_turndone(game.info.timeout);
@@ -961,7 +964,6 @@
bool check_focus = FALSE; /* conservative focus change */
bool moved = FALSE;
bool ret = FALSE;
- struct unit *focus_unit = get_unit_in_focus();
punit = player_find_unit_by_id(packet_unit->owner, packet_unit->id);
if (!punit && find_unit_by_id(packet_unit->id)) {
@@ -973,12 +975,25 @@
if (punit) {
ret = TRUE;
punit->activity_count = packet_unit->activity_count;
+ if (packet_unit->battlegroup < 0
+ || packet_unit->battlegroup >= MAX_NUM_BATTLEGROUPS) {
+ packet_unit->battlegroup = BATTLEGROUP_NONE;
+ }
+ if (punit->battlegroup != packet_unit->battlegroup) {
+ if (packet_unit->battlegroup != BATTLEGROUP_NONE) {
+ unit_list_append(battlegroups[packet_unit->battlegroup], punit);
+ }
+ if (punit->battlegroup != BATTLEGROUP_NONE) {
+ unit_list_unlink(battlegroups[punit->battlegroup], punit);
+ }
+ punit->battlegroup = packet_unit->battlegroup;
+ }
if (punit->ai.control != packet_unit->ai.control) {
punit->ai.control = packet_unit->ai.control;
repaint_unit = TRUE;
/* AI is set: may change focus */
/* AI is cleared: keep focus */
- if (packet_unit->ai.control && punit == get_unit_in_focus()) {
+ if (packet_unit->ai.control && unit_is_in_focus(punit)) {
check_focus = TRUE;
}
}
@@ -997,7 +1012,7 @@
/* May change focus if focus unit gets a new activity.
* But if new activity is Idle, it means user specifically selected
* the unit */
- if (punit == get_unit_in_focus()
+ if (unit_is_in_focus(punit)
&& (packet_unit->activity != ACTIVITY_IDLE
|| packet_unit->has_orders)) {
check_focus = TRUE;
@@ -1013,9 +1028,8 @@
&& punit->activity == ACTIVITY_SENTRY
&& packet_unit->activity == ACTIVITY_IDLE
&& is_player_phase(game.player_ptr, game.info.phase)
- && (!get_unit_in_focus()
/* only 1 wakeup focus per tile is useful */
- || !same_pos(packet_unit->tile, get_unit_in_focus()->tile))) {
+ && !get_focus_unit_on_tile(packet_unit->tile)) {
set_unit_focus(punit);
check_focus = FALSE; /* and keep it */
@@ -1031,7 +1045,7 @@
punit->transported_by = packet_unit->transported_by;
if (punit->occupy != packet_unit->occupy
- && focus_unit && focus_unit->tile == packet_unit->tile) {
+ && get_focus_unit_on_tile(packet_unit->tile)) {
/* Special case: (un)loading a unit in a transporter on the
* same tile as the focus unit may (dis)allow the focus unit to be
* loaded. Thus the orders->(un)load menu item needs updating. */
@@ -1059,7 +1073,7 @@
/* These two lines force the menus to be updated as appropriate when
* the focus unit changes. */
- if (punit == get_unit_in_focus()) {
+ if (unit_is_in_focus(punit)) {
need_update_menus = TRUE;
}
@@ -1094,7 +1108,7 @@
if (pcity && (pcity->id != punit->homecity)) {
refresh_city_dialog(pcity);
}
- if(punit == get_unit_in_focus()) {
+ if (unit_is_in_focus(punit)) {
/* Update the orders menu -- the unit might have new abilities */
need_update_menus = TRUE;
}
@@ -1102,7 +1116,7 @@
/* May change focus if an attempted move or attack exhausted unit */
if (punit->moves_left != packet_unit->moves_left
- && punit == get_unit_in_focus()) {
+ && unit_is_in_focus(punit)) {
check_focus = TRUE;
}
@@ -1206,6 +1220,11 @@
unit_list_prepend(punit->owner->units, punit);
unit_list_prepend(punit->tile->units, punit);
+ if (punit->battlegroup >= 0
+ && punit->battlegroup < MAX_NUM_BATTLEGROUPS) {
+ unit_list_append(battlegroups[punit->battlegroup], punit);
+ }
+
if((pcity=find_city_by_id(punit->homecity))) {
unit_list_prepend(pcity->units_supported, punit);
}
@@ -1226,20 +1245,17 @@
assert(punit != NULL);
- if (punit == get_unit_in_focus()) {
- update_unit_info_label(punit);
- } else if (get_unit_in_focus()
- && (same_pos(get_unit_in_focus()->tile, punit->tile)
- || (moved
- && same_pos(get_unit_in_focus()->tile, old_tile)))) {
- update_unit_info_label(get_unit_in_focus());
+ if (unit_is_in_focus(punit)
+ || get_focus_unit_on_tile(punit->tile)
+ || (moved && get_focus_unit_on_tile(old_tile))) {
+ update_unit_info_label(get_units_in_focus());
}
if (repaint_unit) {
refresh_unit_mapcanvas(punit, punit->tile, TRUE, FALSE);
}
- if ((check_focus || get_unit_in_focus() == NULL)
+ if ((check_focus || get_num_units_in_focus() == 0)
&& game.player_ptr
&& !game.player_ptr->ai.control
&& is_player_phase(game.player_ptr, game.info.phase)) {
@@ -1529,7 +1545,7 @@
/* If we just learned bridge building and focus is on a settler
on a river the road menu item will remain disabled unless we
do this. (applys in other cases as well.) */
- if (get_unit_in_focus()) {
+ if (get_num_units_in_focus() > 0) {
update_menus();
}
}
@@ -2014,8 +2030,7 @@
/* update menus if the focus unit is on the tile. */
if (tile_changed) {
- struct unit *punit = get_unit_in_focus();
- if (punit && same_pos(punit->tile, ptile)) {
+ if (get_focus_unit_on_tile(ptile)) {
update_menus();
}
}
Index: client/goto.h
===================================================================
--- client/goto.h (revision 11154)
+++ client/goto.h (working copy)
@@ -19,7 +19,7 @@
void init_client_goto(void);
void free_client_goto(void);
-void enter_goto_state(struct unit *punit);
+void enter_goto_state(struct unit_list *punits);
void exit_goto_state(void);
bool goto_is_active(void);
struct tile *get_line_dest(void);
@@ -36,9 +36,9 @@
void send_goto_path(struct unit *punit, struct pf_path *path,
struct unit_order *last_order);
bool send_goto_tile(struct unit *punit, struct tile *ptile);
-void send_patrol_route(struct unit *punit);
-void send_goto_route(struct unit *punit);
-void send_connect_route(struct unit *punit, enum unit_activity activity);
+void send_patrol_route(void);
+void send_goto_route(void);
+void send_connect_route(enum unit_activity activity);
struct pf_path *path_to_nearest_allied_city(struct unit *punit);
Index: client/tilespec.c
===================================================================
--- client/tilespec.c (revision 11154)
+++ client/tilespec.c (working copy)
@@ -190,6 +190,7 @@
*transform,
*connect,
*patrol,
+ *battlegroup[MAX_NUM_BATTLEGROUPS],
*lowfuel,
*tired;
} unit;
@@ -1861,7 +1862,7 @@
***********************************************************************/
static void tileset_lookup_sprite_tags(struct tileset *t)
{
- char buffer[512];
+ char buffer[512], buffer2[512];
const char dir_char[] = "nsew";
const int W = t->normal_tile_width, H = t->normal_tile_height;
int i, j;
@@ -2040,6 +2041,12 @@
SET_SPRITE(unit.transform, "unit.transform");
SET_SPRITE(unit.connect, "unit.connect");
SET_SPRITE(unit.patrol, "unit.patrol");
+ for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
+ my_snprintf(buffer, sizeof(buffer), "unit.battlegroup_%d", i);
+ my_snprintf(buffer2, sizeof(buffer2), "city.size_%d", i + 1);
+ assert(MAX_NUM_BATTLEGROUPS < NUM_TILES_DIGITS);
+ SET_SPRITE_ALT(unit.battlegroup[i], buffer, buffer2);
+ }
SET_SPRITE(unit.lowfuel, "unit.lowfuel");
SET_SPRITE(unit.tired, "unit.tired");
@@ -2086,8 +2093,6 @@
SET_SPRITE(city.disorder, "city.disorder");
for(i=0; i<NUM_TILES_DIGITS; i++) {
- char buffer2[512];
-
my_snprintf(buffer, sizeof(buffer), "city.size_%d", i);
SET_SPRITE(city.size[i], buffer);
my_snprintf(buffer2, sizeof(buffer2), "path.turns_%d", i);
@@ -2926,6 +2931,10 @@
}
}
+ if (punit->battlegroup != BATTLEGROUP_NONE) {
+ ADD_SPRITE_FULL(t->sprites.unit.battlegroup[punit->battlegroup]);
+ }
+
if (t->sprites.unit.lowfuel
&& unit_type(punit)->fuel > 0
&& punit->fuel == 1
@@ -3660,7 +3669,7 @@
bool known[NUM_EDGE_TILES], city[NUM_EDGE_TILES];
bool unit[NUM_EDGE_TILES], worked[NUM_EDGE_TILES];
int i;
- struct unit *pfocus = get_unit_in_focus();
+ struct unit_list *pfocus_units = get_units_in_focus();
for (i = 0; i < NUM_EDGE_TILES; i++) {
const struct tile *tile = pedge->tile[i];
@@ -3668,9 +3677,18 @@
int dummy_x, dummy_y;
known[i] = tile && client_tile_get_known(tile) != TILE_UNKNOWN;
- unit[i] = tile && pfocus && unit_flag(pfocus, F_CITIES)
- && city_can_be_built_here(pfocus->tile, pfocus)
- && base_map_to_city_map(&dummy_x, &dummy_y, pfocus->tile, tile);
+ unit[i] = FALSE;
+ if (tile) {
+ unit_list_iterate(pfocus_units, pfocus_unit) {
+ if (unit_flag(pfocus_unit, F_CITIES)
+ && city_can_be_built_here(pfocus_unit->tile, pfocus_unit)
+ && base_map_to_city_map(&dummy_x, &dummy_y,
+ pfocus_unit->tile, tile)) {
+ unit[i] = TRUE;
+ break;
+ }
+ } unit_list_iterate_end;
+ }
worked[i] = FALSE;
city[i] = (tile
@@ -3830,14 +3848,14 @@
struct terrain *pterrain = NULL, *tterrain_near[8];
bv_special tspecial, tspecial_near[8];
int tileno, dir;
- struct unit *pfocus = get_unit_in_focus();
struct drawn_sprite *save_sprs = sprs;
struct player *owner = NULL;
/* Unit drawing is disabled if the view options is turned off, but only
* if we're drawing on the mapview. */
bool do_draw_unit = (punit && (draw_units || !ptile
- || (draw_focus_unit && pfocus == punit)));
+ || (draw_focus_unit
+ && unit_is_in_focus(punit))));
bool solid_bg = (solid_color_behind_units
&& (do_draw_unit
|| (pcity && draw_cities)
@@ -4030,12 +4048,11 @@
case LAYER_UNIT:
case LAYER_FOCUS_UNIT:
- if (do_draw_unit && XOR(layer == LAYER_UNIT,
- punit == get_unit_in_focus())) {
+ if (do_draw_unit && XOR(layer == LAYER_UNIT, unit_is_in_focus(punit))) {
bool stacked = ptile && (unit_list_size(ptile->units) > 1);
bool backdrop = !pcity;
- if (ptile && punit == get_unit_in_focus()
+ if (ptile && unit_is_in_focus(punit)
&& t->sprites.unit.select[0]) {
/* Special case for drawing the selection rectangle. The blinking
* unit is handled separately, inside get_drawable_unit(). */
@@ -4279,7 +4296,6 @@
const struct city *citymode)
{
struct unit *punit = find_visible_unit(ptile);
- struct unit *pfocus = get_unit_in_focus();
if (!punit)
return NULL;
@@ -4287,9 +4303,8 @@
if (citymode && punit->owner == citymode->owner)
return NULL;
- if (punit != pfocus
- || t->sprites.unit.select[0] || focus_unit_state == 0
- || !same_pos(punit->tile, pfocus->tile))
+ if (!unit_is_in_focus(punit)
+ || t->sprites.unit.select[0] || focus_unit_state == 0)
return punit;
else
return NULL;
Index: client/mapctrl_common.c
===================================================================
--- client/mapctrl_common.c (revision 11154)
+++ client/mapctrl_common.c (working copy)
@@ -427,12 +427,9 @@
struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
if (keyboardless_goto_active && hover_state == HOVER_GOTO && ptile) {
- struct unit *punit =
- player_find_unit_by_id(game.player_ptr, hover_unit);
-
do_unit_goto(ptile);
set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
- update_unit_info_label(punit);
+ update_unit_info_label(hover_units);
}
keyboardless_goto_active = FALSE;
keyboardless_goto_button_down = FALSE;
@@ -447,7 +444,7 @@
{
struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
- if (ptile && get_unit_in_focus()
+ if (ptile && get_num_units_in_focus() > 0
&& !same_pos(keyboardless_goto_start_tile, ptile)
&& can_client_issue_orders()) {
keyboardless_goto_active = TRUE;
@@ -658,7 +655,7 @@
{
struct unit *my_unit, *defender, *attacker;
- if (!(my_unit = get_unit_in_focus())
+ if (!unit_is_in_focus(my_unit)
|| !(defender = get_defender(my_unit, ptile))
|| !(attacker = get_attacker(my_unit, ptile))) {
return FALSE;
Index: client/civclient.c
===================================================================
--- client/civclient.c (revision 11154)
+++ client/civclient.c (working copy)
@@ -680,7 +680,7 @@
time_until_next_call = MIN(time_until_next_call, blink_time);
}
- if (get_unit_in_focus()) {
+ if (get_num_units_in_focus() > 0) {
double blink_time = blink_active_unit();
time_until_next_call = MIN(time_until_next_call, blink_time);
Index: client/mapview_common.c
===================================================================
--- client/mapview_common.c (revision 11154)
+++ client/mapview_common.c (working copy)
@@ -1733,9 +1733,9 @@
return;
}
- if (punit == get_unit_in_focus() && hover_state != HOVER_NONE) {
+ if (unit_is_in_focus(punit) && hover_state != HOVER_NONE) {
set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, ORDER_LAST);
- update_unit_info_label(punit);
+ update_unit_info_label(get_units_in_focus());
}
dest_x = src_tile->x + dx;
Index: client/climisc.c
===================================================================
--- client/climisc.c (revision 11154)
+++ client/climisc.c (working copy)
@@ -74,28 +74,28 @@
struct city *pcity;
struct tile *ptile = punit->tile;
int hc = punit->homecity;
- struct unit *ufocus = get_unit_in_focus();
struct unit old_unit = *punit;
+ int old = get_num_units_in_focus();
+ bool update;
+ int i;
freelog(LOG_DEBUG, "removing unit %d, %s %s (%d %d) hcity %d",
punit->id, get_nation_name(unit_owner(punit)->nation),
unit_name(punit->type), TILE_XY(punit->tile), hc);
- if (punit == ufocus) {
- set_unit_focus(NULL);
- game_remove_unit(punit);
- punit = ufocus = NULL;
+ update = (get_first_unit_in_focus()
+ && same_pos(get_first_unit_in_focus()->tile, punit->tile));
+ unit_list_unlink(get_units_in_focus(), punit);
+ unit_list_unlink(hover_units, punit);
+ for (i = 0; i < MAX_NUM_BATTLEGROUPS; i++) {
+ unit_list_unlink(battlegroups[i], punit);
+ }
+ game_remove_unit(punit);
+ punit = NULL;
+ if (old > 0 && get_num_units_in_focus() == 0) {
advance_unit_focus();
- } else {
- /* calculate before punit disappears, use after punit removed: */
- bool update = (ufocus
- && same_pos(ufocus->tile, punit->tile));
-
- game_remove_unit(punit);
- punit = NULL;
- if (update) {
- update_unit_pix_label(ufocus);
- }
+ } else if (update) {
+ update_unit_pix_label(get_units_in_focus());
}
pcity = tile_get_city(ptile);
@@ -409,7 +409,7 @@
}
can_slide = FALSE;
- if ((punit = get_unit_in_focus())) {
+ if ((punit = get_first_unit_in_focus())) {
center_tile_mapcanvas(punit->tile);
} else if (game.player_ptr && (pcity = find_palace(game.player_ptr))) {
/* Else focus on the capital. */
- [Freeciv-Dev] Re: (PR#14365) battlegroups...,
Jason Short <=
- [Freeciv-Dev] (PR#14365) battlegroups..., Thomas Strub, 2005/10/19
- [Freeciv-Dev] (PR#14365) battlegroups..., Mateusz Stefek, 2005/10/19
- [Freeciv-Dev] Re: (PR#14365) battlegroups..., Jason Short, 2005/10/19
- [Freeciv-Dev] Re: (PR#14365) battlegroups..., Andreas Røsdal, 2005/10/20
- [Freeciv-Dev] Re: (PR#14365) battlegroups..., Jason Short, 2005/10/20
- [Freeciv-Dev] (PR#14365) battlegroups..., Mateusz Stefek, 2005/10/20
- [Freeciv-Dev] Re: (PR#14365) battlegroups..., Andreas Røsdal, 2005/10/20
- [Freeciv-Dev] Re: (PR#14365) battlegroups..., Jason Short, 2005/10/20
- [Freeciv-Dev] Re: (PR#14365) battlegroups..., Jason Short, 2005/10/21
- [Freeciv-Dev] (PR#14365) battlegroups..., Mateusz Stefek, 2005/10/21
|
|