跳至正文

On的功能与应用

大家好,我是幽白银。时隔1年07个月,我们又见面了其实我一点都不想更新,今天我们来康康新玩具——On其实不新了只是我懒得更新

关于On


On是基于Mono的一种技术,可以理解为Hook——钩子,用于修改和控制原函数的流程,甚至阻断。

而tml选择给我们 (modder) 提供 On,则是考虑到mod开发的自由性的问题。有了On,我们可以修改原版的公有域的函数。看来私有域还得看我反射

具体的用处是啥呢?比如我想要在添加Buff的时候在左下角提醒一下我挂上了啥Buff

提醒buff

比如我想让所有的伤害都变成真伤(不经过伤害计算)真实伤害,又或者我想在创建角色的页面绘制UI

CandlightMod的职业UI

或者用On干掉原版机制自己重写

本章教学-使用On重写原版的伤害计算


你是不是很久以前就想修改Tr的伤害计算方式了?其实我也是!

在本章我们将使用realDamage = origDamage * const / (defense + const)公式重写原版的伤害计算。

我们首先在Mod主类的Load()函数用On给原版的伤害计算函数挂上一个钩子

public override void Load()
{
  On.Terraria.Main.CalculateDamage += Main_CalculateDamage;
  base.Load();
}

这里需要注意的是,On.Terraria.Main.CalculateDamage语句代表着用OnTerraria.Main类的 CalculateDamage 函数挂上名为Main_CalculateDamage的钩子。一般来说,钩子只需要挂一次,所以我选择在Load函数挂钩子,也就是在加载Mod的那一刻给原版的伤害计算函数挂上钩子。

Main_CalculateDamage实际上是一个委托,其参数是Main_CalculateDamage(On.Terraria.Main.orig_CalculateDamage orig, int Damage, int Defense)。我先解释一下这些参数是个啥。第一个参数(orig)你可以把它当成原版伤害计算的函数,直接orig(Damage, Defense);就能调用原来的伤害计算函数(注:DamageDefense是传入原版伤害计算函数的参数,只要你想可以随便填);第二个参数(Damage)是在其他地方使用伤害计算函数时输入的初始伤害;第三个参数(Defense)是在其他地方使用伤害计算函数时输入的目标防御值。

首先观察我们的公式。 origDamage 是初始伤害值; const是一个常数,根据这个常数来调整防御机制; defense 则是目标的防御力。假设我们输入的 const 是400,那么根据公式转化为代码,是这样的

double realDamage = Damage * 400 / (Defense + 400);

而如果在委托里返回的话,我们只需要这样写

private double Main_CalculateDamage(On.Terraria.Main.orig_CalculateDamage orig, int Damage, int Defense)
{
    return Damage * 400 / (Defense + 400);
}

游戏里的伤害计算机制就被修改了!是不是很简单?我们进游戏里逝逝

猪鲨
猪鲨面板
武器面板
实战效果

经过公式计算,我们造成的伤害是720*400/(400+50),加上伤害浮动,这个伤害算是正常范围。

最后,别忘了在Unload函数里卸载钩子!卸载Mod后恢复原版的样子,是Mod的原则之一。

public override void Unload()
{
    On.Terraria.Main.CalculateDamage -= Main_CalculateDamage;
    base.Unload();
}

至此,原版伤害机制修改完成。

其实还有个东西叫IL,其能精确修改某个函数的IL代码,其自由度比On更高,在某些地方比On要好用。但是本章我们不讨论这个,感兴趣的pong友可以去官方文档查看。

课后作业


今天就不布置作业了,大家玩得开心。

《On的功能与应用》有1个想法

  1. Pingback: 通过 HookEndpointManager 动态挂钩子 - 裙中世界

发表回复