自定义效果、特质与属性
复制人的数值系统主要由三层组成:
- Attribute:属性,比如运动、力量、学习、免疫。
- Effect:临时或永久效果,可以给属性加减值。
- Trait:特质,通常是角色长期拥有的标签和修正。
入门时先做 Effect。它最安全,也最容易测试:注册一个效果,加到复制人身上,看属性有没有变化。
注册 Effect
效果要注册进 Db.Get().effects。常见时机是 Db.Initialize 后:
using HarmonyLib;
using Klei.AI;
namespace MyEffects
{
[HarmonyPatch(typeof(Db), "Initialize")]
public static class Db_Initialize_Patch
{
public static void Postfix(Db __instance)
{
ModEffects.RegisterAll(__instance.effects);
}
}
}Db.Get().effects 的类型是 ResourceSet<Effect>。
建议集中写一个 ModEffects.RegisterAll(),后面维护会清楚很多。
创建一个效果
最直接的写法:
using System.Collections.Generic;
using Klei.AI;
namespace MyEffects
{
public static class ModEffects
{
public const string QUICK_LEARNER = "MyQuickLearner";
public static void RegisterAll(ResourceSet<Effect> effects)
{
Effect effect = new Effect(
QUICK_LEARNER,
"快速学习",
"学习能力提高。",
600f,
true,
true,
false);
effect.SelfModifiers = new List<AttributeModifier>
{
new AttributeModifier(
Db.Get().Attributes.Learning.Id,
3f,
"快速学习")
};
effects.Add(effect);
}
}
}600f 是持续时间,单位是游戏秒。持续时间写 0f 或负数时,要根据具体构造和调用方式测试,不要默认它一定永久。
给复制人添加效果
Effects effects = minion.GetComponent<Effects>();
if (effects != null)
{
effects.Add(ModEffects.QUICK_LEARNER, true);
}移除:
effects.Remove(ModEffects.QUICK_LEARNER);检查:
bool hasEffect = effects.HasEffect(ModEffects.QUICK_LEARNER);常用属性
属性 ID 建议从 Db.Get().Attributes 拿:
Db.Get().Attributes.Athletics.Id
Db.Get().Attributes.Strength.Id
Db.Get().Attributes.Learning.Id
Db.Get().Attributes.Construction.Id
Db.Get().Attributes.Machinery.Id
Db.Get().Attributes.Digging.Id
Db.Get().Attributes.Cooking.Id
Db.Get().Attributes.Caring.Id
Db.Get().Attributes.Immunity.Id不要硬写字符串,除非源码里确认过这个 ID。游戏更新后,直接用 Db 至少更好查。
负面效果
负面效果的构造参数里 isBad 传 true:
Effect tired = new Effect(
"MyHeavyBody",
"身体沉重",
"运动和力量下降。",
1200f,
true,
true,
true);然后加负数修正:
tired.SelfModifiers = new List<AttributeModifier>
{
new AttributeModifier(Db.Get().Attributes.Athletics.Id, -4f, "身体沉重"),
new AttributeModifier(Db.Get().Attributes.Strength.Id, -2f, "身体沉重")
};负面效果最好有清晰的移除条件。只加不移除,玩家会觉得像坏档。
自定义特质
特质适合长期身份,比如“耐寒”“神经敏锐”“不擅长挖掘”。基础写法:
Trait trait = new Trait(
"MyColdResistant",
"耐寒体质",
"这个复制人更适合寒冷环境。",
0f,
false,
null,
true,
true);
trait.SelfModifiers.Add(new AttributeModifier(
Db.Get().Attributes.Immunity.Id,
2f,
"耐寒体质"));
Db.Get().traits.Add(trait);给复制人添加:
Traits traits = minion.GetComponent<Traits>();
Trait trait = Db.Get().traits.Get("MyColdResistant");
if (traits != null && trait != null && !traits.HasTrait(trait))
{
traits.Add(trait);
}特质会进入角色资料,存档影响更长。测试时要多开新档,不要只在旧档里热加载。
自定义属性
自定义 Attribute 可以做,但不建议作为第一步。因为 UI、等级、经验、显示文本、保存读取都要跟上。
如果只是想让某个组件有数值,优先自己写字段:
[Serialize]
private float heatAffinity;只有这个数值需要进入复制人属性面板、被多个系统引用、被效果修正时,再考虑注册新属性。
文字路径
效果文本常见路径:
STRINGS.DUPLICANTS.MODIFIERS.MYQUICKLEARNER.NAME
STRINGS.DUPLICANTS.MODIFIERS.MYQUICKLEARNER.TOOLTIP特质文本常见路径:
STRINGS.DUPLICANTS.TRAITS.MYCOLDRESISTANT.NAME
STRINGS.DUPLICANTS.TRAITS.MYCOLDRESISTANT.DESC路径不统一时,效果能生效,但 UI 显示会很别扭。先把文本整理好,再写大量效果。
常见坑
效果注册太早会找不到 Db.Get().Attributes。放在 Db.Initialize 后最稳。
效果 ID 改名会影响存档。发布后尽量不要改 ID,只改显示名。
属性修正来源名不要空着。属性面板里会显示这条修正从哪里来,空名字很难排查。
永久效果要谨慎。优先用长时间效果加刷新逻辑,确认没问题后再做真正永久。