跳至正文

Modifiers系列-修改受击伤害

“鉴于1436乱七八糟的伤害修改机制,
鸡骨头:无所谓,我会出手
于是新的屎山诞生了。”——摘自《泰拉编年史》

端都端上来了,不吃也得吃,害。

那么首先粗略浏览一下都有肾么菜罢。

Item侧:

1、攻击NPC 2、攻击pvp玩家

Proj侧:

1、攻击NPC 2 、攻击玩家

NPC侧:

1、攻击玩家 2、攻击其他NPC(比如敌怪打城镇)3、被物品攻击 4、被弹幕攻击
补充一个:被攻击(不限伤害源)

以上全部都有Global系列的版本。以及,类似于Global系列的玩家侧:

1、攻击NPC(不限源)2、用物品攻击NPC 3、用弹幕攻击NPC 4.被NPC攻击 5、被弹幕攻击 6、被攻击(不限伤害源)

看起来很多对吧,找找它们的共同点?

对,就是那个带了 ref结构体Modifiers万恶之源

认识Modifiers

很明显这玩意有两个版本,一个是NPC的 HitModifiers,一个是玩家的 HurtModifiers。不急,咱一个个来,使用导航把它看个通透。

再此之前先稍微了解一下 StatModifier 类,这个玩意儿由四个基础元素组成:

参数类型描述默认值
Basefloat额外附加基础伤害0
Additivefloat加算修正,只能在构造时直接设置,但可以用+-运算符操作1
Multiplicativefloat乘算修正,只能在构造时直接设置,但可以用*/运算符操作1
Flatfloat额外附加净伤害0

玩家的 GetDamage 方法拿到的就是对应伤害类的 StatModifier,我们用的所谓增加多少伤害(例:Player实例.GetDamage(DamageClass.Generic) += 0.1f,玩家全伤害增加10%)其实就是对这里的 Additive 属性进行操作,给它增加了0.1f。

你可以给定一个基础伤害,然后传给StatModifier让它进行修正,修正公式为:

(传入伤害+ Base)* Additive * Multipcative + Flat =修正伤害

使用 StatModifier实例.ApplyTo(传入伤害) 就可以获取这个。

Modifiers中有很多 StatModifier 类型的变量,使用时请格外注意四种基础元素的使用,为了你的兼容性。

通用参数

注:下列变量中,AddableFloat 类型使用加算操作,MultipliableFloat 类型使用乘算操作。

名称类型描述备注
SourceDamageStatModifier源伤害修正四基础参均可用
FinalDamageStatModifier终伤害修正由于兼容性,Base 不推荐使用
设定了 Flat 会造成不受任何修正的伤害/减伤
KnockbackStatModifier击退力修正四基础参均可用
ArmorPenetrationAddableFloat固定护甲穿透加算操作
ScalingArmorPenetrationAddableFloat百分比穿甲会在固定穿甲之前结算
不设定为0,为1时忽略100%护甲
HitDirectionint攻击的来向1为右,-1为左,只读,或构造时可设定
HitDirectionOverrideint?修改攻击来向这会影响被击退方向,不赋值则不修改

NPC侧

名称类型描述备注
DamageVariationScaleMultipliableFloat伤害浮动率默认值为1,即默认的+-15%浮动
直接 *= 0 禁用伤害波动
当大于6.67以上时再大也不会有更多效果
因为当趋于6.67的时候浮动已经趋于+-100%
NonCritDamageStatModifier未暴击时修正由于兼容性,Base 不推荐使用
CritDamageStatModifier暴击时修正由于兼容性,Base 不推荐使用
DefenseStatModifier防御力修正四基础参均可用
DefenseEffectivenessMultipliableFloat防御力效力默认值为0.5f,即伤害会被减去NPC的防御力的一半
TargetDamageMultiplierMultipliableFloat目标受伤倍率完全不推荐用此字段,请使用 FinalDamage
原版中用于旗帜、邪教徒的穿透弹幕抗性、
用银制品对抗吸血鬼时造成额外伤害的情况
ScalingBonusDamageAddableFloat额外奖励倍率原版用于招架四倍伤害(+= 4f)和召唤标记增伤
FlatBonusDamageAddableFloat额外奖励净值操作同上
这两奖励跟直接操作 FinalDamage 有区别吗??
DamageTypeDamageClass所属伤害类就是本次攻击所属的伤害类型
SuperArmorbool 超级护甲这就是一个傻逼东西
总之就是 true 的话本次伤害强制为1

