• 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.

Andrei Gijgorev

Civilian
3 Badges
May 23, 2007
686
65
  • Arsenal of Democracy
  • Darkest Hour
  • For The Glory

What is this?

This is the first of a series of posts where I discuss modding techniques, especially in regards to underused triggers/commands.

Right. So what is this really about?

Okay, so it's actually just a thinly veiled attempt at convincing MichaelM to implement certain new triggers and commands I want to use in an own project by demonstrating how they could also be used to do other cool stuff. This first post mostly deals with awesome things you can already do with persistent events and the <tag> trigger, while the following diaries will be written on a what-if basis, in the sense of "what if we had all these awesome triggers and commands?"

To get back on topic, please take a look at this screenshot which was taken after 150+ handsoff-years, and see if you can spot anything unusual:

screensave000398xcuq.png


Right now, you should be thinking "Wait, the game ran for 150+ years and there's no blobbing in the HRE and Italy? How's that even possible on the Watkabaoi map with its many small provinces?"

Now if you've played HoI2, you'll know that AIs have lists of countries they'll try to liberate, which basically just means that if they're at peace and they control the provinces required to create those countries, then they'll do just that. You'll probably also know that the EU2/FtG AI is utterly incapable of doing this, which is why we commonly see a lot of "blobbing", i.e. the expansion of countries with good diplomacy or a strong military into regions with lots of one-province minors (so mainly the HRE). This is generally not considered a desired part of AI behaviour, especially by those who prefer at least vaguely historical AI expansion.

So, the important question is: Can we do anything about blobbing? Keeping the screenshot in mind, the answer of course is: Yes we can! There's more to it than simply changing Austria's colour, though...



How to emulate the liberation AI of HoI2 in For the Glory

Take a look at the following event:
Code:
# OLD - Oldenburg
event = {
	id = 100000335 name = AI_EVENT deathdate = { year = 1999 } persistent = yes
	province = 335
	trigger = { ai = yes atwar = no stability = 1
		OR = { city = 335 colonialcity = 335 }
		NOT = { core_national = { province = 335 data = -1 } capital = 335
			exists = OLD
			exists = GER flag = "hre_noliberate" MUS = { flag = "global_hre_noliberate" }
		} control = { province = 335 data = -1 }
	} action = { command = { type = independence which = OLD }
	command = { trigger = { religion = counterreform NOT = { flag = 6 } } type = trigger which = 200000335 } }
}
This is an event which, under certain circumstances, causes AI countries to release Oldenburg as a vassal. Oldenburg is a one-province minor (in Watkabaoi) so it's pretty much the most simple form of this type of events. Please ignore the somewhat weird formatting; this is because it's actually more readable like this when you have tons of events that are structured similarly.

Let's analyse the event bit by bit:
id = 100000335
province = 335
persistent = yes
deathdate = { year = 1999 }
name = AI_EVENT
This is all pretty straightforward. It's a persistent event because we don't want it to only trigger once; after all OLD will be a vassal of the country the event fires for, and vassals tend to get annexed again after a while. (I've also considerably increased _COUNTRY_MINDIPLOANNEX_MONTHS_ because of this.) Since the event will release OLD, thus invalidating the trigger, we don't need to worry about it firing over and over again. However, if you make an error with province IDs or such, this may happen anyway, so it's a good idea to do a few handsoff games and check the event history for large numbers of IDs beginning with 10000 (or whatever other IDs you've assigned these events).
As long as we have a deathdate, we don't need a startdate or offset, and since we'll have tons of these events, if for some countries we want any additional conditions regarding when those countries can be created, then we should write those conditions in the trigger, and not as startdate/deathdate. And of course it should look like an AI decision, so the name needs to be AI_EVENT.

