(Husky v1.9.3 a7a4) Faulty Vichy France event triggers - fix included

  • We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.

SchwarzKatze

Field Marshal
45 Badges
Nov 8, 2008
6.088
4.771
Crossposting so this issue gets properly logged. Original thread:


There's a pretty serious bug with the Vichy France event (france.10) introduced in 1.9, probably introduced by two people trying to fix the same issue without knowing what each other is doing.

Before 1.9, there's only one event: france.10, which had a long list of triggers and an MTTH of 2 days. This is obviously not ideal so someone tried to optimize it:

1. Someone moved the triggers and MTTH of france.10 into a new hidden event france.101, leaving the former event with no checks.
Code:
#hidden pre-event to check before capitulation
country_event = {
    id = france.101
    hidden = yes
    trigger = {
        tag = FRA
        has_war_with = GER
        has_government = democratic
        16 = { is_controlled_by = GER }
        is_in_faction_with = ENG
        ENG = { has_war_with = GER }
        surrender_progress > 0.7
        GER = {
            OR = {
                is_faction_leader = yes
                has_government = neutrality
            }
        }
        has_civil_war = no
        #Don't fire if France has pushed pretty far into ITA or GER
        NOT = {
            any_state = {
                is_on_continent = europe
                NOT = { state = 158 }
                NOT = { state = 114 }
                NOT = { state = 50 }
                NOT = { state = 42 }
                is_controlled_by = ROOT
                OR = {
                    is_owned_by = GER
                    AND = {
                        FRA = { has_War_with = ITA }
                        is_owned_by = ITA
                    }
                }
            }
        }        

        #Don't fire if any states in France are controlled by a different human player
        NOT = {
            any_country = {
                is_ai = no
                NOT = { tag = GER }
                NOT = { is_in_faction_with = GER }
                has_war_with = ROOT
                any_state = {
                    is_on_continent = europe
                    NOT = { state = 1 }
                    NOT = { state = 735 }
                    NOT = { state = 21 }
                    NOT = { state = 31 }
                    is_owned_by = ROOT
                    is_controlled_by = PREV
                }
            }
        }
    }
    mean_time_to_happen = { days = 2 }
    immediate = {
        country_event = france.10
    }
}

2. Someone else added an on_capitulation on action with a very short list of checks, likely only meant as a sanity check with the assumption that the now-removed triggers in france.10 would do its job
Code:
            if = {
                limit = {
                    original_tag = FRA
                    has_government = democratic
                    NOT = { has_global_flag = achievement_france_surrender } #might as well use the achievement flag to check if france.10 fired
                    is_subject = no
                    is_in_faction_with = ENG
                    has_war_with = GER
                }
                country_event = france.10
            }

The result is the worst of both worlds: not only the MTTH is still being evaluated in france.101, the event can now be triggered with a much shorter list of conditions by the on_action, causing the event to fire in situations where it wouldn't in older versions.

Here's how I'd fix it:
- Remove france.101
- Change the on_action so that it contains these conditions
Code:
            if = {
                limit = {
                    original_tag = FRA
                    has_government = democratic
                    NOT = { has_global_flag = achievement_france_surrender } #might as well use the achievement flag to check if france.10 fired
                    is_subject = no
                    is_in_faction_with = ENG
                    has_war_with = GER
                    ENG = { has_war_with = GER }
                    GER = {
                        OR = {
                            is_faction_leader = yes
                            has_government = neutrality
                        }
                    }
                    #Don't fire if any states in France are controlled by a different human player
                    NOT = {
                        any_country = {
                            is_ai = no
                            NOT = { tag = GER }
                            NOT = { is_in_faction_with = GER }
                            has_war_with = ROOT
                            any_state = {
                                is_on_continent = europe
                                NOT = { state = 1 }
                                NOT = { state = 735 }
                                NOT = { state = 21 }
                                NOT = { state = 31 }
                                is_owned_by = ROOT
                                is_controlled_by = PREV
                            }
                        }
                    }
                }
                country_event = france.10
            }