玩家侧

名称类型描述备注
IncomingDamageMultiplierMultipliableFloat将受伤害倍率用于在结算防御前减少特定来源的伤害
原版中用于冷源伤害抗性和旗帜伤害减免
KnockbackImmunityEffectivenessMultipliableFloat击退免疫效力默认1f(完全免疫击退)
原版中用于食人魔的弹幕(*= 0.8f
玩家即使装备钴盾也受到20%的击退)
DamageSourcePlayerDeathReason玩家死因只读,或构造时可设定
PlayerDeathReason
.TryGetCausingEntity
方法可以拿到杀死玩家的实体实例
PvPboolpvp模式伤害源是否是pvp状态
CooldownCounterint无敌帧类型只读,或构造时可设定
本次伤害使用的无敌帧计时器的类型
Dodgeablebool可否闪避只读,或构造时可设定
说是本次伤害可否闪避
但源码中这个字段并没有被用作任何判定
当然你可以自己写自己判

好诶,这依托答辩的卖相你已经品鉴了,接下来就开吃吧(?


尝试使用Modifiers

以下需要Global寄术>>>

1、血月时,使用银阔剑对怪物造成伤害时,有额外三成的基础伤害。

// 使用GlobalItem中的攻击NPC
public override void ModifyHitNPC(Item item, Player player, NPC target, ref NPC.HitModifiers modifiers)
{
    if (Main.bloodMoon && item.type == ItemID.SilverBroadsword)
    {
        modifiers.SourceDamage += 0.3f;
    }
}

2、城镇NPC受到的伤害在进入困难模式之后只有1/10,并在花后额外有10点固定减伤。

你会发现NPC并没有 修改被其他NPC攻击的 函数,所以这里要把可能的伤害源都做效果。

// 在GlobalNPC中
// 封装一个方法,不然要把同样的一大串内容写两遍
private static void TownNPCEndurance(NPC npc, ref NPC.HitModifiers modifiers)
{
    // NPC不是城镇NPC就返回,后续代码全部不会执行
    if (!npc.townNPC) return;
    // 肉后受到伤害为1/10
    if (Main.hardMode)
    {
        modifiers.FinalDamage /= 10;
    }
    // 花后获得额外固定减伤
    if (NPC.downedPlantBoss)
    {
        modifiers.FinalDamage.Flat -= 10;
    }
}
public override void ModifyHitNPC(NPC npc, NPC target, ref NPC.HitModifiers modifiers)
{
    // 传入被击目标
    TownNPCEndurance(target, ref modifiers);
}
public override void ModifyHitByProjectile(NPC npc, Projectile projectile, ref NPC.HitModifiers modifiers)
{
    // 传入受击目标
    TownNPCEndurance(npc, ref modifiers);
}

3、让狙击步枪射出的弹幕,没暴击时伤害翻倍并附加100固定伤害,暴击时让伤害再被玩家的远程职业加成修正一次。

StatModifier.CombineWith(StatModifier modifier),返回结果是两个 StatModifier 合并的修正。

// 在GlobalProjectile
public bool sniper = false;
public override bool InstancePerEntity => true;
public override void OnSpawn(Projectile projectile, IEntitySource source)
{
    if (source is EntitySource_ItemUse_WithAmmo use && use.Item.type == ItemID.SniperRifle)
    {
        sniper = true;
    }
}
public override void ModifyHitNPC(Projectile projectile, NPC target, ref NPC.HitModifiers modifiers)
{
    if (sniper)
    {
        modifiers.NonCritDamage *= 2;
        modifiers.NonCritDamage.Flat += 100;
        // 把玩家的远程职业修正合并给暴击修正
        modifiers.CritDamage.CombineWith(Main.player[projectile.owner].GetDamage(DamageClass.Ranged));
    }
}

4、你装备了一个饰品,在受伤时,只会受到一点伤害。

啊哈,也许你会写:modifiers.FinalDamage *= 0modifiers.FinalDamage.Flat -= modifiers.FinalDamage.Flat,但这样有些离谱不是吗()

嘿,这有个设置最大伤害的函数,直接把它设置为1就完了。

其实 Modifier 里面不少东西我没介绍过,留给你们自己探索啦。

好了,本篇教程堂堂完结,这Shit山味道如何?(笑)

发表回复