Next, let's have a look at the trigger. For this, I've switched around the conditions to group some of them together:
ai = yes
NOT = { exists = OLD }
control = { province = 335 data = -1 }
OR = { city = 335 colonialcity = 335 }
NOT = { capital = 335 }
These are basic sanity checks: AI country, OLD may not exist, the province must be controlled, and it may be neither a tradingpost nor a capital. Of course it's impossible for Oldenburg to be a tradingpost, but again: We have tons of events, so we want to do it right the first time. It's next to impossible that Oldenburg will be the capital of another country, but we still want to have this condition as strange things may happen (especially with the possibility of revolters being created with only some of their minimum provinces) and even if for some reason the Dutch Republic ended up with Oldenburg as the capital, then we wouldn't want to find a way to make this liberation event work anyway; we'd want to find a way to correct the location of the Dutch Republic's capital. (Which is actually pretty trivial if you create a priority list of capitals for each country and make sure to set flags accordingly whenever the capital is moved by event.)

Anyway, on to the rest of the trigger:
atwar = no
stability = 1
NOT = { core_national = { province = 335 data = -1 } }
NOT = { exists = GER }
NOT = { flag = "hre_noliberate" }
NOT = { MUS = { flag = "global_hre_noliberate" } }
The first two conditions, peace and stability, are more for flavour than anything else. We probably don't want countries being released in the middle of a war, and in my opinion AIs shouldn't do anything of importance when their stability is low. This is of course debatable, so lowering or even removing the stability condition may make sense as well.
Then, we don't want the province to be a national province. This is kind of obvious, however, it begs the question why I didn't exclude claims as well. There's no simple answer here, and in the end it comes down to preference. Basically, if you're trying to achieve somewhat historical progression of the game, then for certain provinces you'll need additional triggers to make sure certain flags are set or other conditions are fulfilled. Maybe you think this could be controlled with claimed provinces, and that would certainly be an option in some cases, but often you'll want countries to keep provinces they don't even have claims on. The inverse case may also happen; for example a France with claims on Naples that has conquered those provinces would still be expected to create a vassal state, rather than ruling those territories directly from Paris. Basically, it boils down to how you want your AI countries to act, and how and where claims are given.
Then, the last three conditions simply make sure there's no other special reason why a country in the HRE shouldn't be created. I'm currently not setting those flags anywhere, but you never know what you might need eventually. Maybe during the 30 Years War you don't want any vassals to be created in the HRE? Set a flag for MUS and clear it later, done.

Now for the event effects:
command = { type = independence which = OLD }
command = { trigger = { religion = counterreform NOT = { flag = 6 } } type = trigger which = 200000335 } }
Obviously we want to create OLD. The other command fires an event that sets OLD's religion to counter-reformed catholic if this is the overlord's state religion. Flag 6 is the edict of tolerance which disables the counter-reformed religion. Event 200000335 looks like this:
event = { id = 200000335 name = AI_EVENT persistent = yes province = 335 deathdate = { year = 1000 } action = { trigger = { OR = { religion = catholic religion = hussite religion = lutheran religion = anglican religion = puritan religion = calvinist religion = zwinglian religion = huguenot religion = presbyterian } } command = { type = religion which = counterreform } } }
It's inline because I batch-created events for all land provinces. There's only two things of interest here: The event is persistent with a deathdate in the past, which is to make sure the event can be fired an infinite number of times by other events but doesn't fire on its own; and the action checks whether the country has a christian non-orthodox religion, and if so, converts to counter-reformed catholic.

Also, once the overlord = <tag> trigger works properly, we can scrap all those events and replace them with one event that is automatically fired for all christian (non-orthodox) vassals of counter-reformed countries to make them counter-reformed as well. This would then be an inherent mechanic of the counter-reformed religion. The trigger for that event could look like this:
Code:
OR = {
	religion = catholic
	religion = hussite
	...
}
OR = {
	AND = { overlord = ABK ABK = { religion = counterreform } }
	AND = { overlord = ACH ACH = { religion = counterreform } }
	...
}
We may also want to create an event that does the inverse, i.e. prevent vassals from being counter-reformed while their overlord isn't. In fact you could combine both into one event if you wanted to do so.



Now let's get back to liberation events. The Oldenburg event was pretty simple since OLD is a one-province minor and there are no other countries in the FtG timeframe that would have specific reasons not to liberate OLD. For example in the case of Napoléon, you'd set the hre_noliberate flag for FRA anyway.

