Project

General

Profile

Feature #1452 ยป 0079-Add-internal-city-action-type-Finish-Unit.patch

Marko Lindqvist, 05/26/2025 05:34 PM

View differences:

common/actions.c
static struct action *
player_action_new(action_id id,
enum action_result result);
static struct action *
city_action_new(action_id id,
enum action_result result);
static bool is_enabler_active(const struct action_enabler *enabler,
const struct req_context *actor,
......
actions[ACTION_CIVIL_WAR] =
player_action_new(ACTION_CIVIL_WAR, ACTRES_ENABLER_CHECK);
actions[ACTION_FINISH_UNIT] =
city_action_new(ACTION_FINISH_UNIT, ACTRES_ENABLER_CHECK);
/* The structure even for these need to be created, for
* the action_id_rule_name() to work on iterations. */
......
/**********************************************************************//**
Create a new action performed by a player actor.
**************************************************************************/
static struct action *
player_action_new(action_id id,
enum action_result result)
static struct action *player_action_new(action_id id,
enum action_result result)
{
struct action *act = action_new(id, result,
0, 0, FALSE);
return act;
}
/**********************************************************************//**
Create a new action performed by a city actor.
**************************************************************************/
static struct action *city_action_new(action_id id,
enum action_result result)
{
struct action *act = action_new(id, result,
0, 0, FALSE);
......
nullptr, nullptr, nullptr);
}
/**********************************************************************//**
Returns TRUE if actor_city can do wanted_action as far as
action enablers are concerned.
**************************************************************************/
bool is_action_enabled_city(const struct civ_map *nmap,
const action_id wanted_action,
const struct city *actor_city)
{
return is_action_enabled(nmap, wanted_action,
&(const struct req_context) {
.player = city_owner(actor_city),
.city = actor_city,
.tile = city_tile(actor_city)
},
nullptr, nullptr, nullptr);
}
/**********************************************************************//**
Find out if the action is enabled, may be enabled or isn't enabled given
what the player owning the actor knowns.
......
case ACTION_GAIN_VETERANCY:
case ACTION_ESCAPE:
case ACTION_CIVIL_WAR:
case ACTION_FINISH_UNIT:
fc_assert(!action_id_is_internal(act)); /* Fail always */
break;
case ACTION_COUNT:
......
return N_("%sEscape%s");
case ACTION_CIVIL_WAR:
return N_("%sCivil War%s");
case ACTION_FINISH_UNIT:
return N_("%sFinish Unit%s");
case ACTION_COUNT:
fc_assert(act != ACTION_COUNT);
break;
......
case ACTION_GAIN_VETERANCY:
case ACTION_ESCAPE:
case ACTION_CIVIL_WAR:
case ACTION_FINISH_UNIT:
/* Min range is not ruleset changeable */
return NULL;
case ACTION_NUKE:
......
case ACTION_GAIN_VETERANCY:
case ACTION_ESCAPE:
case ACTION_CIVIL_WAR:
case ACTION_FINISH_UNIT:
/* Max range is not ruleset changeable */
return NULL;
case ACTION_HELP_WONDER:
......
case ACTION_GAIN_VETERANCY:
case ACTION_ESCAPE:
case ACTION_CIVIL_WAR:
case ACTION_FINISH_UNIT:
/* Target kind is not ruleset changeable */
return NULL;
case ACTION_NUKE:
......
case ACTION_GAIN_VETERANCY:
case ACTION_ESCAPE:
case ACTION_CIVIL_WAR:
case ACTION_FINISH_UNIT:
/* Actor consuming always is not ruleset changeable */
return NULL;
case ACTION_FOUND_CITY:
......
case ACTION_HUT_FRIGHTEN4:
case ACTION_GAIN_VETERANCY:
case ACTION_CIVIL_WAR:
case ACTION_FINISH_UNIT:
case ACTION_ESCAPE:
case ACTION_USER_ACTION1:
case ACTION_USER_ACTION2:
......
case ACTION_GAIN_VETERANCY:
case ACTION_ESCAPE:
case ACTION_CIVIL_WAR:
case ACTION_FINISH_UNIT:
case ACTION_USER_ACTION1:
case ACTION_USER_ACTION2:
case ACTION_USER_ACTION3:
common/actions.h
const action_id wanted_action,
const struct player *actor_plr);
bool is_action_enabled_city(const struct civ_map *nmap,
const action_id wanted_action,
const struct city *actor_city);
struct act_prob action_prob_vs_city(const struct civ_map *nmap,
const struct unit *actor,
const action_id act_id,
data/alien/actions.ruleset
[enabler_gain_veterancy]
action = "Gain Veterancy"
actor_reqs =
{ "type", "name", "range", "present"
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/civ1/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/civ2/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/civ2civ3/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/classic/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/goldkeep/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/granularity/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/multiplayer/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/sandbox/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
data/webperimental/actions.ruleset
actor_reqs =
{ "type", "name", "range", "present"
}
[enabler_finish_unit]
action = "Finish Unit"
actor_reqs =
{ "type", "name", "range", "present"
}
doc/README.actions
* Unit's veterancy system must have veterancy levels for the unit
to advance to.
"Finish Unit" - city can finish building a unit
Ruleset defined actions
=======================
User actions are "blank". The ruleset does everything they do. The following
gen_headers/enums/actions_enums.def
ACTION_GAIN_VETERANCY "Gain Veterancy"
ACTION_ESCAPE "Escape"
ACTION_CIVIL_WAR "Civil War"
ACTION_FINISH_UNIT "Finish Unit"
# User actions
ACTION_USER_ACTION1 "User Action 1"
server/cityturn.c
pcity->before_change_shields -= cost;
pcity->shield_stock -= cost;
pcity->turn_last_built = game.info.turn;
/* to eliminate micromanagement */
/* To eliminate micromanagement */
if (is_great_wonder(pimprove)) {
notify_player(NULL, city_tile(pcity), E_WONDER_BUILD, ftc_server,
_("The %s have finished building %s in %s."),
......
return city_exist(saved_city_id);
}
if (pcity->shield_stock >= unit_shield_cost) {
if (pcity->shield_stock >= unit_shield_cost
&& is_action_enabled_city(nmap, ACTION_FINISH_UNIT, pcity)) {
int pop_cost = utype_pop_value(utype, pcity);
struct unit *punit;
......
case VUT_UTYPE:
return city_build_unit(pplayer, pcity);
default:
/* must never happen! */
/* Must never happen! */
fc_assert(FALSE);
break;
};
return FALSE;
}
server/ruleset/rscompat.c
**************************************************************************/
void rscompat_postprocess(struct rscompat_info *info)
{
struct action_enabler *enabler;
if (!info->compat_mode || info->version >= RSFORMAT_CURRENT) {
/* There isn't anything here that should be done outside of compat
* mode. */
return;
}
enabler = action_enabler_new();
enabler->action = ACTION_FINISH_UNIT;
action_enabler_add(enabler);
/* Upgrade existing effects. Done before new effects are added to prevent
* the new effects from being upgraded by accident. */
iterate_effect_cache(effect_list_compat_cb, info);
    (1-1/1)