From 3570013dea10f6f67cc910cdb092d6f03a8a1040 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Tue, 18 Jul 2023 17:08:39 +0300 Subject: [PATCH 22/22] occupy_move(): Fix crash if unit died on autoperformers See osdn #48300 Signed-off-by: Marko Lindqvist --- server/unithand.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/server/unithand.c b/server/unithand.c index 381fe6b441..373eff52b3 100644 --- a/server/unithand.c +++ b/server/unithand.c @@ -491,7 +491,7 @@ static bool do_capture_units(struct player *pplayer, /**********************************************************************//** Occupying move after an action. **************************************************************************/ -static void occupy_move(struct tile *def_tile, struct unit *punit, +static bool occupy_move(struct tile *def_tile, struct unit *punit, const struct action *paction) { if (!is_non_allied_unit_tile(def_tile, unit_owner(punit))) { @@ -499,6 +499,7 @@ static void occupy_move(struct tile *def_tile, struct unit *punit, * and adjust moves_left to afterward (if successful). */ int old_moves = punit->moves_left; int full_moves = unit_move_rate(punit); + int id = punit->id; punit->moves_left = full_moves; /* Post attack occupy move. */ @@ -506,18 +507,26 @@ static void occupy_move(struct tile *def_tile, struct unit *punit, NULL, NULL, paction, def_tile, tile_city(def_tile), NULL, NULL)) { - int mcost = MAX(0, full_moves - punit->moves_left - SINGLE_MOVE); - - /* Move cost is bigger of attack (SINGLE_MOVE) and occupying move costs. - * Attack SINGLE_COST is already calculated in to old_moves. */ - punit->moves_left = old_moves - mcost; - if (punit->moves_left < 0) { - punit->moves_left = 0; + if (unit_is_alive(id)) { + int mcost = MAX(0, full_moves - punit->moves_left - SINGLE_MOVE); + + /* Move cost is bigger of attack (SINGLE_MOVE) and occupying move costs. + * Attack SINGLE_COST is already calculated in to old_moves. */ + punit->moves_left = old_moves - mcost; + if (punit->moves_left < 0) { + punit->moves_left = 0; + } + } else { + return FALSE; } - } else { + } else if (unit_is_alive(id)) { punit->moves_left = old_moves; + } else { + return FALSE; } } + + return TRUE; } /**********************************************************************//** @@ -531,6 +540,7 @@ static bool do_wipe_units(struct unit *punit, const struct action *paction) { struct player *wiper = unit_owner(punit); + int wid = punit->id; char wiper_link[MAX_LEN_LINK]; const char *wiper_nation = nation_plural_for_player(wiper); const struct unit_type *act_utype = unit_type_get(punit); @@ -562,12 +572,12 @@ static bool do_wipe_units(struct unit *punit, } unit_list_iterate_safe_end; - occupy_move(pdesttile, punit, paction); - - unit_did_action(punit); - unit_forget_last_activity(punit); + if (unit_is_alive(wid) && occupy_move(pdesttile, punit, paction)) { + unit_did_action(punit); + unit_forget_last_activity(punit); - send_unit_info(NULL, punit); + send_unit_info(NULL, punit); + } return TRUE; } @@ -5130,9 +5140,9 @@ static bool do_attack(struct unit *punit, struct tile *def_tile, } } - /* If attacker wins, and occupychance > 0, it might move in. Don't move in + /* If attacker wins, and occupychance > 0, it might move in. Don't move in * if there are enemy units in the tile (a fortress, city or air base with - * multiple defenders and unstacked combat). Note that this could mean + * multiple defenders and unstacked combat). Note that this could mean * capturing (or destroying) a city. */ if (pwinner == punit && fc_rand(100) < game.server.occupychance) { -- 2.40.1