So let's have a look at a somewhat more complex setup, Savoy/Piedmont:
Code:
# SAV - Savoy
event = {
	id = 100000404 name = AI_EVENT deathdate = { year = 1999 } persistent = yes
	province = 404
	trigger = { ai = yes atwar = no stability = 1
		OR = { city = 404 colonialcity = 404 }
		NOT = { core_national = { province = 404 data = -1 } capital = 404
			capital = 405
			capital = 988
			exists = SAV
			exists = ITA flag = "ita_noliberate" MUS = { flag = "global_ita_noliberate" }
			tag = FRA
			tag = SAR
			tag = PIE
			AND = { NOT = { exists = FRA } owned = { province = 385 data = -1 } }
		} control = { province = 404 data = -1 }
		OR = { control = { province = 405 data = -1 } NOT = { owned = { province = 405 data = -1 } } }
		OR = { control = { province = 988 data = -1 } NOT = { owned = { province = 988 data = -1 } } }
	} action = { command = { type = independence which = SAV }
	command = { trigger = { religion = counterreform NOT = { flag = 6 } } type = trigger which = 200000404 } }
}

# PIE - Piedmont
event = {
	id = 101000404 name = AI_EVENT deathdate = { year = 1999 } persistent = yes
	province = 404
	trigger = { ai = yes atwar = no stability = 1
		OR = { city = 404 colonialcity = 404 }
		OR = { exists = SAV tag = FRA }
		NOT = { core_national = { province = 404 data = -1 } capital = 404
			exists = PIE
			exists = ITA flag = "ita_noliberate" MUS = { flag = "global_ita_noliberate" }
			tag = SAV
			tag = SAR
		} control = { province = 404 data = -1 }
	} action = { command = { type = independence which = PIE }
	command = { trigger = { religion = counterreform NOT = { flag = 6 } } type = trigger which = 200000404 } }
}

# SAV - Savoy
event = {
	id = 100000405 name = AI_EVENT deathdate = { year = 1999 } persistent = yes
	province = 405
	trigger = { ai = yes atwar = no stability = 1
		OR = { city = 405 colonialcity = 405 }
		NOT = { core_national = { province = 405 data = -1 } capital = 405
			capital = 404
			capital = 988
			exists = SAV
			tag = FRA
			tag = SAR
			tag = PIE
			AND = { NOT = { exists = FRA } owned = { province = 385 data = -1 } }
			owned = { province = 404 data = -1 }
		} control = { province = 405 data = -1 }
		OR = { control = { province = 988 data = -1 } NOT = { owned = { province = 988 data = -1 } } }
	} action = { command = { type = independence which = SAV }
	command = { trigger = { religion = counterreform NOT = { flag = 6 } } type = trigger which = 200000405 } }
}
For clarification: In Watkabaoi, province 404 is Savoy with the city Chambéry, the old capital of the Duchy of Savoy, and 405 is Piemonte with the city Torino, the later capital of the Duchy of Savoy (and the Kingdom of Sardinia). Here's a picture:

savoyd8fh8.png


Rather than analysing the events, I think it's better to point out the differences to the Oldenburg event:
  • Savoy is a country that has three minimum provinces in revolt.txt.
    These are Savoy, Piemonte, and Nice. Of course, we don't want the capital of the liberating country to be any of those provinces, and the liberating country must also control all of those provinces that it owns. Additionally, we don't want SAV to be created only from Nice, as that would make no sense. So there's two SAV events, one each for 404 and 405.

  • Piedmont is a one-province minor in Piemonte province.
    This means that FRA will always want to release PIE rather than SAV. It also means that other countries should prefer to release SAV, but if SAV already exists, then they should release PIE instead.

  • Savoy, Piedmont and Sardinia are essentially the same country.
    So they will never liberate each other, and in fact there should also be events that e.g. turn PIE into SAV if the other Savoyard provinces are conquered (and also give the respective cores). This is beyond the scope of the liberation AI, but it needs to be taken into account here.

  • The provinces Savoy and Nice are also part of France.
    This means that if a country owns Paris (e.g. SPA having diplo-annexed FRA) then FRA should be created before SAV, or if it's a smaller French country (e.g. LOR) then it should first turn into FRA and then create PIE rather than SAV.


Also, I wrote those liberation events before the vassal = <tag> trigger was implemented, and an AI country that already has SAV as a vassal and then conquers Piemonte province should probably simply give that province to SAV rather than create PIE there. This could easily be implemented in the PIE liberation event:
Code:
action = {
	command = {
		trigger = { vassal = SAV }
		type = cedeprovince which = 404 value = SAV
	}
	command = {
		trigger = { NOT = { vassal = SAV } }
		type = independence which = PIE
	}
}
Alternatively (or additionally) you could create an event for SAV where it would automatically annex PIE if both have the same overlord, once the overlord = <tag> trigger works. This would make sure that the Savoy region is unified regardless of how and when provinces are conquered and vassals created.

And for the sake of completeness, here's the FRA liberation event. I don't think this needs further explanation, it's a long but also very straightforward event:
Code:
# FRA - France
event = {
	id = 100000385 name = AI_EVENT deathdate = { year = 1999 } persistent = yes
	province = 385
	trigger = { ai = yes atwar = no stability = 1
		OR = { city = 385 colonialcity = 385 }
		NOT = { core_national = { province = 385 data = -1 } capital = 385
			capital = 192
			capital = 374
			capital = 375
			capital = 386
			capital = 376
			capital = 405
			capital = 406
			capital = 407
			capital = 408
			capital = 410
			capital = 411
			capital = 416
			capital = 419
			capital = 420
			capital = 409
			capital = 379
			capital = 382
			capital = 383
			capital = 384
			capital = 387
			capital = 412
			capital = 413
			capital = 414
			capital = 415
			capital = 417
			capital = 418
			capital = 421
			capital = 422
			capital = 423
			capital = 424
			capital = 425
			capital = 426
			capital = 877
			capital = 988
			capital = 1415
			capital = 1436
			capital = 1437
			exists = FRA
			tag = FPR
			tag = FUC
			tag = BUR
			tag = SAV
			tag = NAV
			tag = AMG
			tag = ANJ
			tag = AQU
			tag = ART
			tag = AUV
			tag = BEA
			tag = BOU
			tag = BRI
			tag = CMG
			tag = COR
			tag = DAU
			tag = FOI
			tag = LOR
			tag = NEV
			tag = ORL
			tag = POI
			tag = PRO
			tag = STR
			tag = TOU
		} control = { province = 385 data = -1 }
		OR = { control = { province = 192 data = -1 } NOT = { owned = { province = 192 data = -1 } } }
		OR = { control = { province = 374 data = -1 } NOT = { owned = { province = 374 data = -1 } } }
		OR = { control = { province = 375 data = -1 } NOT = { owned = { province = 375 data = -1 } } }
		OR = { control = { province = 386 data = -1 } NOT = { owned = { province = 386 data = -1 } } }
		OR = { control = { province = 376 data = -1 } NOT = { owned = { province = 376 data = -1 } } }
		OR = { control = { province = 405 data = -1 } NOT = { owned = { province = 405 data = -1 } } }
		OR = { control = { province = 406 data = -1 } NOT = { owned = { province = 406 data = -1 } } }
		OR = { control = { province = 407 data = -1 } NOT = { owned = { province = 407 data = -1 } } }
		OR = { control = { province = 408 data = -1 } NOT = { owned = { province = 408 data = -1 } } }
		OR = { control = { province = 410 data = -1 } NOT = { owned = { province = 410 data = -1 } } }
		OR = { control = { province = 411 data = -1 } NOT = { owned = { province = 411 data = -1 } } }
		OR = { control = { province = 416 data = -1 } NOT = { owned = { province = 416 data = -1 } } }
		OR = { control = { province = 419 data = -1 } NOT = { owned = { province = 419 data = -1 } } }
		OR = { control = { province = 420 data = -1 } NOT = { owned = { province = 420 data = -1 } } }
		OR = { control = { province = 409 data = -1 } NOT = { owned = { province = 409 data = -1 } } }
		OR = { control = { province = 379 data = -1 } NOT = { owned = { province = 379 data = -1 } } }
		OR = { control = { province = 382 data = -1 } NOT = { owned = { province = 382 data = -1 } } }
		OR = { control = { province = 383 data = -1 } NOT = { owned = { province = 383 data = -1 } } }
		OR = { control = { province = 384 data = -1 } NOT = { owned = { province = 384 data = -1 } } }
		OR = { control = { province = 387 data = -1 } NOT = { owned = { province = 387 data = -1 } } }
		OR = { control = { province = 412 data = -1 } NOT = { owned = { province = 412 data = -1 } } }
		OR = { control = { province = 413 data = -1 } NOT = { owned = { province = 413 data = -1 } } }
		OR = { control = { province = 414 data = -1 } NOT = { owned = { province = 414 data = -1 } } }
		OR = { control = { province = 415 data = -1 } NOT = { owned = { province = 415 data = -1 } } }
		OR = { control = { province = 417 data = -1 } NOT = { owned = { province = 417 data = -1 } } }
		OR = { control = { province = 418 data = -1 } NOT = { owned = { province = 418 data = -1 } } }
		OR = { control = { province = 421 data = -1 } NOT = { owned = { province = 421 data = -1 } } }
		OR = { control = { province = 422 data = -1 } NOT = { owned = { province = 422 data = -1 } } }
		OR = { control = { province = 423 data = -1 } NOT = { owned = { province = 423 data = -1 } } }
		OR = { control = { province = 424 data = -1 } NOT = { owned = { province = 424 data = -1 } } }
		OR = { control = { province = 425 data = -1 } NOT = { owned = { province = 425 data = -1 } } }
		OR = { control = { province = 426 data = -1 } NOT = { owned = { province = 426 data = -1 } } }
		OR = { control = { province = 877 data = -1 } NOT = { owned = { province = 877 data = -1 } } }
		OR = { control = { province = 988 data = -1 } NOT = { owned = { province = 988 data = -1 } } }
		OR = { control = { province = 1415 data = -1 } NOT = { owned = { province = 1415 data = -1 } } }
		OR = { control = { province = 1436 data = -1 } NOT = { owned = { province = 1436 data = -1 } } }
		OR = { control = { province = 1437 data = -1 } NOT = { owned = { province = 1437 data = -1 } } }
	} action = { command = { type = independence which = FRA }
	command = { trigger = { religion = counterreform NOT = { flag = 6 } } type = trigger which = 200000385 } }
}



And that concludes the topic of liberation AI in FtG. Here's a template for anyone who wants to create their own liberation events; I used big fat special characters as placeholders so it's really, really obvious when you forget to paste a tag/ID:

Code:
# █▓▒░░▒▓█ - COUNTRYNAME
event = {
	id = ID----◄█■■■■█► name = AI_EVENT deathdate = { year = 1999 } persistent = yes
	province = ◄█■■■■█►
	trigger = { ai = yes atwar = no stability = 1
		OR = { city = ◄█■■■■█► colonialcity = ◄█■■■■█► }
		NOT = { core_national = { province = ◄█■■■■█► data = -1 } capital = ◄█■■■■█►
			exists = █▓▒░░▒▓█
			tag = █■█
			tag = █■█
			tag = █■█
			tag = █■█
		} control = { province = ◄█■■■■█► data = -1 }
		OR = { control = { province = ◄█►■■■█► data = -1 } NOT = { owned = { province = ◄█►■■■█► data = -1 } } }
		OR = { control = { province = ◄█■►■■█► data = -1 } NOT = { owned = { province = ◄█■►■■█► data = -1 } } }
		OR = { control = { province = ◄█■■►■█► data = -1 } NOT = { owned = { province = ◄█■■►■█► data = -1 } } }
		OR = { control = { province = ◄█■■■►█► data = -1 } NOT = { owned = { province = ◄█■■■►█► data = -1 } } }
	} action = { command = { type = independence which = █▓▒░░▒▓█ } }
}
Next time, I'll talk about some other cool automations you can do with vassals and overlords, and about new triggers/commands that would come in very handy for that (sameoverlord = <tag> comes to mind). Originally, that was supposed to be part of this post, but I think it's long enough already...

