钢铁雄心 IV 中文离线资料库

Balance of power模组制作

原页面:Balance of power modding

本页中文翻译进度 54%,未译部分暂保留英文原文。

A balance of power (also internally referred to as bop or power balance) is typically used to represent a conflict between two sides, using a progress bar divided into distinct sections and decisions to push it towards some side for benefits. These are defined in /Hearts of Iron IV/common/bop/*.txt files.

Each balance of power consists of 2 or more sides. While a balance of power can contain more than 2 sides, at any time the player may only see 2 which are chosen in the effect to initialise the balance of power.
To track the current balance, a single value is used, which can range from -1 to 1 with up to 3 decimal points. The : [-1; 0) range is used for the left side, : [0; 1] is used for the right side. A side having power only has a cosmetic impact, changing the icon and the text used in scripted localisation. A side isn't inherently set as being left or right, instead it is assigned which side is on which half when the power balance is initialised.

Depending on the value, the country is placed in some range representing the exact degree of power on a certain side. This is usually used to grant certain 修正 or to execute an effect upon entering it. Most ranges are placed inside of sides, making it only possible to enter when that side is active. A range may also not be assigned to any side and be always visible, usually used for a single "balanced" range in the middle.
A range being assigned to a side only means that it'll be visible when the range is active, and a side may have ranges on both halves of the balance at the same time. Entering a range defined on a certain side does not necessitate that the balance is tipped in favour of that side. For example, if a side is set as a left side and yet it includes a range of : [0.1, 0.3) , then if the value is at 0.2, then the balance will be tipped towards the right side visually, but it will still be inside of that range.

A balance of power is tracked globally. If 2 countries are assigned the same BoP, then the value of the balance will always be exactly the same between both countries. If both of these countries have modifiers pushing the BoP to some side daily or weekly, the effects of these modifiers will stack.

代码结构

Balances of power are created in any /Hearts of Iron IV/common/bop/*.txt file. A BoP is defined as a root-level block, where the name of the block determines the unique ID of the BoP. In case of duplicates, the error.log entry Template ID duplicate: bop_name is generated and the game will prioritise the one that was created later, determined using the filename and order in files.
There are no strictly mandatory arguments, however it is preferred to have at least 2 sides as the UI is built on the assumption that there is always a left and a right side active. In particular, these arguments exist:

  • intial_value = -0.1 is the default value of the BoP. If unset, defaults to 0.
  • left_side = side_id is the default left side of the BoP.
  • right_side = side_id is the default right side of the BoP.

The default values are used when the BoP is first initialised with set_power_balance (unless overwritten by its arguments) or when that same effect includes set_default = yes to reset it.

  • decision_category = TAG_example_category will move that 决议 category to the balance of power view. In particular, this ensures that it's impossible to access the decision category in any way other than by the balance of power. Any trigger blocks in the decision category, such as allowed = { ... }, are still checked for the country with the BoP, however.

In addition, side = { ... }和range = { ... } are possible with more detail.

Side

Each side is defined using a side = { ... } block in the balance of power. In particular, these arguments exist:

  • id = side_id is the identifier used for the side. There should not be overlap in the same BoP, however overlap may exist between different BoPs. In case of overlap in the same BoP, only the first-created side will be used with a Side ID duplicate: side_id entry in error.log.
  • icon = GFX_idea_unknown is the spriteType used as the image to represent the side. If undefined or if the spriteType doesn't exist, the icon will not be created with no default to replace it.
Sprite 通用概览
为了加载 GFX,游戏使用 sprite 系统。sprite 是一种代码定义,它把一个名称附加到一个图像文件上,并且可以选择性地添加额外信息,例如动画、帧数、图像的加载方式等等。这意味着 把图像放进 gfx 文件夹并不足以让它生效,一个 sprite 也必须使用该图像文件。

Sprites are defined in any /Hearts of Iron IV/interface/*.gfx file (this is separate from gfx/interface/), opened with a text editor. To create a new .gfx file, a text file can be created and renamed to change the extension (on Windows, the Windows Explorer needs to show the extensions, which it doesn't by default). In particular, sprites are defined within a spriteTypes = { ... } block, as to separate from fonts and map arrows also defined in that folder, while the simplest sprite with the least mandatory properties is a spriteType = { ... }. The simplest sprite definition looks like the following:

spriteTypes = {
    spriteType = {
        name = GFX_first_sprite                         # In some cases, beginning with GFX_ is mandatory for it to work.
        texturefile = gfx/interface/folder/filename.dds # The folder and filename don't matter, as long as they are correct
    }                                                   # Only the forward slash '/' (can be doubled as '//') can be used to separate folders.
    spriteType = {                                      # The image doesn't have to be .dds, as .tga and .png are acceptable.
        name = GFX_second_sprite
        texturefile = gfx/interface/folder2/filename2.dds
        noOfFrames = 2 # Splits the image into 2 halves, which may be switched between dynamically in GUI
    }
}

In this case, this creates a sprite with the name of GFX_first_sprite and attaches the /Hearts of Iron IV/gfx/interface/folder/filename.dds image to it, and a second sprite similarly. The second sprite will be split into 2 frames: this is decided by having the left half of the image as the first frame and the right half as the second frame (more frames would further split the image horizontally). This doesn't make the sprite animated, just turns on the option to switch between the two halves as needed. GFX_second_sprite:1 serves as a reference to the first frame, and GUI can be set up to change the shown frame depending on context, such as with radio stations.
In order to add animation, a frameAnimatedSpriteType is used.

要修改某个 sprite,从来都不是必须复制基础游戏文件。如果在不同文件中对同名 sprite 存在重复定义,游戏将优先使用稍后根据文件名求值的那个,较旧的 sprite 会被完全忽略。可以通过把替换文件名的首字符设为 ASCII 字符表中较靠后的符号来确保这一点。通常为此使用小写字母 'z'。例如,要把GFX_idea_traits_strip中的帧数改为 10,可以在模组的modname/interface/zz_replace.gfx文件中定义一个同名、含 10 帧的 sprite,而不必复制基础游戏文件。由于大多数 .gfx 文件定义了用户界面的组成部分,在游戏大版本更新时复制它们可能导致模组已加载的文件缺少 sprite,这在游戏内会显示为默认图像,即默认的错误狗。为了减轻检查界面文件的负担,最好永远不要复制 .gfx 文件,除非更多新增内容会主动损害模组,例如interface/subuniticons.gfx的情况

  • range = { ... } is a range set to exist if and only if that side is active.

Range

A range is defined as a range = { ... } block which may exist either directly in the BoP or inside of a side = { ... }. This is used to determine when the range will be visible to the player: a range directly in a BoP is always visible, while a range in a side will only be visible if that side is visible. There are 3 mandatory attributes:

  • id = range_id is used to assign an ID to the specified range. There shouldn't be duplicates across the entire BoP (even in different sides), but there may be between different BoPs. A duplicate will be marked with a Range ID duplicate: range_id entry in error.log. In this case, the game will still display each range with the same ID that is not in a disabled side. However, this can cause issues with strict non-equal comparison when using is_power_balance_in_range: in particular, the game will only recognise the range that's placed furthest to the left. For example, if there are duplicate range_id on intervals of : [-0.3, -0.1)和: [0.1, 0.3) , then a strict equilibrium will be recognised as being to the right of range_id, but not to the left of it.
  • min = -0.1 is the minimum value in the range's interval. If the value is exactly at this point, this range will be applied.
  • max = 0.1 is the maximum value in the range's interval. If the value is exactly at this point, this range will be applied if and only if max is set to 1. Otherwise, the exact point is excluded from the interval.

There are also blocks that decide which impact exactly a range has on the country when the value is inside that. In particular:

  • modifier = { ... } decides on the 修正 applying to the country when the value is in that range.
  • rule = { ... } decides on the 游戏规则 applying to the country when the value is in that range.
  • on_activate = { ... } executes 效果 the instant that the value enters this range.
  • on_deactivate = { ... } executes 效果 the instant that the value exits this range.

示例

TAG_example_balance = {
    initial_value = 0.25
    left_side = default_left_side
    right_side = default_right_side
    decision_category = TAG_example_category
    range = {
        id = mid_range
        min = -0.1
        max = 0.1
        modifier = {
            war_support_weekly = 0.5
        }
        rule = {
            can_create_faction = yes
        }
    }

    side = {
        id = default_left_side
        icon = GFX_idea_generic_agrarian_society
        range = {
            id = left_side_range
            min = -1
            max = -0.1
            modifier = {
                war_support_weekly = 0.1
            }
            on_activate = {
                random_owned_controlled_state = {
                    limit = {
                        NOT = { is_core_of = PREV }
                    }
                    add_core_of = PREV
                    set_state_flag = cored_by_bop
                }
            }
            on_deactivate = {
                random_owned_controlled_state = {
                    limit = {
                        has_state_flag = cored_by_bop
                    }
                    remove_core_of = PREV
                    clr_state_flag = cored_by_bop
                }
            }
        }
    }
    side = {
        id = default_right_side
        icon = GFX_idea_generic_degauss_ship_hulls
        range = {
            id = right_side_range
            min = 0.1
            max = 1
            modifier = {
                war_support_weekly = 0.9
            }
        }
    }
}

实现

As a balance of power isn't inherently assigned to any country, it must be manually initialised. This is done using the set_power_balance effect. For example, this is the most bare-bones way to initialise the BoP, which will set it to the default:

set_power_balance = {
    id = TAG_example_balance
}

The effect can also be used to change details about the currently-active balance of power, such as changing the sides or the value:

set_power_balance = {
    id = TAG_example_balance
    left_side = default_left_side
    right_side = default_right_side
    set_value = 0.1
}

If necessary to reset it completely to the default, set_default = yes will do so.

set_power_balance = {
    id = TAG_example_balance
    set_default = yes
}

As an effect, it can be used in any effect block. If it should be initialised at the game's start, this is usually done in country history, alternatively it can be initialised when needed, such as in a focus reward or an event option.

力量平衡修正

另见:修正 § 静态修正

Balance of power modifiers are 静态修正 that are applied directly to a balance of power, from which they are cloned to each country that has the BoP assigned. As static modifiers, they're defined in any /Hearts of Iron IV/common/modifiers/*.txt file. They typically include within of themselves only the power_balance_daily and/or power_balance_weekly modifiers in order to gradually tip the balance towards one side. These modifiers will be shown in the tooltip when hovering over the current value.

An example of a BoP modifier is as such:

my_bop_modifier = {
    power_balance_weekly = -0.01 # Changes by 1% each week to the left
}

力量平衡修正通过add_power_balance_modifier 效果添加,如下所示:

add_power_balance_modifier = {
    id = my_bop    # The ID of the balance of power
    modifier = my_bop_modifier # The modifier to add
}

可以用相同语法的remove_power_balance_modifier 效果,或用remove_all_power_balance_modifiers把这些修正从国家上移除。

Since these are duplicated to each country that has the BoP, the weekly or daily effect for each modifier will increase for each country that is assigned the BoP. For example, if the BoP is assigned to 3 countries, power_balance_daily = 0.01 in a BoP modifier will, in practice, make the balance get pushed by 3% to the right in total daily.

效果

Parts of this section are transcluded from 效果 § 权力平衡.

Other than set_power_balance, these effects exist which can be used to modify a balance of power:


与权力平衡相关的国家作用域效果:
名称 参数 示例 描述 备注 加入版本
remove_power_balance id = <BoP ID> 要修改的权力平衡。
remove_power_balance = {
    id = my_bop
}
完全移除该权力平衡。 1.12
add_power_balance_value id = <BoP ID> 要修改的权力平衡。

value = <decimal> 要添加的数值。tooltip_side = <BoP side ID> 要在提示框中显示的一方。可选。

add_power_balance_value = {
    id = my_bop
    value = -0.1
    tooltip_side = my_bop_side
}
将权力平衡推向某一侧。 1.12
add_power_balance_modifier id = <BoP ID> 要修改的权力平衡。

modifier = <static modifier> 要应用的静态修正。

add_power_balance_modifier = {
    id = my_bop
    modifier = my_static_modifier
}
应用一个权力平衡修正。 1.12
remove_power_balance_modifier id = <BoP ID> 要修改的权力平衡。

modifier = <static modifier> 要应用的静态修正。

remove_power_balance_modifier = {
    id = my_bop
    modifier = my_static_modifier
}
取消一个权力平衡修正。 1.12
remove_all_power_balance_modifiers id = <BoP ID> 要修改的权力平衡。
remove_all_power_balance_modifiers = {
    id = my_bop
}
取消所有权力平衡修正。 1.12
set_power_balance_gfx id = <BoP ID> 要修改的权力平衡。

side = <BoP side ID> 要更改其 GFX 的一方。gfx = <sprite> 要用于更改 GFX 的 sprite。

set_power_balance_gfx = {
    id = my_bop
    side = my_bop_side
    gfx = GFX_my_bop_side_new
}
更改权力平衡中某一侧的外观。 Sprite 定义于 /Hearts of Iron IV/interface/*.gfx 文件中。 1.12


触发器

Parts of this section are transcluded from 触发条件 § 权力平衡.

These triggers exist for checking the state of a balance of power. Some of these can only be used in country scope.

Balance of power-related country-scoped triggers:
名称 参数 示例 描述 备注 加入版本
has_power_balance id = <bop ID>
The balance to check for.
has_power_balance = {
    id = TAG_my_bop
}
Checks if the current scope has the specified balance of power active. 1.12
has_any_power_balance <bool> 布尔值。
has_any_power_balance = yes
Checks if the current scope has any balance of power active. 1.12
power_balance_value id = <bop ID> 要检查的力量平衡。

value = <float>
The value to check for.

power_balance_value = {
    id = TAG_my_bop
    value > 0.7
}
Checks if the current scope has the specified value within the balance of power. Either =, >, or < operators are allowed. 1.12
power_balance_daily_change id = <bop ID> 要检查的力量平衡。

value = <float>
The value to check for.

power_balance_daily_change = {
    id = TAG_my_bop
    value < -0.01
}
Checks if the current scope's balance of power changes each day by the specified value. Either =, >, or < operators are allowed. 1.12
power_balance_weekly_change id = <bop ID> 要检查的力量平衡。

value = <float>
The value to check for.

power_balance_weekly_change = {
    id = TAG_my_bop
    value < -0.01
}
Checks if the current scope's balance of power changes each week by the specified value. Either =, >, or < operators are allowed. 1.12
is_power_balance_in_range id = <bop ID> 要检查的力量平衡。

range = <range ID>
The range to check for.

is_power_balance_in_range = {
    id = TAG_my_bop
    range > TAG_my_bop_right_range
}
Checks if the current scope's balance of power value lies within the specified range. Ranges are defined within the balance of power. Can use either =, >, and < operators. In case of > or <, the comparison is 'strict', i.e. excluding the range itself. 1.12
is_power_balance_side_active id = <bop ID> 要检查的力量平衡。

side = <side ID>
The side to check.

is_power_balance_side_active = {
    id = TAG_my_bop
    side = TAG_my_bop_right_range
}
Checks if the specified balance of power has a side active. Sides are defined within the balance of power. "Active" means that the side is among those that are currently visible instead of relying on the current value. 1.12
has_power_balance_modifier id = <bop ID> 要检查的力量平衡。

modifier = <modifier ID>
The static modifier.

has_power_balance_modifier = {
    id = TAG_my_bop
    modifier = TAG_my_bop_modifier
}
Checks if the current scope's balance of power value activates a modifier. BoP modifiers are defined within /Hearts of Iron IV/common/modifiers/*.txt files, while they're activated in the balance of power definition. 1.12
模组制作
文档 效果 • 触发器 • 定义文件 • 修正项 • 修正项列表 • 作用域 • 本地化文件 • 事件钩子 • 数据结构(标记、事件目标、国家标签别名、变量、数组)
脚本 成就 • AI • AI 焦点 • 自治领 • 力量均势 • 书签/剧本 (游戏规则) • 建筑 • 角色与特质 • 外观标签 • 国家 • 师 • 决议 • 学说 • 装备 • 事件 • 阵营 • 理念 • 意识形态 • 军事工业组织 • 国策 • 资源 • 脚本化 GUI • 科技与学说 • 单位
地图 地图 • 州 • 补给区域 • 战略区域
图形 界面 • 图形资源 • 实体 • 后期特效 • 粒子 • 字体
外观 肖像 • 名称列表 • 音乐 • 音效
其他 控制台指令 • 疑难排查 • 模组结构 • 模组 • 地图编辑器