From 56ac192d6a706f2941e68980318034b94e00986a Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Thu, 5 Oct 2023 22:34:33 +0300 Subject: [PATCH 53/53] Add action type Collect Ransom See osdn #42028 Signed-off-by: Marko Lindqvist --- ai/default/daicity.c | 2 +- ai/default/daidiplomacy.c | 1 + common/actions.c | 39 ++++++- common/actions.h | 43 ++++---- common/actres.c | 20 +++- common/actres.h | 3 - common/fc_types.h | 12 +-- data/alien/actions.ruleset | 70 +++++++++---- data/alien/effects.ruleset | 8 ++ data/civ1/actions.ruleset | 41 +++++++- data/civ1/effects.ruleset | 18 ++++ data/civ2/actions.ruleset | 53 +++++++++- data/civ2/effects.ruleset | 18 ++++ data/civ2civ3/actions.ruleset | 62 ++++++++++-- data/civ2civ3/effects.ruleset | 18 ++++ data/classic/actions.ruleset | 59 +++++++++-- data/classic/effects.ruleset | 18 ++++ data/goldkeep/actions.ruleset | 53 +++++++++- data/goldkeep/effects.ruleset | 18 ++++ data/granularity/actions.ruleset | 8 +- data/multiplayer/actions.ruleset | 53 +++++++++- data/multiplayer/effects.ruleset | 18 ++++ data/sandbox/actions.ruleset | 91 ++++++++++++++++- data/sandbox/effects.ruleset | 18 ++++ data/stub/actions.ruleset | 9 +- data/webperimental/actions.ruleset | 50 ++++++++- data/webperimental/effects.ruleset | 18 ++++ doc/README.actions | 23 +++++ server/advisors/advdata.c | 1 + server/rssanity.c | 7 +- server/ruleset.c | 5 + server/unithand.c | 12 ++- server/unittools.c | 157 +++++++++++++++++++---------- server/unittools.h | 3 +- 34 files changed, 880 insertions(+), 149 deletions(-) diff --git a/ai/default/daicity.c b/ai/default/daicity.c index 3f24966c7f..78c4a5f104 100644 --- a/ai/default/daicity.c +++ b/ai/default/daicity.c @@ -1287,6 +1287,7 @@ static int action_target_neg_util(action_id act_id, case ACTRES_PARADROP: case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: + case ACTRES_COLLECT_RANSOM: case ACTRES_HEAL_UNIT: case ACTRES_TRANSFORM_TERRAIN: case ACTRES_CULTIVATE: @@ -1315,7 +1316,6 @@ static int action_target_neg_util(action_id act_id, case ACTRES_ENABLER_CHECK: case ACTRES_UNUSED_1: - case ACTRES_UNUSED_2: fc_assert_msg(action_id_get_target_kind(act_id) == ATK_CITY, "Action not aimed at cities"); break; diff --git a/ai/default/daidiplomacy.c b/ai/default/daidiplomacy.c index 5e04394949..3ef8550385 100644 --- a/ai/default/daidiplomacy.c +++ b/ai/default/daidiplomacy.c @@ -1997,6 +1997,7 @@ void dai_incident(struct ai_type *ait, enum incident_type type, case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: case ACTRES_SPY_ATTACK: + case ACTRES_COLLECT_RANSOM: /* Unit loss */ dai_incident_simple(receiver, violator, victim, scope, 5); break; diff --git a/common/actions.c b/common/actions.c index 79abe2962b..32881fcc8f 100644 --- a/common/actions.c +++ b/common/actions.c @@ -728,6 +728,14 @@ static void hard_code_actions(void) MAK_UNREPRESENTABLE, /* Overwritten by the ruleset */ 0, 1, FALSE); + actions[ACTION_COLLECT_RANSOM] = + unit_action_new(ACTION_COLLECT_RANSOM, ACTRES_COLLECT_RANSOM, + FALSE, TRUE, + /* Tries a forced move if the target unit's tile has + * no non-allied units and the occupychance dice roll + * tells it to move. */ + MAK_FORCED, + 1, 1, FALSE); /* The structure even for these need to be created, for * the action_id_rule_name() to work on iterations. */ @@ -2353,6 +2361,7 @@ action_actor_utype_hard_reqs_ok_full(const struct action *paction, case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: + case ACTRES_COLLECT_RANSOM: if (actor_unittype->attack_strength <= 0) { /* Reason: Can't attack without strength. */ return FALSE; @@ -2673,6 +2682,7 @@ action_hard_reqs_actor(const struct action *paction, case ACTRES_UPGRADE_UNIT: case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: + case ACTRES_COLLECT_RANSOM: case ACTRES_STRIKE_BUILDING: case ACTRES_STRIKE_PRODUCTION: case ACTRES_CONQUER_CITY: @@ -2819,7 +2829,8 @@ is_action_possible(const action_id wanted_action, /* Quick checks for action itself */ if (paction->result == ACTRES_ATTACK - || paction->result == ACTRES_WIPE_UNITS) { + || paction->result == ACTRES_WIPE_UNITS + || paction->result == ACTRES_COLLECT_RANSOM) { /* Reason: Keep the old rules. */ if (!can_unit_attack_tile(actor->unit, paction, target->tile)) { return TRI_NO; @@ -3915,6 +3926,7 @@ action_prob(const action_id wanted_action, chance = ACTPROB_CERTAIN; break; case ACTRES_ATTACK: + case ACTRES_COLLECT_RANSOM: { struct unit *defender_unit = get_defender(nmap, actor->unit, target->tile, paction); @@ -4017,7 +4029,6 @@ action_prob(const action_id wanted_action, break; case ACTRES_UNUSED_1: - case ACTRES_UNUSED_2: chance = ACTPROB_NOT_IMPLEMENTED; break; } @@ -4321,7 +4332,8 @@ action_prob_vs_units_full(const struct unit* actor_unit, } if ((action_id_has_result_safe(act_id, ACTRES_ATTACK) - || action_id_has_result_safe(act_id, ACTRES_WIPE_UNITS)) + || action_id_has_result_safe(act_id, ACTRES_WIPE_UNITS) + || action_id_has_result_safe(act_id, ACTRES_COLLECT_RANSOM)) && tile_city(target_tile) != NULL && !pplayers_at_war(city_owner(tile_city(target_tile)), unit_owner(actor_unit))) { @@ -4332,7 +4344,8 @@ action_prob_vs_units_full(const struct unit* actor_unit, if ((action_id_has_result_safe(act_id, ACTRES_ATTACK) || action_id_has_result_safe(act_id, ACTRES_WIPE_UNITS) - || action_id_has_result_safe(act_id, ACTRES_NUKE_UNITS)) + || action_id_has_result_safe(act_id, ACTRES_NUKE_UNITS) + || action_id_has_result_safe(act_id, ACTRES_COLLECT_RANSOM)) && !is_native_tile(unit_type_get(actor_unit), target_tile) && !can_attack_non_native(unit_type_get(actor_unit))) { /* Hard coded rule: can't "Nuke Units", "Wipe Units", "Suicide Attack", @@ -5788,6 +5801,8 @@ const char *action_ui_name_ruleset_var_name(int act) return "ui_name_suicide_attack_2"; case ACTION_WIPE_UNITS: return "ui_name_wipe_units"; + case ACTION_COLLECT_RANSOM: + return "ui_name_collect_ransom"; case ACTION_STRIKE_BUILDING: return "ui_name_surgical_strike_building"; case ACTION_STRIKE_PRODUCTION: @@ -6106,6 +6121,9 @@ const char *action_ui_name_default(int act) case ACTION_WIPE_UNITS: /* TRANS: _Wipe Units (100% chance of success). */ return N_("%sWipe Units%s"); + case ACTION_COLLECT_RANSOM: + /* TRANS: Collect _Ransom (100% chance of success). */ + return N_("Collect %sRansom%s"); case ACTION_STRIKE_BUILDING: /* TRANS: Surgical Str_ike Building (100% chance of success). */ return N_("Surgical Str%sike Building%s"); @@ -6308,6 +6326,7 @@ const char *action_min_range_ruleset_var_name(int act) case ACTION_SUICIDE_ATTACK: case ACTION_SUICIDE_ATTACK2: case ACTION_WIPE_UNITS: + case ACTION_COLLECT_RANSOM: case ACTION_STRIKE_BUILDING: case ACTION_STRIKE_PRODUCTION: case ACTION_CONQUER_CITY: @@ -6442,6 +6461,7 @@ int action_min_range_default(enum action_result result) case ACTRES_STRIKE_PRODUCTION: case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: + case ACTRES_COLLECT_RANSOM: case ACTRES_CONQUER_CITY: case ACTRES_HEAL_UNIT: case ACTRES_TRANSFORM_TERRAIN: @@ -6548,6 +6568,7 @@ const char *action_max_range_ruleset_var_name(int act) case ACTION_SUICIDE_ATTACK: case ACTION_SUICIDE_ATTACK2: case ACTION_WIPE_UNITS: + case ACTION_COLLECT_RANSOM: case ACTION_STRIKE_BUILDING: case ACTION_STRIKE_PRODUCTION: case ACTION_CONQUER_CITY: @@ -6689,6 +6710,7 @@ int action_max_range_default(enum action_result result) case ACTRES_STRIKE_PRODUCTION: case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: + case ACTRES_COLLECT_RANSOM: case ACTRES_CONQUER_CITY: case ACTRES_HEAL_UNIT: case ACTRES_TRANSFORM_TERRAIN: @@ -6806,6 +6828,7 @@ const char *action_target_kind_ruleset_var_name(int act) case ACTION_SUICIDE_ATTACK: case ACTION_SUICIDE_ATTACK2: case ACTION_WIPE_UNITS: + case ACTION_COLLECT_RANSOM: case ACTION_STRIKE_BUILDING: case ACTION_STRIKE_PRODUCTION: case ACTION_CONQUER_CITY: @@ -6947,6 +6970,7 @@ action_target_kind_default(enum action_result result) case ACTRES_CAPTURE_UNITS: case ACTRES_NUKE_UNITS: case ACTRES_SPY_ATTACK: + case ACTRES_COLLECT_RANSOM: return ATK_UNITS; case ACTRES_FOUND_CITY: case ACTRES_NUKE: @@ -7042,6 +7066,7 @@ bool action_result_legal_target_kind(enum action_result result, case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: case ACTRES_SPY_ATTACK: + case ACTRES_COLLECT_RANSOM: return tgt_kind == ATK_UNITS; case ACTRES_FOUND_CITY: case ACTRES_PARADROP: @@ -7151,6 +7176,7 @@ action_sub_target_kind_default(enum action_result result) case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: case ACTRES_SPY_ATTACK: + case ACTRES_COLLECT_RANSOM: return ASTK_NONE; case ACTRES_FOUND_CITY: case ACTRES_NUKE: @@ -7253,6 +7279,7 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act) case ACTION_SUICIDE_ATTACK: case ACTION_SUICIDE_ATTACK2: case ACTION_WIPE_UNITS: + case ACTION_COLLECT_RANSOM: case ACTION_STRIKE_BUILDING: case ACTION_STRIKE_PRODUCTION: case ACTION_CONQUER_CITY: @@ -7386,6 +7413,8 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act) return "suicide_attack_2_blocked_by"; case ACTION_WIPE_UNITS: return "wipe_units_blocked_by"; + case ACTION_COLLECT_RANSOM: + return "collect_ransom_blocked_by"; case ACTION_CONQUER_CITY: return "conquer_city_blocked_by"; case ACTION_CONQUER_CITY2: @@ -7542,6 +7571,8 @@ action_post_success_forced_ruleset_var_name(const struct action *act) return "attack_2_post_success_forced_actions"; case ACTION_WIPE_UNITS: return "wipe_units_post_success_forced_actions"; + case ACTION_COLLECT_RANSOM: + return "collect_ransom_post_success_forced_actions"; case ACTION_MARKETPLACE: case ACTION_BOMBARD: case ACTION_BOMBARD2: diff --git a/common/actions.h b/common/actions.h index 0e1eccbc18..ae7ac20e7e 100644 --- a/common/actions.h +++ b/common/actions.h @@ -282,20 +282,22 @@ const char *gen_action_name_update_cb(const char *old_name); #define SPECENUM_VALUE115NAME "Teleport Conquer" #define SPECENUM_VALUE116 ACTION_CLEAN #define SPECENUM_VALUE116NAME "Clean" +#define SPECENUM_VALUE117 ACTION_COLLECT_RANSOM +#define SPECENUM_VALUE117NAME "Collect Ransom" /* Enabler checks only */ -#define SPECENUM_VALUE117 ACTION_GAIN_VETERANCY -#define SPECENUM_VALUE117NAME "Gain Veterancy" +#define SPECENUM_VALUE118 ACTION_GAIN_VETERANCY +#define SPECENUM_VALUE118NAME "Gain Veterancy" /* User actions */ -#define SPECENUM_VALUE118 ACTION_USER_ACTION1 -#define SPECENUM_VALUE118NAME "User Action 1" -#define SPECENUM_VALUE119 ACTION_USER_ACTION2 -#define SPECENUM_VALUE119NAME "User Action 2" -#define SPECENUM_VALUE120 ACTION_USER_ACTION3 -#define SPECENUM_VALUE120NAME "User Action 3" -#define SPECENUM_VALUE121 ACTION_USER_ACTION4 -#define SPECENUM_VALUE121NAME "User Action 4" +#define SPECENUM_VALUE119 ACTION_USER_ACTION1 +#define SPECENUM_VALUE119NAME "User Action 1" +#define SPECENUM_VALUE120 ACTION_USER_ACTION2 +#define SPECENUM_VALUE120NAME "User Action 2" +#define SPECENUM_VALUE121 ACTION_USER_ACTION3 +#define SPECENUM_VALUE121NAME "User Action 3" +#define SPECENUM_VALUE122 ACTION_USER_ACTION4 +#define SPECENUM_VALUE122NAME "User Action 4" #define SPECENUM_BITVECTOR bv_actions #define SPECENUM_COUNT ACTION_COUNT #define SPECENUM_NAME_UPDATER @@ -613,16 +615,17 @@ action_auto_perf_iterate(_act_perf_) { \ /* Hard coded location of action auto performers. Used for conversion while * action auto performers aren't directly exposed to the ruleset. * Remember to update also MAX_NUM_ACTION_AUTO_PERFORMERS when changing these. */ -#define ACTION_AUTO_UPKEEP_FOOD 0 -#define ACTION_AUTO_UPKEEP_GOLD 1 -#define ACTION_AUTO_UPKEEP_SHIELD 2 -#define ACTION_AUTO_MOVED_ADJ 3 -#define ACTION_AUTO_POST_BRIBE 4 -#define ACTION_AUTO_POST_ATTACK 5 -#define ACTION_AUTO_POST_ATTACK2 6 -#define ACTION_AUTO_ESCAPE_CITY 7 -#define ACTION_AUTO_ESCAPE_STACK 8 -#define ACTION_AUTO_POST_WIPE_UNITS 9 +#define ACTION_AUTO_UPKEEP_FOOD 0 +#define ACTION_AUTO_UPKEEP_GOLD 1 +#define ACTION_AUTO_UPKEEP_SHIELD 2 +#define ACTION_AUTO_MOVED_ADJ 3 +#define ACTION_AUTO_POST_BRIBE 4 +#define ACTION_AUTO_POST_ATTACK 5 +#define ACTION_AUTO_POST_ATTACK2 6 +#define ACTION_AUTO_POST_COLLECT_RANSOM 7 +#define ACTION_AUTO_ESCAPE_CITY 8 +#define ACTION_AUTO_ESCAPE_STACK 9 +#define ACTION_AUTO_POST_WIPE_UNITS 10 /* Initialization */ void actions_init(void); diff --git a/common/actres.c b/common/actres.c index 4c11bd8da4..3f71d3a6ea 100644 --- a/common/actres.c +++ b/common/actres.c @@ -169,10 +169,10 @@ static struct actres act_results[ACTRES_LAST] = { { ACT_TGT_COMPL_MANDATORY, ABK_NONE, /* ACTRES_IRRIGATE */ FALSE, ACTIVITY_IRRIGATE, DRT_NONE, EC_IRRIGATION, ERM_NONE }, - { ACT_TGT_COMPL_FLEXIBLE, ABK_NONE, /* ACTRES_UNUSED_1 */ - FALSE, ACTIVITY_LAST, DRT_NONE, + { ACT_TGT_COMPL_SIMPLE, ABK_STANDARD, /* ACTRES_COLLECT_RANSOM */ + TRUE, ACTIVITY_LAST, DRT_NONE, EC_NONE, ERM_NONE }, - { ACT_TGT_COMPL_FLEXIBLE, ABK_NONE, /* ACTRES_UNUSED_2 */ + { ACT_TGT_COMPL_FLEXIBLE, ABK_NONE, /* ACTRES_UNUSED_1 */ FALSE, ACTIVITY_LAST, DRT_NONE, EC_NONE, ERM_NONE }, { ACT_TGT_COMPL_SIMPLE, ABK_NONE, /* ACTRES_TRANSPORT_DEBOARD */ @@ -671,6 +671,20 @@ enum fc_tristate actres_possible(enum action_result result, } unit_list_iterate_end; break; + case ACTRES_COLLECT_RANSOM: + if (!is_barbarian(actor->player) + || !uclass_has_flag(unit_class_get(actor->unit), UCF_COLLECT_RANSOM)) { + return FALSE; + } + + unit_list_iterate(target->tile->units, punit) { + if (!unit_has_type_role(punit, L_BARBARIAN_LEADER)) { + /* Cannot get ransom when there are other kind of units in the tile */ + return FALSE; + } + } unit_list_iterate_end; + break; + case ACTRES_CONQUER_CITY: /* Reason: "Conquer City" involves moving into the city. */ if (!unit_can_move_to_tile(nmap, actor->unit, target->tile, diff --git a/common/actres.h b/common/actres.h index 353299ed52..7f20f6719d 100644 --- a/common/actres.h +++ b/common/actres.h @@ -36,9 +36,6 @@ struct req_context; #define ASSERT_UNUSED_ACTRES_CASES \ case ACTRES_UNUSED_1: \ fc_assert_msg(FALSE, "ACTRES_UNUSED_1"); \ - break; \ - case ACTRES_UNUSED_2: \ - fc_assert_msg(FALSE, "ACTRES_UNUSED_2"); \ break; /* When making changes to this, update also atk_helpnames at actions.c */ diff --git a/common/fc_types.h b/common/fc_types.h index 586d03e5c2..3541ddab68 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -51,7 +51,7 @@ extern "C" { #define MAX_GOODS_TYPES 25 #define MAX_DISASTER_TYPES 10 #define MAX_ACHIEVEMENT_TYPES 40 -#define MAX_NUM_ACTION_AUTO_PERFORMERS 10 +#define MAX_NUM_ACTION_AUTO_PERFORMERS 11 #define MAX_NUM_MULTIPLIERS 15 #define MAX_NUM_LEADERS MAX_NUM_ITEMS /* Used in the network protocol. */ #define MAX_NUM_NATION_SETS 32 /* Used in the network protocol. @@ -275,11 +275,11 @@ enum counter_target { CTGT_CITY }; #define SPECENUM_VALUE44NAME "Unit Build Mine" #define SPECENUM_VALUE45 ACTRES_IRRIGATE #define SPECENUM_VALUE45NAME "Unit Build Irrigation" -/* TODO: Rearrange action results to get rid of these */ -#define SPECENUM_VALUE46 ACTRES_UNUSED_1 -#define SPECENUM_VALUE46NAME "Unused1" -#define SPECENUM_VALUE47 ACTRES_UNUSED_2 -#define SPECENUM_VALUE47NAME "Unused2" +#define SPECENUM_VALUE46 ACTRES_COLLECT_RANSOM +#define SPECENUM_VALUE46NAME "Collect Ransom" +/* TODO: Rearrange action results to get rid of this */ +#define SPECENUM_VALUE47 ACTRES_UNUSED_1 +#define SPECENUM_VALUE47NAME "Unused1" #define SPECENUM_VALUE48 ACTRES_TRANSPORT_DEBOARD #define SPECENUM_VALUE48NAME "Unit Transport Deboard" #define SPECENUM_VALUE49 ACTRES_TRANSPORT_UNLOAD diff --git a/data/alien/actions.ruleset b/data/alien/actions.ruleset index 0b68e2d209..a017433b79 100644 --- a/data/alien/actions.ruleset +++ b/data/alien/actions.ruleset @@ -30,7 +30,8 @@ if_attacker = "MinMoveFrags", "1", "Local", TRUE } -attack_actions = "Capture Units", "Bombard", "Attack", "Suicide Attack" +attack_actions = "Capture Units", "Bombard", + "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid "Enter Marketplace" if any one of the listed actions are legal. @@ -40,10 +41,10 @@ enter_marketplace_blocked_by = "Establish Trade Route" bombard_blocked_by = "Capture Units" ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Capture Units", "Bombard" +attack_blocked_by = "Collect Ransom", "Capture Units", "Bombard" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Capture Units", "Bombard" +suicide_attack_blocked_by = "Collect Ransom", "Capture Units", "Bombard" ; Forbid "Conquer City" if any one of the listed actions are legal. conquer_city_blocked_by = "Capture Units", "Bombard", "Attack", @@ -74,6 +75,17 @@ attack_post_success_forced_actions = "Conquer City", "Conquer City 2", "Enter Hut", "Enter Hut 2", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. @@ -550,14 +562,14 @@ actor_reqs = "MinMoveFrags", "1", "Local", TRUE "DiplRel", "Foreign", "Local", FALSE } -target_reqs = +target_reqs = { "type", "name", "range", "present" "CityTile", "Claimed", "Tile", TRUE "TerrainFlag", "NoCities", "Tile", FALSE } [actionenabler_attack_from_native] -action = "Attack" +action = "Attack" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE @@ -568,7 +580,29 @@ actor_reqs = } [actionenabler_attack_uclass_sea] -action = "Attack" +action = "Attack" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClass", "Sea", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_uclass_sea] +action = "Collect Ransom" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE @@ -579,7 +613,7 @@ actor_reqs = } [actionenabler_explode_missile] -action = "Suicide Attack" +action = "Suicide Attack" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE @@ -589,7 +623,7 @@ actor_reqs = } [actionenabler_conquer_city_native] -action = "Conquer City" +action = "Conquer City" actor_reqs = { "type", "name", "range", "present" "UnitClassFlag", "CanOccupyCity", "Local", TRUE @@ -598,13 +632,13 @@ actor_reqs = "MinMoveFrags", "1", "Local", TRUE "UnitState", "OnLivableTile", "Local", TRUE } -target_reqs = +target_reqs = { "type", "name", "range", "present" "MaxUnitsOnTile", "0", "Tile", TRUE } [actionenabler_change_home_city] -action = "Home City" +action = "Home City" actor_reqs = { "type", "name", "range", "present" "UnitState", "HasHomeCity", "Local", TRUE @@ -612,7 +646,7 @@ actor_reqs = } [actionenabler_paradrop_base_to_claimed] -action = "Paradrop Unit Enter" +action = "Paradrop Unit Enter" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "Paratroopers", "Local", TRUE @@ -628,7 +662,7 @@ target_reqs = } [actionenabler_paradrop_base_to_unclaimed] -action = "Paradrop Unit Enter" +action = "Paradrop Unit Enter" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "Paratroopers", "Local", TRUE @@ -642,7 +676,7 @@ target_reqs = } [actionenabler_paradrop_base_to_war_conquer] -action = "Paradrop Unit Enter Conquer" +action = "Paradrop Unit Enter Conquer" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "Paratroopers", "Local", TRUE @@ -659,7 +693,7 @@ target_reqs = } [actionenabler_paradrop_city_to_claimed] -action = "Paradrop Unit Enter" +action = "Paradrop Unit Enter" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "Paratroopers", "Local", TRUE @@ -675,7 +709,7 @@ target_reqs = } [actionenabler_paradrop_city_to_unclaimed] -action = "Paradrop Unit Enter" +action = "Paradrop Unit Enter" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "Paratroopers", "Local", TRUE @@ -689,7 +723,7 @@ target_reqs = } [actionenabler_paradrop_city_to_war_conquer] -action = "Paradrop Unit Enter Conquer" +action = "Paradrop Unit Enter Conquer" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "Paratroopers", "Local", TRUE @@ -706,14 +740,14 @@ target_reqs = } [actionenabler_upgrade_unit] -action = "Upgrade Unit" +action = "Upgrade Unit" actor_reqs = { "type", "name", "range", "present" "DiplRel", "Foreign", "Local", FALSE } [actionenabler_airlift_unit] -action = "Airlift Unit" +action = "Airlift Unit" actor_reqs = { "type", "name", "range", "present" "UnitClassFlag", "Airliftable", "Local", TRUE diff --git a/data/alien/effects.ruleset b/data/alien/effects.ruleset index 38ed5f0d7d..1facafaf65 100644 --- a/data/alien/effects.ruleset +++ b/data/alien/effects.ruleset @@ -1063,6 +1063,14 @@ reqs = "Action", "Attack", "Local", TRUE } +[effect_action_success_move_cost_ransom] +type = "Action_Success_Actor_Move_Cost" +value = 4 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + } + [effect_action_success_move_cost_paradrop] type = "Action_Success_Actor_Move_Cost" value = 4 diff --git a/data/civ1/actions.ruleset b/data/civ1/actions.ruleset index 9a0bb18d9c..bbd0beda2f 100644 --- a/data/civ1/actions.ruleset +++ b/data/civ1/actions.ruleset @@ -31,17 +31,19 @@ if_attacker = "UnitFlag", "Nuclear", "Local", FALSE } -attack_actions = "Attack", "Suicide Attack" +attack_actions = "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid "Enter Marketplace" if any one of the listed actions are legal. enter_marketplace_blocked_by = "Establish Trade Route" ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +attack_blocked_by = "Collect Ransom", "Explode Nuclear", "Nuke City", + "Nuke Units" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +suicide_attack_blocked_by = "Collect Ransom", "Explode Nuclear", + "Nuke City", "Nuke Units" ; Forbid "Conquer City" if any one of the listed actions are legal. conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", @@ -71,6 +73,17 @@ attack_post_success_forced_actions = "Conquer City", "Conquer City 2", "Enter Hut", "Enter Hut 2", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. @@ -566,6 +579,28 @@ actor_reqs = "DiplRel", "War", "Local", TRUE } +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_uclass_sea] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClass", "Sea", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + [actionenabler_explode_missile] action = "Suicide Attack" actor_reqs = diff --git a/data/civ1/effects.ruleset b/data/civ1/effects.ruleset index 3602bf2c45..d0089b6d58 100644 --- a/data/civ1/effects.ruleset +++ b/data/civ1/effects.ruleset @@ -1566,6 +1566,24 @@ reqs = "UnitFlag", "OneAttack", "Local", FALSE } +[effect_action_success_ransom_one_attack] +type = "Action_Success_Actor_Move_Cost" +value = 65535 +reqs = + { "type", "name", "range", "quiet" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", TRUE + } + +[effect_action_success_ransom] +type = "Action_Success_Actor_Move_Cost" +value = 3 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", FALSE + } + [effect_unit_shield_value_recycle] type = "Unit_Shield_Value_Pct" value = -50 diff --git a/data/civ2/actions.ruleset b/data/civ2/actions.ruleset index e4977154f0..dda788a271 100644 --- a/data/civ2/actions.ruleset +++ b/data/civ2/actions.ruleset @@ -31,17 +31,19 @@ if_attacker = "UnitFlag", "Nuclear", "Local", FALSE } -attack_actions = "Attack", "Suicide Attack" +attack_actions = "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid "Enter Marketplace" if any one of the listed actions are legal. enter_marketplace_blocked_by = "Establish Trade Route" ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Explode Nuclear","Nuke City","Nuke Units" +attack_blocked_by = "Collect Ransom", "Explode Nuclear", + "Nuke City", "Nuke Units" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +suicide_attack_blocked_by = "Collect Ransom", "Explode Nuclear", + "Nuke City", "Nuke Units" ; Forbid "Conquer City" if any one of the listed actions are legal. conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", @@ -73,6 +75,18 @@ attack_post_success_forced_actions = "Conquer City", "Conquer City 2", "Frighten Hut", "Frighten Hut 2", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2", + "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. @@ -753,6 +767,39 @@ actor_reqs = "DiplRel", "War", "Local", TRUE } +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_marines] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitFlag", "Marines", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_uclass_sea] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClass", "Sea", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + [actionenabler_explode_missile] action = "Suicide Attack" actor_reqs = diff --git a/data/civ2/effects.ruleset b/data/civ2/effects.ruleset index e95a03ab0a..0fb2f6fefb 100644 --- a/data/civ2/effects.ruleset +++ b/data/civ2/effects.ruleset @@ -2641,6 +2641,24 @@ reqs = "UnitFlag", "OneAttack", "Local", FALSE } +[effect_action_success_ransom_one_attack] +type = "Action_Success_Actor_Move_Cost" +value = 65535 +reqs = + { "type", "name", "range", "quiet" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", TRUE + } + +[effect_action_success_ransom_normal] +type = "Action_Success_Actor_Move_Cost" +value = 3 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", FALSE + } + [effect_unit_shield_value_recycle] type = "Unit_Shield_Value_Pct" value = -50 diff --git a/data/civ2civ3/actions.ruleset b/data/civ2civ3/actions.ruleset index 420ab75213..923b886656 100644 --- a/data/civ2civ3/actions.ruleset +++ b/data/civ2civ3/actions.ruleset @@ -31,7 +31,8 @@ if_attacker = "UnitFlag", "Nuclear", "Local", FALSE } -attack_actions = "Capture Units", "Bombard", "Attack", "Suicide Attack" +attack_actions = "Capture Units", "Bombard", "Collect Ransom", "Attack", + "Suicide Attack" [actions] ; Forbid "Bombard" if any one of the listed actions are legal. @@ -47,12 +48,12 @@ nuke_city_blocked_by = "Capture Units", "Bombard" nuke_units_blocked_by = "Capture Units", "Bombard" ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Capture Units", "Bombard", "Explode Nuclear", - "Nuke City", "Nuke Units" +attack_blocked_by = "Collect Ransom", "Capture Units", "Bombard", + "Explode Nuclear", "Nuke City", "Nuke Units" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Capture Units", "Bombard", "Explode Nuclear", - "Nuke City", "Nuke Units" +suicide_attack_blocked_by = "Collect Ransom", "Capture Units", "Bombard", + "Explode Nuclear", "Nuke City", "Nuke Units" ; Forbid "Conquer City" if any one of the listed actions are legal. conquer_city_blocked_by = "Capture Units", "Bombard", "Explode Nuclear", @@ -92,6 +93,18 @@ attack_post_success_forced_actions = "Conquer City", "Conquer City 2", "Frighten Hut", "Frighten Hut 2", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2", + "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. @@ -869,7 +882,7 @@ target_reqs = } [actionenabler_attack_from_native] -action = "Attack" +action = "Attack" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE @@ -880,7 +893,7 @@ actor_reqs = } [actionenabler_attack_marines] -action = "Attack" +action = "Attack" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE @@ -891,7 +904,40 @@ actor_reqs = } [actionenabler_attack_att_from_non_native] -action = "Attack" +action = "Attack" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClassFlag", "AttFromNonNative", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_marines] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitFlag", "Marines", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_att_from_non_native] +action = "Collect Ransom" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE diff --git a/data/civ2civ3/effects.ruleset b/data/civ2civ3/effects.ruleset index 4df71d409e..a03335fdda 100644 --- a/data/civ2civ3/effects.ruleset +++ b/data/civ2civ3/effects.ruleset @@ -4567,6 +4567,24 @@ reqs = "UnitFlag", "OneAttack", "Local", FALSE } +[effect_action_success_ransom_one_attack] +type = "Action_Success_Actor_Move_Cost" +value = 65535 +reqs = + { "type", "name", "range", "quiet" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", TRUE + } + +[effect_action_success_ransom] +type = "Action_Success_Actor_Move_Cost" +value = 6 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", FALSE + } + [effect_unit_shield_value_recycle] type = "Unit_Shield_Value_Pct" value = -50 diff --git a/data/classic/actions.ruleset b/data/classic/actions.ruleset index c35847417f..38bcc8563a 100644 --- a/data/classic/actions.ruleset +++ b/data/classic/actions.ruleset @@ -32,17 +32,19 @@ if_attacker = "UnitFlag", "Nuclear", "Local", FALSE } -attack_actions = "Attack", "Suicide Attack" +attack_actions = "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid "Enter Marketplace" if any one of the listed actions are legal. enter_marketplace_blocked_by = "Establish Trade Route" ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +attack_blocked_by = "Collect Ransom", "Explode Nuclear", "Nuke City", + "Nuke Units" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +suicide_attack_blocked_by = "Collect Ransom", "Explode Nuclear", + "Nuke City", "Nuke Units" ; Forbid "Conquer City" if any one of the listed actions are legal. conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", @@ -81,6 +83,18 @@ attack_post_success_forced_actions = "Conquer City", "Conquer City 2", "Frighten Hut", "Frighten Hut 2", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2", + "Unit Move" + ; The city that made the unit´s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. @@ -794,7 +808,7 @@ target_reqs = } [actionenabler_attack_from_native] -action = "Attack" +action = "Attack" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE @@ -805,7 +819,7 @@ actor_reqs = } [actionenabler_attack_marines] -action = "Attack" +action = "Attack" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE @@ -816,7 +830,40 @@ actor_reqs = } [actionenabler_attack_att_from_non_native] -action = "Attack" +action = "Attack" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClassFlag", "AttFromNonNative", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_marines] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitFlag", "Marines", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_att_from_non_native] +action = "Collect Ransom" actor_reqs = { "type", "name", "range", "present" "UnitFlag", "NonMil", "Local", FALSE diff --git a/data/classic/effects.ruleset b/data/classic/effects.ruleset index 1ecbeb83af..426f571b70 100644 --- a/data/classic/effects.ruleset +++ b/data/classic/effects.ruleset @@ -2696,6 +2696,24 @@ reqs = "UnitFlag", "OneAttack", "Local", FALSE } +[effect_action_success_ransom_one_attack] +type = "Action_Success_Actor_Move_Cost" +value = 65535 +reqs = + { "type", "name", "range", "quiet" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", TRUE + } + +[effect_action_success_ransom] +type = "Action_Success_Actor_Move_Cost" +value = 3 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", FALSE + } + [effect_unit_shield_value_recycle] type = "Unit_Shield_Value_Pct" value = -50 diff --git a/data/goldkeep/actions.ruleset b/data/goldkeep/actions.ruleset index 63c4f597de..d80e6d2714 100644 --- a/data/goldkeep/actions.ruleset +++ b/data/goldkeep/actions.ruleset @@ -35,14 +35,16 @@ if_attacker = "UnitFlag", "Nuclear", "Local", FALSE } -attack_actions = "Attack", "Suicide Attack" +attack_actions = "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +attack_blocked_by = "Collect Ransom", "Explode Nuclear", "Nuke City", + "Nuke Units" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +suicide_attack_blocked_by = "Collect Ransom", "Explode Nuclear", + "Nuke City", "Nuke Units" ; Forbid "Conquer City" if any one of the listed actions are legal. conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", @@ -81,6 +83,18 @@ attack_post_success_forced_actions = "Conquer City", "Conquer City 2", "Frighten Hut", "Frighten Hut 2", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2", + "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. @@ -840,6 +854,39 @@ actor_reqs = "DiplRel", "War", "Local", TRUE } +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_marines] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitFlag", "Marines", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_att_from_non_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClassFlag", "AttFromNonNative", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + [actionenabler_explode_missile] action = "Suicide Attack" actor_reqs = diff --git a/data/goldkeep/effects.ruleset b/data/goldkeep/effects.ruleset index 650a10bfb3..76c0cc1425 100644 --- a/data/goldkeep/effects.ruleset +++ b/data/goldkeep/effects.ruleset @@ -2965,6 +2965,24 @@ reqs = "UnitFlag", "OneAttack", "Local", FALSE } +[effect_action_success_ransom_one_attack] +type = "Action_Success_Actor_Move_Cost" +value = 65535 +reqs = + { "type", "name", "range", "quiet" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", TRUE + } + +[effect_action_success_ransom] +type = "Action_Success_Actor_Move_Cost" +value = 9 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", FALSE + } + [effect_action_establish_embassy_success_move_cost] type = "Action_Success_Actor_Move_Cost" value = 1 diff --git a/data/granularity/actions.ruleset b/data/granularity/actions.ruleset index e541dd1301..9ad6214d79 100644 --- a/data/granularity/actions.ruleset +++ b/data/granularity/actions.ruleset @@ -30,7 +30,8 @@ format_version = 40 ; "MinMoveFrags", "10" "Local", TRUE ; } -;attack_actions = "Capture Units", "Bombard", "Attack", "Suicide Attack" +;attack_actions = "Capture Units", "Bombard", +; "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid regular unit move if one of the actions below is legal. @@ -46,6 +47,11 @@ bribe_unit_post_success_forced_actions = "Unit Move" ; performing "Attack". attack_post_success_forced_actions = "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. diff --git a/data/multiplayer/actions.ruleset b/data/multiplayer/actions.ruleset index d96dd9b4c4..51f03fb39d 100644 --- a/data/multiplayer/actions.ruleset +++ b/data/multiplayer/actions.ruleset @@ -32,14 +32,16 @@ if_attacker = "UnitFlag", "Nuclear", "Local", FALSE } -attack_actions = "Attack", "Suicide Attack" +attack_actions = "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +attack_blocked_by = "Collect Ransom", "Explode Nuclear", "Nuke City", + "Nuke Units" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +suicide_attack_blocked_by = "Collect Ransom", "Explode Nuclear", + "Nuke City", "Nuke Units" ; Forbid "Conquer City" if any one of the listed actions are legal. conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", @@ -78,6 +80,18 @@ attack_post_success_forced_actions = "Conquer City", "Conquer City 2", "Frighten Hut", "Frighten Hut 2", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2", + "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. @@ -814,6 +828,39 @@ actor_reqs = "DiplRel", "War", "Local", TRUE } +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_marines] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitFlag", "Marines", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_att_from_non_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClassFlag", "AttFromNonNative", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + [actionenabler_explode_missile] action = "Suicide Attack" actor_reqs = diff --git a/data/multiplayer/effects.ruleset b/data/multiplayer/effects.ruleset index f0699ad389..6970378876 100644 --- a/data/multiplayer/effects.ruleset +++ b/data/multiplayer/effects.ruleset @@ -2663,6 +2663,24 @@ reqs = "UnitFlag", "OneAttack", "Local", FALSE } +[effect_action_success_ransom_one_attack] +type = "Action_Success_Actor_Move_Cost" +value = 65535 +reqs = + { "type", "name", "range", "quiet" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", TRUE + } + +[effect_action_success_ransom] +type = "Action_Success_Actor_Move_Cost" +value = 3 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", FALSE + } + [effect_action_establish_embassy_success_move_cost] type = "Action_Success_Actor_Move_Cost" value = 1 diff --git a/data/sandbox/actions.ruleset b/data/sandbox/actions.ruleset index 78ff7de1d6..11fea4f7a7 100644 --- a/data/sandbox/actions.ruleset +++ b/data/sandbox/actions.ruleset @@ -33,7 +33,8 @@ if_attacker = "UnitFlag", "NuclearOP", "Local", FALSE } -attack_actions = "Capture Units", "Bombard", "Attack", "Suicide Attack" +attack_actions = "Capture Units", "Bombard", + "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid "Bombard" if any one of the listed actions are legal. @@ -49,12 +50,12 @@ nuke_city_blocked_by = "Capture Units", "Bombard" nuke_units_blocked_by = "Capture Units", "Bombard" ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Capture Units", "Bombard", +attack_blocked_by = "Collect Ransom", "Capture Units", "Bombard", "Explode Nuclear", "Nuke City", "Nuke Units", "Wipe Units" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Capture Units", "Bombard", +suicide_attack_blocked_by = "Collect Ransom", "Capture Units", "Bombard", "Explode Nuclear", "Nuke City", "Nuke Units" ; Forbid "Conquer City" if any one of the listed actions are legal. @@ -96,6 +97,18 @@ attack_post_success_forced_actions = "Conquer City", "Conquer City 2", "Frighten Hut", "Frighten Hut 2", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Conquer City 2", + "Transport Disembark", + "Transport Disembark 2", + "Conquer Extras", "Conquer Extras 2", + "Enter Hut", "Enter Hut 2", + "Frighten Hut", "Frighten Hut 2", + "Unit Move" + ; Actor units will be forced to try performing the following actions ; in the specified order after successfully performing "Wipe Units". wipe_units_post_success_forced_actions = "Conquer City", "Conquer City 2", @@ -1531,6 +1544,78 @@ actor_reqs = "Tech", "Communism", "World", TRUE, TRUE } +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + "Building", "Treuga Dei", "World", FALSE + } + +[actionenabler_ransom_from_native_despite_treuga_dei] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present", "survives" + "UnitFlag", "NonMil", "Local", FALSE, FALSE + "UnitClassFlag", "Missile", "Local", FALSE, FALSE + "MinMoveFrags", "1", "Local", TRUE, FALSE + "UnitState", "OnNativeTile", "Local", TRUE, FALSE + "DiplRel", "War", "Local", TRUE, FALSE + "Tech", "Communism", "World", TRUE, TRUE + } + +[actionenabler_ransom_marines] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitFlag", "Marines", "Local", TRUE + "DiplRel", "War", "Local", TRUE + "Building", "Treuga Dei", "World", FALSE + } + +[actionenabler_ransom_marines_despite_treuga_dei] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present", "survives" + "UnitFlag", "NonMil", "Local", FALSE, FALSE + "UnitClassFlag", "Missile", "Local", FALSE, FALSE + "MinMoveFrags", "1", "Local", TRUE, FALSE + "UnitFlag", "Marines", "Local", TRUE, FALSE + "DiplRel", "War", "Local", TRUE, FALSE + "Tech", "Communism", "World", TRUE, TRUE + } + +[actionenabler_ransom_att_from_non_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClassFlag", "AttFromNonNative", "Local", TRUE + "DiplRel", "War", "Local", TRUE + "Building", "Treuga Dei", "World", FALSE + } + +[actionenabler_ransom_att_from_non_native_despite_treuga_dei] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present", "survives" + "UnitFlag", "NonMil", "Local", FALSE, FALSE + "UnitClassFlag", "Missile", "Local", FALSE, FALSE + "MinMoveFrags", "1", "Local", TRUE, FALSE + "UnitClassFlag", "AttFromNonNative", "Local", TRUE, FALSE + "DiplRel", "War", "Local", TRUE, FALSE + "Tech", "Communism", "World", TRUE, TRUE + } + [actionenabler_explode_missile] action = "Suicide Attack" actor_reqs = diff --git a/data/sandbox/effects.ruleset b/data/sandbox/effects.ruleset index 823935a761..7821c53bdf 100644 --- a/data/sandbox/effects.ruleset +++ b/data/sandbox/effects.ruleset @@ -4929,6 +4929,24 @@ reqs = "UnitFlag", "OneAttack", "Local", FALSE } +[effect_action_success_ransom_one_attack] +type = "Action_Success_Actor_Move_Cost" +value = 65535 +reqs = + { "type", "name", "range", "quiet" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", TRUE + } + +[effect_action_success_ransom] +type = "Action_Success_Actor_Move_Cost" +value = 6 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", FALSE + } + [effect_action_success_move_cost_cut_root] type = "Action_Success_Actor_Move_Cost" value = 65535 diff --git a/data/stub/actions.ruleset b/data/stub/actions.ruleset index 11b10f8a53..6c5e31457c 100644 --- a/data/stub/actions.ruleset +++ b/data/stub/actions.ruleset @@ -20,7 +20,8 @@ format_version = 40 ; { "type", "name", "range", "present" ; } -;attack_actions = "Capture Units", "Bombard", "Attack", "Suicide Attack" +;attack_actions = "Capture Units", "Bombard", +; "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid regular unit move if one of the actions below is legal. @@ -37,6 +38,12 @@ format_version = 40 ;attack_post_success_forced_actions = "Conquer City", "Conquer City 2", ; "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +;collect_ransom_post_success_forced_actions = "Conquer City", "Conquer City 2", +; "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an ; adjacent tile. Currently only able to target native tiles. diff --git a/data/webperimental/actions.ruleset b/data/webperimental/actions.ruleset index 9259ef0401..d02280c2a2 100644 --- a/data/webperimental/actions.ruleset +++ b/data/webperimental/actions.ruleset @@ -32,17 +32,19 @@ if_attacker = "UnitFlag", "Nuclear", "Local", FALSE } -attack_actions = "Bombard", "Attack", "Suicide Attack" +attack_actions = "Bombard", "Collect Ransom", "Attack", "Suicide Attack" [actions] ; Forbid "Enter Marketplace" if any one of the listed actions are legal. enter_marketplace_blocked_by = "Establish Trade Route" ; Forbid "Attack" if any one of the listed actions are legal. -attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +attack_blocked_by = "Collect Ransom", "Explode Nuclear", "Nuke City", + "Nuke Units" ; Forbid "Suicide Attack" if any one of the listed actions are legal. -suicide_attack_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units" +suicide_attack_blocked_by = "Collect Ransom", "Explode Nuclear", + "Nuke City", "Nuke Units" ; Forbid "Conquer City" if any one of the listed actions are legal. conquer_city_blocked_by = "Explode Nuclear", "Nuke City", "Nuke Units", @@ -68,6 +70,15 @@ attack_post_success_forced_actions = "Conquer City", "Transport Disembark", "Conquer Extras", "Enter Hut","Frighten Hut", "Unit Move" +; Actor units will - under certain circumstances - be forced to try +; performing the following actions in the specified order after successfully +; performing "Collect Ransom". +collect_ransom_post_success_forced_actions = + "Conquer City", "Transport Disembark", + "Conquer Extras", + "Enter Hut","Frighten Hut", + "Unit Move" + ; The city that made the unit`s current tile native is gone. This is a Hail ; Mary attempt at survival by performing an action. Evaluated against an @@ -1096,6 +1107,39 @@ actor_reqs = "DiplRel", "War", "Local", TRUE } +[actionenabler_ransom_from_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitState", "OnNativeTile", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_marines] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitFlag", "Marines", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + +[actionenabler_ransom_att_from_non_native] +action = "Collect Ransom" +actor_reqs = + { "type", "name", "range", "present" + "UnitFlag", "NonMil", "Local", FALSE + "UnitClassFlag", "Missile", "Local", FALSE + "MinMoveFrags", "1", "Local", TRUE + "UnitClassFlag", "AttFromNonNative", "Local", TRUE + "DiplRel", "War", "Local", TRUE + } + [actionenabler_explode_missile] action = "Suicide Attack" actor_reqs = diff --git a/data/webperimental/effects.ruleset b/data/webperimental/effects.ruleset index 24689e3c7d..d6546e73ca 100644 --- a/data/webperimental/effects.ruleset +++ b/data/webperimental/effects.ruleset @@ -2974,6 +2974,24 @@ reqs = "UnitFlag", "OneAttack", "Local", FALSE } +[effect_action_success_ransom_one_attack] +type = "Action_Success_Actor_Move_Cost" +value = 65535 +reqs = + { "type", "name", "range", "quiet" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", TRUE + } + +[effect_action_success_ransom] +type = "Action_Success_Actor_Move_Cost" +value = 3 +reqs = + { "type", "name", "range", "present" + "Action", "Collect Ransom", "Local", TRUE + "UnitFlag", "OneAttack", "Local", FALSE + } + [effect_strike_half_chance] type = "Action_Odds_Pct" value = -50 diff --git a/doc/README.actions b/doc/README.actions index cff1b70969..5bb64152fa 100644 --- a/doc/README.actions +++ b/doc/README.actions @@ -897,6 +897,29 @@ Actions done by a unit against all units at a tile - it is in a city - it is on a tile with a native Extra +"Collect Ransom" + * UI name can be set using ui_name_collect_ransom + * any action listed in collect_ransom_blocked_by must be impossible + * forced actions after success can be set with + collect_ransom_post_success_forced_actions + * the actor must be on the tile next to the target. + * the actor's attack must be above 0 + * the actor can't have the "NonMil" unit type flag (!) + * the actor must be native to the target tile unless it has the + "AttackNonNative" unit class flag and not the "Only_Native_Attack" unit + type flag. + * the target tile has no non enemy units. (!) + * the target tile has no non enemy city. + * the target must be barbarian + * the actor must have "CollectRansom" unit class flag + * one or all (unreachableprotects) non transported units at the target + tile must be reachable. A unit is reachable if any of the following is + true: + - it doesn't have the "Unreachable" unit class flag + - it is listed in the actor unit's targets + - it is in a city + - it is on a tile with a native Extra + "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 diff --git a/server/advisors/advdata.c b/server/advisors/advdata.c index b40879ba37..decfa2a73a 100644 --- a/server/advisors/advdata.c +++ b/server/advisors/advdata.c @@ -837,6 +837,7 @@ adv_want adv_gov_action_immunity_want(struct government *gov) case ACTRES_ATTACK: case ACTRES_SPY_INCITE_CITY: case ACTRES_CONQUER_CITY: + case ACTRES_COLLECT_RANSOM: bonus += 4; break; case ACTRES_SPY_BRIBE_UNIT: diff --git a/server/rssanity.c b/server/rssanity.c index f24a99f900..4c45f9efd1 100644 --- a/server/rssanity.c +++ b/server/rssanity.c @@ -1405,9 +1405,10 @@ bool sanity_check_ruleset_data(struct rscompat_info *compat) action_auto_perf_actions_iterate(auto_perf, act_id) { struct action *paction = action_by_number(act_id); - if (!(action_has_result(paction, ACTRES_CAPTURE_UNITS) - || action_has_result(paction, ACTRES_BOMBARD) - || action_has_result(paction, ACTRES_ATTACK))) { + if (!action_has_result(paction, ACTRES_CAPTURE_UNITS) + && !action_has_result(paction, ACTRES_BOMBARD) + && !action_has_result(paction, ACTRES_ATTACK) + && !action_has_result(paction, ACTRES_COLLECT_RANSOM)) { /* Only allow removing and changing the order of old auto * attack actions for now. Other actions need more testing and * fixing of issues caused by a worst case action probability of diff --git a/server/ruleset.c b/server/ruleset.c index 1cd054cf73..75f01dd8b2 100644 --- a/server/ruleset.c +++ b/server/ruleset.c @@ -7762,6 +7762,11 @@ static bool load_ruleset_actions(struct section_file *file, action_by_number( ACTION_ATTACK2))) { ok = FALSE; + } else if (!load_action_post_success_force(file, filename, + ACTION_AUTO_POST_COLLECT_RANSOM, + action_by_number( + ACTION_COLLECT_RANSOM))) { + ok = FALSE; } else if (!load_action_post_success_force(file, filename, ACTION_AUTO_POST_WIPE_UNITS, action_by_number( diff --git a/server/unithand.c b/server/unithand.c index 6562d8fab6..167ed68bdb 100644 --- a/server/unithand.c +++ b/server/unithand.c @@ -1107,6 +1107,7 @@ static struct player *need_war_player_hlp(const struct unit *actor, switch (paction->result) { case ACTRES_ATTACK: case ACTRES_WIPE_UNITS: + case ACTRES_COLLECT_RANSOM: /* Target is a unit stack but a city can block it. */ fc_assert_action(action_get_target_kind(paction) == ATK_UNITS, break); @@ -3874,6 +3875,7 @@ bool unit_perform_action(struct player *pplayer, paction)); break; case ACTRES_ATTACK: + case ACTRES_COLLECT_RANSOM: /* Difference is caused by data in the action structure. */ ACTION_PERFORM_UNIT_UNITS(action_type, actor_unit, target_tile, do_attack(actor_unit, target_tile, paction)); @@ -5135,8 +5137,14 @@ static bool do_attack(struct unit *punit, struct tile *def_tile, def_hp_start); punit->moved = TRUE; /* We moved */ - kill_unit(pwinner, ploser, - vet && !utype_is_consumed_by_action(paction, punit->utype)); + + if (paction->result == ACTRES_COLLECT_RANSOM) { + collect_ransom(pwinner, ploser, + vet && !utype_is_consumed_by_action(paction, punit->utype)); + } else { + kill_unit(pwinner, ploser, + vet && !utype_is_consumed_by_action(paction, punit->utype)); + } /* Now that dead defender is certainly no longer listed as unit * supported by the city, we may even remove the city diff --git a/server/unittools.c b/server/unittools.c index ac1f3d49c3..9e5189fe04 100644 --- a/server/unittools.c +++ b/server/unittools.c @@ -2279,7 +2279,7 @@ struct unit *unit_change_owner(struct unit *punit, struct player *pplayer, /**********************************************************************//** Called when one unit kills another in combat (this function is only - called in one place). It handles all side effects including + called in one place). It handles all side effects including notifications and killstack. **************************************************************************/ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) @@ -2288,9 +2288,8 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) struct player *pvictim = unit_owner(punit); struct player *pvictor = unit_owner(pkiller); struct tile *deftile = unit_tile(punit); - int ransom, unitcount = 0; + int unitcount = 0; bool escaped; - bool collect_ransom = FALSE; sz_strlcpy(pkiller_link, unit_link(pkiller)); sz_strlcpy(punit_link, unit_tile_link(punit)); @@ -2298,58 +2297,19 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) /* The unit is doomed. */ punit->server.dying = TRUE; - /* barbarian leader ransom hack */ - if (is_barbarian(pvictim) - && uclass_has_flag(unit_class_get(pkiller), UCF_COLLECT_RANSOM)) { - collect_ransom = TRUE; - - unit_list_iterate(deftile->units, capture) { - if (!unit_has_type_role(capture, L_BARBARIAN_LEADER)) { - /* Cannot get ransom when there are other kind of units in the tile */ - collect_ransom = FALSE; - break; - } - } unit_list_iterate_end; - - if (collect_ransom) { - unitcount = unit_list_size(deftile->units); - ransom = unitcount * game.server.ransom_gold; - - if (pvictim->economic.gold < ransom) { - ransom = pvictim->economic.gold; - } - - notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server, - PL_("%d Barbarian leader captured.", - "%d Barbarian leaders captured.", - unitcount), - unitcount); - notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server, - PL_("%d gold ransom paid.", - "%d gold ransom paid.", - ransom), - ransom); - pvictor->economic.gold += ransom; - pvictim->economic.gold -= ransom; - send_player_info_c(pvictor, NULL); /* let me see my new gold :-) */ + unit_list_iterate(deftile->units, vunit) { + if (pplayers_at_war(pvictor, unit_owner(vunit)) + && is_unit_reachable_at(vunit, pkiller, deftile)) { + unitcount++; } - } - - if (unitcount == 0) { - unit_list_iterate(deftile->units, vunit) { - if (pplayers_at_war(pvictor, unit_owner(vunit)) - && is_unit_reachable_at(vunit, pkiller, deftile)) { - unitcount++; - } - } unit_list_iterate_end; - } + } unit_list_iterate_end; if (!is_stack_vulnerable(deftile) || unitcount == 1) { if (vet) { notify_unit_experience(pkiller); } wipe_unit(punit, ULR_KILLED, pvictor); - } else { /* unitcount > 1 */ + } else { /* Unitcount > 1 */ int i; int slots = player_slot_count(); int num_killed[slots]; @@ -2358,14 +2318,14 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) fc_assert(unitcount > 1); - /* initialize */ + /* Initialize */ for (i = 0; i < slots; i++) { num_killed[i] = 0; other_killed[i] = NULL; num_escaped[i] = 0; } - /* count killed units */ + /* Count killed units */ unit_list_iterate_safe(deftile->units, vunit) { struct player *vplayer = unit_owner(vunit); @@ -2429,7 +2389,7 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) } unit_list_iterate_safe_end; /* Inform the destroyer again if more than one unit was killed */ - if (unitcount > 1 && !collect_ransom) { + if (unitcount > 1) { notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server, /* TRANS: "... Cannon ... the Polish Destroyer ...." */ PL_("Your attacking %s succeeded against the %s %s " @@ -2446,7 +2406,7 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) notify_unit_experience(pkiller); } - /* inform the owners: this only tells about owned units that were killed. + /* Inform the owners: this only tells about owned units that were killed. * there may have been 20 units who died but if only 2 belonged to the * particular player they'll only learn about those. * @@ -2541,9 +2501,9 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) } } - /* remove the units - note the logic of which units actually die + /* Remove the units - note the logic of which units actually die * must be mimiced exactly in at least one place up above. */ - punit = NULL; /* wiped during following iteration so unsafe to use */ + punit = NULL; /* Wiped during following iteration so unsafe to use */ unit_list_iterate_safe(deftile->units, punit2) { if (pplayers_at_war(pvictor, unit_owner(punit2)) @@ -2554,6 +2514,95 @@ void kill_unit(struct unit *pkiller, struct unit *punit, bool vet) } } +/**********************************************************************//** + Called when one unit collects ransom of another. +**************************************************************************/ +void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet) +{ + struct player *pvictim = unit_owner(punit); + struct player *pvictor = unit_owner(pcollector); + char pcollector_link[MAX_LEN_LINK], punit_link[MAX_LEN_LINK]; + struct tile *deftile = unit_tile(punit); + int unitcount, ransom; + + /* The unit is doomed. */ + punit->server.dying = TRUE; + + unitcount = unit_list_size(deftile->units); + ransom = unitcount * game.server.ransom_gold; + + if (pvictim->economic.gold < ransom) { + ransom = pvictim->economic.gold; + } + + notify_player(pvictor, unit_tile(pcollector), E_UNIT_WIN_ATT, ftc_server, + PL_("%d Barbarian leader captured.", + "%d Barbarian leaders captured.", + unitcount), + unitcount); + notify_player(pvictor, unit_tile(pcollector), E_UNIT_WIN_ATT, ftc_server, + PL_("%d gold ransom paid.", + "%d gold ransom paid.", + ransom), + ransom); + pvictor->economic.gold += ransom; + pvictim->economic.gold -= ransom; + send_player_info_c(pvictor, NULL); /* Let me see my new gold :-) */ + + if (vet) { + notify_unit_experience(pcollector); + } + + sz_strlcpy(pcollector_link, unit_link(pcollector)); + sz_strlcpy(punit_link, unit_tile_link(punit)); + + if (!is_stack_vulnerable(deftile) || unitcount == 1) { + wipe_unit(punit, ULR_KILLED, pvictor); + } else { + int i; + int slots = player_slot_count(); + int num_collected[slots]; + + fc_assert(unitcount > 1); + + /* Initialize */ + for (i = 0; i < slots; i++) { + num_collected[i] = 0; + } + + /* Count captured units */ + unit_list_iterate_safe(deftile->units, vunit) { + struct player *vplayer = unit_owner(vunit); + + num_collected[player_index(vplayer)]++; + } unit_list_iterate_safe_end; + + for (i = 0; i < slots; i++) { + if (num_collected[i] == 1) { + notify_player(player_by_number(i), deftile, + E_UNIT_LOST_DEF, ftc_server, + _("%s %s collected ransom of %s."), + nation_adjective_for_player(pvictor), + pcollector_link, punit_link); + } else if (num_collected[i] > 1) { + notify_player(player_by_number(i), deftile, + E_UNIT_LOST_DEF, ftc_server, + PL_("%s %s collected ransom of %s and %d other unit.", + "%s %s collected ransom of %s and %d other units.", + num_collected[i] - 1), + nation_adjective_for_player(pvictor), + pcollector_link, + punit_link, + num_collected[i] - 1); + } + } + + unit_list_iterate_safe(deftile->units, punit2) { + wipe_unit(punit2, ULR_KILLED, pvictor); + } unit_list_iterate_safe_end; + } +} + /**********************************************************************//** Package a unit_info packet. This packet contains basically all information about a unit. diff --git a/server/unittools.h b/server/unittools.h index 4eecaca3a2..c2f8b60637 100644 --- a/server/unittools.h +++ b/server/unittools.h @@ -144,6 +144,7 @@ bool place_unit(struct unit *punit, struct player *pplayer, void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer); void kill_unit(struct unit *pkiller, struct unit *punit, bool vet); +void collect_ransom(struct unit *pkiller, struct unit *punit, bool vet); struct unit *unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason) @@ -153,7 +154,7 @@ void unit_set_removal_callback(struct unit *punit, void (*callback)(struct unit *punit)); void unit_unset_removal_callback(struct unit *punit); -/* sending to client */ +/* Sending to client */ void package_unit(struct unit *punit, struct packet_unit_info *packet); void package_short_unit(struct unit *punit, struct packet_unit_short_info *packet, -- 2.40.1