Modding extensions
March 30, 2026 ยท View on GitHub
This document covers modding extensions that have been added to Project Alice in addition to what Victoria 2 provided. We are generally open to adding more modding extensions by request, under the condition that you actually plan to use them. Generally, we are not interested in speculatively adding extensions just because they might be useful.
Scripting
Trigger Condition Parsing
In Victoria 2, a trigger condition such as as prestige = 5 will trigger when the nation's prestige is greater than or equal to 5. If you want to test whether the value is less than 5, you would have to bury it inside a NOT scope. And testing for exact equality would be even more complicated. To simplify things, we support replacing the = with one of the following tokens: ==, !=, <, >, <=, >=. == tests for exact equality, != for inequality, and the rest have their ordinary meanings. We also support replacing = with != in most situations. For example, tag != USA is the same as NOT = { tag = USA }.
Additionally, any effect scope can have a limit, in the original, THIS, TAG, FROM, overlord, capital_scope and any_greater_power couldn't reliably have a limit = { ... } defined within them. However Alice supports defining limits for any of them.
Also, province scopes will not crash the game, take for example:
252 = {
owner = { prestige = 5 }
owner = { badboy = 0.2 }
secede_province = THIS
}
This would certainly be unthinkable, as in the original, anything after the first owner gets ignored. But not anymore.
ENG_52 = {
secede_province = QQQ
change_region_name = "Test"
secede_province = THIS
}
This often caused crashes if not handled carefully (especially the seceding to a null tag part). Not anymore.
Another new feature is allowing usage of uniform yes/no inside triggers, in the original engine, triggers such as unit_has_leader = yes was the same as unit_has_leader = no, so it'd need to be wrapped around a NOT = { unit_has_leader = yes }. Not anymore.
Additionally, triggers such as technology triggers no longer suffer from having to be specified like: nationalism_n_imperialism = 1, they can alternatively be specified as nationalism_n_imperialism = yes. For ease of reading and uniformity.
New effects
increment_variable = ...: Shorthand to increment by 1decrement_variable = ...: Shorthand to decrement by 1set_variable_to_zero = ...: Shorthand to set a variable to 0ruling_party_ideology = THIS/FROM: Appoints the ruling party with an ideology ofTHISorFROMadd_accepted_culture = THIS/FROM: Now withTHIS/FROMadds the PRIMARY culture ofTHIS/FROMto the nation in scopeadd_accepted_culture = this_union/from_union: Adds the culture union of the primary culture ofTHIS/FROMas accepted to the nation in scopekill_leader = "name of leader": kills a leader (admiral or general) belonging to the nation in scope with the given name. Note that this will only reliably function if you have explicitly created a leader with that name via effect or via definition in the history files.annex_to = null: this turns all the provinces owned by the nation in scope into un-owned provinces (which defeats the nation, liberates its puppets, etc).secede_province = null: turns the province in scope into an un-owned province. This is to replace some of the tricks mods did to turn provinces un-owned, such as seceding them to nonexistent tags, etcrandom_greater_power = { ... }: Likeany_greater_power, but only one random great power is scoped.random_empty_neighbor_province- selects random empty neighbor province in nation/province scope.any_empty_neighbor_province = { ... }: Likerandom_empty_neighbor_province, but all of the empty adjacent provinces are scoped. Can be used in province or nation scope.random_neighbor_provincecan be used in nation and province scope.any_neighbor_provincecan be used in nation and province scope.change_terrain = terrain: Changes the terrain of the province on scope, can be used on pop scopes too (will default to the location of the pop)religion = religion_name: Effect can be used in a province and pops scope to change the religion of the province/pop.assimilate = yes: Effect can be used in a pop/province/state scope to change the culture of pops in the scope to primary culture.reduce_pop_abs = amount: Reduce pop in the pop scope by absolute amount (e.g. 500 soldiers). Use with negative values to increase pop size. Use with very big number to remove pop completely.set_culture = culture: Set culture of a pop in scope to a named culture.any_existing_country_except_scoped: Same behavior ofany_countryon decisions, any existing nation except the one scopedany_defined_country: Same behavior ofany_countryon events, scope all countries even those that don't exist and includes the current countryrandom_neighbor_country: A random neighboring country.all_core = { ... } (for provinces): The ability to use it within provinces to scope all the cores of the province in question, for example if England and Russia have cores on Houston, then this will scope both England and Russiaany_core = { ... }: Effects dont haveany_core, but triggers do, so for consistency its supported too.from_bounce = { ... }: Forward whatever is in the current scope to be "bounced" toFROM, until the end of this scopethis_bounce = { ... }: Same as above but withTHIS.random_by_modifier = { ... }: See below for syntax usagebuild_bank_in_capital = { ... }: Invalid in vanilla, added for mods to use.build_university_in_capital = { ... }: Invalid in vanilla, added for mods to use.any_owned_province = { ... }: Providing uniformity with respect to triggers.any_prov = { ... }: Shorthand forany_owned.any_owned_province = { ... }: Shorthand forany_owned.any_substate = { ... }: For parity with triggers, scopes any substates of the country.remove_country_flag = flag: Alias ofclr_country_flag.clear_global_flag = flag: Alias ofclr_global_flag.province_immigrator = n:ncan only be1or-1. This is the "province selector" used in various mods.immigrator = n: Alias ofprovince_immigrator.immigrator_selector = n: Alias ofprovince_immigrator.if = { ... }: See below for if-else usage.else_if = { ... }: See below.else = { ... }: See below.add_country_modifier = modifier: Shorthand foradd_country_modifier = { name = modifier duration = -1 }add_province_modifier = modifier: Shorthand foradd_province_modifier = { name = modifier duration = -1 }masquerade_as_nation = THIS/FROM: Use the visual flag ofTHIS/FROMas the flag of the nation, most useful for dynamic rebellions for example.change_party_name = { ... }: This effect is defined using a block with two members. The first member isideology = ...where...is either the name of an ideology orruling_party. This member determines which party the effect will apply to. If an ideology is provided, it will apply to the first active political party with that ideology (generally the "first" party is the political party defined earlier in the files). Ifruling_partyis provided, the current ruling party of the nation in scope will be affected. The second member isname = .... This value is the new name that the party will be given. This effect can be used only within a national scope. Example:
change_party_name = {
ideology = conservative
name = NEW_PARTY_NAME
}
change_party_position = { ... }: This effect is defined using a block with two members. The first member isideology = ...where...is either the name of an ideology orruling_party, which determines which party the effect applies to as described above. The second member isposition = ...where...is one of the options for a party issue or a political or social reform. The effect will cause the political party determined by theideologymember to change their party position to the givenposition, if it is a party issue or it will give them a voting preference in favor of that particular reform and remove any voting preference in favor of another reform in that group (see below for more on the extension of party preferences). This effect can be used only within a national scope. Example:
change_party_position = {
ideology = ruling_party
position = free_trade
}
diplo_points = ...: Will add the number to the currently stored diplomatic points of the nation in scope. (Note: so you can use a negative number to subtract points. Diplomatic points can not be reduced to less than zero.)suppression_points = ...: Will add the number to the currently stored suppression points of the nation in scope. (Note: so you can use a negative number to subtract points. Suppression points can not be reduced to less than zero.)
As for build_xxx_in_capital, the game doesn't allow custom defined buildings to be used in this mode as an effect.
The syntax for build_bank_in_capital and it's university counterpart is the same:
build_bank_in_capital = {
in_whole_capital_state = yes/no
limit_to_world_greatest_level = yes/no
}
New trigger conditions
test = name_of_scripted_trigger: evaluates a scripted trigger (see below)any_country = { ... }: tests whether any existent country satisfies the conditions given in.... This is essentially just mirroring how the existingany_countryeffect scope works but for trigger conditions.any_known_country = { ... }: same as above, aliasevery_country = { ... }: Likeany_country, but applies to EVERY country.has_global_flag = project_alice: true if playing on Project Alice, false if notall_war_countries = { ... }: All countries we're at war with MUST fulfill the condition, as opposed towar_countrieswere only one country has to fulfill the conditionany_war_countries = { ... }: Equivalent towar_countriesall_state = { ... }: All states must fulfill condition, similar toany_stateall_substate = { ... }: All substates must fulfill condition, similar toany_substateall_sphere_member = { ... }: All sphere members must fulfill condition, similar toany_sphere_memberall_pop = { ... }: All POPs must fulfill condition, similar toany_popall_greater_power = { ... }: All greater powers must fulfill condition.any_owned = { ... }: Shorthand forany_owned_province.is_ai = yes/no: Alias ofai = yes/no.recently_lost_war: Alias ofhas_recently_lost_war = yeshas_recent_immigration: Alias ofhas_recent_imigration(the original is misspelled).industry_score: Alias ofindustrial_score.has_accepted_culture: Alias ofaccepted_culture.number_of_cities: Alias ofnum_of_cities.disarmed: Alias ofis_disarmed.is_vassal_of: Alias ofvassal_of.has_national_focus = focus: Checks if a state (or province) in scope has a focusfocus.party_name = { ... }: This trigger condition is defined using a block with two members. The first member isideology = ...where...is either the name of an ideology orruling_party. This member determines which political party the trigger condition will test. If an ideology is provided, it will test to the first active political party with that ideology (generally the "first" party is the political party defined earlier in the files). Ifruling_partyis provided, the current ruling party of the nation in scope will be tested. The second member isname = .... This value is what the name of the selected party is tested against. An exact match evaluates astrue, while a party with any other name will yield false. This trigger condition can be used only within a national scope. Example:
party_name = {
ideology = conservative
name = SOME_PARTY_NAME
}
party_position = { ... }: This trigger condition is defined using a block with two members. The first member isideology = ...where...is either the name of an ideology orruling_party, which determines which political party the trigger condition will test, as described above. The second member isposition = ...where...is one of the options for a party issue or a political or social reform. The trigger condition will test whether the political party determined by theideologymember holds the specified party position (if a party issue) or whether it has a specific voting preference in favor of that particular reform (see below for more on the extension of party preferences). This trigger condition can be used only within a national scope. Example:
party_position = {
ideology = ruling_party
position = free_trade
}
diplo_points = ...: This trigger condition is true if the nation in scope has saved diplomatic points greater than or equal to the given number.suppression_points = ...: This trigger condition is true if the nation in scope has saved suppression points greater than or equal to the given number.check_gamerule_ = { ... }: Checks if a given gamerule has a selected option. Example in gamerules section.
New modifiers
Technologies
Technologies can have their cost in leadership_cost.
FROM bounce
FROM bouncing is a technique where before, modders would do:
country_event (THIS = USA, FROM = ---) -> fire for X
country_event (THIS = X, FROM = USA) -> Fire for Y
country_event (THIS = Y, FROM = X) -> <Dynamic effects>
However this can be tedious to perform, hence we added a from_bounce effect scope, that can be used as follows:
any_country = {
#Assume FROM = ENG
from_bounce = {
FROM = { add_accepted_culture = THIS }
THIS = { add_accepted_culture = FROM }
}
#FROM is now again = ENG
}
You can even nest them! Why would you want this? Up to you really.
any_country = {
limit = { has_country_flag = paid_the_sultan }
from_bounce = {
prestige = 5
SUL = { random_owned = { annex_to = FROM } } #Partition the sultan
any_country = {
#All countries at war with us will get annexed
limit = { war_with = FROM }
from_bounce = { inherit = FROM }
}
}
}
If the from_bounce has a limit, it will evaluate with FROM-relativity:
ENG = {
from_bounce = {
limit = { FROM = { tag != ENG } }
prestige = 5
}
}
The above code will never execute because it will never be true. Same applies for this_bounce.
Before, this would've required something akin to:
country_event = { #Setup THIS
id = 50000
option = {
name = "Ok"
any_country = { country_event = 50001 }
}
}
country_event = { #Setup THIS-FROM
id = 50001
is_triggered_only = yes
option = {
name = "Ok"
any_country = {
limit = { NOT = { tag = FROM } }
country_event = 50002
}
}
}
country_event = {
id = 50002
is_triggered_only = yes
option = {
name = "OK"
FROM = { add_accepted_culture = THIS }
THIS = { add_accepted_culture = FROM }
}
}
Random by modifier
The question of: How can we have probabilities which change depending on various factors?
Well the answer is random_by_modifier:
random_by_modifier = {
chance = {
base = 50 #50% chance
modifier = {
factor = 1.5 # x1.5 (50% x 1.5 = 75%)
is_colonial = yes
}
}
#50% base chance
#75% chance if colonial
secede_province = THIS
}
Custom tooltip
custom_tooltip = {
x = <variable> #$x$
y = <variable> #$x$
text = "localisation_key"
}
Alternatively:
custom_tooltip = "localisation_key"
Lambda events
Define anonymous lambda events within events, no need to give them an ID.
country_event = {
id = 1000
# etc...
option = {
name = "Option A"
lambda_country_event = {
#No need to define ID
option = {
name = "Option A"
#...
}
option = {
name = "Option B"
#...
}
}
}
option = {
name = "Option B"
lambda_country_event = {
#No need to define ID
option = {
name = "Option A"
#...
}
option = {
name = "Option B"
#...
}
}
}
}
This allows essentially to "inline" anonymous events, for example when doing a FAQ section event, or doing a long event chain for setup or "LARP choices" purposes.
These events can't be triggered with the event command, nor can they be referenced by other events, they never will trigger on their own and will always be treated as if they were is_triggered_only = yes.
lambda_country_event: Main slot is acountry, inheritsFROMandTHISslot types.lambda_province_event: Main slot is aprovince, inheritsFROMandTHISslot types.
Scripted Triggers
We have added the ability to write complicated trigger conditions once and then to use that same condition multiple times inside other trigger conditions. To use these "scripted triggers," you must add a scripted triggers directory to your mod (at the top level of your mod, so the path will look like: ...\mod name\scripted triggers). Place any number of .txt files inside this directory, each of which can contain any number of scripted triggers.
Each scripted trigger in such a file should look like:
name_of_condition = {
main_parameter = nation/state/province/pop/rebel/none
this_parameter = ...
from_parameter = ...
... contents of the trigger condition go here...
}
You should add an entry for name_of_condition to your csv file, since it will appear in tool tips when you use the scripted trigger. The three parameter entries define the content that the trigger will be tested upon (you must pick one of the possibilities). A scripted trigger can only be used in a context where the various parameters either match or where the parameter of the scripted trigger is none (you can think of none as matching everything). For example, if the main parameter is province then you could only evaluate the scripted trigger when there was a province in scope. The this_parameter and from_parameter are optional and may be omitted (they default to none). You can define more than one scripted trigger with the same name, so long as they have different parameter types. When using a scripted trigger with multiple versions, the one that fits the current parameters will automatically be selected.
To use a scripted trigger simply add test = name_of_condition in a trigger wherever you want to evaluate your scripted trigger and it will work as if you had copied its content into that location. I advise you not to use scripted triggers from within other scripted triggers while defining them. You can safely refer to scripted triggers earlier in the same file, but doing so across files will put you at the mercy of the file loading order.
If/Else
If and Else statements are now provided to avoid code duplication and make your life easier. A else with a limit is equivalent to an else_if with a limit, and a else_if without a limit is equal to a else without a limit. In other words, else and else_if are essentially synonyms, provided for code clarity.
For example:
if = { #run if limit is true
limit = { ... }
...
} else_if = { #run only if the limit above is false, and this limit is true
limit = { ... }
...
} else = { #only if both cases are not fulfilled AND the limit is true
limit = { ... }
...
}
No limit specified equals to an always = yes.
Additionally, the order of execution for if and else/else_if statements allows for nested code:
if = {
limit = { a = yes }
money = 1
if = {
limit = { b = yes }
money = 50
} else {
money = 100
}
}
This is equivalent to:
if = {
limit = { a = yes b = yes }
money = 1
money = 50
} else_if {
limit = { a = yes }
money = 1
money = 100
}
Additionally, negation of statements are implicit, in other words:
if = {
limit = { test == yes }
} else {
limit = { test != yes }
}
Is implicitly assumed for every else after a if, this means that an explicit negation (rewriting everything inside a big NOT statement) is not required for else statements, as they now logically are tied to all statements beforehand being false, and the statement of it's own limit being true.
An issue which might exist due to the volatility of the syntax could be:
else_if = {
limit = { ... }
} if = {
limit = { ... }
}
The behavior of this statement is that, since there is no preceding if before the else_if, the else_if will be able to run as if it was chained with an if that evaluated to false, in the case of it's limit evaluating to true, then it will run its own effect. However, the other if statement will run regardless of the previous expression.
As the lexicographical order of the statements are sequential, this is, every else_if and else must be preceded by an if statement, otherwise they will be chained to the nearest preceding if statement before them for their lexicographical evaluation, otherwise they will act as an if in itself if none is present.
else_if = {
limit = { ... }
} else_if = {
limit = { ... }
}
These else_if statements are chained together, if the first runs, the second will not, and vice versa. If no preceding if exists before them, the first else_if takes the role of the if statement.
UI Modding
Extension controls
It is now possible to add new controls (such as buttons, text labels, and so on) to an existing window control without modifying the original file. To add new controls to a window simply define additional top level controls like the example below:
guiButtonType = {
name = "alice_move_capital"
extends = "province_view_header"
position = { x= 180 y = 3 }
quadTextureSprite = "GFX_move_capital"
}
This control will then automatically be inserted into the window named province_view_header when it is created. This allows you to extend a window defined in a .gui file without editing that file. The example above comes from alice.gui and is used to add a button to a window defined in province_interface.gui without editing that file. You mod can thus define a new .gui file, add new controls there, and have them show up in existing windows without interfering with another mod that also wants to add controls to that window (because now both mods don't have to make changes to the same .gui file).
Scriptable buttons
Of course, adding new buttons wouldn't mean much if you couldn't make them do things. To allow you to add custom button effects to the game, we have introduced two new ui element types: provinceScriptButtonType and nationScriptButtonType. These buttons are defined in the same way as a guiButtonType, except that they can be given additional allow and effect parameters. For example:
provinceScriptButtonType = {
name = "wololo_button"
extends = "province_view_header"
position = { x= 146 y = 3 }
quadTextureSprite = "GFX_wololo"
allow = {
owner = { tag = FROM }
}
effect = {
assimilate = "yes please"
}
}
A province script button has its main and THIS slots filled with the province that the containing window is about, with FROM the player's nation. A nation script button has its main and THIS slots filled with the nation that the containing window is about, if there is one, or the player's nation if there is not, and has FROM populated with the player's nation.
The allow trigger condition is optional and is used to determine when the button is enabled. If the allow condition is omitted, the button will always be enabled.
The tooltip for these scriptable buttons will always display the relevant allow condition and the effect. You may also optionally add a custom description to the tooltip by adding a localization key that is the name of the button followed by _tooltip. In the case of the button above, for example, the tooltip is defined as wololo_button_tooltip;Wololo $PROVINCE$. The following three variables can be used in the tooltip: $PROVINCE$, which will resolve to the targeted province, $NATION$, which will resolve to the targeted nation or the owner of the targeted province, and $PLAYER$, which will always resolve to the player's own nation.
Abbreviated .gui syntax
size = { x = 5 y = 10 } can be written as size = { 5 10 }, as can most places expecting an x and y pair.
Additionally, maxwidth = 5 and maxheight = 10 can be written as maxsize = { 5 10 }
.gui layout extensions
Laying out elements in the GUI can be a tedious process, while a WYSWYG editor would be ideal, it's not currently available at the moment.
However, the following new extensions will make GUI editing way less painful:
add_size = { x y }: Adds the specified amount to the currentsizeadd_position = { x y }: Adds the specified amount to the currentpositiontable_layout = { x y }: Wherexis the column andyis the row, this basically translates toposition.x = column * size.x, andposition.y = row * size.y. Useful for laying out elements in a table-like way
Game rules modding
New defines
Alice adds a handful of new defines:
factories_per_state: Factories allowed per state, default 8alice_speed_1: Speed 1 in millisecondsalice_speed_2: Same as above but with speed 2alice_speed_3: Same as above but with speed 3alice_speed_4: Same as above but with speed 4alice_speed_5: Same as above but with speed 5alice_ai_gather_radius: Radius AI will use to gather nearby armies to make deathstacksalice_ai_threat_radius: Radius AI will scan for threatsalice_ai_threat_overestimate: Overestimate AI opponents (higher values leads to camping)alice_ai_attack_target_radius: Radius AI will perform attacksalice_full_reinforce: 1 = Normal vanilla behavior, 0 = Understaffed armies are allowedalice_ai_offensive_strength_overestimate: Overestimate strength of an offensive opponent (makes AI less aggressive)alice_lf_needs_scale: Scale multiplier for life needsalice_ev_needs_scale: Scale multiplier for everyday needsalice_lx_needs_scale: Scale multiplier for luxury needsalice_max_event_iterations: The maximum number of iterations that are possible within recursive events, by default this will be8, so you can only recursively fire events8levels deep. If modders wish to increase their "recursiveness" they may increase this value up to whatever they wish.alice_needs_scaling_factor: Scale factor multiplier for all needsalice_base_rgo_employment_bonus: Additional rgo size of the main rgo.alice_base_rgo_efficiency_bonus: Additional rgo efficiency of the main rgo.alice_factory_per_level_employment: Employment per factory level.alice_domestic_investment_multiplier: Multiplier of domestic investment.alice_rgo_boost: Boost given to RGOs (for example, 1.2 produces 120% more)alice_inputs_base_factor_artisans: Artisan input base factor + modifiers.alice_output_base_factor_artisans: See above.alice_inputs_base_factor: See above, for factories.alice_rgo_overhire_multiplier: Overhire multiplier for RGOs.alice_rgo_production_scale_neg_delta: Scale delta for RGO production.alice_invest_capitalist: % of total budget that capitalists will invest in the private investment poolalice_invest_aristocrat: See above.alice_needs_lf_spend: % of total budget dedicated to life needsalice_needs_ev_spend: See above, but everyday needsalice_needs_lx_spend: See above, but luxury needsalice_sat_delay_factor: Satisfaction delay factoralice_need_drift_speed: Drift speed of need weights for POPsalice_disable_divergent_any_country_effect: On events,any_country = { ... }refers to any country, including nonexistent and the one scoped, in decisions,any_country = { ... }refers only to existing nations and not the one on scope. Set 0 to keep this behavior, set 1 to use a universalany_country = { ... }that scopes existing countries including the currently scoped nation.alice_unciv_civ_forbid_war: Forbids civilized nations from aiding uncivilized ones except via scripted eventsalice_ideology_base_change_rate: Base change rate for ideology for popsalice_nurture_religion_assimilation: Whether religion assimilation should also convert pops or not (0 = yes, 1 = no)alice_surrender_on_cores_lost: Force AI to surrender when they have lost their cores, or if they have no cores, all of their landalice_artificial_gp_limitant: Limit the number of GP allies the AI can havealice_rename_dont_use_localisation: Keys specified onchange_region_nameorchange_province_namewill be treated as CSV keys, otherwise they will define in-line.alice_spherelings_only_ally_sphere: Spherelings will only ally their spherelord.alice_overseas_mil: Militancy increase in overseas provinces when overseas maintenance is at zero.alice_substate_subject_money_transfer: Percentage [0;100] of subjects' budget revenues transferred to the overlord. Default: 30.0alice_puppet_subject_money_transfer. Percentage [0;100] of substates' budget revenues transferred to the overlord. Default: 40.0alice_privateinvestment_subject_transfer: Percentage [0;100] of subjects' and overlord's private investment pool transferred daily when no useful projects are done. Overlord distributes money to subjects and subjects contribute to the overlord. Default: 2.0alice_allow_revoke_subject_states: Allows overlord to take subjects' states raising their militancy and giving separatism. Default: 0.0alice_leadership_generation_divisor: To allow for battles to generate leadership, passive leadership generation is divided by this.alice_auto_hire_generals: set to 0.0 to disable the game hiring generals and admirals automatically.alice_allow_factories_in_colonies: if set to 1, allows to build factories that havecan_be_built_in_colonies = yesflag in coloniesalice_naval_base_to_colonial_distance_factor(default 0.04): multiplier in the formula for colonial distance unlocked by 1 lvl of naval base.alice_always_available_cbs_zero_infamy- if set to 0, then CBs withalways = yeswill have infamy cost calculated as perbadboy_factor.alice_max_starvation_degrowth- the maximum possible popgrowth penalty for a starving pop (below life_need_starvation_limit), reaching this maximum value when fufillment hits 0%. This penalty will not be overidden by other popgrowth techs&modifiers, so a fully starving pop will have this negative popgrowth at minimum.alice_can_add_constructable_cbs_as_wargoals- if set to zero, then one can't add constructable (but not constructed) CBs as wargoals to the ongoing war.alice_render_on_map_generals- if non-zero, thenmap_generalelement oftop_unit_iconGUI is rendered with an on-map general iconalice_economy_presim_days- The number of days in which the economy will presimulate when creating scenario, so that the economy starts on a decent footing in the start date. Setting this value higher will increase scenario creation time however.
Crises and conferences:
alice_crisis_necessary_base_win_ratio = 2.5f: Strength Ratio at which AI submits to demands after 80 temperaturealice_crisis_necessary_base_fast_win_ratio = 3.5f: Strength Ratio at which AI submits to demands before 80 temperaturealice_crisis_per_wg_ratio = 0.1f: Added necessary ratio per every WG
Military:
These relate to the added ability for reserve regiments to reinforce while in battle.
alice_reg_move_to_reserve_org = 0.1f: if a regiment's org goes below this decimal in battle, it wil be taken out from the front, and moved to reserves. Default: 1.0alice_reg_move_to_reserve_str = 0.0f: if a regiment's strength is equal to or less than this decimal in battle, it wil be taken out from the front, and moved to reserves. Default 0.0alice_reg_deploy_from_reserve_org = 0.1f: if a reserve regiments org is equal to or higher than this decimal, it can be deployed to the front, if alice_reg_deploy_from_reserve_str is also fufilled. Default 0.1alice_reg_deploy_from_reserve_str = 0.0f: if a reserve regiments strength is greater than this decimal, it can be deployed to the front, if alice_reg_deploy_from_reserve_org is also fufilled. Default 0.0
These relate to battles:
alice_naval_combat_enemy_stacking_target_select_bonus = 0.5f: The target-picking bonus a ship gets if they are outnumbered in a battle. This is added to the base, which by default is 0.5. It makes outnumbered navies find a target fasteralice_naval_combat_stacking_damage_penalty = 0.5f: The max damage reduction to org and str applied to a fleet which outnumbers the enemy by define:NAVAL_COMBAT_MAX_TARGETS or more. The penalty will scale up starting when a side is outnumbered, and will max out at the given value when outnumbered by NAVAL_COMBAT_MAX_TARGETS times.alice_fort_mil_tactics_discipline_per_level = 0.1f: Modifier to military tactics and discipline to units per fort level while defending.alice_combat_min_dice_roll = 0.0f: Minimum dice roll which can be rolled in combat (inclusive)alice_combat_max_dice_roll = 9.0f: Maxmimum dice roll which can be rolled in combat (inclusive)
These relate to army attrition
alice_army_sea_transport_attrition = 2.5f: The monthly attrition (in percent) for armies on the sea in transports to take. Can be reduced by national "land_attrition" modifiersalice_fort_siege_attrition_per_level = 0.35f: Additional attrition (in percent) per fort level for armies sieging the province, stacking with the base siege attrition.alice_attrition_war_exhaustion = 1.5: Multiplier to the war exhaustion gained from taking attrition losses. Works similar to the "COMBATLOSS_WAR_EXHAUSTION" define, but for attrition losses instead. Set to 0 to disable all attrition war exhaustion.
These relate to unit movement
alice_army_marching_hours_per_day = 5.0f: The amount of hours an army marches per day on average. Effectively this is a multiplier to the army's km/hour stat deciding how far an army can move in a single dayalice_navy_sailing_hours_per_day = 20.0f: The amount of hours a navy sails per day on average. Effectively this is a multiplier to the navy's km/hour stat deciding how far a navy can sail in a single day As the above defines implies, the distances between provinces are measured in kilometers now when it comes to unit-movement, and maps directly onto the km/hour stat.strategic_redeployment_speed_modifier = 1.3f: base speed increase from strategic redeployment special army orderstrategic_redeployment_infrastructure_factor = 1.0f: factor for infrastructure effect on speed increase from strategic redeployment special army order
These relate to occupations
alice_fort_siege_slowdown = 0.75f: Slowdown modifier to siege speed for each fort level in the province. 0.75 = takes 75% of base siege time longer per fort level. 0.75 is the default vanilla valuealice_rebel_reduction_after_reoccupation = 7.0f: When a rebel province is reoccupied by the owner, all pops which were part of the controlling rebel faction gets their militancy divided by this amount
These relate to gamerules
alice_can_goto_war_against_spherelord_default_setting = 1.0f- Sets the default setting for the hardcoded gamerule deciding whether a sphereling can goto war against its spherelord. Can be either 1 (which means they can declare war against spherelord), or 0 (which means they cannot). Default is 1alice_fog_of_war_default_setting = 1.0f- Sets the default setting for the hardcoded gamerule deciding whether fog og war is on or off. 1.0 means fog of war is on, 0.0 means it is off, and at 2.0 it is disabled only for the observer tagalice_auto_concession_peace_default_setting = 1.0f- Sets the default setting for the hardcoded gamerule deciding whether a peacedeal will be force-accepted if it is conceding all wargoals (or if the peacedeal concedes 100 warscore or higher). 1.0 means forced-peaces are disabled, where 0.0 means they are enabled.alice_command_units_default_setting = 0.0f- Decides whether AI puppets' units can be commanded by players while at war. A value of 0.0f means it is disabled, while a value of 1.0f means it is enabled
Support for reforms based on party issues
In issues.txt you can add a vote_modifiers = { ... } section to any particular issue option within the party issues section. For example, one could go here:
party_issues = {
trade_policy = {
protectionism = {
vote_modifiers = { ... }
...
Inside the vote_modifiers section one or more modifiers can be defined for reform options belonging to social or political issues. (These modifiers share the same format with the add_political_reform modifiers in the ideology file. Like those modifiers, they are computed additively, and like those modifiers they contain the nation in their primary and THIS scopes.) For example, you could add something like the following (not that it makes much sense as an example, but whatever).
trinket_health_care = {
base = 1
modifier = {
factor = -1
NOT = { ruling_party_ideology = fascist }
}
}
When these modifiers are present, instead of using the generic add/remove political/social reform modifiers for an ideology to determine reform support the support for a particular reform option, the game will first attempt to use the modifier(s) associated with the active issue options of the active party associated with that ideology (if there is more than one such party, one will be picked arbitrarily for this). This will completely override the generic add/remove reform modifiers, allowing a party-ideology combination to support (or oppose) particular reforms in a category even when it would otherwise generically oppose (or support) all such reforms.
Party reform support overrides
Previously in a party definition it was possible to insert a line such as economic_policy = laissez_faire which would define the specific party issue that the party would have. This has been extended so that any political or social reform category and option may appear there. For example pensions = good_pensions in the following party description is now valid
party = {
name = "ENG_liberal"
start_date = 1830.1.1
end_date = 1859.1.1
ideology = liberal
economic_policy = laissez_faire
trade_policy = free_trade
religious_policy = pluralism
citizenship_policy = limited_citizenship
war_policy = anti_military
pensions = good_pensions
}
What this means is that the party will always support that particular reform in that category (or the closest reform if the category can only be changed step by step) and that it will not support any other reforms in that category. This will override any other preference either via ideology or the extended support weights described above.
Political party triggers
Now you can turn on/off political parties, aside from the usual start_date and end_date. Remember that parties can be shared between countries, and that like other template types, tags you want this to apply to need an 'template = "test.txt"'- entry in their countries file.
party = {
name = "default_fascist_military_junta"
start_date = 1836.1.1 #also part of trigger check
end_date = 2000.1.1 #same here
ideology = fascist
#[...]
#Example trigger!
trigger = {
war = yes
nationalism_n_imperialism = 1
}
}
Extra on-actions
on_election_started: When an election startson_election_finished: When an election ends
New data formats
Dense CSV pop listing
This is an extension that allows you to use CSV files instead of scripting pops manually, this allowing you to edit the pop files on a spreadsheet program, for example:
province-id;size;culture;religion;pop-type;rebel-faction(optional)
825;100;albanian;orthodox;clergymen;jacobin
825;150;albanian;orthodox;aristocrats;jacobin
825;744;albanian;orthodox;capitalists;jacobin
825;4019578;albanian;orthodox;farmers;jacobin
...
This allows for higher volume of data, while keeping it readable, editable and most importantly: able to be edited on your favorite office spreadsheet program.
Using this in your mod is simple, create a file ending with .csv, like, Africa.csv, Alice will load it alongside other files, even .txt files, if you want to mix them you absolutely can, just bear in mind that every file in the history/pops/yyyy.mm.dd is loaded, so be aware of that.
Dense CSV province history
Sometimes having too many history text files for provinces can make handling files a pain, or mess up compression algorithms with having too many province files.
Redundant data is the enemy of file size, and, while most province history files don't take much space, it is still good to load them:
province-id;owner;controller;core;trade_goods;life_rating;colonial;slave;
142;RPL;RPL;RPL;coal;31;1;0;
Similar to POP CSV format. The CSV files will be loaded first in the history folder, this means you can mix both CSV and text files to make greater granularity. For example when multiple cores are involved.
Country templates
This allows to remove a lot of copy-pasting for countries, and other common files.
template = "test.txt"
Where test.txt would be in common/templates/test.txt.
This works as a general "copy and paste" macro to use, so you can put anything that is valid for a country file within the template, as long as it's things for the root (i.e you can't specify a template inside a last names list).
New event substitutions
Events-only:
$POP$: Total population ofTHIS.$FROMCONTINENT$: Continent ofFROM.$FROMCAPITAL$: Capital ofFROM.$GOOD$,$RESOURCE$: Good produced by provinceTHIS.$NUMFACTORIES$: Factories in stateTHIS.$FROMRULER$: Equivalent to$MONARCHTITLE$but forFROM$FOCUS$,$NF$: National focus of stateTHIS.$TEMPERATURE$: Current temperature of crisis.$TERRAIN$: Name of the terrain of provinceTHIS.$FROMSTATENAME$: State name ofFROM.$FACTORY$: Name of the factory ofTHISprovince.$DATE$: Date that the event fired on.$CONTROL$: Nation that is currently controllingTHISprovince.$OWNER$: Nation that has ownership overTHISprovince.
If THIS/FROM is a nation, the state and province are deduced from the capital. If THIS/FROM is a state, the nation is deduced from the owner, and the province from the state capital. If THIS/FROM is a province, the nation is deduced from the owner and the state from the state it pertains to (but it will only choose the state instance of the owner).
For example, Nejd and Hedjaz share state ENG_1, the FROM is on a province owned by Nejd on ENG_1, then the state will refer to the state owned by Nejd not by Hedjaz.
Decision and events:
$GOVERNMENT$: Name of the government ofTHIS.$IDEOLOGY$: Name of the ideology of the ruling party ofTHIS.$PARTY$: Name of the party ofTHIS.$INFAMY$,$BADBOY$: Current infamy.$SPHEREMASTER$: Sphere master ofTHIS.$OVERLORD$: Overlord ofTHIS.$NATIONALVALUE$: Name of the national value ofTHIS.$CULTURE_FIRST_NAME$: Randomly generated first-name, of primary culture ofTHIS.$CULTURE_LAST_NAME$: Randomly generated last-name, of primary culture ofTHIS.$TECH$: Currently researched tech.$NOW$: Current date.$ANYPROVINCE$: Any (random) province owned by this nation.
Decisions now can use crisis substitutions: $CRISISTAKER$, $CRISISTAKER_ADJ$, $CRISISATTACKER$, $CRISISDEFENDER$, $CRISISTARGET$, $CRISISTARGET_ADJ$ and $CRISISAREA$ - additionally, they can use $CULTURE$, $CULTURE_GROUP_UNION$, $UNION_ADJ$ and $COUNTRYCULTURE$, working in the same fashion as their event counterparts.
New crisis substitutions:
$CRISISTAKER_CAPITAL$: Capital of liberation tag.$CRISISTAKER_CONTINENT$: Continent of liberation tag, based from capital.$CRISISATTACKER_CAPITAL$: Capital of attacker.$CRISISATTACKER_CONTINENT$: Continent of attacker, based from capital.$CRISISDEFENDER_CAPITAL$: Capital of defender.$CRISISDEFENDER_CONTINENT$: Continent of attacker, based from capital.
New modifier description substitutions
$COUNTRY$: The nation of the modifier.$COUNTRY_ADJ$: The adjective of the nation of the modifier.$CAPITAL$: The capital of the nation of the modifier.$CONTINENTNAME$: The continent of the modifier (capital used as reference if national modifier).$PROVINCENAME$: The province of the modifier (capital used as reference if national modifier).
Government ruler-names
Now you can define ruler names for a specific nation with a specific government type, for example:
RUS_absolute_monarchy;The Russian Empire
RUS_absolute_monarchy_ruler;Tsar
Definitions for multiple goods produced by local RGO
As RGO can produce a whole distribution of goods, you can define your own distribution for specific provinces:
Example (history\provinces files):
rgo_distribution = {
entry = {
trade_good = silk
max_employment = 100000
}
entry = {
trade_good = opium
max_employment = 100000
}
}
To add some RGO entries without overriding ones generated from climate, terrain and primary trade_goods use rgo_distribution_add_.
rgo_distribution_add = {
entry = {
trade_good = coal
max_employment = 100000
}
}
Factory potentials
Factory potentials (e.g. resource potentials) is a feature that allows modders to limit number of factories per province (state).
To limit factory creation to states that have provinces with corresponding commodity potentials, commodity definition must have uses_potentials = yes.
In province history files define limits as follows:
factory_limit = {
entry = {
trade_good = iron
max_level = 16
}
}
To change the limit during runtime use the effect. As of v1.2.3 decreasing factory limits has no implemented checks:
change_factory_limit = {
trade_good = rubber
value = 15
}
Religion
State Religion can give a national modifier like this:
shinto = {
color = { 0.8 0 0 }
icon = 12
nation_modifier = {
education_efficiency = 0.05
}
}
Gamerules
Custom toggleable gamerules can be defined in gamerules.txt file inside of the common folder. If you have no gamerules file, then create one.
The selected option of each gamerule is stored in the savegame, and is thus kept persistent between game launches.
A gamerule is defined like this:
scripted_gamerule = {
name = "test_gamerule"
option = {
name = "test__gameruleopt_1"
on_select = "opt1_on_select"
on_deselect = "opt1_on_deselect"
}
option = {
name = "test__gameruleopt_2"
default_option = yes
on_select = "opt2_on_select"
on_deselect = "opt2_on_deselect"
}
The name member is a unique string identifier for said gamerule and is mandatory. Two or more gamerules may not have the same name.
The localization key is the same as the name (in this case test_gamerule). The loc key for the description of the gamerule (Which is displayed in a tooltip) is the name plus _desc. So the desctiption loc key for this gamerule would be test_gamerule_desc.
Each gamerule may have one or more options. Each option also has a mandatory name member, which works similarly to the name of the gamerule itelf (except each option does not have a description loc key, only a name loc key). Each option name key is globally unique.
Next there is the default_option member. This simply signals which of the options is selected by default on a new save.
Lastly, there is the on_select and on_deselect members. These describe the name of a lua function which should be run when the corrosponding option is selected/deselected. The function should start with the "alice" prefix take a single parameter, which is the numeric ID of the gamerule which was changed.
Eg. in the previous example, if "test_gameruleopt_2" was selected, the function named alice.opt2_on_select would be run.
You can also check the state of a gamerule directly in a trigger, with the following trigger:
check_gamerule = {
gamerule = "test_gamerule"
option = "test_gameruleopt_1"
}_
Here, it evaluates if the gamerule with name test_gamerule is set to the option with the name test_gameruleopt_1.
The gamerule can also be checked in lua code, by calling GAMERULE.check_gamerule_option_by_name or GAMERULE.check_gamerule_option_by_id.
There are also some hardcoded gamerules which interact with base gameplay directly which is not present in the gamerules.txt file. These can also have their selected option checked with check_gamerule trigger. Below is a list of names of the hardcoded gamerules and their options:
-
alice_gamerule_allow_sphereling_declare_war_on_spherelord: Name of gamerule checking if spheres can declare wars on their spherelords directly or indirectly.alice_gamerule_allow_sphereling_declare_war_on_spherelord_opt_no: Option for no.alice_gamerule_allow_sphereling_declare_war_on_spherelord_opt_yes: Option for yes.
-
alice_gamerule_allow_partial_retreat: Name of gamerule for enabling/disabling partial retreats.alice_gamerule_allow_partial_retreat_opt_disabled: Option for disabledalice_gamerule_allow_partial_retreat_opt_enabled: Option for yes.
-
alice_gamerule_fog_of_war: Name of gamerule for enabling/disabling fog of waralice_gamerule_fog_of_war_opt_disabled: Option for disabled fog of waralice_gamerule_fog_of_war_opt_enabled: Option for enabled fog of war
-
alice_gamerule_auto_concession_peace: Name of gamerule for enabling/disabling auto peacing in cases of the enemy conceding all wargoalsalice_gamerule_auto_concession_peace_opt_cannot_reject: Option for the auto-peace being enabledalice_gamerule_auto_concession_peace_opt_can_reject: Option for the auto-peace being disabled
-
alice_gamerule_command_units: Name of gamerule for enabling/disabling commanding AI puppets' troops in warsalice_gamerule_command_units_opt_disabled: Option for it being disabledalice_gamerule_command_units_opt_disabled: Option for it being enabled