From 9c9b79ad23d9f8c58ea39ab827164252c1ef1bd0 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Fri, 12 May 2023 21:18:55 +0300 Subject: [PATCH 14/14] Delay city size change when restoring protected unit upkeep Actually updating the city while calculating what needs to be done caused the data to get inconsistent. Some of the used values were from the city before it had shrunk, and others (reduced production) from the smaller city. See osdn #48023 Signed-off-by: Marko Lindqvist --- server/cityturn.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/server/cityturn.c b/server/cityturn.c index 4ca857e315..8262f37c76 100644 --- a/server/cityturn.c +++ b/server/cityturn.c @@ -89,7 +89,7 @@ static bool worklist_change_build_target(struct player *pplayer, struct city *pcity); static bool city_distribute_surplus_shields(struct player *pplayer, - struct city *pcity); + struct city *pcity); static bool city_build_building(struct player *pplayer, struct city *pcity); static bool city_build_unit(struct player *pplayer, struct city *pcity); static bool city_build_stuff(struct player *pplayer, struct city *pcity); @@ -2077,12 +2077,15 @@ static void upgrade_unit_prod(struct city *pcity) } /************************************************************************** - Disband units if we don't have enough shields to support them. Returns - FALSE if the _city_ is disbanded as a result. + Disband units if we don't have enough shields to support them. + Returns FALSE if the _city_ is disbanded as a result. **************************************************************************/ static bool city_distribute_surplus_shields(struct player *pplayer, - struct city *pcity) + struct city *pcity) { + int size_reduction = 0; + struct unit *sacrifizer; + if (pcity->surplus[O_SHIELD] < 0) { unit_list_iterate_safe(pcity->units_supported, punit) { if (utype_upkeep_cost(unit_type_get(punit), pplayer, O_SHIELD) > 0 @@ -2109,14 +2112,9 @@ static bool city_distribute_surplus_shields(struct player *pplayer, if (upkeep > 0 && pcity->surplus[O_SHIELD] < 0) { fc_assert_action(unit_has_type_flag(punit, UTYF_UNDISBANDABLE), continue); - notify_player(pplayer, city_tile(pcity), - E_UNIT_LOST_MISC, ftc_server, - _("Citizens in %s perish for their failure to " - "upkeep %s!"), - city_link(pcity), unit_link(punit)); - if (!city_reduce_size(pcity, 1, NULL, "upkeep_failure")) { - return FALSE; - } + + size_reduction++; + sacrifizer = punit; /* Last one, if there's multiple */ /* No upkeep for the unit this turn. */ pcity->surplus[O_SHIELD] += upkeep; @@ -2129,6 +2127,18 @@ static bool city_distribute_surplus_shields(struct player *pplayer, pcity->before_change_shields = pcity->shield_stock; pcity->last_turns_shield_surplus = pcity->surplus[O_SHIELD]; + if (size_reduction > 0) { + notify_player(pplayer, city_tile(pcity), + E_UNIT_LOST_MISC, ftc_server, + _("Citizens in %s perish for their failure to " + "upkeep %s!"), + city_link(pcity), unit_link(sacrifizer)); + + if (!city_reduce_size(pcity, size_reduction, NULL, "upkeep_failure")) { + return FALSE; + } + } + return TRUE; } -- 2.39.2