“鉴于1436乱七八糟的伤害修改机制, 鸡骨头:无所谓,我会出手 于是新的屎山诞生了。”——摘自《泰拉编年史》
端都端上来了,不吃也得吃,害。
那么首先粗略浏览一下都有肾么菜罢。
Item侧:
Proj侧:
NPC侧:
以上全部都有Global系列的版本。以及,类似于Global系列的玩家侧:
看起来很多对吧,找找它们的共同点?
对,就是那个带了 ref
的结构体,Modifiers
,万恶之源
认识Modifiers
很明显这玩意有两个版本,一个是NPC的 HitModifiers
,一个是玩家的 HurtModifiers
。不急,咱一个个来,使用导航把它看个通透。
再此之前先稍微了解一下 StatModifier
类,这个玩意儿由四个基础元素组成:
参数 | 类型 | 描述 | 默认值 |
---|---|---|---|
Base | float | 额外附加基础伤害 | 0 |
Additive | float | 加算修正,只能在构造时直接设置,但可以用+-运算符操作 | 1 |
Multiplicative | float | 乘算修正,只能在构造时直接设置,但可以用*/运算符操作 | 1 |
Flat | float | 额外附加净伤害 | 0 |
玩家的 GetDamage
方法拿到的就是对应伤害类的 StatModifier
,我们用的所谓增加多少伤害(例:Player实例.GetDamage(DamageClass.Generic) += 0.1f
,玩家全伤害增加10%)其实就是对这里的 Additive
属性进行操作,给它增加了0.1f。
你可以给定一个基础伤害,然后传给StatModifier
让它进行修正,修正公式为:
(传入伤害+ Base
)* Additive
* Multipcative
+ Flat
=修正伤害
使用 StatModifier实例.ApplyTo(传入伤害)
就可以获取这个。
Modifiers
中有很多 StatModifier
类型的变量,使用时请格外注意四种基础元素的使用,为了你的兼容性。
通用参数
注:下列变量中,AddableFloat
类型使用加算操作,MultipliableFloat
类型使用乘算操作。
名称 | 类型 | 描述 | 备注 |
---|---|---|---|
SourceDamage | StatModifier | 源伤害修正 | 四基础参均可用 |
FinalDamage | StatModifier | 终伤害修正 | 由于兼容性,Base 不推荐使用设定了 Flat 会造成不受任何修正的伤害/减伤 |
Knockback | StatModifier | 击退力修正 | 四基础参均可用 |
ArmorPenetration | AddableFloat | 固定护甲穿透 | 加算操作 |
ScalingArmorPenetration | AddableFloat | 百分比穿甲 | 会在固定穿甲之前结算 不设定为0,为1时忽略100%护甲 |
HitDirection | int | 攻击的来向 | 1为右,-1为左,只读,或构造时可设定 |
HitDirectionOverride | int? | 修改攻击来向 | 这会影响被击退方向,不赋值则不修改 |
NPC侧
名称 | 类型 | 描述 | 备注 |
---|---|---|---|
DamageVariationScale | MultipliableFloat | 伤害浮动率 | 默认值为1,即默认的+-15%浮动 直接 *= 0 禁用伤害波动当大于6.67以上时再大也不会有更多效果 因为当趋于6.67的时候浮动已经趋于+-100% |
NonCritDamage | StatModifier | 未暴击时修正 | 由于兼容性,Base 不推荐使用 |
CritDamage | StatModifier | 暴击时修正 | 由于兼容性,Base 不推荐使用 |
Defense | StatModifier | 防御力修正 | 四基础参均可用 |
DefenseEffectiveness | MultipliableFloat | 防御力效力 | 默认值为0.5f,即伤害会被减去NPC的防御力的一半 |
TargetDamageMultiplier | MultipliableFloat | 目标受伤倍率 | 完全不推荐用此字段,请使用 FinalDamage 原版中用于旗帜、邪教徒的穿透弹幕抗性、 用银制品对抗吸血鬼时造成额外伤害的情况 |
ScalingBonusDamage | AddableFloat | 额外奖励倍率 | 原版用于招架四倍伤害(+= 4f )和召唤标记增伤 |
FlatBonusDamage | AddableFloat | 额外奖励净值 | 操作同上 这两奖励跟直接操作 FinalDamage 有区别吗?? |
DamageType | DamageClass | 所属伤害类 | 就是本次攻击所属的伤害类型 |
SuperArmor | bool | 超级护甲 | 这就是一个傻逼东西 总之就是 true 的话本次伤害强制为1 |
玩家侧
名称 | 类型 | 描述 | 备注 |
---|---|---|---|
IncomingDamageMultiplier | MultipliableFloat | 将受伤害倍率 | 用于在结算防御前减少特定来源的伤害 原版中用于冷源伤害抗性和旗帜伤害减免 |
KnockbackImmunityEffectiveness | MultipliableFloat | 击退免疫效力 | 默认1f(完全免疫击退) 原版中用于食人魔的弹幕( *= 0.8f ,玩家即使装备钴盾也受到20%的击退) |
DamageSource | PlayerDeathReason | 玩家死因 | 只读,或构造时可设定 用 PlayerDeathReason .TryGetCausingEntity 方法可以拿到杀死玩家的实体实例 |
PvP | bool | pvp模式 | 伤害源是否是pvp状态 |
CooldownCounter | int | 无敌帧类型 | 只读,或构造时可设定 本次伤害使用的无敌帧计时器的类型 |
Dodgeable | bool | 可否闪避 | 只读,或构造时可设定 说是本次伤害可否闪避 但源码中这个字段并没有被用作任何判定 当然你可以自己写自己判 |
好诶,这依托答辩的卖相你已经品鉴了,接下来就开吃吧(?
尝试使用Modifiers
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 = modifiers.CritDamage.CombineWith(Main.player[projectile.owner].GetDamage(DamageClass.Ranged)); } }
4、你装备了一个饰品,在受伤时,只会受到一点伤害。
啊哈,也许你会写:modifiers.FinalDamage *= 0
,modifiers.FinalDamage.Flat -= modifiers.FinalDamage.Flat
,但这样有些离谱不是吗()
嘿,这有个设置最大伤害的函数,直接把它设置为1就完了。
其实 Modifier
里面不少东西我没介绍过,留给你们自己探索啦。
好了,本篇教程堂堂完结,这Shit山味道如何?(笑)