This would get rid of the MTTH for improved performance as well as keeping all the conditions intact. I removed the checks for French advance and surrender progress as this on_action fires after France has already capitulated so they don't matter.
 
  • 4Like
Reactions:
Upvote 0
Alternatively i have simply removed the script under on_capitulation in the on_actions file so that only the hidden event france.101 controls with it's sophisticated triggers whether the armistice event can happen.
 
I think the france.101 hidden pre-event was designed with a purpose as if you leave the checks to capitulation time it might mess it up as Germany tends to gather a very high warscore in the Axis essentially independent of their battlefield performance so if let's say Axis Italy has conquered France and Germany stuck at Maginot and Belgium France might still capitulate to Germany, making Paris German occupied and so an on_capitulation event will get Vichy fired regardless of the Italian success. But if you check the conditions at 70% capitulation level as france.101 does this is not a problem. So i think leaving france.101 do it's job and removing the leftover script from on_actions is the right answer. The script in on_actions is probably left there by an oversight.
 
probably introduced by two people trying to fix the same issue without knowing what each other is doing
I don't think those were two independent changes. Splitting the condition of france.10 into the separate event france.101 would make no sense by itself:
Before 1.9, there's only one event: france.10, which had a long list of triggers and an MTTH of 2 days. This is obviously not ideal so someone tried to optimize it
The event check frequency is 20 days (NCountry.EVENT_PROCESS_OFFSET) independent from the MTTH. Any MTTH at or below 20 is completely pointless anyway (https://hoi4.paradoxwikis.com/Event_modding#mean_time_to_happen). And regardless, the new event france.101 still has the same properties so nothing is gained in terms of performance. A hidden event with the exact same conditions and no effects except immediately triggering another event would be equivalent to just having a single event in the first place.
More likely the very reason for the event to be split up is for the on_action to be able to circumvent the conditions.

I think the problem might stem from france.10 having three different purposes. First, it is the only place to permanently mark France being ineligible for the Vive la France achievement. The on_action using the flag as a check may be an indication of it being intended towards this purpose. The achievement "Reach 1948 as France without capitulating or surrendering" requires very loose conditions.
Secondly (since LaR) France has the option to fight on despite the event given enough war support. In this case marking the achievement as failed does not make sense (unless fired from on_capitulation).
And thirdly, due to the Vichy France options, the event needs to be limited to specific circumstances where Germany "deserves" to get Vichy France. The other response options in france.10 are somewhere in the middle. I.e. if France is losing against both Germany and even more so Italy, why would that preclude the Franco-British Union?

@kettyo Due to the 20 day event period, any check between 70% surrender progress and capitulation should be treated as unreliable. I.e. it might be possible to detect something there but France might capitulate before the next check comes around. Especially with Italy being more successful in the south, it is quite likely that the fall of Paris and regular capitulation are only a few days apart.

I'd propose the following fix(es):
  • set achievement_france_surrender only in on_capitulation directly and in submissive event options of france.10 (a, b & c). This way the event does not necessarily mean the achievement fails but all cases are covered that should cause it to fail.
  • move the check for non-German human attacker into the Vichy options' trigger or ai_will_do; the event itself can still trigger anyway but AI (and potentially human) France has to pick from the other options
  • instead of abusing achievement_france_surrender, the france.10 should have a proper flag to ensure it is only triggered once
 
I don't think those were two independent changes. Splitting the condition of france.10 into the separate event france.101 would make no sense by itself:

The event check frequency is 20 days (NCountry.EVENT_PROCESS_OFFSET) independent from the MTTH. Any MTTH at or below 20 is completely pointless anyway (https://hoi4.paradoxwikis.com/Event_modding#mean_time_to_happen). And regardless, the new event france.101 still has the same properties so nothing is gained in terms of performance. A hidden event with the exact same conditions and no effects except immediately triggering another event would be equivalent to just having a single event in the first place.
More likely the very reason for the event to be split up is for the on_action to be able to circumvent the conditions.

I think the problem might stem from france.10 having three different purposes. First, it is the only place to permanently mark France being ineligible for the Vive la France achievement. The on_action using the flag as a check may be an indication of it being intended towards this purpose. The achievement "Reach 1948 as France without capitulating or surrendering" requires very loose conditions.
Secondly (since LaR) France has the option to fight on despite the event given enough war support. In this case marking the achievement as failed does not make sense (unless fired from on_capitulation).
And thirdly, due to the Vichy France options, the event needs to be limited to specific circumstances where Germany "deserves" to get Vichy France. The other response options in france.10 are somewhere in the middle. I.e. if France is losing against both Germany and even more so Italy, why would that preclude the Franco-British Union?

@kettyo Due to the 20 day event period, any check between 70% surrender progress and capitulation should be treated as unreliable. I.e. it might be possible to detect something there but France might capitulate before the next check comes around. Especially with Italy being more successful in the south, it is quite likely that the fall of Paris and regular capitulation are only a few days apart.

I'd propose the following fix(es):
  • set achievement_france_surrender only in on_capitulation directly and in submissive event options of france.10 (a, b & c). This way the event does not necessarily mean the achievement fails but all cases are covered that should cause it to fail.
  • move the check for non-German human attacker into the Vichy options' trigger or ai_will_do; the event itself can still trigger anyway but AI (and potentially human) France has to pick from the other options
  • instead of abusing achievement_france_surrender, the france.10 should have a proper flag to ensure it is only triggered once
Does firing an event through country_event bypass the triggers? IIRC triggered events still respect their triggers, at least in CK2, so it should be possible to put the triggers in france.101 back into france.10 to fine-tune the conditions, and set the flags in the on_action after firing the event.

And instead of MTTH, the 70% surrender progress variant can probably be moved into an on_state_control_changed, since it's virtually impossible to cause France to capitulate from 70% percent surrender progress without taking control of any other states. The AI won't bypass all the VP, and a human Germany has no reason to not trigger it.
 
Does firing an event through country_event bypass the triggers? IIRC triggered events still respect their triggers, at least in CK2, so it should be possible to put the triggers in france.101 back into france.10 to fine-tune the conditions, and set the flags in the on_action after firing the event.
Yes, country_event respects the trigger. I agree, at least some of the conditions need to go back into the trigger of france.10; it is just not clear what the developers actually intended with their change.
And instead of MTTH, the 70% surrender progress variant can probably be moved into an on_state_control_changed, since it's virtually impossible to cause France to capitulate from 70% percent surrender progress without taking control of any other states. The AI won't bypass all the VP, and a human Germany has no reason to not trigger it.
Sounds reasonable.
 
Due to the 20 day event period, any check between 70% surrender progress and capitulation should be treated as unreliable. I.e. it might be possible to detect something there but France might capitulate before the next check comes around. Especially with Italy being more successful in the south, it is quite likely that the fall of Paris and regular capitulation are only a few days apart.

It depends on whether surrender_progress > 0.7 will trigger also if France is capitulated (surrender progress 1). If this is the case it's not a problem as Vichy can still fire a few days after capitulation which is even more realistic as you can't bring an armistice deal around in a few hours.

Also it's kinda good as an Allied player you have a few days of grace period to liberate France under 70% occupation or liberate Paris so that the armistice will not happen.

If the trigger doesn't work as i expect it then it might be expanded so:
Code:
OR = {
    surrender_progress > 0.7
    has_capitulated = yes
}
but i'd bet it's unnecessary.
 
Last edited:
It depends on whether surrender_progress > 0.7 will trigger also if France is capitulated (surrender progress 1). If this is the case it's not a problem as Vichy can still fire a few days after capitulation which is even more realistic as you can't bring an armistice deal around in a few hours.
You are right, the trigger works past capitulation as well. I was just referring to the possibility of assessing the situation before the capitulation hands over all the remaining land to one country:
if you leave the checks to capitulation time it might mess it up as Germany tends to gather a very high warscore in the Axis essentially independent of their battlefield performance so if let's say Axis Italy has conquered France and Germany stuck at Maginot and Belgium France might still capitulate to Germany
Post-capitulation the event trigger does not really have an advantage over the on_action (see below). Maybe it would be neat to have an on_action right before capitulation.

Also it's kinda good as an Allied player you have a few days of grace period to liberate France under 70% occupation or liberate Paris so that the armistice will not happen.
For that to work, the conditions would need to be detected precisely at the moment they become true and then frequently check whether they flipped back to give the Allies a shot. The game does not do that for performance reasons. The delay will be between zero and 19 days, but it just depends on the calendar day, not the MTTH setting. (Except for much longer running events of course, of which there are only very few.)
 
For that to work, the conditions would need to be detected precisely at the moment they become true and then frequently check whether they flipped back to give the Allies a shot. The game does not do that for performance reasons. The delay will be between zero and 19 days, but it just depends on the calendar day, not the MTTH setting. (Except for much longer running events of course, of which there are only very few.)

As i understand the MTTH events are checked every 20 days so that the Allies have a mean time of 10 days to recapture Paris (or liberate France below 70% surrender level) before the pre-event would fire with a 0-2 days interval to the armistice event. This can be of course just 1-2 days with bad calendar luck but can be 17-18 days either with good luck. This isn't too bad i think. You can generally liberate Paris ill-defended by the French AI in a few days at most. If you're actually overrun by the nazis it doesn't really matter anyway :)

Post-capitulation the event trigger does not really have an advantage over the on_action (see below). Maybe it would be neat to have an on_action right before capitulation.

That's certainly true. Maybe ideally you could tie the pre-event to on_state_control_changed as @SchwarzKatze proposes so that it fires only when Germany actually conquers Paris in combat, not just get it by warscore farming. It would be too much of a deviation from the current PDX script though so i'd rather use the mimimalistic approach of simply removing the on_capitulation leftover script in my upcoming mod as a bugfix. Moreover can the on_state_control_changed solution grant a similar kind of grace period for the Allies to intervene as the current MTTH event solution does?

Of course it wouldn't harm if PDX tweaked the event further in 1.10 but probably the intended mechanic now is controlling the fall of France via the france.101 event with the on_capitulation script left there as an oversight.
 
Last edited:
the pre-event would fire with a 0-2 days interval to the armistice event
But that's thing, there (currently) is no interval at all between the two events. Though I agree it would make some sense. The MTTH is implemented as a probability of whether an event fires when its conditions are met. It is not inherently a delay. At some point during an event check, france.101's trigger becomes true. Then immediately an MTTH probability check is done. The probability is 20/MTTH, which is 1000% in this case. So without any delay country_event = france.10 gets executed, always.
Actually adding a random delay between two events is done like this:
Code:
country_event = {
  id = france.10
  random = 48
}[/ICODE]
(For some reason this is never used in the base game but works fine)
 
  • 1
Reactions:
@bitmode Ahh i get it now, thanks a lot for the education, you're most helpful as always :)

So practically any MTTH day event with a day value of 20 or less means a certain immediate execution. In this sense day values up to 20 make no difference whatsoever.

So for france.101 or any other MTTH day event we can assume a mean delay of 10 days between the fulfillment of trigger conditions and the execution of the event because of the 20 days event check intervals. This dynamic delay time can be assumed as a grace period while the other side can still cancel the trigger conditions before the event execution takes place.

I guess the event under random delay can't be aborted the same way, it will be executed even if the triggers become unfulfilled in the meantime.
 
  • 1
Reactions: