How to make events for one nation only, or for every nation
An event is never "shown on screen" by itself. It is delivered to a country. A player sees an event only if it was delivered to the country they are playing.
So the event itself is written the same way in both cases. What changes is who you send it to.
news_eventThe game can only put a picture at the top of the window in the news window. A country_event is text only: if you write country_event, the picture will never appear.
A 581x436 image that contains the header bar (with its label, for example COUNTRY EVENT) and the 557x372 photo. A plain photo would land in the top-left corner of the window.
A news_event is a normal event in every other way: it can go to one country only, have several options, and have effects.
| What | Where |
|---|---|
| The event | events/<your_file>.txt |
| Title, text, button text | localisation/english/<your_file>_l_english.yml |
| The picture | gfx/event_pictures/DVE_news/<name>.png (or .dds) |
| Registering the picture | interface/DVE_event_panels.gfx |
| When it fires and for whom | common/on_actions/<your_file>.txt, or the effect of a focus, decision or other event |
Create a file in events/, for example events/DVE_ROM_2025.txt.
add_namespace = dve_rom
news_event = {
id = dve_rom.2
title = dve_rom.2.t
desc = dve_rom.2.d
picture = GFX_news_event_DVE_rom_january_strikes
is_triggered_only = yes
option = {
name = dve_rom.2.a
}
}add_namespace = dve_rom: must be at the top of the file, once. Every id in the file starts with this name. Pick a name nobody else uses. Already taken: dve_news, dve_rom, dve_lba, dve_frapro, dve_itapro, dve_mayday, and the same names ending in _send.id = dve_rom.2: namespace, a dot, a number. An id must be unique in the whole mod. If two events share an id, only one of them works. Search the mod for the id before using it.title / desc: localisation keys, not the text itself (see step 3).picture: the sprite name of your panel (see step 4). Leave the line out for an event with no picture: the window then shows the WORLD NEWS header with an empty screen.is_triggered_only = yes: the event fires only when something sends it. Always include it, otherwise the game fires it randomly for every country.option: one button. name is the localisation key of the button text. Effects go inside the option. option = {
name = dve_rom.2.a
add_stability = -0.05
add_popularity = { ideology = progressive popularity = 0.02 }
}popularity = 0.02 means +2%. The ideology must be one of the 14 groups of the mod: progressive, revolutionary_socialism, vanguard_socialism, authoritarian_socialism, totalitarian_socialism, liberal, centrist, conservative, reactionary, authoritarianism, autocracy, absolutism, ultranationalism, fundamentalism.
For several buttons, write several option blocks. AI countries pick an option by themselves.
Create localisation/english/DVE_ROM_2025_l_english.yml. The name must end in _l_english.yml.
l_english:
dve_rom.2.t:0 "The January Strikes"
dve_rom.2.d:0 "First paragraph of the text.\n\nSecond paragraph."
dve_rom.2.a:0 "Hope the people get what they want."Rules that break the game if ignored
l_english:.key:0 "text".'austerity ordinance'. An unclosed double quote in a localisation file can crash the game.\n is a line break; \n\n leaves an empty line between paragraphs.- and é-style accents are fine.tools/panel_templates/: panel_COUNTRY_EVENT.png, panel_WORLD_NEWS.png, or panel_no_label.png if you want to write your own header text.gfx/event_pictures/DVE_news/, for example news_event_DVE_rom_january_strikes.png.python3 tools/dve_event_panel.py photo.png "COUNTRY EVENT" gfx/event_pictures/DVE_news/news_event_DVE_rom_january_strikes.ddsAdd a block inside spriteTypes = { ... } in interface/DVE_event_panels.gfx:
spriteType = {
name = "GFX_news_event_DVE_rom_january_strikes"
texturefile = "gfx/event_pictures/DVE_news/news_event_DVE_rom_january_strikes.png"
}The name here is what you write after picture = in the event. The texturefile must match the real file name exactly, including capital letters and the extension.
Send the event to that country's tag:
ROM = { news_event = { id = dve_rom.2 } }Only the player of Romania sees it. Its options and effects apply to Romania only.
If the effect already runs "as" Romania (for example inside a Romanian focus, a Romanian decision, or the option of another Romanian event), you do not need the tag:
news_event = { id = dve_rom.2 }Send it to all existing countries:
every_country = { news_event = { id = dve_rom.1 } }Be careful: the options and their effects now run in every country. If the option gives +2% popularity, every country gets +2%.
Send it to everyone as in B, and wrap the effects in a check on the tag:
option = {
name = dve_frapro.1.a
if = {
limit = { tag = FRA }
add_popularity = { ideology = progressive popularity = 0.02 }
add_popularity = { ideology = vanguard_socialism popularity = 0.05 }
}
}Everyone reads the event; only France gets the popularity change. Other countries see the button with no effect listed.
All scheduling goes in a file in common/on_actions/, for example common/on_actions/DVE_ROM_2025_on_actions.txt.
Put the line from step 5 directly in the effect:
completion_reward = {
ROM = { news_event = { id = dve_rom.2 } }
}Add a delay with days or hours:
ROM = { news_event = { id = dve_rom.2 days = 3 } }The game starts on 2025.01.01 at 12:00. Count the hours from that moment to your date.
hours = (days between 1 January and your date) x 24 + (your hour - 12)Days already passed at the start of each month: Jan 0, Feb 31, Mar 59, Apr 90, May 120, Jun 151, Jul 181, Aug 212, Sep 243, Oct 273, Nov 304, Dec 334. The game has no leap years: every year is 365 days.
| Date | Calculation | Hours |
|---|---|---|
| 2025.01.03 06:00 | 2 x 24 - 6 | 42 |
| 2025.02.10 10:00 | 40 x 24 - 2 | 958 |
| 2025.05.18 12:00 | 137 x 24 + 0 | 3288 |
One nation
on_actions = {
on_startup = {
effect = {
if = {
limit = { NOT = { has_global_flag = DVE_ROM_2025_scheduled } }
set_global_flag = DVE_ROM_2025_scheduled
ROM = {
news_event = { id = dve_rom.2 hours = 42 }
}
}
}
}
}Two things matter here
on_startup has no country behind it, so you must wrap the event in a tag (ROM = { ... }) or in every_country.Every nation
Do not schedule the news directly. Countries that are born later (civil war factions) and players who change tag would miss it. Schedule a hidden "sender" event instead, and let it deliver the news on the day.
In the events file:
add_namespace = dve_rom
add_namespace = dve_rom_send
country_event = {
id = dve_rom_send.1
hidden = yes
is_triggered_only = yes
immediate = {
if = {
limit = { NOT = { has_global_flag = dve_rom_1_sent } }
set_global_flag = dve_rom_1_sent
every_country = { news_event = { id = dve_rom.1 } }
}
}
}In the on_actions file, inside the same on_startup block:
every_country = {
country_event = { id = dve_rom_send.1 hours = 1 }
}Every country receives the hidden sender at the same hour. The first one sends the news to all countries that exist at that moment; the flag stops the others from sending it again.
For dates a year or more away, check the date daily instead of counting hours. on_daily_TAG runs every day for that country, as long as it exists.
One nation
on_actions = {
on_daily_LBA = {
effect = {
if = {
limit = {
date > 2026.2.16
NOT = { has_global_flag = dve_lba_1_fired }
}
set_global_flag = dve_lba_1_fired
news_event = { id = dve_lba.1 hours = 6 }
}
}
}
}date > 2026.2.16 becomes true on 17 February: always write the day before the one you want.hours = 6 makes it appear at 06:00 of that day.on_daily_LBA you are already Libya, so no tag is needed.Every nation
Use the same block but send to everyone. Use the tag of the country the event is about, so it only fires while that country exists:
on_daily_FRA = {
effect = {
if = {
limit = {
date > 2026.9.16
date < 2026.10.1
NOT = { has_global_flag = dve_frapro_1_fired }
}
set_global_flag = dve_frapro_1_fired
every_country = { news_event = { id = dve_frapro.1 hours = 8 } }
}
}
}The second date < line is a window: it stops an old save from receiving a pile of outdated events on the same day.
You can add any other condition to the limit, for example "only while France is not in its civil war":
limit = { NOT = { has_country_flag = FRA_civil_war } }Schedule the first one from game start with a sender (6.2), and let the sender book itself again 365 days later for every country:
every_country = {
news_event = { id = dve_mayday.1 }
country_event = { id = dve_mayday_send.1 days = 365 }
}Use a flag that expires so it can fire again next year:
set_global_flag = { flag = dve_mayday_sent days = 30 value = 1 }on_startup (it only runs when a game begins).event dve_rom.2tag FRA
event dve_frapro.1logs/error.log in the game's documents folder and search for your namespace or file name.The console does not work in Ironman.
add_namespace at the top of the events file, and the namespace is not used elsewhere.news_event if it has a picture.is_triggered_only = yes is there..t, .d and every option key exist in the _l_english.yml file.l_english:, and has no double quotes inside the texts.interface/DVE_event_panels.gfx with the exact file name.TAG = { news_event = { ... } }. All nations: sent with every_country = { news_event = { ... } }.if = { limit = { tag = XXX } ... }.{ has its }.| Symptom | Cause |
|---|---|
| No picture | The event is a country_event, or the sprite name / file name does not match. |
| Photo in the top-left corner, covering the header | The picture is a plain photo, not a 581x436 panel. |
Title or text shows the key (dve_rom.2.t) | Missing localisation key, wrong file name, or file not saved with BOM. |
| The event never fires | on_startup without a tag or every_country; flag already set in an old save; wrong date (remember: the day before). |
| Only some players see an "all nations" event | It was scheduled directly at game start instead of through a sender, so later-born countries missed it. |
| Every country got the effects | Effects in the option without the tag check. |
| Another event appears instead of yours | Two events share the same id. |
| The event fires again and again | No flag, or is_triggered_only is missing. |