Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b5e61ff
Subjects are forced to accept demands of military access and call to …
ZombieFreak115 Aug 15, 2025
c4a6820
Implement proper truces, can only bypass truce by getting a defensive…
ZombieFreak115 Aug 16, 2025
3c66d7c
added additional check on call to arms
ZombieFreak115 Aug 16, 2025
11f89e2
Merge branch 'schombert:main' into small-diplo-fixes-and-additions
ZombieFreak115 Aug 18, 2025
3b4ea6a
Implemented command units diplo option, still need triggers to disabl…
ZombieFreak115 Aug 19, 2025
ccfae32
Battle reports for any player who is in the battle now, and add trigg…
ZombieFreak115 Aug 19, 2025
52cd0ca
Refactor some embargo code, clean up embagoes& free trade agreements …
ZombieFreak115 Aug 21, 2025
84da282
Refactor free trade command code and add MP diplo localization
ZombieFreak115 Aug 22, 2025
11596a7
Fix embargo properly applying on subjects
ZombieFreak115 Aug 22, 2025
b2a90e4
add command units description
ZombieFreak115 Aug 22, 2025
53edd76
remove embargo message spam
ZombieFreak115 Aug 22, 2025
fbceb4b
Refactored free trade agreements to be properly sphere-wide, and prev…
ZombieFreak115 Aug 22, 2025
65f2852
Spherelings can remove trade agreements, if they have the rights to it
ZombieFreak115 Aug 23, 2025
1b2b6e8
added free trade to embargo tooltip, and fixed up the rest of the logic
ZombieFreak115 Aug 24, 2025
5caa22e
More tooltip loc
ZombieFreak115 Aug 24, 2025
cfe1bcd
Added checks for sphere-related war blocks which exist in Vic2
ZombieFreak115 Aug 24, 2025
bd0319b
Change truce logic when joining wars to only check for a truce with t…
ZombieFreak115 Sep 2, 2025
4151c55
changed command units to onyl work in MP. Always receive supply limit…
ZombieFreak115 Sep 9, 2025
7218939
Refactored sphereing and most of unsphereing calls into respective fu…
ZombieFreak115 Sep 9, 2025
111b77b
Merge branch 'main' into small-diplo-fixes-and-additions
ZombieFreak115 Sep 9, 2025
ae3a1ef
Fix influence overflow bug where it would use 100 influence instead o…
ZombieFreak115 Sep 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion assets/alice.gui
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,19 @@ guiTypes = {
}

}

iconType = {
name = "original_defender"
position = { x = 410 y = 0 }
extends = "diplomacy_war_info"
spriteType = "GFX_flag_tiny"
}
iconType = {
name = "original_attacker"
position = { x = 157 y = 0 }
extends = "diplomacy_war_info"
spriteType = "GFX_flag_tiny"

}