Questions and comments are welcome. I'll also do my best to help if you have problems getting any of the things I've talked about to work. :)
 
Last edited:
The AGCEEP events are very rudimentary though; they're not using the <tag> trigger and for some reason they're random events. They're also missing basic sanity checks. Basically, they're designed to counter a very specific problem, namely the BWB, rather than blobbing in general. My post isn't just about "how to write an event that does x" but also about "how to write good events that won't break easily and can be adapted to specific needs". This will hopefully become more apparent in one of the next posts where I'll talk about province trading between AI countries, which AGCEEP also does, but without any regard to what kind of relation those countries have.

In your trigger please remember that checking for a national core is not enough as there are 3 types of core a state could have on a province now unlike in EU2.
You must have missed this paragraph:
Then, we don't want the province to be a national province. This is kind of obvious, however, it begs the question why I didn't exclude claims as well. There's no simple answer here, and in the end it comes down to preference. Basically, if you're trying to achieve somewhat historical progression of the game, then for certain provinces you'll need additional triggers to make sure certain flags are set or other conditions are fulfilled. Maybe you think this could be controlled with claimed provinces, and that would certainly be an option in some cases, but often you'll want countries to keep provinces they don't even have claims on. The inverse case may also happen; for example a France with claims on Naples that has conquered those provinces would still be expected to create a vassal state, rather than ruling those territories directly from Paris. Basically, it boils down to how you want your AI countries to act, and how and where claims are given.
 
The AGCEEP events are very rudimentary though; they're not using the <tag> trigger and for some reason they're random events. They're also missing basic sanity checks.

Yes of course they do. Back then when those events were first discussed and created "persistent" events and many scripting options that were introduced in FtG did simply not exist in EU2. Without persistent events that can fire more than once the only way to have events that can happen more than once were random events.
 
I'll read your post later but that looks like a fabulously historical screenshot.

Also, HAB has an amazing amount of refineries. How did you manage that?
 
I'll read your post later but that looks like a fabulously historical screenshot.

Also, HAB has an amazing amount of refineries. How did you manage that?

10 years after the 30years-war there is nothing historical about a Habsburg Empire fielding that much refineries outside provinces with the fitting wine or sugar.
 
The overlord = TAG trigger has the same problem that the num_of_ports trigger and its kin had: it was fully implemented except nobody told the lexer how to recognize the "overlord" token.
 
10 years after the 30years-war there is nothing historical about a Habsburg Empire fielding that much refineries outside provinces with the fitting wine or sugar.
The political borders are very historical.

The refineries are another issue. Since only HAB seems to have that much, I'm guessing he tweaked its AI file in such a way that resulted in all those refineries. That type of AI file can be very useful for trade-oriented countries.
 
The AI file has very little to do with AI manufactory construction. Under 1.3, if the AI is wealthy, they are likely to take a bit of inflation to build manufactories; many of those refineries were probably built before weapons or naval manufactories were available.
 
The political borders are very historical.
Most of it was due to chance, though. If you look at the diplomatic landscape it's not historical at all; Brandenburg has like 5 vassals and Pomerania is a vassal of Poland, which is also why the partition between Brandenburg and Sweden didn't happen. I still have to write the event for Swedish Bremen-Verden, and the event for the creation of the Dutch Republic currently simply gives HOL the historical provinces because the way I want to structure the event chain can't be implemented yet. And of course colonisation is pretty much a free-for-all disaster anyway. Even something as simple as getting Portugal to conquer Goa is a nigh-impossible task, which is why Watkabaoi has Goa as a Portuguese province in the 1492 scenario. :D

The refineries are another issue. Since only HAB seems to have that much, I'm guessing he tweaked its AI file in such a way that resulted in all those refineries.
I haven't even concerned myself with AI in regards to economics yet. I've overhauled the naval tech and I'll probably do the same with the other techs eventually, and when that's done I'll take a look at what the AI actually does within its own borders...