特殊调整 Modifier
Modifier是整个Mod制作中比较复杂的部分,理解了这个就可以做出绝大部分的特殊效果。
以水磨为例
还记得水磨的特殊效果么?拥有水磨的城市,大米和小麦资源的粮食产出+1。这个效果无法通过直接对水磨这个建筑进行修改,它的实现需要用到特殊调整 Modifier。Modifier和建筑、改良、资源等等是平行的关系,也是数据库中的一个表。
我们抽出Buildings.xml
中水磨的部分,来研究这个效果是怎么达成的。
<Modifiers>
<!--Adjust Plot Yield-->
<Row>
<ModifierId>WATERMILL_ADDRICEFOOD</ModifierId>
<ModifierType>MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD</ModifierType>
<SubjectRequirementSetId>RESOURCE_IS_RICE</SubjectRequirementSetId>
</Row>
<Row>
<ModifierId>WATERMILL_ADDWHEATYIELD</ModifierId>
<ModifierType>MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD</ModifierType>
<SubjectRequirementSetId>RESOURCE_IS_WHEAT</SubjectRequirementSetId>
</Row>
</Modifiers>
这几句为Modifier的表增加了两个条目,分别指代了水磨_增加大米食物WATERMILL_ADDRICEFOOD
和水磨_增加小麦产出WATERMILL_ADDWHEATYIELD
。由于这两条几乎一模一样,在下面我只选取了大米进行解释。
条目的第二个属性是调整种类ModifierType
,Civ6定义了近100种类型的调整种类,比如说增加贸易路线产出的、增加地块产出的、增加单位力量的等等。这些都可以在Modifiers.xml
中找到声明。值得注意的是,我们只能在这些现有的种类中选择,不能新增调整种类,因为这涉及到游戏的核心程序部分,加了以后并没有代码支持也是没有作用的。MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD
的意思是,本城的地块产出调整,我们需要拥有水磨的城市的粮食地块产出增加,所以需要这个调整种类。
条目的第三个属性是要求集idSubjectRequirementSetId
(可有可无),这个定义了该调整在什么条件下成立,比如说水磨就要求地块的资源必须是小麦或大米,这在之后会提到。
<ModifierArguments>
<Row>
<ModifierId>WATERMILL_ADDRICEFOOD</ModifierId>
<Name>Amount</Name>
<Value>1</Value>
</Row>
<Row>
<ModifierId>WATERMILL_ADDRICEFOOD</ModifierId>
<Name>YieldType</Name>
<Value>YIELD_FOOD</Value>
</Row>
</ModifierArguments>
调整种类有了,可是MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD
只说了增加,那增加什么,增加多少呢?这就需要在调整参数ModifierArguments
里进行定义。我们看到,通过指定调整的主键,我们将两个参数数量Amount
与产出种类YieldType
赋予了这个调整,两个参数的值分别为1和产出食物YIELD_FOOD
。
<BuildingModifiers>
<Row>
<BuildingType>BUILDING_WATER_MILL</BuildingType>
<ModifierId>WATERMILL_ADDRICEFOOD</ModifierId>
</Row>
</BuildingModifiers>
光有Modifier还不够,我们需要在水磨和这个调整之间建立起联系,所以在BuildingModifiers
的表中,我们便添加了如上这一条。一个建筑可以联系多个调整。
接下来我们看要求。
要求 Reqirements
调整需要的第三个参数是SubjectRequirementSetId
,即要求集,表示它所需要的要求的集合。我们首先需要构建一个要求集。水磨需要的是:RESOURCE_IS_RICE
<RequirementSets>
<Row>
<RequirementSetId>RESOURCE_IS_RICE</RequirementSetId>
<RequirementSetType>REQUIREMENTSET_TEST_ALL</RequirementSetType>
</Row>
</RequirementSets>
定义要求集的第二个属性是RequirementSetType
,它有两个值可选:REQUIREMENTSET_TEST_ALL
和REQUIREMENTSET_TEST_ANY
。前者表示,在它包含的要求中,所有要求全部满足,这个要求集才满足;后者表示,只要有一个要求满足,那么这个要求集就是满足的(All 和 Any 的逻辑)。一般来说,大部分的都是ALL
。
<RequirementSetRequirements>
<Row>
<RequirementSetId>RESOURCE_IS_RICE</RequirementSetId>
<RequirementId>REQUIRES_RICE_IN_PLOT</RequirementId>
</Row>
</RequirementSetRequirements>
对于一个要求集,RequirementSetRequirements
列出了属于这个要求集的所有要求,用id指代,一个要求集可以包含多个要求。当然,本例中只有一个要求:REQUIRES_RICE_IN_PLOT
。
<Requirements>
<Row>
<RequirementId>REQUIRES_RICE_IN_PLOT</RequirementId>
<RequirementType>REQUIREMENT_PLOT_RESOURCE_TYPE_MATCHES</RequirementType>
</Row>
</Requirements>
在Requirements
表中,我们新增了这个要求,它的要求种类RequirementType
是REQUIREMENT_PLOT_RESOURCE_TYPE_MATCHES
,即“地块的资源符合……”,所有要求种类可以在Requirements.xml
中找到声明,这个和调整种类类似。
<RequirementArguments>
<Row>
<RequirementId>REQUIRES_RICE_IN_PLOT</RequirementId>
<Name>ResourceType</Name>
<Value>RESOURCE_RICE</Value>
</Row>
</RequirementArguments>
同样的,要求也需要参数,这里的参数是ResourceType="RESOURCE_RICE"
,表示需要大米资源。