本文内容整理自 tModLoader 官方 Wiki(Terraria 模组开发指南),原文:ModPlayer Guide

想让玩家在满足某个条件时获得某种效果,基本都得靠 ModPlayer。它负责把状态挂在玩家身上,再让这些状态去改变玩家的行为 —— 这篇讲的就是这套”如果 X,就做 Y”的写法。

ModPlayer 是什么

ModPlayer 是用来给玩家添加数据和功能的类。每个玩家身上都会自动挂一份你写的每个 ModPlayer 类的实例,于是它实际充当了原版 Player 类的一条延伸。

日常用法就两步:先用 ModPlayer 存状态,再拿这些状态去驱动逻辑,从而影响玩家的行为。

如果 X,就做 Y

ModPlayer 最常见的用法,是在某个条件成立时让玩家做点什么 —— 换成一句话就是”如果 X,就做 Y”。这里用”饰品给玩家附加某个效果”来举例,不过同样的思路对增益、护甲、药水一样成立。下面跟着 SimpleModPlayer 的代码走一遍。

先在这个 ModPlayer 里加个字段,记录效果当前是否生效:

1
public bool FrostBurnSummon;

接着用 ResetEffects 把它恢复成默认值。游戏的设计是每次更新时重算所有玩法效果和属性数值,这个钩子就是为这件事准备的:

1
2
3
public override void ResetEffects() {
	FrostBurnSummon = false;
}

然后是”做 Y”:拿这个字段去驱动玩法逻辑。做什么都行,比如玩家受伤时、打中敌人时、回血时,或者每次游戏更新时。具体做法通常是去 ModPlayer 里找一个和目标效果对得上的钩子,ModPlayer 文档 和 ExampleMod 里的各种示例都能帮你找到最合适的那个。这个例子里用的是 ModPlayer.OnHitNPCWithProj

1
2
3
4
5
public override void OnHitNPCWithProj(Projectile proj, NPC target, NPC.HitInfo hit, int damageDone) {
	if ((proj.minion || ProjectileID.Sets.MinionShot[proj.type]) && FrostBurnSummon && !proj.noEnchantments) {
		target.AddBuff(BuffID.Frostburn, 60 * Main.rand.Next(3, 6));
	}
}

最后补上”如果 X”:在一定条件下把效果挂到玩家身上。因为这个例子是饰品,所以正确的位置是 ModItem.UpdateAccessory

1
2
3
public override void UpdateAccessory(Player player, bool hideVisual) {
	player.GetModPlayer<SimpleModPlayer>().FrostBurnSummon = true;
}

到这就齐了。效果的实际逻辑由 ModPlayer 负责,而饰品、增益、护甲这些只负责告诉玩家”这个效果应该生效”。

注意:你可能会以为饰品里应该直接写着它提供的效果代码,但游戏不是这么设计的。做饰品的升级版时这点尤其明显 —— 升级版饰品里只要把原饰品设过的那些 ModPlayer 字段照设一遍,再补一点额外效果就行,玩法逻辑不必写两份。

多个 ModPlayer 类

一个模组可以有很多个 ModPlayer 类,而且我们强烈建议这么做。具体来说,建议让每个 ModPlayer 只担一件事:管钓鱼数值调整的那个类,就不该同时塞进最大生命值的调整。

更多资料

ExampleMod 里有一大批 ModPlayer 示例,每个都带注释说明,可以拿来研究再搬进自己的模组。

其它相关 Wiki 页面: