小 (→触发器) |
小 (重写mtth,至少像段人话) |
||
第63行: | 第63行: | ||
}</pre>请注意:如不注明<code>is_triggered_only = yes</code>游戏将每20天检查一次是否符合触发条件<ref>NDefines.NCountry.EVENT_PROCESS_OFFSET = 20 in [[Defines]]</ref>。如用[[控制台指令]]强行调出事件( 此处使用指令应为<code>event my_event.123</code> ),控制台会显示事件强行触发时已满足和未满足的条件。 | }</pre>请注意:如不注明<code>is_triggered_only = yes</code>游戏将每20天检查一次是否符合触发条件<ref>NDefines.NCountry.EVENT_PROCESS_OFFSET = 20 in [[Defines]]</ref>。如用[[控制台指令]]强行调出事件( 此处使用指令应为<code>event my_event.123</code> ),控制台会显示事件强行触发时已满足和未满足的条件。 | ||
<code>mean_time_to_happen</code> 可用于让事件在指定的时间 | <code>mean_time_to_happen</code> 可用于让事件在指定的时间 前后 随机触发。用<code>days</code>、<code>months</code>和<code>years</code>来表示事件 从符合 触发 条件到触发所 需的 大概用时 ,其中<code>months</code>按30天计,<code>years</code>按365天计。此外还可以用 <code>modifier</code>来对上述时间做运算,其中<code>add</code>增加时间、<code>factor</code> 乘以系数、<code>base</code> 直接改变 计算基 数。例子如下: | ||
<pre>mean_time_to_happen = { | <pre>mean_time_to_happen = { | ||
days = 10 | days = 10 | ||
第72行: | 第72行: | ||
} | } | ||
}</pre> | }</pre> | ||
一旦事件符合通过上述20天检查,游戏就将每天判定是否要触发此事件。 | 一旦事件符合通过上述20天检查,游戏就将每天判定是否要触发此事件。 | ||
<math>1 | 值得注意的是,使用此功能会使事件的触发服从失败率为<math>2^{-\frac{1}{指定的触发天数}}</math>的[https://baike.baidu.com/item/%E5%87%A0%E4%BD%95%E5%88%86%E5%B8%83 几何分布]。考虑到其数学期望为<math>frac{2^{\frac{1}{指定的触发天数}}}{2^{\frac{1}{指定的触发天数}}-1}</math> 而非指定天数,此功能与设置的不是每天判定开始到触发用时的算术平均——对每天概率加和就会发现其实是中位数。 | ||
由于每天判定时也同时判断事件是否仍符合触发条件,建议各位用户在自定义事件时限制此类事件数量以防性能不良。 | 由于每天判定时也同时判断事件是否仍符合触发条件,建议各位用户在自定义事件时限制此类事件数量以防性能不良。 | ||
第85行: | 第85行: | ||
如需像新闻一样让所有国家都能看到此事件,请用<code>major = yes</code>。请注意此代码不能和<code>fire_only_once = yes</code>并用,后者指的是总触发次数只有1次而非每个国家1次,并用将导致此事件只能在触发此事件的国家触发。This will bypass the <code>trigger = { ... }</code> block for the countries that did not have this event fired originally, instead relying on the <code>show_major = { ... }</code> trigger block, if one is present. Additionally, <code>fire_for_sender = no</code>, if added, will prevent the major event from appearing for the country that it originally got fired for, via an effect or by the trigger being met. | 如需像新闻一样让所有国家都能看到此事件,请用<code>major = yes</code>。请注意此代码不能和<code>fire_only_once = yes</code>并用,后者指的是总触发次数只有1次而非每个国家1次,并用将导致此事件只能在触发此事件的国家触发。This will bypass the <code>trigger = { ... }</code> block for the countries that did not have this event fired originally, instead relying on the <code>show_major = { ... }</code> trigger block, if one is present. Additionally, <code>fire_for_sender = no</code>, if added, will prevent the major event from appearing for the country that it originally got fired for, via an effect or by the trigger being met. | ||
=== 选项 === | === 选项=== | ||
An event option is added with an <code>option = { ... }</code> block. An event option is an [[effect]] block, with a few extra options: | An event option is added with an <code>option = { ... }</code> block. An event option is an [[effect]] block, with a few extra options: | ||
第94行: | 第94行: | ||
<code>ai_chance = { ... }</code> is a block deciding the [[AI modding#AI will do|AI chance]] for event options: deciding in a proportional way which option to pick. The AI chance in event options do not have to add up to 100, as it is proportional. It is structured in a near-identical way to the mean time to happen. If unset, assumed to be 1. The probability of each option is its weight divided by the sum of all option weights. If all options have a weight of zero, the first one is chosen. The randomized choice is made by rolling a d100, so options can't have an effective non-zero probability below 1%. The choice remains consistent across reloads, based on unique game seed, in-game time, country, and unit leader. | <code>ai_chance = { ... }</code> is a block deciding the [[AI modding#AI will do|AI chance]] for event options: deciding in a proportional way which option to pick. The AI chance in event options do not have to add up to 100, as it is proportional. It is structured in a near-identical way to the mean time to happen. If unset, assumed to be 1. The probability of each option is its weight divided by the sum of all option weights. If all options have a weight of zero, the first one is chosen. The randomized choice is made by rolling a d100, so options can't have an effective non-zero probability below 1%. The choice remains consistent across reloads, based on unique game seed, in-game time, country, and unit leader. | ||
=== | ===其他可指定参数=== | ||
<code>immediate = { ... }</code> is an [[effect]] block, executed as soon as the event is fired, before an option is chosen by the player. This can also be used for AI: AI only picks an option after the event triggers are evaluated for every other country, while immediate is executed immediately, before evaluating other events. This can be used in mean-time-to-happen type major events: by making the immediate set a global flag, which is required to be unset in the event trigger, this will prevent it from being fired more than once for each country, but it is preferable to avoid mean-time-to-happen events in entirety. Note that the effect will appear in the tooltip after the event's description, so the hidden_effect flow tool can be helpful. | <code>immediate = { ... }</code> is an [[effect]] block, executed as soon as the event is fired, before an option is chosen by the player. This can also be used for AI: AI only picks an option after the event triggers are evaluated for every other country, while immediate is executed immediately, before evaluating other events. This can be used in mean-time-to-happen type major events: by making the immediate set a global flag, which is required to be unset in the event trigger, this will prevent it from being fired more than once for each country, but it is preferable to avoid mean-time-to-happen events in entirety. Note that the effect will appear in the tooltip after the event's description, so the hidden_effect flow tool can be helpful. | ||
第103行: | 第103行: | ||
<code>minor_flavor = yes</code> marks the event as being a minor flavour event. This does not change its appearance or change its effects, but allows turning off the pop-up within the game's decision menu. | <code>minor_flavor = yes</code> marks the event as being a minor flavour event. This does not change its appearance or change its effects, but allows turning off the pop-up within the game's decision menu. | ||
== | ==事件效果 == | ||
Any [[effect|effect block]] can be used to fire an event, such as focus rewards, [[#Options|event options]], or decision effects. This is usually paired with <code>is_triggered_only = yes</code> within the event as to disable automatic firing. | Any [[effect|effect block]] can be used to fire an event, such as focus rewards, [[#Options|event options]], or decision effects. This is usually paired with <code>is_triggered_only = yes</code> within the event as to disable automatic firing. | ||
In its simplest way, this is done with the effect of <code>country_event = my_event.1</code> (or <code>news_event = my_event.1</code>), which'll instantly fire the event for the scoped country. As country and news events are the exact same thing under the surface, both shortened effects can be used for either country and news events, with there being no difference between them whatsoever.<br/> | In its simplest way, this is done with the effect of <code>country_event = my_event.1</code> (or <code>news_event = my_event.1</code>), which'll instantly fire the event for the scoped country. As country and news events are the exact same thing under the surface, both shortened effects can be used for either country and news events, with there being no difference between them whatsoever.<br /> | ||
However, more options can be added primarily for setting up the delay. Additionally, expanded versions are mandatory for state and operative leader events. | However, more options can be added primarily for setting up the delay. Additionally, expanded versions are mandatory for state and operative leader events. | ||
A more complex effect to fire is <code>country_event = { id = my_event.1 days = 100 random_days = 123 }</code>. This'll fire the event in 100 to 223 (<math>100 + 123</math>) days. There are the following arguments that can go into the effect (All of them are optional with one exception): | A more complex effect to fire is <code>country_event = { id = my_event.1 days = 100 random_days = 123 }</code>. This'll fire the event in 100 to 223 (<math>100 + 123</math>) days. There are the following arguments that can go into the effect (All of them are optional with one exception): | ||
* <code>id = my_event.1</code> — The ID of the event to fire. This is mandatory as to let the game know which event to fire. | *<code>id = my_event.1</code> — The ID of the event to fire. This is mandatory as to let the game know which event to fire. | ||
* <code>hours = 1</code>|<code>days = 2</code>|<code>months = 3</code> — The lower bound on the needed time that the event will fire in. In this case, a month is treated as exactly 30 days. If multiple of these are used, the game will add them up together (e.g. the example with 1 hour, 2 days, and 3 months will fire in 92 days and 1 hour). | *<code>hours = 1</code>|<code>days = 2</code>|<code>months = 3</code> — The lower bound on the needed time that the event will fire in. In this case, a month is treated as exactly 30 days. If multiple of these are used, the game will add them up together (e.g. the example with 1 hour, 2 days, and 3 months will fire in 92 days and 1 hour). | ||
* <code>random_hours = 1</code>|<code>random_days = 2</code> — This sets the upper bound on the needed time that the event will fire in. The game selects a random amount (uniform distribution) of days and hours between 0 and the set amount, including both ends, and adds them to the delay to fire the event. Similarly to above, if both are specified, the game will add them together. <code>random = 123</code> also serves as an equivalent for <code>random_hours = 123</code>. | *<code>random_hours = 1</code>|<code>random_days = 2</code> — This sets the upper bound on the needed time that the event will fire in. The game selects a random amount (uniform distribution) of days and hours between 0 and the set amount, including both ends, and adds them to the delay to fire the event. Similarly to above, if both are specified, the game will add them together. <code>random = 123</code> also serves as an equivalent for <code>random_hours = 123</code>. | ||
* <code>tooltip = my_event.1.t</code> — This decides what the name of the event that would fire would be displayed as in localisation. Defaults to the event's name, this may be useful if the title may change between the effect to fire it and its actual appearance. | *<code>tooltip = my_event.1.t</code> — This decides what the name of the event that would fire would be displayed as in localisation. Defaults to the event's name, this may be useful if the title may change between the effect to fire it and its actual appearance. | ||
Example effect using several of these parameters: | Example effect using several of these parameters: | ||
第124行: | 第124行: | ||
}</pre> | }</pre> | ||
The optional delay is incredibly useful, as hidden events can be used to create a delay between an effect block's execution and the actual application of effects without the player detecting anything. This can also be used to make the events appear more "natural": news events can have a delay of a few hours (typically around 6-12) in order to simulate the time it takes for the news agencies to report on the event. Similarly can be done with other event types to simulate waiting a few hours for a diplomatic response, rather than it being unnaturally instant.<br/> | The optional delay is incredibly useful, as hidden events can be used to create a delay between an effect block's execution and the actual application of effects without the player detecting anything. This can also be used to make the events appear more "natural": news events can have a delay of a few hours (typically around 6-12) in order to simulate the time it takes for the news agencies to report on the event. Similarly can be done with other event types to simulate waiting a few hours for a diplomatic response, rather than it being unnaturally instant.<br /> | ||
<code>trigger = { ... }</code> of the event gets checked when it would fire, meaning that it's also possible to [[On actions#on_startup|fire the event on startup of the game]] with a needed delay to get it on a specific day, then use the event's trigger to simulate additional requirements. | <code>trigger = { ... }</code> of the event gets checked when it would fire, meaning that it's also possible to [[On actions#on_startup|fire the event on startup of the game]] with a needed delay to get it on a specific day, then use the event's trigger to simulate additional requirements. | ||
Additionally, there are these event type-specific arguments: | Additionally, there are these event type-specific arguments: | ||
* <code>trigger_for = TAG</code> (Unique to state events) — The country for which the event will fire for. This is mandatory as state events are to be fired in state scope. This can also be replaced with <code>controller</code>, <code>owner</code>, <code>occupied</code>, or a [[Scopes#Dual scopes|dual scope that can be used as a target]], such as ROOT or FROM. | * <code>trigger_for = TAG</code> (Unique to state events) — The country for which the event will fire for. This is mandatory as state events are to be fired in state scope. This can also be replaced with <code>controller</code>, <code>owner</code>, <code>occupied</code>, or a [[Scopes#Dual scopes|dual scope that can be used as a target]], such as ROOT or FROM. | ||
* <code>originator = TAG</code> (Unique to operative leader events) — The country which serves as the originator of the event (i.e. FROM). Defaults to the operative's owner if unset. | *<code>originator = TAG</code> (Unique to operative leader events) — The country which serves as the originator of the event (i.e. FROM). Defaults to the operative's owner if unset. | ||
* <code>recipient = TAG</code> (Unique to operative leader events) — The country which would receive the event. Defaults to the operative's owner if unset. | *<code>recipient = TAG</code> (Unique to operative leader events) — The country which would receive the event. Defaults to the operative's owner if unset. | ||
* <code>set_root = TAG</code> (Unique to operative leader events) — Changes the scope of ROOT within the dynamic localisation of the event, without actually changing it in code. | *<code>set_root = TAG</code> (Unique to operative leader events) — Changes the scope of ROOT within the dynamic localisation of the event, without actually changing it in code. | ||
* <code>set_from = TAG</code> (Unique to operative leader events) — Changes the scope of FROM within the dynamic localisation of the event, without actually changing it in code. | *<code>set_from = TAG</code> (Unique to operative leader events) — Changes the scope of FROM within the dynamic localisation of the event, without actually changing it in code. | ||
* <code>set_from_from = TAG</code> (Unique to operative leader events) — Changes the scope of FROM.FROM within the dynamic localisation of the event, without actually changing it in code. | *<code>set_from_from = TAG</code> (Unique to operative leader events) — Changes the scope of FROM.FROM within the dynamic localisation of the event, without actually changing it in code. | ||
== | ==实践易错点== | ||
Some errors are quite common to make when beginning to make events, whether it's poor practice or if it would prevent the event from working in entirely. Some of them may be hard to notice when modding, with the event seemingly working fine, such as the error that prevents news events from being fired for more than one country.<br/> | Some errors are quite common to make when beginning to make events, whether it's poor practice or if it would prevent the event from working in entirely. Some of them may be hard to notice when modding, with the event seemingly working fine, such as the error that prevents news events from being fired for more than one country.<br /> | ||
This covers some of them, as well as the less intuitive errors in the log. | This covers some of them, as well as the less intuitive errors in the log. | ||
=== Unlogged errors === | ===Unlogged errors=== | ||
* '''Leaving an event as triggered only when it's to be fired automatically''' (''Event never fires'') – <code>is_triggered_only = yes</code> disables the automatic firing of the event, instead enforcing [[Effect#country_event|using the effect to do so]]. Therefore, if it is left in within an event intended to fire automatically, the event will never do so.<br/> | *'''Leaving an event as triggered only when it's to be fired automatically''' (''Event never fires'') – <code>is_triggered_only = yes</code> disables the automatic firing of the event, instead enforcing [[Effect#country_event|using the effect to do so]]. Therefore, if it is left in within an event intended to fire automatically, the event will never do so.<br /> | ||
: Note that <code>trigger = { ... }</code> can still co-exist with <code>is_triggered_only = yes</code>, so an event with both <code>is_triggered_only = yes</code> and <code>trigger = { ... }</code> may still be correct. Valid usages of them at the same time include the event being triggered via an [[on action]]'s <code>random_events</code> or the effect firing it has a delay (where the trigger would check if when the event is to be received), along others. | :Note that <code>trigger = { ... }</code> can still co-exist with <code>is_triggered_only = yes</code>, so an event with both <code>is_triggered_only = yes</code> and <code>trigger = { ... }</code> may still be correct. Valid usages of them at the same time include the event being triggered via an [[on action]]'s <code>random_events</code> or the effect firing it has a delay (where the trigger would check if when the event is to be received), along others. | ||
{{VisibleCollapse| | {{VisibleCollapse| | ||
'''Broken:''' | '''Broken:''' | ||
第179行: | 第179行: | ||
}</pre> | }</pre> | ||
|Collapsed example event with this issue and a correction to it}} | |Collapsed example event with this issue and a correction to it}} | ||
* '''Not checking the country in the trigger for country-specific auto-triggered events''' (''Event fires for the wrong country/never fires'') – The events are not assigned to countries in any way (namespaces and filenames serve a purely organisational purpose), and each event trigger is checked for each country in order specified in the tag list. | *'''Not checking the country in the trigger for country-specific auto-triggered events''' (''Event fires for the wrong country/never fires'') – The events are not assigned to countries in any way (namespaces and filenames serve a purely organisational purpose), and each event trigger is checked for each country in order specified in the tag list. | ||
: In the provided example, the event requires ITA to have more than 123 political power, upon which the country receiving the event would annex AUS. However, once ITA has that much, this trigger would be true ''regardless'' of where it's checked. The first country in the taglist by default is GER, and so it'll be the first country where the triggers are checked. In practice, this event will result in GER annexing AUS rather than ITA. | :In the provided example, the event requires ITA to have more than 123 political power, upon which the country receiving the event would annex AUS. However, once ITA has that much, this trigger would be true ''regardless'' of where it's checked. The first country in the taglist by default is GER, and so it'll be the first country where the triggers are checked. In practice, this event will result in GER annexing AUS rather than ITA. | ||
: In the correction, a change is made: first it checks that the country that would receive the event is ITA, and only then then it checks that it has more than enough political power. This makes sure that no other countries can receive this event. Specifying the tag is unnecessary if the trigger itself already implies a certain tag (e.g. <code>has_completed_focus</code> with a tag-specific focus tree), but is needed otherwise. | :In the correction, a change is made: first it checks that the country that would receive the event is ITA, and only then then it checks that it has more than enough political power. This makes sure that no other countries can receive this event. Specifying the tag is unnecessary if the trigger itself already implies a certain tag (e.g. <code>has_completed_focus</code> with a tag-specific focus tree), but is needed otherwise. | ||
{{VisibleCollapse| | {{VisibleCollapse| | ||
<pre>country_event = { | <pre>country_event = { | ||
第215行: | 第215行: | ||
} | } | ||
</pre> | </pre> | ||
|Collapsed example event with this issue and a correction to it}} | |Collapsed example event with this issue and a correction to it}} | ||
* '''Unnecessarily using auto-triggered events instead of ones that are triggered only''' (''Poor practice/optimisation'') – This is more of a poor practice than an error. In general, if an event's condition can be triggered with an effect, it should be. | *'''Unnecessarily using auto-triggered events instead of ones that are triggered only''' (''Poor practice/optimisation'') – This is more of a poor practice than an error. In general, if an event's condition can be triggered with an effect, it should be. | ||
: The example is the most obvious way of doing this: a [[Triggers#has_completed_focus|has_completed_focus check]] instead of firing it directly in the focus. However, other such cases can occur, e.g. when a war starts between two countries, when a state gets occupied, or for firing one on a specific date. It's best practice to check [[on actions]] before creating an automatically-triggered event to see if they can be made to replicate. | :The example is the most obvious way of doing this: a [[Triggers#has_completed_focus|has_completed_focus check]] instead of firing it directly in the focus. However, other such cases can occur, e.g. when a war starts between two countries, when a state gets occupied, or for firing one on a specific date. It's best practice to check [[on actions]] before creating an automatically-triggered event to see if they can be made to replicate. | ||
: Firing it via an effect has a purpose of being instant instead of having to wait up to 20 days. If so desired, a delay of a few hours can be added to make it appear more natural to the player. Additionally, it serves as a way to optimise the modification, as this reduces the amount of trigger checks repeatedly done. Events with a large mean-time-to-happen are particularly awful for performance and can be replaced with an effect block firing one with a large [[Effects#country_event|delay created with random_days within the effect]] in some cases. | : Firing it via an effect has a purpose of being instant instead of having to wait up to 20 days. If so desired, a delay of a few hours can be added to make it appear more natural to the player. Additionally, it serves as a way to optimise the modification, as this reduces the amount of trigger checks repeatedly done. Events with a large mean-time-to-happen are particularly awful for performance and can be replaced with an effect block firing one with a large [[Effects#country_event|delay created with random_days within the effect]] in some cases. | ||
{{VisibleCollapse| | {{VisibleCollapse| | ||
第261行: | 第261行: | ||
}</pre> | }</pre> | ||
|Collapsed example event with this issue and a correction to it}} | |Collapsed example event with this issue and a correction to it}} | ||
* '''Setting a news event to fire only once or not setting one as major''' (''News event only fires for one country'') – An event requires <code>major = yes</code> in order to appear for every country. News events are purely a reskin of country events and are not set to fire for every country by default, so this line is mandatory. Alongside that, events that fire only once don't appear more than once ''globally'' rather than per country. The event appearing for more than one country counts as it firing once again, so setting an event to fire only once will lead to only one country getting the news event instead of every one as intended. | *'''Setting a news event to fire only once or not setting one as major''' (''News event only fires for one country'') – An event requires <code>major = yes</code> in order to appear for every country. News events are purely a reskin of country events and are not set to fire for every country by default, so this line is mandatory. Alongside that, events that fire only once don't appear more than once ''globally'' rather than per country. The event appearing for more than one country counts as it firing once again, so setting an event to fire only once will lead to only one country getting the news event instead of every one as intended. | ||
{{VisibleCollapse| | {{VisibleCollapse| | ||
<pre>news_event = { | <pre>news_event = { | ||
第290行: | 第290行: | ||
|Collapsed example events with this issue}} | |Collapsed example events with this issue}} | ||
=== Unintuitive logged errors === | ===Unintuitive logged errors === | ||
* '''Event is triggered only, but does not have a 1 base-factor.''' – This occurs when there are contradictory arguments within an event about whether it's allowed to be fired automatically or if it can only be fired manually. In particular, {{nowrap|1=<code>mean_time_to_happen = { ... }</code>}} only has an effect when the event can only be fired automatically. However, if the event is triggered only, it cannot be fired automatically, resulting in the error being created. | *'''Event is triggered only, but does not have a 1 base-factor.''' – This occurs when there are contradictory arguments within an event about whether it's allowed to be fired automatically or if it can only be fired manually. In particular, {{nowrap|1=<code>mean_time_to_happen = { ... }</code>}} only has an effect when the event can only be fired automatically. However, if the event is triggered only, it cannot be fired automatically, resulting in the error being created. | ||
{{VisibleCollapse| | {{VisibleCollapse| | ||
<pre>country_event = { | <pre>country_event = { | ||
第304行: | 第304行: | ||
|Collapsed example event with this issue}} | |Collapsed example event with this issue}} | ||
* '''Event is set to trigger every day.''' – This occurs when all of the following is true for the event: | * '''Event is set to trigger every day.''' – This occurs when all of the following is true for the event: | ||
** The event is possible to be fired automatically. In other words, <code>is_triggered_only = yes</code> is '''not''' present in the event. | **The event is possible to be fired automatically. In other words, <code>is_triggered_only = yes</code> is '''not''' present in the event. | ||
** The event has a mean time to happen of 1 or less days. If it is omitted, it counts as 1 day. | **The event has a mean time to happen of 1 or less days. If it is omitted, it counts as 1 day. | ||
** The event can fire more than once. In other words, <code>fire_only_once = yes</code> is '''not''' present in the event. | **The event can fire more than once. In other words, <code>fire_only_once = yes</code> is '''not''' present in the event. | ||
: This error warns the player that the event may fire every day once the 20-day period passes. In order to remove the error, either of the three necessary clauses can be made to be not true for the event. For example, in a lot of cases, it is possible to make the event not be fired automatically and use an effect block to fire it instead, [[on actions|such as by using on actions]]. | :This error warns the player that the event may fire every day once the 20-day period passes. In order to remove the error, either of the three necessary clauses can be made to be not true for the event. For example, in a lot of cases, it is possible to make the event not be fired automatically and use an effect block to fire it instead, [[on actions|such as by using on actions]]. | ||
{{VisibleCollapse| | {{VisibleCollapse| | ||
<pre>country_event = { | <pre>country_event = { | ||
第324行: | 第324行: | ||
}</pre> | }</pre> | ||
|Collapsed example event with this issue}} | |Collapsed example event with this issue}} | ||
* '''Malformed token: event_id.123, near line''' on a line specifying the event ID – This occurs if [[#ID rules|the event namespace was not added as needed]]. | *'''Malformed token: event_id.123, near line''' on a line specifying the event ID – This occurs if [[#ID rules|the event namespace was not added as needed]]. | ||
* '''Failed to create id 12300000 50. Already exists in game. This might crash the game. Reverse id lookup: id 12300000 = my_namespace.0''' – Note that this is the exact same error split into two instead of being two separate errors as it might seem on the first glance. This means that the internal event ID is used by 2 or more events. There are the following reasons for this error to appear: | *'''Failed to create id 12300000 50. Already exists in game. This might crash the game. Reverse id lookup: id 12300000 = my_namespace.0''' – Note that this is the exact same error split into two instead of being two separate errors as it might seem on the first glance. This means that the internal event ID is used by 2 or more events. There are the following reasons for this error to appear: | ||
** Putting 2 events with the exact same ID by error – <code>id = my_namespace.0</code> is included in two events at once. This is self-explanatory. | **Putting 2 events with the exact same ID by error – <code>id = my_namespace.0</code> is included in two events at once. This is self-explanatory. | ||
** Using non-integers as the numeric ID after the namespace – One event has <code>id = my_namespace.abc</code>, the other has <code>id = my_namespace.cba</code>. [[#ID rules|Due to how the game generates internal IDs]], a non-numeric ID is not supported, always becoming the number 0. As such, these are the exact same ID, even if they appear different. | ** Using non-integers as the numeric ID after the namespace – One event has <code>id = my_namespace.abc</code>, the other has <code>id = my_namespace.cba</code>. [[#ID rules|Due to how the game generates internal IDs]], a non-numeric ID is not supported, always becoming the number 0. As such, these are the exact same ID, even if they appear different. | ||
** Using a numeric ID not smaller than 100000 – Two events across different namespaces got assigned the same internal IDs. By the virtue of how the game generates internal IDs, each namespace is assigned 100000 numeric IDs, from 0 to 99999. Anything larger than that will start encroaching to other namespaces' IDs. The game fully allows numbers this large as the numeric IDs, so the event might work, but the duplicate internal ID means that there is a pair of events that are treated as the same event, meaning one of them will fire the other one instead. | **Using a numeric ID not smaller than 100000 – Two events across different namespaces got assigned the same internal IDs. By the virtue of how the game generates internal IDs, each namespace is assigned 100000 numeric IDs, from 0 to 99999. Anything larger than that will start encroaching to other namespaces' IDs. The game fully allows numbers this large as the numeric IDs, so the event might work, but the duplicate internal ID means that there is a pair of events that are treated as the same event, meaning one of them will fire the other one instead. | ||
: Since the reverse id lookup is not always provided, the way to tell if this is event-related is the second number: <code>50</code> signifies that it's event-related, while a different number means a different database entry, e.g. <code>54</code> means country leader IDs and <code>55</code> means unit leader IDs, the numeric legacy IDs which are unneeded due to the [[Character modding|1.11-introduced character system]] | :Since the reverse id lookup is not always provided, the way to tell if this is event-related is the second number: <code>50</code> signifies that it's event-related, while a different number means a different database entry, e.g. <code>54</code> means country leader IDs and <code>55</code> means unit leader IDs, the numeric legacy IDs which are unneeded due to the [[Character modding|1.11-introduced character system]] | ||
{{VisibleCollapse| | {{VisibleCollapse| | ||
<pre> | <pre> | ||
第357行: | 第357行: | ||
|Collapsed example event file with this issue}} | |Collapsed example event file with this issue}} | ||
== | ==成品案例 == | ||
<pre>add_namespace = my_event | <pre>add_namespace = my_event | ||
add_namespace = my_hidden_event | add_namespace = my_hidden_event | ||
第485行: | 第485行: | ||
} | } | ||
}</pre> | }</pre> | ||
=== Integration with on actions === | ===Integration with on actions=== | ||
{{See also|On actions}} | {{See also|On actions}} | ||
These events are the primary types to trigger via on_actions: | These events are the primary types to trigger via on_actions: | ||
第626行: | 第626行: | ||
} | } | ||
}</pre> | }</pre> | ||
== | ==参考资料 == | ||
<references/> | <references /> | ||
Note that when editing defines, it is far preferable to use an [[Defines#Overrides|override file]] than copying over the entire file, as defines are edited commonly even in 'minor' updates, which can cause crashes when the game updates. | Note that when editing defines, it is far preferable to use an [[Defines#Overrides|override file]] than copying over the entire file, as defines are edited commonly even in 'minor' updates, which can cause crashes when the game updates. | ||
{{Modding navbox}} | {{Modding navbox}} | ||
[[分类:Modding]] | [[分类:Modding]] |
2023年8月4日 (五) 22:41的版本
事件定义于/Hearts of Iron IV/events/文件夹中。事件分为以下5类:
country_event
、news_event
、state_event
、unit_leader_event
和operative_leader_event
。
事件外观和目标因类别而异。
不论何种事件,ROOT作用域总是国家。但是THIS作用域不是,在state_event
、unit_leader_event
和operative_leader_event
三类事件中,作用域还包含事件类型对应作用域,自动分类接受适用于对应作用域的效果。为防部分效果作用域重合(例:add_manpower
同时对地区和国家生效),建议编写效果时指定国家。
出于同样的原因,建议少写state_event
,因为其与country_event
相像。(Event targets can be used within country events aimed to a specific state instead), however unit leader and operative leader events can be unavoidable due to their distinct appearance.事件虽然分类,其编写时几乎没有区别, with the exception of appearance, default scopes, and the fact that news event can have their pop-up disabled (However, the country will still get them). If the player country gets an event and doesn't pick a choice, the first option will get assumed by default.
When fired using an effect, the game ports over the regular event targets existing in the previous effect block to the event, as well as the ROOT scope of the block, which becomes FROM within the event. The previous effect block's FROM scopes get shifted one level down, with the effect block's FROM becoming FROM.FROM, previous FROM.FROM becoming FROM.FROM.FROM, and et cetera. Due to this, FROM is commonly called the 'sender' of the event in jargon, making FROM.FROM the sender to the sender. Although this does not always apply, as FROM.FROM can be something else entirely, e.g. an additional scope within on actions or the target of a decision. Importantly, it's what the FROM block of the effect block that fired it is, which depends on where it's fired exactly.
This does not happen if the event gets fired using an on action's random_events block: the same scoping rules as in the regular on action apply.
请注意:因不拥有任何土地等原因而不存在的国家无法看到事件,即使是指令触发的或指定了major = yes
的也如此。这些国家出现后上述事件会一并触发。
创建一个事件
每个事件都包含于一个对应事件类型的代码块,如 country_event
或 news_event
。每个事件的id
是必填项,例如 id = my_event.123
。
ID编号规则
事件ID应符合以下编号规则: <命名空间>.<编号>
。例如,事件 my_event.123
的命名空间是“my_event”、ID是“123”。编号应为整数,原因见下文。
定义用到某命名空间的事件前应先定义此命名空间。要定义命名空间,请在事件内容外使用 add_namespace
语句,例: add_namespace = my_event
。如不定义命名空间,游戏将视此事件ID生成有误、不生效,所谓malformed token。命名空间命名可包含字符、下划线和点(是的 my_event.subtopic
也是合法的命名空间名,只要事件id写成 id = my_event.subtopic.1
这样就行)。
在游戏内部,事件ID还将被转换为内部ID,转换方法为:按命名空间所在文件的ASCII可显示字符顺序和命名空间在文件中的位置先后给各命名空间分配命名空间ID,第一个命名空间ID为10,第二个为11,以此类推,分配好后各命名空间ID乘以100000加上各事件ID中的编号。值得注意的是,游戏视事件ID最后一个点后的字符串为其编号,并将其转换为整数,如编号转换失败则默认记为0,这意味着同一命名空间下所有非整数编号事件会被游戏视为同一事件,因此事件编号必须为整数。
本地化
title
和 desc
行用于指定事件的 本地化条目 的名称、并按玩家的游戏语言显示其游戏内标题和描述,例: title = my_event.123.t
、 desc = my_event_description
。每个事件都应该有标题和描述,除非它是隐藏事件。
本地化条目定义于 /Hearts of Iron IV/localisation/<语言>/ 文件夹中。我们强烈建议开展本地化工作时创建一个全新的文件而非随便复制粘贴一个游戏本体文件过来清空内容重写以防游戏本体版本更新后兼容性不良。游戏要求本地化文件使用带BOM的UTF-8编码。要使游戏能正确加载本地化文件,本地化文件的文件名应以 _l_<语言>.yml
结尾(下划线后面的字符是小写L,不是大写i)。文件第一行应先写 l_<语言>:
。本地化内容格式如下所示:
my_event.123.t: "My event title" my_event_description: "My event description"
写好几个标题让游戏按实际状况选择事件标题和描述是可行的,游戏会选择满足要求的本地化条目,如有多个则选择第一个。比如:
title = { text = my_event.123.t.a trigger = { tag = ENG } } title = { text = my_event.123.t.b }
此例中如弹出事件的国家的tag为ENG,游戏将选取本地化条目 my_event.123.t.a 指定的内容作为事件的标题,否则选取本地化条目 my_event.123.t.b 指定的内容作为事件的标题。 trigger
用于填写触发器 ,默认要求其中所有条件都为真。
描述和标题格式一样, title
换成 desc
就行。
事件配图
要给事件配图,请加 picture
代码块。参数填指向图片的sprite名,例: picture = GFX_my_sprite
.
sprite定义于 /Hearts of Iron IV/interface 文件夹中所有文件后缀为.gfx的文件,默认为eventpictures.gfx。这些文件用普通文件编辑器是打得开的。和本地化文件一样,也建议用新文件写这些sprite相关内容。要定义sprite,请使用 spriteTypes
代码块,例:
spriteType = { name = "GFX_my_sprite" texturefile = "gfx/event_pictures/my_event_picture.dds" }
创建此sprite后 <你正在做的mod文件夹>/gfx/event_pictures/my_event_picture.dds 即可以 picture = GFX_my_sprite
的身份出现在事件中。
触发器
要控制何时触发事件,请使用 trigger
代码块。满足所有条件才能触发事件。例:
trigger = { tag = GER has_political_power > 100 }
请注意:如不注明is_triggered_only = yes
游戏将每20天检查一次是否符合触发条件[1]。如用控制台指令强行调出事件( 此处使用指令应为event my_event.123
),控制台会显示事件强行触发时已满足和未满足的条件。
mean_time_to_happen
可用于让事件在指定的时间前后随机触发。用days
、months
和years
来表示事件从符合触发条件到触发所需的大概用时,其中months
按30天计,years
按365天计。此外还可以用 modifier
来对上述时间做运算,其中add
增加时间、factor
乘以系数、base
直接改变计算基数。例子如下:
mean_time_to_happen = { days = 10 years = 1 modifier = { factor = 0.2 #对tag为POL的国家,触发时间乘20%。 tag = POL } }
一旦事件符合通过上述20天检查,游戏就将每天判定是否要触发此事件。
值得注意的是,使用此功能会使事件的触发服从失败率为[math]\displaystyle{ 2^{-\frac{1}{指定的触发天数}} }[/math]的几何分布。考虑到其数学期望为[math]\displaystyle{ frac{2^{\frac{1}{指定的触发天数}}}{2^{\frac{1}{指定的触发天数}}-1} }[/math]而非指定天数,此功能与设置的不是每天判定开始到触发用时的算术平均——对每天概率加和就会发现其实是中位数。
由于每天判定时也同时判断事件是否仍符合触发条件,建议各位用户在自定义事件时限制此类事件数量以防性能不良。
出于同样的原因也建议:如无必要,可用is_triggered_only = yes
关闭事件自动触发。做此设置可保证事件不能自动触发,而只能为国策效果或其他事件等指令触发,尤以国家事件、新闻等为甚,因事件类型而异。这对事件链编写很重要。如不做或忽略此设置,即使不定义触发条件事件也会自动触发。
It is to be noted that trigger
is not entirely useless in this case: it will be evaluated when the event is intended to fire, preventing it from firing if not met, which can be useful if the event is set to fire with a delay or for the random_events section in on actions. For optimisation reasons, it is preferable to make the event be triggered only if possible: on actions can commonly be used to fire the event, such as on_startup serving as a way to fire an event on a specific day, by defining a delay in days from the start date of the game.
如果希望待设计的事件整场游戏只触发一次,请使用fire_only_once = yes
,这将防止事件以控制台以外的任何方式被再度触发,不论是效果、mean_time_to_happen
还是别的什么机制。 如上所述,如此设置后待设计的事件整场游戏只触发一次,如果一个国家触发了此事件,其他国家就不能再次触发了,除非上控制台。
如需像新闻一样让所有国家都能看到此事件,请用major = yes
。请注意此代码不能和fire_only_once = yes
并用,后者指的是总触发次数只有1次而非每个国家1次,并用将导致此事件只能在触发此事件的国家触发。This will bypass the trigger = { ... }
block for the countries that did not have this event fired originally, instead relying on the show_major = { ... }
trigger block, if one is present. Additionally, fire_for_sender = no
, if added, will prevent the major event from appearing for the country that it originally got fired for, via an effect or by the trigger being met.
选项
An event option is added with an option = { ... }
block. An event option is an effect block, with a few extra options:
name
decides the localisation key used for the event, such as name = my_option_name
. It is not possible to make the option name depend on the triggers in the same way it's possible for event titles, instead, completely different event options can be used, disabling each one with a name that shouldn't be used.
trigger = { ... }
is a trigger block, deciding when the option is visible to be picked. If the trigger is false at the time of being fired, it will not appear until the event is fired again. Additionally, for major events, original_recipient_only = yes
can be used to ensure that only the country that fired the event has this option available, with others not having it.
ai_chance = { ... }
is a block deciding the AI chance for event options: deciding in a proportional way which option to pick. The AI chance in event options do not have to add up to 100, as it is proportional. It is structured in a near-identical way to the mean time to happen. If unset, assumed to be 1. The probability of each option is its weight divided by the sum of all option weights. If all options have a weight of zero, the first one is chosen. The randomized choice is made by rolling a d100, so options can't have an effective non-zero probability below 1%. The choice remains consistent across reloads, based on unique game seed, in-game time, country, and unit leader.
其他可指定参数
immediate = { ... }
is an effect block, executed as soon as the event is fired, before an option is chosen by the player. This can also be used for AI: AI only picks an option after the event triggers are evaluated for every other country, while immediate is executed immediately, before evaluating other events. This can be used in mean-time-to-happen type major events: by making the immediate set a global flag, which is required to be unset in the event trigger, this will prevent it from being fired more than once for each country, but it is preferable to avoid mean-time-to-happen events in entirety. Note that the effect will appear in the tooltip after the event's description, so the hidden_effect flow tool can be helpful.
timeout_days = 20
sets the amount of days that the player has to pick an option before the first option is automatically selected. This can be used to make the event be more or less urgent than default. If unset, assumes to be 13 days[2].
hidden = yes
will make an event hidden. A hidden event does not need a title or a description. The first defined option, if one is present, will be automatically picked upon being fired. Hidden events can be useful instead of scripted effects to delay the execution of an effect block by a period of time or to utilise the FROM scope.
minor_flavor = yes
marks the event as being a minor flavour event. This does not change its appearance or change its effects, but allows turning off the pop-up within the game's decision menu.
事件效果
Any effect block can be used to fire an event, such as focus rewards, event options, or decision effects. This is usually paired with is_triggered_only = yes
within the event as to disable automatic firing.
In its simplest way, this is done with the effect of country_event = my_event.1
(or news_event = my_event.1
), which'll instantly fire the event for the scoped country. As country and news events are the exact same thing under the surface, both shortened effects can be used for either country and news events, with there being no difference between them whatsoever.
However, more options can be added primarily for setting up the delay. Additionally, expanded versions are mandatory for state and operative leader events.
A more complex effect to fire is country_event = { id = my_event.1 days = 100 random_days = 123 }
. This'll fire the event in 100 to 223 ([math]\displaystyle{ 100 + 123 }[/math]) days. There are the following arguments that can go into the effect (All of them are optional with one exception):
id = my_event.1
— The ID of the event to fire. This is mandatory as to let the game know which event to fire.hours = 1
|days = 2
|months = 3
— The lower bound on the needed time that the event will fire in. In this case, a month is treated as exactly 30 days. If multiple of these are used, the game will add them up together (e.g. the example with 1 hour, 2 days, and 3 months will fire in 92 days and 1 hour).random_hours = 1
|random_days = 2
— This sets the upper bound on the needed time that the event will fire in. The game selects a random amount (uniform distribution) of days and hours between 0 and the set amount, including both ends, and adds them to the delay to fire the event. Similarly to above, if both are specified, the game will add them together.random = 123
also serves as an equivalent forrandom_hours = 123
.tooltip = my_event.1.t
— This decides what the name of the event that would fire would be displayed as in localisation. Defaults to the event's name, this may be useful if the title may change between the effect to fire it and its actual appearance.
Example effect using several of these parameters:
country_event = { id = my_event.1 hours = 12 random_hours = 6 days = 2 tooltip = another_event.1.t }
The optional delay is incredibly useful, as hidden events can be used to create a delay between an effect block's execution and the actual application of effects without the player detecting anything. This can also be used to make the events appear more "natural": news events can have a delay of a few hours (typically around 6-12) in order to simulate the time it takes for the news agencies to report on the event. Similarly can be done with other event types to simulate waiting a few hours for a diplomatic response, rather than it being unnaturally instant.
trigger = { ... }
of the event gets checked when it would fire, meaning that it's also possible to fire the event on startup of the game with a needed delay to get it on a specific day, then use the event's trigger to simulate additional requirements.
Additionally, there are these event type-specific arguments:
trigger_for = TAG
(Unique to state events) — The country for which the event will fire for. This is mandatory as state events are to be fired in state scope. This can also be replaced withcontroller
,owner
,occupied
, or a dual scope that can be used as a target, such as ROOT or FROM.originator = TAG
(Unique to operative leader events) — The country which serves as the originator of the event (i.e. FROM). Defaults to the operative's owner if unset.recipient = TAG
(Unique to operative leader events) — The country which would receive the event. Defaults to the operative's owner if unset.set_root = TAG
(Unique to operative leader events) — Changes the scope of ROOT within the dynamic localisation of the event, without actually changing it in code.set_from = TAG
(Unique to operative leader events) — Changes the scope of FROM within the dynamic localisation of the event, without actually changing it in code.set_from_from = TAG
(Unique to operative leader events) — Changes the scope of FROM.FROM within the dynamic localisation of the event, without actually changing it in code.
实践易错点
Some errors are quite common to make when beginning to make events, whether it's poor practice or if it would prevent the event from working in entirely. Some of them may be hard to notice when modding, with the event seemingly working fine, such as the error that prevents news events from being fired for more than one country.
This covers some of them, as well as the less intuitive errors in the log.
Unlogged errors
- Leaving an event as triggered only when it's to be fired automatically (Event never fires) –
is_triggered_only = yes
disables the automatic firing of the event, instead enforcing using the effect to do so. Therefore, if it is left in within an event intended to fire automatically, the event will never do so.
- Note that
trigger = { ... }
can still co-exist withis_triggered_only = yes
, so an event with bothis_triggered_only = yes
andtrigger = { ... }
may still be correct. Valid usages of them at the same time include the event being triggered via an on action'srandom_events
or the effect firing it has a delay (where the trigger would check if when the event is to be received), along others.
Collapsed example event with this issue and a correction to it |
---|
Broken: country_event = { id = my_event.1 title = my_event.1.t desc = my_event.1.desc trigger = { tag = GHA has_stability > 0.9 } fire_only_once = yes is_triggered_only = yes # Will make the event never automatically trigger. option = { name = my_event.1.a add_war_support = 0.2 } } Corrected: country_event = { id = my_event.1 title = my_event.1.t desc = my_event.1.desc trigger = { tag = GHA has_stability > 0.9 } fire_only_once = yes option = { name = my_event.1.a add_war_support = 0.2 } } |
- Not checking the country in the trigger for country-specific auto-triggered events (Event fires for the wrong country/never fires) – The events are not assigned to countries in any way (namespaces and filenames serve a purely organisational purpose), and each event trigger is checked for each country in order specified in the tag list.
- In the provided example, the event requires ITA to have more than 123 political power, upon which the country receiving the event would annex AUS. However, once ITA has that much, this trigger would be true regardless of where it's checked. The first country in the taglist by default is GER, and so it'll be the first country where the triggers are checked. In practice, this event will result in GER annexing AUS rather than ITA.
- In the correction, a change is made: first it checks that the country that would receive the event is ITA, and only then then it checks that it has more than enough political power. This makes sure that no other countries can receive this event. Specifying the tag is unnecessary if the trigger itself already implies a certain tag (e.g.
has_completed_focus
with a tag-specific focus tree), but is needed otherwise.
Collapsed example event with this issue and a correction to it |
---|
country_event = { id = my_event.1 # Broken event title = my_event.1.t desc = my_event.1.desc trigger = { ITA = { has_political_power > 123 } # Either true within every country's scope or for none } # First fires for GER, since it's true in GER's scope and GER is the first country. fire_only_once = yes option = { name = my_event.1.a annex_country = { target = AUS } # Results in GER annexing AUS instead of ITA as intended. } } country_event = { id = my_event.2 # Fixed version title = my_event.2.t desc = my_event.2.desc trigger = { tag = ITA # Checks that the country is ITA has_political_power > 123 # Checks current political power of ITA (as any other country is disqualified by the previous trigger) } fire_only_once = yes option = { name = my_event.2.a annex_country = { target = AUS } } } |
- Unnecessarily using auto-triggered events instead of ones that are triggered only (Poor practice/optimisation) – This is more of a poor practice than an error. In general, if an event's condition can be triggered with an effect, it should be.
- The example is the most obvious way of doing this: a has_completed_focus check instead of firing it directly in the focus. However, other such cases can occur, e.g. when a war starts between two countries, when a state gets occupied, or for firing one on a specific date. It's best practice to check on actions before creating an automatically-triggered event to see if they can be made to replicate.
- Firing it via an effect has a purpose of being instant instead of having to wait up to 20 days. If so desired, a delay of a few hours can be added to make it appear more natural to the player. Additionally, it serves as a way to optimise the modification, as this reduces the amount of trigger checks repeatedly done. Events with a large mean-time-to-happen are particularly awful for performance and can be replaced with an effect block firing one with a large delay created with random_days within the effect in some cases.
Collapsed example event with this issue and a correction to it |
---|
Broken event: country_event = { id = my_event.1 title = my_event.1.t desc = my_event.1.desc trigger = { has_completed_focus = TAG_focus_name } fire_only_once = yes option = { name = my_event.1.a } } Corrected event and focus: country_event = { id = my_event.1 title = my_event.1.t desc = my_event.1.desc is_triggered_only = yes option = { name = my_event.1.a } } focus = { id = TAG_focus_name x = 5 y = 0 icon = GFX_focus_icon_name cost = 8 search_filters = { FOCUS_FILTER_POLITICAL } completion_reward = { country_event = { id = my_event.1 hours = 6 random_hours = 3 } # Fires the event in 6-9 hours. } } |
- Setting a news event to fire only once or not setting one as major (News event only fires for one country) – An event requires
major = yes
in order to appear for every country. News events are purely a reskin of country events and are not set to fire for every country by default, so this line is mandatory. Alongside that, events that fire only once don't appear more than once globally rather than per country. The event appearing for more than one country counts as it firing once again, so setting an event to fire only once will lead to only one country getting the news event instead of every one as intended.
Collapsed example events with this issue |
---|
news_event = { id = my_event.1 title = my_event.1.t desc = my_event.1.desc is_triggered_only = yes # Missing 'major = yes', only will fire for one country. option = { name = my_event.1.a } } news_event = { id = my_event.2 title = my_event.2.t desc = my_event.2.desc is_triggered_only = yes major = yes fire_only_once = yes # Fires only once, only will file for one country. Remove this line to fix. option = { name = my_event.2.a } } |
Unintuitive logged errors
- Event is triggered only, but does not have a 1 base-factor. – This occurs when there are contradictory arguments within an event about whether it's allowed to be fired automatically or if it can only be fired manually. In particular,
mean_time_to_happen = { ... }
only has an effect when the event can only be fired automatically. However, if the event is triggered only, it cannot be fired automatically, resulting in the error being created.
Collapsed example event with this issue |
---|
country_event = { id = my_event.1 hidden = yes is_triggered_only = yes mean_time_to_happen = { days = 1 } } |
- Event is set to trigger every day. – This occurs when all of the following is true for the event:
- The event is possible to be fired automatically. In other words,
is_triggered_only = yes
is not present in the event. - The event has a mean time to happen of 1 or less days. If it is omitted, it counts as 1 day.
- The event can fire more than once. In other words,
fire_only_once = yes
is not present in the event.
- The event is possible to be fired automatically. In other words,
- This error warns the player that the event may fire every day once the 20-day period passes. In order to remove the error, either of the three necessary clauses can be made to be not true for the event. For example, in a lot of cases, it is possible to make the event not be fired automatically and use an effect block to fire it instead, such as by using on actions.
Collapsed example event with this issue |
---|
country_event = { id = my_event.1 hidden = yes is_triggered_only = no # Changing to yes will fix the error fire_only_once = no # Changing to yes will fix the error trigger = { tag = BHR controls_state = 123 } mean_time_to_happen = { days = 1 # Changing to 2 or more will fix the error } } |
- Malformed token: event_id.123, near line on a line specifying the event ID – This occurs if the event namespace was not added as needed.
- Failed to create id 12300000 50. Already exists in game. This might crash the game. Reverse id lookup: id 12300000 = my_namespace.0 – Note that this is the exact same error split into two instead of being two separate errors as it might seem on the first glance. This means that the internal event ID is used by 2 or more events. There are the following reasons for this error to appear:
- Putting 2 events with the exact same ID by error –
id = my_namespace.0
is included in two events at once. This is self-explanatory. - Using non-integers as the numeric ID after the namespace – One event has
id = my_namespace.abc
, the other hasid = my_namespace.cba
. Due to how the game generates internal IDs, a non-numeric ID is not supported, always becoming the number 0. As such, these are the exact same ID, even if they appear different. - Using a numeric ID not smaller than 100000 – Two events across different namespaces got assigned the same internal IDs. By the virtue of how the game generates internal IDs, each namespace is assigned 100000 numeric IDs, from 0 to 99999. Anything larger than that will start encroaching to other namespaces' IDs. The game fully allows numbers this large as the numeric IDs, so the event might work, but the duplicate internal ID means that there is a pair of events that are treated as the same event, meaning one of them will fire the other one instead.
- Putting 2 events with the exact same ID by error –
- Since the reverse id lookup is not always provided, the way to tell if this is event-related is the second number:
50
signifies that it's event-related, while a different number means a different database entry, e.g.54
means country leader IDs and55
means unit leader IDs, the numeric legacy IDs which are unneeded due to the 1.11-introduced character system
Collapsed example event file with this issue |
---|
add_namespace = prev_event add_namespace = my_event # Let this namespace have an ID of 321 in calculations, meaning the previous one has an ID of 320. country_event = { id = my_event.1 hidden = yes } country_event = { id = my_event.1 # Creates "Failed to create id 32100001 50. Reverse id lookup: id 32100001 = my_event.1" hidden = yes } country_event = { id = my_event.abc hidden = yes } country_event = { id = my_event.letters # Creates "Failed to create id 32100000 50. Reverse id lookup: id 32100000 = my_event.abc" hidden = yes } country_event = { id = prev_event.100001 # Creates "Failed to create id 32100001 50. Reverse id lookup: id 32100001 = my_event.1" hidden = yes } |
成品案例
add_namespace = my_event add_namespace = my_hidden_event country_event = { id = my_event.1 title = my_event.1.t desc = my_event.1.desc is_triggered_only = yes option = { name = my_event.1.a add_political_power = 100 } } add_namespace = my_news_event news_event = { id = my_news_event.1 title = { text = my_news_event.1.t.a trigger = { tag = POL } } title = { text = my_event.1.t } desc = { text = my_news_event.1.desc.a trigger = { tag = POL } } desc = { text = my_event.1.desc } picture = GFX_my_news_event_picture is_triggered_only = yes major = yes option = { name = my_news_event.1.a trigger = { tag = POL } } option = { name = my_news_event.1.b trigger = { NOT = { tag = POL } } } option = { name = my_news_event.1.c original_recipient_only = yes } } country_event = { id = my_hidden_event.1 trigger = { has_country_flag = event_happened country_exists = BHR } mean_time_to_happen = { days = 10 months = 2 years = 1 modifier = { base = 300 country_exists = QAT } modifier = { add = 10 country_exists = OMA } } fire_only_once = yes hidden = yes immediate = { random_country = { limit = { is_neighbor_of = BHR } annex_country = { target = BHR transfer_troops = yes } } } } state_event = { id = my_event.2 title = my_event.2.t desc = my_event.2.desc picture = GFX_my_event_picture trigger = { ROOT = { has_country_flag = fire_this_event } } is_triggered_only = yes option = { name = my_event.2.a transfer_state_to = ROOT } option = { name = my_event.2.b ai_chance = { base = 0 # Never pick this option. } transfer_state_to = FROM } }
Integration with on actions
- 参见:On actions
These events are the primary types to trigger via on_actions:
add_namespace = on_action_events news_event = { # City capture news event id = on_action_events.1 title = on_action_events.1.t # Fall of Giza desc = on_action_events.1.desc is_triggered_only = yes major = yes option = { trigger = { OR = { tag = EGY is_in_faction_with = EGY is_subject_of = EGY } } name = on_action_events.1.a } option = { trigger = { NOT = { tag = EGY is_in_faction_with = EGY is_subject_of = EGY } } name = on_action_events.1.b } } country_event = { # Fired on a specific day if circumstances are met id = on_action_events.2 title = on_action_events.2.t desc = on_action_events.2.desc is_triggered_only = yes # Prevents from firing automatically. trigger = { has_completed_focus = BHR_focus_name # If the focus isn't completed, will never fire. } option = { name = on_action_events.2 } } country_event = { # Other types of on_actions id = on_action_events.3 # In this case, a prompt on annexing a country with an option to release it. title = on_action_events.3.t desc = on_action_events.3.desc is_triggered_only = yes # Prevents from firing automatically. trigger = { # If all core states of FROM are cored or claimed by ROOT, should never appear. NOT = { # Triggered within on_annex's random_events = { ... }, so has the same FROM as the on_action any_state = { NOT = { is_core_of = ROOT is_claimed_by = ROOT } is_core_of = FROM } } FROM = { NOT = { tag = GER # Has separate event } } } option = { name = on_action_events.3.a # "Release [FROM.GetName] as puppet" every_owned_state = { limit = { is_core_of = FROM NOT = { is_core_of = ROOT is_claimed_by = ROOT } } transfer_state_to = FROM } if = { limit = { has_dlc = "Together for Victory" } set_autonomy = { target = FROM autonomy_state = autonomy_integrated_puppet } } else = { puppet = FROM } } option = { name = on_action_events.3.b # "Don't release [FROM.GetName]" add_stability = -0.1 add_war_support = -0.1 } }
In order to fire this, code has to be created within any /Hearts of Iron IV/common/on_actions/*.txt file, sometimes paired with boolean flags to prevent them from being fired more than once if fire_only_once is impossible. In the above example, this would be used:
on_actions = { on_state_control_changed = { effect = { if = { limit = { FROM.FROM = { state = 999 # Custom state ID. Will crash the game if doesn't exist. } NOT = { has_global_flag = giza_fall # To prevent from firing twice. } # Due to 'major = yes', a fire_only_once will NOT work } news_event = { id = on_action_events.1 hours = 6 random_hours = 3 } # Fires in 6-9 hours to feel more natural. } } } on_startup = { effect = { BHR = { country_event = { id = on_action_events.2 days = 357 random_days = 7 # Fires in the last week of 1936, assuming default start date. } } } } on_annex = { random_events = { 1 = on_action_events.3 } } }
参考资料
Note that when editing defines, it is far preferable to use an override file than copying over the entire file, as defines are edited commonly even in 'minor' updates, which can cause crashes when the game updates.
文件 | 效果 • 条件 • 定义 • 修正 • 修正列表 • 作用域 • 本地化 • on action • 数据结构 (标记, 临时标记, 国家别名, 变量, 数组) |
脚本 | 成就修改 • AI修改 • AI focuses • 自治领修改 • 权力平衡修改 • 剧本/标签 (游戏规则)• 建筑修改 • 人物修改 • 修饰性TAG修改 • 国家创建 • 军队修改 • 决议制作 • 装备修改 • 事件修改 • Idea修改 • 意识形态修改 • 军工商修改 • 国策制作 • 资源修改 • Scripted GUI • 科技制作 • 单位修改 |
地图 | 地图 • 省份 • 补给区域 • 战略区域 |
图形图像 | 界面 • 图形资产 • 实体模型 • 后期特效 • 离子效果 • 字体 |
装饰性 | 肖像 • 命名列表 • 音乐 • 音效 |
其他 | 控制台指令 • 故障排除 • 模组结构 • 成就代码分析 • Mod相关 • Nudger修改 |