From a524f93df917b9896550c2e41403ba78ba59e06b Mon Sep 17 00:00:00 2001 From: Ihnatus Date: Wed, 9 Feb 2022 22:07:48 +0300 Subject: [PATCH] Unhardcode autoupgrade mechanism. The mechanics behind "Upgrade_Unit" effect and game.ruleset:civstyle.autoupgrade_veteran_loss is now performed by default.lua:_deflua_do_auto_upgrades() callback at "player_alive_phase_end" signal, and ruleset authors may override it with whatever. AI evaluation of the effect and automatic help text were not changed. See OSDN#42659. Signed-off-by: Ihnatus --- data/default/default.lua | 39 ++++++++++++++++++++- server/unittools.c | 74 +++++++--------------------------------- 2 files changed, 51 insertions(+), 62 deletions(-) diff --git a/data/default/default.lua b/data/default/default.lua index 03d4c5779e..9ba7a06a54 100644 --- a/data/default/default.lua +++ b/data/default/default.lua @@ -114,7 +114,7 @@ function _deflua_hut_get_barbarians(unit) _("An abandoned village is here.")) return true end - + local alive = tile:unleash_barbarians() if alive then notify.event(owner, tile, E.HUT_BARB, @@ -217,6 +217,43 @@ end signal.connect("city_transferred", "_deflua_make_partisans_callback") +-- Do unit auto-upgrades to players with the "Upgrade_Unit" effect +-- (traditionally from Leonardo's Workshop). +function _deflua_do_upgrade_effects(player) + local upgrades, candidates + = effects.player_bonus(player, "Upgrade_Unit"); + + if upgrades <= 0 then + return; + end + + candidates = {}; + for u in player:units_iterate() do + -- We have to be careful not to strand units at sea, for example by + -- upgrading a frigate to an ironclad while it was carrying a unit. + if u:can_upgrade() then + table.insert(candidates, u) -- Potential candidate :) + end + end + + while upgrades > 0 and #candidates > 0 do + -- Upgrade one unit. The unit is chosen at random from the list of + -- available candidates. + local candidate_to_upgrade = random(1, #candidates) + local u = candidates[candidate_to_upgrade] + local type_from = u.utype; + local type_to = player:can_upgrade(type_from); + + u:transform(type_to, game.autoupgrade_veteran_loss); + notify.event(player, u.tile, E.UNIT_UPGRADED, + _("%s was upgraded for free to %s."), + type_from:name_translation(), u:link_text()); + table.remove(candidates, candidate_to_upgrade) + upgrades = upgrades - 1 + end +end + +signal.connect("player_alive_phase_end", "_deflua_do_upgrade_effects") -- Notify player about the fact that disaster had no effect if that is -- the case diff --git a/server/unittools.c b/server/unittools.c index c4020b2b64..2b1344a894 100644 --- a/server/unittools.c +++ b/server/unittools.c @@ -137,7 +137,6 @@ static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype, bool helpless, bool teleporting, const struct city *pexclcity); static void wakeup_neighbor_sentries(struct unit *punit); -static void do_upgrade_effects(struct player *pplayer); static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit); @@ -404,73 +403,26 @@ void combat_veterans(struct unit *attacker, struct unit *defender, } /**********************************************************************//** - Do unit auto-upgrades to players with the EFT_UNIT_UPGRADE effect - (traditionally from Leonardo's Workshop). -**************************************************************************/ -static void do_upgrade_effects(struct player *pplayer) -{ - int upgrades = get_player_bonus(pplayer, EFT_UPGRADE_UNIT); - struct unit_list *candidates; + 1. Restore/decrease unit hitpoints. - if (upgrades <= 0) { - return; - } - candidates = unit_list_new(); + 2. Kill dead units. - unit_list_iterate(pplayer->units, punit) { - /* We have to be careful not to strand units at sea, for example by - * upgrading a frigate to an ironclad while it was carrying a unit. */ - if (UU_OK == unit_upgrade_test(punit, TRUE)) { - unit_list_prepend(candidates, punit); /* Potential candidate :) */ - } - } unit_list_iterate_end; + 3. Rescue airplanes by returning them to base automatically. - while (upgrades > 0 && unit_list_size(candidates) > 0) { - /* Upgrade one unit. The unit is chosen at random from the list of - * available candidates. */ - int candidate_to_upgrade = fc_rand(unit_list_size(candidates)); - struct unit *punit = unit_list_get(candidates, candidate_to_upgrade); - const struct unit_type *type_from = unit_type_get(punit); - const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from); - - transform_unit(punit, type_to, game.server.autoupgrade_veteran_loss); - notify_player(pplayer, unit_tile(punit), E_UNIT_UPGRADED, ftc_server, - _("%s was upgraded for free to %s."), - utype_name_translation(type_from), - unit_link(punit)); - unit_list_remove(candidates, punit); - upgrades--; - } + 4. Decrease fuel of planes in the air. - unit_list_destroy(candidates); -} + 5. Refuel planes that are in bases. -/**********************************************************************//** - 1. Do Leonardo's Workshop upgrade if applicable. - - 2. Restore/decrease unit hitpoints. - - 3. Kill dead units. - - 4. Rescue airplanes by returning them to base automatically. - - 5. Decrease fuel of planes in the air. - - 6. Refuel planes that are in bases. - - 7. Kill planes that are out of fuel. + 6. Kill planes that are out of fuel. **************************************************************************/ void player_restore_units(struct player *pplayer) { - /* 1) get Leonardo out of the way first: */ - do_upgrade_effects(pplayer); - unit_list_iterate_safe(pplayer->units, punit) { - /* 2) Modify unit hitpoints. Helicopters can even lose them. */ + /* 1) Modify unit hitpoints. Helicopters can even lose them. */ unit_restore_hitpoints(punit); - /* 3) Check that unit has hitpoints */ + /* 2) Check that unit has hitpoints */ if (punit->hp <= 0) { /* This should usually only happen for heli units, but if any other * units get 0 hp somehow, catch them too. --dwp */ @@ -491,7 +443,7 @@ void player_restore_units(struct player *pplayer) continue; /* Continue iterating... */ } - /* 4) Rescue planes if needed */ + /* 3) Rescue planes if needed */ if (utype_fuel(unit_type_get(punit))) { /* Shall we emergency return home on the last vapors? */ @@ -575,10 +527,10 @@ void player_restore_units(struct player *pplayer) } } - /* 5) Update fuel */ + /* 4) Update fuel */ punit->fuel--; - /* 6) Automatically refuel air units in cities, airbases, and + /* 5) Automatically refuel air units in cities, airbases, and * transporters (carriers). */ if (is_unit_being_refueled(punit)) { punit->fuel = utype_fuel(unit_type_get(punit)); @@ -586,14 +538,14 @@ void player_restore_units(struct player *pplayer) } } unit_list_iterate_safe_end; - /* 7) Check if there are air units without fuel */ + /* 6) Check if there are air units without fuel */ unit_list_iterate_safe(pplayer->units, punit) { const struct unit_type *utype = unit_type_get(punit); if (punit->fuel <= 0 && utype_fuel(utype)) { /* Notifications sent from the lua script when unit wiped. */ wipe_unit(punit, ULR_FUEL, NULL); - } + } } unit_list_iterate_safe_end; /* Send all updates. */ -- 2.32.0