From 5b9067ddac92f5ea397544525a1c6b8ece8fb2ac Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Thu, 28 Sep 2023 09:30:53 +0300 Subject: [PATCH 56/56] Add "Teleport Conquer" action type See osdn #48665 Signed-off-by: Marko Lindqvist --- ai/default/daicity.c | 1 + ai/default/daidiplomacy.c | 1 + common/actions.c | 33 ++++++++++++++++++++++++++++++--- common/actions.h | 26 ++++++++++++++------------ common/actres.c | 11 +++++++---- common/fc_types.h | 3 ++- common/oblig_reqs.c | 2 +- doc/README.actions | 18 ++++++++++++++++++ server/advisors/advdata.c | 1 + server/unithand.c | 8 ++++++-- 10 files changed, 81 insertions(+), 23 deletions(-) diff --git a/ai/default/daicity.c b/ai/default/daicity.c index da102b9c39..3f24966c7f 100644 --- a/ai/default/daicity.c +++ b/ai/default/daicity.c @@ -1310,6 +1310,7 @@ static int action_target_neg_util(action_id act_id, case ACTRES_HUT_FRIGHTEN: case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: case ACTRES_HOMELESS: case ACTRES_ENABLER_CHECK: diff --git a/ai/default/daidiplomacy.c b/ai/default/daidiplomacy.c index ec6711542b..5e04394949 100644 --- a/ai/default/daidiplomacy.c +++ b/ai/default/daidiplomacy.c @@ -2030,6 +2030,7 @@ void dai_incident(struct ai_type *ait, enum incident_type type, break; case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: case ACTRES_SPY_ESCAPE: case ACTRES_TRADE_ROUTE: case ACTRES_MARKETPLACE: diff --git a/common/actions.c b/common/actions.c index 5a818ce7bd..18f5f9f8de 100644 --- a/common/actions.c +++ b/common/actions.c @@ -685,6 +685,11 @@ static void hard_code_actions(void) unit_action_new(ACTION_TELEPORT3, ACTRES_TELEPORT, TRUE, TRUE, MAK_TELEPORT, 1, 1, FALSE); + actions[ACTION_TELEPORT_CONQUER] = + unit_action_new(ACTION_TELEPORT_CONQUER, ACTRES_TELEPORT_CONQUER, + TRUE, TRUE, + MAK_TELEPORT, 1, + ACTION_DISTANCE_MAX, FALSE); actions[ACTION_GAIN_VETERANCY] = unit_action_new(ACTION_GAIN_VETERANCY, ACTRES_ENABLER_CHECK, TRUE, FALSE, @@ -2484,6 +2489,7 @@ action_actor_utype_hard_reqs_ok_full(const struct action *paction, case ACTRES_SPY_ATTACK: case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: case ACTRES_ENABLER_CHECK: case ACTRES_NONE: /* No hard unit type requirements. */ @@ -2626,6 +2632,7 @@ action_hard_reqs_actor(const struct action *paction, case ACTRES_HOMELESS: case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: case ACTRES_ESTABLISH_EMBASSY: case ACTRES_SPY_INVESTIGATE_CITY: case ACTRES_SPY_POISON: @@ -2698,9 +2705,9 @@ action_hard_reqs_actor(const struct action *paction, Can return maybe when not omniscient. Should always return yes or no when omniscient. - This is done by checking the action's hard requirements. Hard - requirements must be fulfilled before an action can be done. The reason - why is usually that code dealing with the action assumes that the + This is done by checking the action's hard requirements. + Hard requirements must be fulfilled before an action can be done. + The reason why is usually that code dealing with the action assumes that requirements are true. A requirement may also end up here if it can't be expressed in a requirement vector or if its absence makes the action pointless. @@ -3987,6 +3994,7 @@ action_prob(const action_id wanted_action, break; case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: chance = ACTPROB_CERTAIN; break; /* Not UI action, so chance is meaningless */ @@ -5879,6 +5887,8 @@ const char *action_ui_name_ruleset_var_name(int act) return "ui_name_teleport_2"; case ACTION_TELEPORT3: return "ui_name_teleport_3"; + case ACTION_TELEPORT_CONQUER: + return "ui_name_teleport_conquer"; case ACTION_SPY_ESCAPE: return "ui_name_escape"; case ACTION_USER_ACTION1: @@ -6200,6 +6210,9 @@ const char *action_ui_name_default(int act) case ACTION_TELEPORT3: /* TRANS: _Teleport (100% chance of success). */ return N_("%sTeleport%s"); + case ACTION_TELEPORT_CONQUER: + /* TRANS: _Teleport to Conquer (100% chance of success). */ + return N_("%sTeleport to Conquer%s"); case ACTION_SPY_ESCAPE: /* TRANS: _Escape To Nearest City (100% chance of success). */ return N_("%sEscape To Nearest City%s"); @@ -6356,6 +6369,8 @@ const char *action_min_range_ruleset_var_name(int act) return "teleport_2_min_range"; case ACTION_TELEPORT3: return "teleport_3_min_range"; + case ACTION_TELEPORT_CONQUER: + return "teleport_conquer_min_range"; case ACTION_USER_ACTION1: return "user_action_1_min_range"; case ACTION_USER_ACTION2: @@ -6450,6 +6465,7 @@ int action_min_range_default(enum action_result result) case ACTRES_NUKE_UNITS: return RS_DEFAULT_ACTION_MIN_RANGE; case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: return RS_DEFAULT_MOVE_MIN_RANGE; case ACTRES_NONE: return RS_DEFAULT_ACTION_MIN_RANGE; @@ -6602,6 +6618,8 @@ const char *action_max_range_ruleset_var_name(int act) return "teleport_2_max_range"; case ACTION_TELEPORT3: return "teleport_3_max_range"; + case ACTION_TELEPORT_CONQUER: + return "teleport_conquer_max_range"; case ACTION_USER_ACTION1: return "user_action_1_max_range"; case ACTION_USER_ACTION2: @@ -6699,6 +6717,7 @@ int action_max_range_default(enum action_result result) return RS_DEFAULT_ACTION_MAX_RANGE; case ACTRES_AIRLIFT: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: return ACTION_DISTANCE_UNLIMITED; case ACTRES_NONE: return RS_DEFAULT_ACTION_MAX_RANGE; @@ -6831,6 +6850,7 @@ const char *action_target_kind_ruleset_var_name(int act) case ACTION_TELEPORT: case ACTION_TELEPORT2: case ACTION_TELEPORT3: + case ACTION_TELEPORT_CONQUER: case ACTION_SPY_ESCAPE: case ACTION_GAIN_VETERANCY: /* Target kind is not ruleset changeable */ @@ -6932,6 +6952,7 @@ action_target_kind_default(enum action_result result) case ACTRES_HUT_FRIGHTEN: case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: return ATK_TILE; case ACTRES_CONQUER_EXTRAS: return ATK_EXTRAS; @@ -7024,6 +7045,7 @@ bool action_result_legal_target_kind(enum action_result result, case ACTRES_HUT_FRIGHTEN: case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: return tgt_kind == ATK_TILE; case ACTRES_CONQUER_EXTRAS: return tgt_kind == ATK_EXTRAS; @@ -7128,6 +7150,7 @@ action_sub_target_kind_default(enum action_result result) case ACTRES_HUT_FRIGHTEN: case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: case ACTRES_ENABLER_CHECK: case ACTRES_SPY_ESCAPE: return ASTK_NONE; @@ -7274,6 +7297,7 @@ const char *action_actor_consuming_always_ruleset_var_name(action_id act) case ACTION_TELEPORT: case ACTION_TELEPORT2: case ACTION_TELEPORT3: + case ACTION_TELEPORT_CONQUER: case ACTION_GAIN_VETERANCY: case ACTION_SPY_ESCAPE: /* Actor consuming always is not ruleset changeable */ @@ -7365,6 +7389,8 @@ const char *action_blocked_by_ruleset_var_name(const struct action *act) return "teleport_2_blocked_by"; case ACTION_TELEPORT3: return "teleport_3_blocked_by"; + case ACTION_TELEPORT_CONQUER: + return "teleport_conquer_blocked_by"; case ACTION_SPY_ESCAPE: case ACTION_SPY_POISON: case ACTION_SPY_POISON_ESC: @@ -7609,6 +7635,7 @@ action_post_success_forced_ruleset_var_name(const struct action *act) case ACTION_TELEPORT: case ACTION_TELEPORT2: case ACTION_TELEPORT3: + case ACTION_TELEPORT_CONQUER: case ACTION_GAIN_VETERANCY: case ACTION_SPY_ESCAPE: case ACTION_USER_ACTION1: diff --git a/common/actions.h b/common/actions.h index 4d04ffd1e6..cfbbf3235e 100644 --- a/common/actions.h +++ b/common/actions.h @@ -276,22 +276,24 @@ const char *gen_action_name_update_cb(const char *old_name); #define SPECENUM_VALUE112NAME "Teleport2" #define SPECENUM_VALUE113 ACTION_TELEPORT3 #define SPECENUM_VALUE113NAME "Teleport3" -#define SPECENUM_VALUE114 ACTION_CLEAN -#define SPECENUM_VALUE114NAME "Clean" +#define SPECENUM_VALUE114 ACTION_TELEPORT_CONQUER +#define SPECENUM_VALUE114NAME "Teleport Conquer" +#define SPECENUM_VALUE115 ACTION_CLEAN +#define SPECENUM_VALUE115NAME "Clean" /* Enabler checks only */ -#define SPECENUM_VALUE115 ACTION_GAIN_VETERANCY -#define SPECENUM_VALUE115NAME "Gain Veterancy" +#define SPECENUM_VALUE116 ACTION_GAIN_VETERANCY +#define SPECENUM_VALUE116NAME "Gain Veterancy" /* User actions */ -#define SPECENUM_VALUE116 ACTION_USER_ACTION1 -#define SPECENUM_VALUE116NAME "User Action 1" -#define SPECENUM_VALUE117 ACTION_USER_ACTION2 -#define SPECENUM_VALUE117NAME "User Action 2" -#define SPECENUM_VALUE118 ACTION_USER_ACTION3 -#define SPECENUM_VALUE118NAME "User Action 3" -#define SPECENUM_VALUE119 ACTION_USER_ACTION4 -#define SPECENUM_VALUE119NAME "User Action 4" +#define SPECENUM_VALUE117 ACTION_USER_ACTION1 +#define SPECENUM_VALUE117NAME "User Action 1" +#define SPECENUM_VALUE118 ACTION_USER_ACTION2 +#define SPECENUM_VALUE118NAME "User Action 2" +#define SPECENUM_VALUE119 ACTION_USER_ACTION3 +#define SPECENUM_VALUE119NAME "User Action 3" +#define SPECENUM_VALUE120 ACTION_USER_ACTION4 +#define SPECENUM_VALUE120NAME "User Action 4" #define SPECENUM_BITVECTOR bv_actions #define SPECENUM_COUNT ACTION_COUNT #define SPECENUM_NAME_UPDATER diff --git a/common/actres.c b/common/actres.c index b24ac76958..8ed851584c 100644 --- a/common/actres.c +++ b/common/actres.c @@ -229,6 +229,9 @@ static struct actres act_results[ACTRES_LAST] = { { ACT_TGT_COMPL_SIMPLE, ABK_NONE, /* ACTRES_TELEPORT */ FALSE, ACTIVITY_LAST, DRT_NONE, EC_NONE, ERM_NONE }, + { ACT_TGT_COMPL_SIMPLE, ABK_NONE, /* ACTRES_TELEPORT_CONQUER */ + FALSE, ACTIVITY_LAST, DRT_NONE, + EC_NONE, ERM_NONE }, { ACT_TGT_COMPL_SIMPLE, ABK_NONE, /* ACTRES_ENABLER_CHECK */ FALSE, ACTIVITY_LAST, DRT_NONE, EC_NONE, ERM_NONE } @@ -1047,7 +1050,7 @@ enum fc_tristate actres_possible(enum action_result result, case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: - + case ACTRES_TELEPORT_CONQUER: if (result == ACTRES_UNIT_MOVE) { /* Reason: is moving to the tile. */ if (!unit_can_move_to_tile(nmap, actor->unit, target->tile, @@ -1055,11 +1058,11 @@ enum fc_tristate actres_possible(enum action_result result, return TRI_NO; } } else { - fc_assert(result == ACTRES_TELEPORT); + fc_assert(result == ACTRES_TELEPORT || result == ACTRES_TELEPORT_CONQUER); /* Reason: is teleporting to the tile. */ if (!unit_can_teleport_to_tile(nmap, actor->unit, target->tile, - FALSE, FALSE)) { + FALSE, result == ACTRES_TELEPORT_CONQUER)) { return TRI_NO; } } @@ -1070,7 +1073,7 @@ enum fc_tristate actres_possible(enum action_result result, } /* We cannot move a transport into a tile that holds - * units or cities not allied with all of our cargo. */ + * units or cities not allied with ani of our cargo. */ if (get_transporter_capacity(actor->unit) > 0) { unit_list_iterate(unit_tile(actor->unit)->units, pcargo) { if (unit_contained_in(pcargo, actor->unit) diff --git a/common/fc_types.h b/common/fc_types.h index bafb4c2782..b690ae0789 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -317,8 +317,9 @@ enum counter_target { CTGT_CITY }; /* TODO: Move close to "Move" */ #define SPECENUM_VALUE65 ACTRES_TELEPORT #define SPECENUM_VALUE65NAME "Teleport" +#define SPECENUM_VALUE66 ACTRES_TELEPORT_CONQUER /* Hardcoded action that's just controlled by enablers */ -#define SPECENUM_VALUE66 ACTRES_ENABLER_CHECK +#define SPECENUM_VALUE67 ACTRES_ENABLER_CHECK /* All consequences are handled as (ruleset) action data. */ #define SPECENUM_COUNT ACTRES_LAST #include "specenum_gen.h" diff --git a/common/oblig_reqs.c b/common/oblig_reqs.c index 3ffe36499c..1a13e57f31 100644 --- a/common/oblig_reqs.c +++ b/common/oblig_reqs.c @@ -736,7 +736,7 @@ void hard_code_oblig_hard_reqs(void) N_("All action enablers for %s must require" " that the actor isn't transported."), ACTRES_UNIT_MOVE, - ACTRES_TELEPORT, + ACTRES_TELEPORT, ACTRES_TELEPORT_CONQUER, ACTRES_NONE); /* Why this is a hard requirement: assumed by the Freeciv code. */ diff --git a/doc/README.actions b/doc/README.actions index 19d3b09e84..28ee8aaee4 100644 --- a/doc/README.actions +++ b/doc/README.actions @@ -1439,6 +1439,24 @@ Actions done by a unit against a tile must be between teleport_3_min_range and teleport_3_max_range * See "Teleport" for everything else. +"Teleport Conquer" - telepor unit to the target tile and conquer it +* UI name can be set using ui_name_teleport_conquer +* any action listed in teleport_conquer_blocked_by must be impossible +* the range of legal distance between actor unit and target tile + must be between teleport_conquer_min_range and teleport_conquer_max_range +* the actor unit may not be transported (!) +* the actor unit's type must be the target tile's terrain animal if the + player's nation is an animal barbarian. +* the actor unit must be able to exist outside of a transport at the target + tile. +* the actor unit doesn't have the "CoastStrict" unit type flag or the + target tile is on or adjacent to a tile that doesn't have the + "UnsafeCoast" terrain flag. +* the actor unit can't be diplomatically forbidden from entering the target + tile. +* the target tile can't contain any units not allied to the actor + unit and all its cargo. + Actions done by a unit against all extras at a tile =================================================== "Conquer Extras" - Claim ownership of an extra. diff --git a/server/advisors/advdata.c b/server/advisors/advdata.c index 9f987d1da1..b40879ba37 100644 --- a/server/advisors/advdata.c +++ b/server/advisors/advdata.c @@ -887,6 +887,7 @@ adv_want adv_gov_action_immunity_want(struct government *gov) case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: case ACTRES_ENABLER_CHECK: case ACTRES_MARKETPLACE: case ACTRES_FOUND_CITY: diff --git a/server/unithand.c b/server/unithand.c index c1e280cfb8..8c40ffdb13 100644 --- a/server/unithand.c +++ b/server/unithand.c @@ -1118,7 +1118,7 @@ static struct player *need_war_player_hlp(const struct unit *actor, case ACTRES_PARADROP_CONQUER: /* Target is a tile but a city can block it. */ fc_assert_action(action_get_target_kind(paction) == ATK_TILE, break); - if (target_tile + if (target_tile != NULL && map_is_known_and_seen(target_tile, actor_player, V_MAIN)) { /* Seen tile unit savers */ @@ -1188,6 +1188,7 @@ static struct player *need_war_player_hlp(const struct unit *actor, case ACTRES_HUT_FRIGHTEN: case ACTRES_UNIT_MOVE: case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: case ACTRES_ENABLER_CHECK: case ACTRES_SPY_ESCAPE: case ACTRES_NONE: @@ -3923,9 +3924,12 @@ bool unit_perform_action(struct player *pplayer, target_tile, paction)); break; case ACTRES_TELEPORT: + case ACTRES_TELEPORT_CONQUER: ACTION_PERFORM_UNIT_TILE(action_type, actor_unit, target_tile, unit_move(actor_unit, target_tile, 0, - NULL, FALSE, FALSE, FALSE, + NULL, FALSE, + paction->result == ACTRES_TELEPORT_CONQUER, + paction->result == ACTRES_TELEPORT_CONQUER, FALSE, FALSE)); break; case ACTRES_TRANSFORM_TERRAIN: -- 2.40.1