Mod语法
Rusted Wiki欢迎您参与完善本条目 |
.ini文件
纯文本文件。游戏通过读取以.ini
为扩展名的文件来获取具体单位的属性。内容组成方面,由节(section)、键(key)、注释(comment)三个部分组成:
节(section)
包含用两个半角英文方括号包围的节的名称([section]),单独占一行。用于声明相关的键从属于该节。其后的行直到另一个节前一行的键均归属于该节。名称不同的节视为不同类型的节。
节的类型:
[core] [canBuild_NAME] [graphics] [attack] [turret_NAME] [projectile_NAME] [movement] [ai] [leg_#] [arm_#] [attachment_NAME] [action_NAME] [hiddenAction_NAME] [effect_NAME] [animation_NAME] [placementRule_NAME] [global_resource_NAME] [resource_NAME] [template_NAME] [comment_NAME]
属性(property)
在Rusted Warfare中,属性包含一组键值对。键(key)的名称与其对应的值(value)用半角冒号隔开,单独占一行。用于规定单位的具体属性。名称不同的键视为不同类型的键,名称相同的键从属于不同类型的节视为不同类型的键。
键的类型(施工中):
Section | Code | Value | Default | Notes |
---|---|---|---|---|
[core] | name | "string" | ||
[core] | altNames | "string"(s) | ||
[core] | class | CustomUnitMetadata | CustomUnitMetadata | |
[core] | strictLevel | 0/1 | 0 | |
[core] | price | "int"/"customResourceX"="float"(s) | "int" = credits="int";[global_resource_"customResourceX"]/[resource_"customResourceX"] | |
[core] | mass | "int"(>=0) | ||
[core] | techLevel | 1/2/3 | 1 | |
[core] | buildSpeed | "float"/"float"s | 1 | "float"=1/("float"s*60) |
[core] | radius | "int"(>=0) | ||
[core] | isBio | "bool" | false | |
[core] | isBug | "bool" | false | |
[core] | isBuilder | bool | false | |
[core] | streamingCost | "int"/"customResourceX"="float"(s) | "int" = credits="int";[global_resource_"customResourceX"]/[resource_"customResourceX"];[core]resourceRate:0;[core]switchPriceWithStreamingCost:false | |
[core] | switchPriceWithStreamingCost | "bool" | false | [core]resourceRate:0;[core] |
[core] | maxHp | "int"(>=0, if ${core.disableDeathOnZeroHp} != true) | ||
[core] | selfRegenRate | "float" | 0 | hp/s=("float"*60)/s |
[core] | maxShield | "int"(>=0) | 0 | |
[core] | startShieldAtZero | "bool" | false | |
[core] | shieldRegen | "float" | 0.25 | shield/s=("float"*60)/s |
[core] | energyMax | "float"(>=0) | 0 | |
[core] | energyRegen | "float" | 0 | energy/s=("float"*60)/s |
[core] | energyStartingPercentage | "float"(0-1) | 1 | |
[core] | energyNeedsToRechargeToFull | "bool" | false | |
[core] | energyRegenWhenRecharging | "float" | ${core.energyRegen} | energy/s=("float"*60)/s |
[core] | armour | "int" | 0 | |
[core] | armourMinDamageToKeep | "int" | 1 | |
[core] | borrowResourcesWhileAlive | "int"/"customResourceX"="float"(s) | "int" = credits="int";[global_resource_"customResourceX"]/[resource_"customResourceX"] | |
[core] | borrowResourcesWhileBuilt | "int"/"customResourceX"="float"(s) | "int" = credits="int";[global_resource_"customResourceX"]/[resource_"customResourceX"] | |
[core] | generation_resources | "int"/"customResourceX"="float"(s) | "int" = credits="int";[global_resource_"customResourceX"]/[resource_"customResourceX"] | |
[core] | generation_active | "logicBoolean" | true | |
[core] | generation_credits | "int" | ||
[core] | generation_delay | "int"(>=0) | 40 | |
[core] | showInEditor | "bool" | true | |
[core] | displayText | "string"/i:"localeKey" | /assets/translations/Strings.properties-->"localeKey"=xxx;if displayText:i:"localeKey", displayText_"LANG":"string" | |
[core] | displayText_"LANG" | "string"/i:"localeKey" | "LANG" = ISO 639-1 Code(zh,ru,ja...);/assets/translations/Strings.properties-->"localeKey"=xxx;displayText:"string"(/i:"localeKey");if displayText_"LANG":i:"localeKey", displayText:"string" | |
[core] | displayDescription | "string"/i:"localeKey" | /assets/translations/Strings.properties-->"localeKey"=xxx;if displayDescription:i:"localeKey", displayDescription_"LANG":"string" | |
[core] | displayDescription_"LANG" | "string"/i:"localeKey" | "LANG" = ISO 639-1 Code(zh,ru,ja...);/assets/translations/Strings.properties-->"localeKey"=xxx;displayDescription:"string"(/i:"localeKey");if displayDescription_"LANG":i:"localeKey", displayDescription:"string" | |
[core] | displayLocaleKey | "unitLocaleKey" | /assets/translations/Strings.properties-->units."unitLocaleKey".name | |
[core] | displayRadius | "int"(>=0) | ${core.radius} | |
[core] | uiTargetRadius | "int"(>=0;==6, if ${core.radius} < 6) | ${core.radius} | |
[core] | shieldRenderRadius | "int"(>=0) | ${core.radius} | |
[core] | shieldDisplayOnlyDeflection | "bool" | false | |
[core] | shieldDeflectionDisplayRate | "float" | 4 | Unfiled |
[core] | showOnMinimap | "bool" | true | |
[core] | showActionsWithMixedSelectionIfOtherUnitsHaveTag | "tag"(s) | ||
[core] | showOnMinimapToEnemies | "bool" | ${graphics.isVisibleToEnemies} | |
[core] | isBuilding | "bool" | false | |
[core] | footprint | -"int",-"int","int","int"(>=0) | -0,-0,0,0 | "int"="int"*tile="int"*(20px*20px) |
[core] | constructionFootprint | -"int",-"int","int","int"<(>=0)/td> | -0,-0,0,0 | "int"="int"*tile="int"*(20px*20px) |
[core] | displayFootprint | -"int",-"int","int","int"(>=0) | ${core.footprint} | "int"="int"*tile="int"*(20px*20px) |
[core] | buildingSelectionOffset | "int" | 0 | "int"="int"px*"int"px |
[core] | buildingToFootprintOffsetX | "float" | 10 | "float"="float"px |
[core] | buildingToFootprintOffsetY | "float" | 10 | "float"="float"px |
[core] | placeOnlyOnResPool | "bool" | false | |
[core] | selfBuildRate | "float"/"float"s | 0 | "float"=1/("float"s*60) |
[core] | ignoreInUnitCapCalculation | "bool" | ${core.isBuilding} | |
[core] | copyFrom | "filePath"(.ini)(s) | "filePath" = ./../xxx/xx/xxxx.ini | |
[core] | dont_load | "bool" | false | |
[core] | overrideAndReplace | "unitName"(s) | "unitName" = ${core.name} | |
[core] | onNewMapSpawn | emptyResourcePools_asNeutral/emptyOrOccupiedResourcePools_asNeutral/mapCenter_asNeutral/mapCenter_eachActiveTeam/spawnPoint_eachActiveTeam | ||
[core] | isLocked | "bool" | false | |
[core] | isLockedIfGameModeNoNuke | "bool" | false | |
[core] | experimental | "bool" | false | |
[core] | stayNeutral | "bool" | false | |
[core] | createNeutral | "bool" | false | |
[core] | createOnAggressiveTeam | "bool" | false | |
[core] | tags | "tag"(s) | ||
[core] | defineUnitMemory | boolean/float/number/unit/string "string"(s) | ||
[core] | fogOfWarSightRange | "int"(>=0) | 15 | "int"="int"px |
[core] | fogOfWarSightRangeWhileNotBuilt | "int"(>=0) | ${core.fogOfWarSightRange} | "int"="int"px |
[core] | softCollisionOnAll | "int"(>=0) | 0 | |
[core] | disableAllUnitCollisions | "bool" | false | |
[core] | isUnrepairableUnit | "bool" | false | |
[core] | isUnselectable | "bool" | false | |
[core] | isUnselectableAsTarget | "bool" | ${core.isUnselectable} | |
[core] | isPickableStartingUnit | "bool" | false | |
[core] | startFallingWhenStartingUnit | "bool" | false | |
[core] | soundOnAttackOrder | "filePath"(.ogg/.wav)(s) | "filePath" = ./../xxx/xx/xxxx.ogg(/.wav) | |
[core] | soundOnMoveOrder | "filePath"(.ogg/.wav)(s) | "filePath" = ./../xxx/xx/xxxx.ogg(/.wav) | |
[core] | soundOnNewSelection | "filePath"(.ogg/.wav)(s) | "filePath" = ./../xxx/xx/xxxx.ogg(/.wav) | |
[core] | canNotBeDirectlyAttacked | "bool" | false | [core] |
[core] | canNotBeDamaged | "bool" | ${core.canNotBeDirectlyAttacked} | |
[core] | canNotBeGivenOrdersByPlayer | "bool" | false | |
[core] | canOnlyBeAttackedByUnitsWithTags | "tag"(s) | [core] | |
[core] | disableDeathOnZeroHp | "bool" | false | |
[core] | transportSlotsNeeded | "int"(>=0) | 1 | |
[core] | maxTransportingUnits | "int"(>=0) | 0 | |
[core] | transportUnitsRequireTag | "tag"(s) | ||
[core] | transportUnitsRequireMovementType | NONE/LAND/BUILDING/HOVER/OVER_CLIFF/OVER_CLIFF_WATER/AIR/WATER(s) | ||
[core] | transportUnitsBlockAirAndWaterUnits | "bool" | true | |
[core] | transportUnitsKeepBuiltUnits | "logicBoolean" | false | |
[core] | transportUnitsCanUnloadUnits | "logicBoolean" | if not (self.isOverLiquid or self.isMoving) | |
[core] | transportUnitsAddUnloadOption | "bool" | true/false(if ${core.transportUnitsCanUnloadUnits} == false) | |
[core] | transportUnitsUnloadDelayBetweenEachUnit | "float"/"float"s | 30 | "float"s="float"*60 |
[core] | transportUnitsKillOnDeath | "logicBoolean" | true | |
[core] | transportUnitsHealBy | "float" | 0 | hp/s=("float"*60)/s |
[core] | transportUnitsBlockOtherTransports | "bool" | true | |
[core] | whileNeutralTransportAnyTeam | "bool" | false | |
[core] | whileNeutralConvertToTransportedTeam | "bool" | false | |
[core] | convertToNeutralIfNotTransporting | "bool" | false | |
[core] | transportUnitsOnTeamChangeKeepCurrentTeam | "bool" | false | |
[core] | resourceRate | "float"(>0) | 0 | [core]switchPriceWithStreamingCost:false;[core] |
[core] | similarResourcesHaveTag | "tag"(s) | ||
[core] | resourceMaxConcurrentReclaimingThis | "int"(>=0) | ||
[core] | reclaimPrice | "int"/"customResourceX"="float"(s) | "int" = credits="int";[global_resource_"customResourceX"]/[resource_"customResourceX"] | |
[core] | canReclaimResources | "bool" | false | |
[core] | canReclaimResourcesNextSearchRange | "int"(>=0) | 500 | |
[core] | canReclaimResourcesOnlyWithTags | "tag"(s) | ||
[core] | canReclaimUnitsOnlyWithTags | "tag"(s) | [core]canRepairBuildings:true/[core]canRepairUnits:true | |
[core] | resourceReclaimMultiplier | "float" | 1 | |
[core] | canRepairUnitsOnlyWithTags | "tag"(s) | [core]canRepairBuildings:true/[core]canRepairUnits:true | |
[core] | canRepairBuildings | "bool" | false | |
[core] | canRepairUnits | "bool" | false | |
[core] | autoRepair | "bool" | false | |
[core] | nanoRange | "int"(>=0) | 85 | |
[core] | nanoRepairSpeed | "float" | 0.2 | hp/s=("float"*60)/s |
[core] | nanoBuildSpeed | "float"(>=0) | 1 | |
[core] | nanoUnbuildSpeed | "float"(>=0) | 1 | |
[core] | nanoReclaimSpeed | "float"(>=0) | ${core.nanoRepairSpeed}*5.1 | hp/s=("float"*60)/s |
[core] | nanoRangeForRepairIsMelee | "bool" | false | |
[core] | nanoRangeForReclaimIsMelee | "bool" | false | |
[core] | nanoRangeForRepair | "int"(>=0) | ${core.nanoRange} | |
[core] | nanoRangeForReclaim | "int"(>=0) | ${core.nanoRange} | |
[core] | nanoFactorySpeed | "float"(>=0) | 1 | |
[core] | extraBuildRangeWhenBuildingThis | "int" | 0 | |
[core] | builtFrom_"#"_name | "unitName"(s) | "#" = "int"(>=0);"unitName" = ${core.name} | |
[core] | builtFrom_"#"_pos | "float" | "#" = "int"(>=0) | |
[core] | builtFrom_"#"_forceNano | "bool" | false | "#" = "int"(>=0) |
[core] | builtFrom_"#"_isLocked | "logicBoolean" | false | "#" = "int"(>=0) |
[core] | builtFrom_"#"_isLockedMessage | "string"/i:"localeKey" | "#" = "int"(>=0);/assets/translations/Strings.properties-->"localeKey"=xxx | |
[core] | exit_x | "float" | 0 | |
[core] | exit_y | "float" | 9 | |
[core] | exit_dirOffset | "float" | 180(units)/0(buildings) | |
[core] | exit_heightOffset | "float" | 0 | |
[core] | exit_moveAwayAmount | "float" | 70 | |
[core] | exitHeightIgnoreParent | "bool" | false | |
[core] | dieOnConstruct | "bool" | false | |
[core] | dieOnZeroEnergy | "bool" | false | |
[core] | numBitsOnDeath | "int"(>=0) | 4(if ${core.mass} <= 30000)/8(if ${core.mass} > 30000)/7(buildings) | |
[core] | nukeOnDeath | "bool" | false | |
[core] | nukeOnDeathRange | "float"(>=0) | 250 | |
[core] | nukeOnDeathDamage | "float" | 5400 | |
[core] | nukeOnDeathDisableWhenNoNuke | "bool" | false | |
[core] | fireTurretXAtSelfOnDeath | "turretX" | [turret_"turretX"] | |
[core] | explodeOnDeath | "bool" | true | |
[core] | explodeOnDeathGroundCollision | "bool" | true | |
[core] | explodeTypeOnDeath | verysmall/small/normal/large/largeUnit/building/buildingNoShockwaveOrSmoke/verylargeBuilding(s) | normal | |
[core] | effectOnDeath | smoke/shockwave/small/medium/large/CUSTOM:"customEffectX"*"int"(>=0)(s) | [effect_"customEffectX"] | |
[core] | effectOnDeathGroundCollision | smoke/shockwave/small/medium/large/CUSTOM:"customEffectX"*"int"(>=0)(s) | [effect_"customEffectX"] | |
[core] | unitsSpawnedOnDeath | "unitName"*"int"(>=0)(s) | "unitName" = ${core.name} | |
[core] | unitsSpawnedOnDeath_setToTeamOfLastAttacker | "bool" | false | |
[core] | hideScorchMark | "bool" | false | |
[core] | soundOnDeath | "built-inSound"/"filePath"(.ogg/.wav)(s) | \res\raw\"built-inSound".ogg(/.wav) | |
[core] | effectOnDeathIfUnbuilt | smoke/shockwave/small/medium/large/CUSTOM:"customEffectX"*"int"(>=0)(s) | [effect_"customEffectX"] | |
[core] | autoTriggerCooldownTime | "float"(>=5;<120;>=0,if ${core.autoTriggerCooldownTime_allowDangerousHighCPU} == true)/"float"s(>=${5/60}s;<2s;>=0s,if ${core.autoTriggerCooldownTime_allowDangerousHighCPU} == true) | 60 | |
[core] | autoTriggerCooldownTime_allowDangerousHighCPU | "bool" | false | |
[core] | autoTriggerCheckRate | everyFrame/every4Frames/every8Frames | everyFrame |
注释
注释即为对代码的解释和说明。清晰的注释有利于帮助理解代码的含义。铁锈战争的.ini
文件语法在注释方面提供了三种方式:
(1)用#
进行单行的注释
在行的开头加上符号#
后,游戏程序会忽略这一行的内容,不将其作为代码解析。但编写这些的人类可以注意到这些。
[projectile_1] #directDamage: 20 #有人反映单发伤害太低,这里改成了30 directDamage: 30 …
(2)用"""
和"""
的组合进行多行注释
在行头使用"""
作为起始,在之后的行尾使用"""
作为结束。在其之间的内容均会被游戏忽略。
""" 这是三个英文引号 实际上这个组合还有个功能,就是用它引住key: value的value使value可以换行输入如: builtFrom_1_name: airFactory 可以是 builtFrom_1_name: """airF actory""" 可是有一种情况,你用多行注释注释掉了有换行输入的内容它显然就会混乱,也就是目前的情况 """
(3)用[comment_NAME]
进行成节的注释
该节之后的行直到下一个节前一行均不会被加载。
[comment_hiddenAction_1] autoTriggerOnEvent: created addGlobalTeamTags: 计时 [comment_1] maxHp: 2000 [core] #[comment_NAME]节下的东西是不会被加载的,去引用它会提示找不到任何key @copyFromSection: comment_1 …
mod-info.txt文件
纯文本文件。游戏通过在mod文件夹根目录读取mod-info.txt
这样命名的文件来获得mod作者提供的mod描述信息。
相关参数解释:
#(必填) [mod] #(选填)告诉游戏能够支持该mod运行的最低游戏版本。若不满足最低版本,提示后仍可加载,但除地图外不可用,同时不提供代码错误的报错提醒。 minVersion: v1.14 #(必填)该mod在游戏中显示的标题。 title: Mega Builders #(选填)该mod在游戏中显示的描述。使用"\n"使其在游戏中换行显示(pc版并不会换行显示)。 description: Example mod which replaces builders with Mega Builders. #(选填,在游戏中播放mod中的.ogg文件作为背景音乐)#关于.ogg文件的说明仍待补充 [music] #填音乐文件夹路径。 sourceFolder: soundtrack #当使用该mod的单位时仅播放该mod的音乐,填"true"或"false"。 whenUsingUnitsFromThisMod_playExclusively: true #该文件支持单行注释 """和 多行 注释"""
all-units.template文件
all-units.template
也是INI格式的文件。文件中的代码会自动应用到模组内的所有单位中(效果与使用core
节下的copyFrom
一致)到同级及以下级文件夹的所有.ini
文件中。若存在代码错误,报错不会指向其本身,而是其所应用的.ini
文件。