iconType = {
Expand Down
37 changes: 32 additions & 5 deletions assets/localisation/en-US/alice.csv
Original file line number Diff line number Diff line change
Expand Up @@ -876,17 +876,20 @@ ally_explain_5;You're not a subject nation
ally_explain_6;You're not currently at war with the target
ally_explain_7;The AI will accept
ally_explain_8;The target isn't a subject nation
call_ally_explain_1;You have an alliance with this nation
call_ally_explain_1;You have an alliance with this nation, or this nation is your subject
call_ally_explain_2;You have at least $x$ diplomatic point(s)
call_ally_explain_3;You're at war
call_ally_explain_4;There is a war this nation can be called into
call_ally_explain_5;The AI will accept
call_ally_explain_6;Spherelord is not in the war on the enemy side OR sphere war restrictions are turned OFF
cancel_access_explain_1;You have at least $x$ diplomatic point(s)
ask_access_explain_1;You can't get military access from yourself
ask_access_explain_2;You have at least $x$ diplomatic point(s)
ask_access_explain_3;The AI will accept
ask_access_explain_4;You are not currently at war with the target
ask_access_explain_5;Nation is your subject
cancel_given_access_explain_1;You have at least $x$ diplomatic point(s)
cancel_given_access_explain_2;You are not a subject of this nation
give_access_explain_1;You can't give military access to yourself
give_access_explain_2;You have at least $x$ diplomatic point(s)
give_access_explain_3;You are not currently at war with the target
Expand Down Expand Up @@ -923,20 +926,26 @@ revoke_trade_rights;Revoke trade rights
msg_trade_rights_revoked;Nation ?Y$y$?W has revoked free trade rights of ?Y$x$?! in their country.
trade_rights_desc;Trade rights or unequal treaties give the other party preferential treatment in trade ignoring tariffs of our country. Once imposed, cannot be revoked for ?Y$x$ years.
revoke_trade_rights_explain_1;Enough time has passed since trade rights were imposed
free_trade_desc;If another party agrees, we'll enter into trade agreement removing all tariffs between our nations for ?Y$x$ years?W.
revoke_trade_rights_explain_2;We have the rights to revoke the agreement
free_trade_desc;If another party agrees, we'll enter into trade agreement removing all tariffs between our markets and their markets (spheres & subjects) for ?Y$x$ years?W.
free_trade_explain_1;Our traders won't pay their tariffs until ?G$date$?!
free_trade_explain_2;Their traders won't pay our tariffs until ?R$date$?!
free_trade_explain_3;We are embargoeing them
free_trade_explain_4;They are embargoing us
free_trade_explain_5;Target is not a subject OR Target is a our subject
free_trade_explain_6;We aren't in a sphere
free_trade_explain_7;Target isn't in a sphere OR Target is in our sphere
free_trade_explain_8;$x$ and their spheres&subjects ?Ghas free trade with?! $y$ and their spheres&subjects.
issue_embargo;Issue Embargo
lift_embargo;Lift Embargo
embargo_desc;Embargo prevents all trade between our nations. Embargoes are applied automatically to enemies during war.
embargo_explain_1;?G$x$ embargoes $y$.?!
embargo_explain_2;?R$x$ embargoes $y$.?!
embargo_desc;Embargo prevents all trade between our markets and their markets (spheres & subjects). Embargoes are applied automatically to enemies during war.
embargo_explain_1;$x$ and their spheres&subjects ?Gembargoes?! $y$ and their spheres&subjects.
embargo_explain_2;$x$ and their spheres&subjects ?Rembargoes?! $y$ and their spheres&subjects.
embargo_explain_3;We don't have trade rights in their country
embargo_explain_4;They don't have trade rights in our country
embargo_explain_5;We aren't in a sphere
embargo_explain_6;They aren't in a sphere
embargo_explain_7;The target isn't in our sphere
fab_explain_1;You can't justify war against yourself
fab_explain_2;You have at least $x$ diplomatic point(s)
fab_explain_3;You are not currently fabricating a casus belli
Expand All @@ -954,6 +963,12 @@ war_explain_1;You can't declare war upon yourself
war_explain_2;You have a casus belli to use against this nation
war_explain_3;You have at least $x$ diplomatic point(s)
war_explain_4;You are not already in a war with this nation
war_explain_5;Does not have units stationed inside this nation
war_explain_6;Does not have units stationed inside this nation's overlord
war_explain_7;Is not allied to target
war_explain_8;Is not allied to target's overlord
war_explain_9;Target is not our spherelord AND is not allied to our spherelord AND sphere war restrictions are turned ON
war_explain_10;Target is not our sphereling
wg_result_1;On adding this war goal:
wg_result_2;On achieving this war goal:
wg_result_3;On failing to achieve this war goal:
Expand Down Expand Up @@ -1730,3 +1745,15 @@ alice_naval_retreat_condition_3;Access to an available port
alice_navalattackitem_4;An enemy fleet consisting of ships from $DEFENDER$ will be destroyed by us.
alice_attackthem_4;We are attacking forces of $DEFENDER$ and attempting to dislodge their defences.
alice_attackus_4;Hostile forces from $ATTACKER$ have engaged us.
alice_truce_with_explain;?Y$WAR$?W: Have truce with ?Y$NATION$?W. Truce lasts until $DATE$
alice_declarewar_truce_with_explain;?Y$NATION$?W: Have truce with ?Y$TARGET$?W. Truce lasts until $DATE$
alice_command_units_condition_1;?Y$NATION$?W is our subject
alice_command_units_condition_2;Both you and the target is at war
alice_command_units_condition_3;Target is not a player
alice_command_units_condition_4;Playing singleplayer
free_trade_di;Free trade agreement
free_trade_offer;$actor$ is offering a free trade agreement, allowing us to trade tariff-free for $years$ years
alice_original_war_participant_not_in_war;?Y$NATION$?W is no longer in the war
alice_original_war_participant_desc;?Y$NATION$?W is the original $ACTOR$ of this war
alice_original_war_participant_desc_2;Only the truces of the original attacker or defender can block joining a war
alice_original_war_participant_notinvolved;?Y$NATION$?W ?Ris no longer involved in the war?W
3 changes: 2 additions & 1 deletion docs/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,8 @@ Alice adds a handful of new defines:
- `alice_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 with `always = yes` will have infamy cost calculated as per `badboy_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_goto_war_against_spherelord` - defines whether or not a sphereling can directly go to war with its spherelord or its allies. Also covers joining wars in which the spherelord is on the enemy side. This is basically the vanilla v2 sphereblock behvavoir. Set to 1.0f to disable.
-
**Crises and conferences:**
- `alice_crisis_necessary_base_win_ratio = 2.5f`: Strength Ratio at which AI submits to demands after 80 temperature
- `alice_crisis_necessary_base_fast_win_ratio = 3.5f`: Strength Ratio at which AI submits to demands before 80 temperature
Expand Down
25 changes: 16 additions & 9 deletions src/ai/ai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,16 +359,20 @@ void remove_ai_data(sys::state& state, dcon::nation_id n) {

bool unit_on_ai_control(sys::state& state, dcon::army_id a) {
auto fat_id = dcon::fatten(state.world, a);
if(fat_id.get_controller_from_army_control().get_overlord_commanding_units()) {
return false;
}
return fat_id.get_controller_from_army_control().get_is_player_controlled()
? fat_id.get_is_ai_controlled()
: true;
}
/*bool unit_on_ai_control(sys::state& state, dcon::navy_id a) {
bool unit_on_ai_control(sys::state& state, dcon::navy_id a) {
auto fat_id = dcon::fatten(state.world, a);
return fat_id.get_controller_from_navy_control().get_is_player_controlled()
? fat_id.get_is_ai_controlled()
: true;
}*/
if(fat_id.get_controller_from_navy_control().get_overlord_commanding_units()) {
return false;
}
return !fat_id.get_controller_from_navy_control().get_is_player_controlled();
}

bool will_upgrade_ships(sys::state& state, dcon::nation_id n) {
auto fid = dcon::fatten(state.world, n);
Expand Down Expand Up @@ -400,7 +404,7 @@ void update_ships(sys::state& state) {
// Landlocked nation shouldn't keep fleet
if(n.get_is_at_war() == false && nations::is_landlocked(state, n)) {
for(auto v : n.get_navy_control()) {
if(!v.get_navy().get_battle_from_navy_battle_participation()) {
if(!v.get_navy().get_battle_from_navy_battle_participation() && unit_on_ai_control(state, v.get_navy())) {
to_delete.push_back(v.get_navy());
}
}
Expand All @@ -410,7 +414,7 @@ void update_ships(sys::state& state) {
dcon::unit_type_id best_big = military::get_best_big_ship(state, n);

for(auto v : n.get_navy_control()) {
if(!v.get_navy().get_battle_from_navy_battle_participation()) {
if(!v.get_navy().get_battle_from_navy_battle_participation() && unit_on_ai_control(state, v.get_navy())) {
auto trange = v.get_navy().get_army_transport();
bool transporting = trange.begin() != trange.end();

Expand Down Expand Up @@ -479,6 +483,9 @@ void build_ships(sys::state& state) {
int32_t fleet_cap_in_big = 0;

for(auto v : n.get_navy_control()) {
if(!unit_on_ai_control(state, v.get_navy())) {
continue;
}
for(auto s : v.get_navy().get_navy_membership()) {
auto type = s.get_ship().get_type();
if(state.military_definitions.unit_base_definitions[type].type == military::unit_type::transport) {
Expand Down Expand Up @@ -754,7 +761,7 @@ void pickup_idle_ships(sys::state& state) {

auto owner = n.get_controller_from_navy_control();

if(!owner || owner.get_is_player_controlled() || owner.get_owned_province_count() == 0)
if(!owner || owner.get_is_player_controlled() || owner.get_owned_province_count() == 0 || !unit_on_ai_control(state, n))
continue;

auto home_port = state.world.nation_get_ai_home_port(owner);
Expand Down Expand Up @@ -1097,7 +1104,7 @@ dcon::navy_id find_transport_fleet(sys::state& state, dcon::nation_id controller
dcon::navy_id transport_fleet;

for(auto v : state.world.nation_get_navy_control(controller)) {
if(v.get_navy().get_battle_from_navy_battle_participation())
if(v.get_navy().get_battle_from_navy_battle_participation() || !unit_on_ai_control(state, v.get_navy()))
continue;
auto members = v.get_navy().get_navy_membership();

Expand Down
53 changes: 38 additions & 15 deletions src/economy/economy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,22 +429,31 @@ bool nation_has_closed_factories(sys::state& state, dcon::nation_id n) { // TODO
return false;
}

// Check if source gives trade rights to target
// Check if source gives trade rights to target. Includes derived rights from sphere/overlord
dcon::unilateral_relationship_id nation_gives_free_trade_rights(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
auto sphere_A = state.world.nation_get_in_sphere_of(target);
auto sphere_B = state.world.nation_get_in_sphere_of(source);

auto overlord_A = state.world.overlord_get_ruler(
state.world.nation_get_overlord_as_subject(target)
);
auto overlord_B = state.world.overlord_get_ruler(
state.world.nation_get_overlord_as_subject(source)
);

auto market_leader_target = (overlord_A) ? overlord_A : ((sphere_A) ? sphere_A : target);
auto market_leader_source = (overlord_B) ? overlord_B : ((sphere_B) ? sphere_B : source);

auto source_tariffs_rel = state.world.get_unilateral_relationship_by_unilateral_pair(market_leader_target, market_leader_source);
auto market_leader_target = nations::get_market_leader(state, target);
auto market_leader_source = nations::get_market_leader(state, source);
dcon::unilateral_relationship_id source_tariffs_rel;
if(market_leader_target == market_leader_source) {
source_tariffs_rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, source);
}
else {
source_tariffs_rel = state.world.get_unilateral_relationship_by_unilateral_pair(market_leader_target, market_leader_source);
}
if(source_tariffs_rel) {
auto enddt = state.world.unilateral_relationship_get_no_tariffs_until(source_tariffs_rel);
// Enddt empty signalises revoken agreement
// Enddt > cur_date signalises that the agreement can't be broken
if(enddt) {
return source_tariffs_rel;
}
}
return dcon::unilateral_relationship_id{};
}
// Check if source gives trade rights to target. Only include direct relationship
dcon::unilateral_relationship_id nation_gives_direct_free_trade_rights(sys::state& state, dcon::nation_id source, dcon::nation_id target) {
auto source_tariffs_rel = state.world.get_unilateral_relationship_by_unilateral_pair(target, source);
if(source_tariffs_rel) {
auto enddt = state.world.unilateral_relationship_get_no_tariffs_until(source_tariffs_rel);
// Enddt empty signalises revoken agreement
Expand All @@ -456,6 +465,20 @@ dcon::unilateral_relationship_id nation_gives_free_trade_rights(sys::state& stat
return dcon::unilateral_relationship_id{};
}















void initialize(sys::state& state) {
initialize_artisan_distribution(state);

Expand Down Expand Up @@ -4115,7 +4138,7 @@ void resolve_constructions(sys::state& state) {
}

// US2AC5. But no faster than construction_time
if(!state.cheat_data.instant_army) {
if(!state.cheat_data.instant_navy) {
if(state.current_date < c.get_start_date() + construction_time) {
ready_for_deployment = false;
}
Expand Down
1 change: 1 addition & 0 deletions src/economy/economy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ bool nation_is_constructing_factories(sys::state& state, dcon::nation_id n);
bool nation_has_closed_factories(sys::state& state, dcon::nation_id n);

dcon::unilateral_relationship_id nation_gives_free_trade_rights(sys::state& state, dcon::nation_id source, dcon::nation_id target);
dcon::unilateral_relationship_id nation_gives_direct_free_trade_rights(sys::state& state, dcon::nation_id source, dcon::nation_id target);

void initialize(sys::state& state);
void regenerate_unsaved_values(sys::state& state);
Expand Down
24 changes: 23 additions & 1 deletion src/economy/economy_government.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,30 @@ tax_information explain_tax_income(sys::state& state, dcon::nation_id n) {
return result;
}


bool non_war_embargo_status(sys::state& state, dcon::nation_id n_a, dcon::nation_id n_b, dcon::nation_id market_leader_a, dcon::nation_id market_leader_b) {
auto leader_source_tariffs_rel = state.world.get_unilateral_relationship_by_unilateral_pair(market_leader_b, market_leader_a);
auto leader_target_tariffs_rel = state.world.get_unilateral_relationship_by_unilateral_pair(market_leader_a, market_leader_b);
auto nation_source_tariffs_rel = state.world.get_unilateral_relationship_by_unilateral_pair(n_b, n_a);
auto nation_target_tariffs_rel = state.world.get_unilateral_relationship_by_unilateral_pair(n_a, n_b);
if(state.world.unilateral_relationship_get_embargo(leader_source_tariffs_rel) || state.world.unilateral_relationship_get_embargo(leader_target_tariffs_rel)) {
return true;
}

return state.world.unilateral_relationship_get_embargo(nation_source_tariffs_rel) || state.world.unilateral_relationship_get_embargo(nation_target_tariffs_rel);
}

bool war_embargo_status(sys::state& state, dcon::nation_id n_a, dcon::nation_id n_b, dcon::nation_id market_leader_a, dcon::nation_id market_leader_b) {
auto market_leaders_at_war = military::are_at_war(state, market_leader_a, market_leader_a);
if(market_leaders_at_war) {
return true;
}
return military::are_at_war(state, n_a, n_b);

}

bool has_active_embargo(sys::state& state, dcon::nation_id from, dcon::nation_id to) {
// When embargo is issued, it is automatically propagated onto all subjects. Therefore, checking for direct relationship is enough
// Only shows if the diplomatic relationship has an embargo, and dosent show "derived" embargos from spheres and subjects

auto rel_1 = state.world.get_unilateral_relationship_by_unilateral_pair(to, from);
if(!rel_1) {
Expand Down
2 changes: 2 additions & 0 deletions src/economy/economy_government.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ struct tax_information {
tax_information explain_tax_income(sys::state& state, dcon::nation_id n);
tax_information explain_tax_income_local(sys::state& state, dcon::nation_id n, dcon::province_id sid);

bool war_embargo_status(sys::state& state, dcon::nation_id n_a, dcon::nation_id n_b, dcon::nation_id market_leader_a, dcon::nation_id market_leader_b);
bool non_war_embargo_status(sys::state& state, dcon::nation_id n_a, dcon::nation_id n_b, dcon::nation_id market_leader_a, dcon::nation_id market_leader_b);
bool has_active_embargo(sys::state& state, dcon::nation_id from, dcon::nation_id to);
std::vector<employment_record> explain_local_administration_employment(sys::state& state, dcon::province_id p);
std::vector<employment_record> explain_capital_administration_employment(sys::state& state, dcon::nation_id n);
Expand Down
Loading
Loading