From 366ba2dcdd94a3ec8a144f984c628a1d5150f85e Mon Sep 17 00:00:00 2001 From: Sveinung Kvilhaugsvik Date: Wed, 3 Mar 2021 03:49:01 +0100 Subject: [PATCH] Ruleset actor consuming always for nukes A nuke can have a max range where the resulting explosion won't destroy the actor unit. In that case the ruleset should also be able to set that the actor unit isn't consumed by it. This allows (ISFJ girl joke) units like "Pink Unicorn Princess of Doom" or (more serious) units like "Nuclear Sub" to case a nuclear explosion somewhere without being destroyed them self. The "ammo" of the action can - as an example - be represented as a loss of MP when performing the action and a minimum MP requirement to perform the action if it is desired to restore the ammo at turn change. See osdn #41681 --- common/actions.c | 9 ++++++--- data/alien/game.ruleset | 9 +++++++++ data/civ1/game.ruleset | 9 +++++++++ data/civ2/game.ruleset | 9 +++++++++ data/civ2civ3/game.ruleset | 9 +++++++++ data/classic/game.ruleset | 9 +++++++++ data/experimental/game.ruleset | 9 +++++++++ data/granularity/game.ruleset | 9 +++++++++ data/multiplayer/game.ruleset | 9 +++++++++ data/sandbox/game.ruleset | 9 +++++++++ data/stub/game.ruleset | 9 +++++++++ data/webperimental/game.ruleset | 9 +++++++++ doc/README.actions | 3 +++ server/rscompat.c | 7 +++++++ server/unithand.c | 6 +++--- 15 files changed, 118 insertions(+), 6 deletions(-) diff --git a/common/actions.c b/common/actions.c index e5225579d7..7690ede21b 100644 --- a/common/actions.c +++ b/common/actions.c @@ -8410,8 +8410,6 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act) case ACTION_JOIN_CITY: case ACTION_SPY_NUKE: case ACTION_SPY_NUKE_ESC: - case ACTION_NUKE_CITY: - case ACTION_NUKE_UNITS: case ACTION_DESTROY_CITY: case ACTION_RECYCLE_UNIT: case ACTION_DISBAND_UNIT: @@ -8454,7 +8452,6 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act) case ACTION_BOMBARD: case ACTION_BOMBARD2: case ACTION_BOMBARD3: - case ACTION_NUKE: case ACTION_SPY_ATTACK: case ACTION_CONQUER_EXTRAS: case ACTION_CONQUER_EXTRAS2: @@ -8473,6 +8470,12 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act) case ACTION_UNIT_MOVE3: /* actor consuming always is not ruleset changeable */ return NULL; + case ACTION_NUKE: + return "explode_nuclear_consuming_always"; + case ACTION_NUKE_CITY: + return "nuke_city_consuming_always"; + case ACTION_NUKE_UNITS: + return "nuke_units_consuming_always"; case ACTION_SPY_SPREAD_PLAGUE: return "spread_plague_actor_consuming_always"; case ACTION_USER_ACTION1: diff --git a/data/alien/game.ruleset b/data/alien/game.ruleset index 116063c34a..a97a2e8d2a 100644 --- a/data/alien/game.ruleset +++ b/data/alien/game.ruleset @@ -353,6 +353,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -360,6 +363,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -373,6 +379,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the "Airlift Unit" ; action. The value 1 means that the targets must be on a tile adjacent to ; the actor unit. The special value "unlimited" lifts the maximum distance diff --git a/data/civ1/game.ruleset b/data/civ1/game.ruleset index 5b76019989..d9d0304b26 100644 --- a/data/civ1/game.ruleset +++ b/data/civ1/game.ruleset @@ -336,6 +336,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -343,6 +346,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -356,6 +362,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; What each action should be called when showing them to the player. ; The first %s should be before the mnemonic of the action. A Freeciv client ; that supports mnemonics will replace it with the in-band signal that marks diff --git a/data/civ2/game.ruleset b/data/civ2/game.ruleset index 9e44cb579b..6821c52457 100644 --- a/data/civ2/game.ruleset +++ b/data/civ2/game.ruleset @@ -335,6 +335,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -342,6 +345,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -355,6 +361,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the "Airlift Unit" ; action. The value 1 means that the targets must be on a tile adjacent to ; the actor unit. The special value "unlimited" lifts the maximum distance diff --git a/data/civ2civ3/game.ruleset b/data/civ2civ3/game.ruleset index 58ffc2fe54..d948fc67d1 100644 --- a/data/civ2civ3/game.ruleset +++ b/data/civ2civ3/game.ruleset @@ -380,6 +380,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -387,6 +390,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -400,6 +406,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the "Airlift Unit" ; action. The value 1 means that the targets must be on a tile adjacent to ; the actor unit. The special value "unlimited" lifts the maximum distance diff --git a/data/classic/game.ruleset b/data/classic/game.ruleset index 33897d03a7..dcef4b67cc 100644 --- a/data/classic/game.ruleset +++ b/data/classic/game.ruleset @@ -364,6 +364,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -371,6 +374,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -384,6 +390,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the "Airlift Unit" ; action. The value 1 means that the targets must be on a tile adjacent to ; the actor unit. The special value "unlimited" lifts the maximum distance diff --git a/data/experimental/game.ruleset b/data/experimental/game.ruleset index 576cc4a1c5..7d112a1417 100644 --- a/data/experimental/game.ruleset +++ b/data/experimental/game.ruleset @@ -369,6 +369,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -376,6 +379,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -389,6 +395,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the "Airlift Unit" ; action. The value 1 means that the targets must be on a tile adjacent to ; the actor unit. The special value "unlimited" lifts the maximum distance diff --git a/data/granularity/game.ruleset b/data/granularity/game.ruleset index 26ebd61706..fdca65f575 100644 --- a/data/granularity/game.ruleset +++ b/data/granularity/game.ruleset @@ -304,6 +304,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -311,6 +314,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -324,6 +330,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; What each action should be called when showing them to the player. ; The first %s should be before the mnemonic of the action. A Freeciv client ; that supports mnemonics will replace it with the in-band signal that marks diff --git a/data/multiplayer/game.ruleset b/data/multiplayer/game.ruleset index ab7f59e23c..027bfbfeba 100644 --- a/data/multiplayer/game.ruleset +++ b/data/multiplayer/game.ruleset @@ -362,6 +362,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -369,6 +372,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -382,6 +388,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the "Airlift Unit" ; action. The value 1 means that the targets must be on a tile adjacent to ; the actor unit. The special value "unlimited" lifts the maximum distance diff --git a/data/sandbox/game.ruleset b/data/sandbox/game.ruleset index c103ed8bbf..27c13234a9 100644 --- a/data/sandbox/game.ruleset +++ b/data/sandbox/game.ruleset @@ -380,6 +380,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = "unlimited" +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -387,6 +390,9 @@ explode_nuclear_max_range = "unlimited" ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -400,6 +406,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the "Airlift Unit" ; action. The value 1 means that the targets must be on a tile adjacent to ; the actor unit. The special value "unlimited" lifts the maximum distance diff --git a/data/stub/game.ruleset b/data/stub/game.ruleset index 25c351561e..976765bc4d 100644 --- a/data/stub/game.ruleset +++ b/data/stub/game.ruleset @@ -295,6 +295,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -302,6 +305,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -315,6 +321,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; What each action should be called when showing them to the player. ; The first %s should be before the mnemonic of the action. A Freeciv client ; that supports mnemonics will replace it with the in-band signal that marks diff --git a/data/webperimental/game.ruleset b/data/webperimental/game.ruleset index c160fce10d..bb9a0f6c5c 100644 --- a/data/webperimental/game.ruleset +++ b/data/webperimental/game.ruleset @@ -337,6 +337,9 @@ bombard_3_max_range = 1 ; the minimum distance. explode_nuclear_max_range = 0 +; Will performing this action always consume the actor unit? +explode_nuclear_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the ; "Nuke City" action. The value 1 means that the tile must be a tile ; adjacent to the actor unit. The special value "unlimited" lifts the @@ -344,6 +347,9 @@ explode_nuclear_max_range = 0 ; the minimum distance. nuke_city_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_city_consuming_always = TRUE; + ; The kind of target the "Nuke City" action has. The target requirements of ; its enablers are evaluated against the target. The target owner is the one ; that gets a Casus Belli if the ruleset has a Casus Belli for this action. @@ -357,6 +363,9 @@ nuke_city_target_kind = "individual cities" ; the minimum distance. nuke_units_max_range = 1 +; Will performing this action always consume the actor unit? +nuke_units_consuming_always = TRUE; + ; The maximum distance from the actor unit to the target of the "Airlift Unit" ; action. The value 1 means that the targets must be on a tile adjacent to ; the actor unit. The special value "unlimited" lifts the maximum distance diff --git a/doc/README.actions b/doc/README.actions index a8057c6e27..87f2f9f51d 100644 --- a/doc/README.actions +++ b/doc/README.actions @@ -769,6 +769,7 @@ Actions done by a unit against all units at a tile "Nuke Units" - Detonate at the target unit stack. Cause a nuclear explosion. * UI name can be set using ui_name_nuke_units + * set if the actor unit is spent with nuke_units_consuming_always * any action listed in nuke_units_blocked_by must be impossible * the actor unit must be on a tile next to the target unless nuke_units_max_range allows it to be further away. @@ -797,6 +798,7 @@ Actions done by a unit against a tile "Explode Nuclear" - Detonate at the target tile. Cause a nuclear explosion. * UI name can be set using ui_name_explode_nuclear + * set if the actor unit is spent with explode_nuclear_consuming_always * target kind can be changed with explode_nuclear_target_kind * any action listed in explode_nuclear_blocked_by must be impossible * actor must be on the same tile as the target unless @@ -804,6 +806,7 @@ Actions done by a unit against a tile "Nuke City" - Detonate in the target city. Cause a nuclear explosion. * UI name can be set using ui_name_nuke_city + * set if the actor unit is spent with nuke_city_consuming_always * target kind can be changed with nuke_city_target_kind * any action listed in nuke_city_blocked_by must be impossible * the actor unit must be on a tile next to the target unless diff --git a/server/rscompat.c b/server/rscompat.c index c2eb50efeb..18c3d93e32 100644 --- a/server/rscompat.c +++ b/server/rscompat.c @@ -837,6 +837,13 @@ void rscompat_postprocess(struct rscompat_info *info) paction = action_by_number(ACTION_NUKE_CITY); paction->target_kind = ATK_CITY; + paction->actor_consuming_always = TRUE; + + paction = action_by_number(ACTION_NUKE); + paction->actor_consuming_always = TRUE; + + paction = action_by_number(ACTION_NUKE_UNITS); + paction->actor_consuming_always = TRUE; enabler = action_enabler_new(); enabler->action = ACTION_PILLAGE; diff --git a/server/unithand.c b/server/unithand.c index 50cc3dfa6a..5129c726f9 100644 --- a/server/unithand.c +++ b/server/unithand.c @@ -4161,12 +4161,12 @@ static bool unit_nuke(struct player *pplayer, struct unit *punit, dlsend_packet_nuke_tile_info(game.est_connections, tile_index(def_tile)); - /* A nuke is always consumed when it detonates. See below. */ - fc_assert(paction->actor_consuming_always); /* The nuke must be wiped here so it won't be seen as a victim of its own * detonation. */ - wipe_unit(punit, ULR_DETONATED, NULL); + if (paction->actor_consuming_always) { + wipe_unit(punit, ULR_DETONATED, NULL); + } do_nuclear_explosion(pplayer, def_tile); -- 2.20.1