Featured image of post 闪耀星骑士的伤害计算

闪耀星骑士的伤害计算

前言

wiki上的ダメージ計算式基本算是完全正确,这里结合逆向的代码随意解释分析一下。

最终公式:

1
Damage = ATK × A × B × C × D × E × F × G × H × I × J

总而言之就是ATK乘上一大堆乘区,TSKBattleCalculationManager.CaluculationNormalDamage就是当前攻击造成伤害的计算函数。多段攻击的每一段对上每个敌人都会分别计算。

ATK

出発前ATKTSKBattleNote.GetBaseAttack,也是在有着出击的编队界面点点右上角的反转按钮能看到的ATK数值。

出発前ATKATK倍率(加算倍率)计算后的ATK是TSKBattleNote.GetAttack,也就是战斗中选技能前能看到的ATK数值。

GetAttack通过GetBaseAttack获取baseAttack后,判断有没有charge,之后计算各个SkillEffect,包括最常见的AtkUp。

实战试了下。baseAttack=3550 attack=298619的情况下倍率约为84.118。相关SkillEffect如下:

1
2
3
4
AtkUp: value=437560 effectValue=437560
AtkUpStepUp: value=6020 effectValue=64120
AtkUpRaceAffiliat: value=26500 effectValue=79500
AtkUpTypeOut: value=50000 effectValue=250000

大家的effectValue加起来刚好是831180,8311.80%即是83.11倍的加攻,与倍率对的上。分别按全体、基礎ATK、种族个数、属性个数赋予的加攻。

一开始还想着同一个乘区的加攻分这么复杂干嘛,转念一想未来说不定想出个能力是“队伍中按属性加攻效果翻倍”的角色,那还挺期待的,游戏初期怎样抽象都不是坏事,虽然已经三周年的现在不是游戏初期,出个这种神奇能力的新角色也不一定是好事。

AtkUpRaceAffiliat

顺带一提,AtkUpRaceAffiliat具体SkillEffect长这样:

1
effect 41: type=AtkUpRaceAffiliat time=17 value=5300 effectValue=15900 value2=1 value3=7 value4=1 value5=0

value2=1 value3=7 value4=1 value5=0太过意义不明先不去考虑,value=5300是33%+20%,对应我美の冒涜者 (ヴァレリー)的7级技能和满配装饰,effectValue是value*3,是技能中条件符合的人数,因为我在玩魔菲队。

AtkUpStepUp

再一提,AtkUpStepUp具体SkillEffect长这样:

1
effect 16: type=AtkUpStepUp time=30 value=2700 effectValue=31200 value2=200 value3=45000 value4=1 value5=15000

我使用的是ex2技能10:

1
人間または光属性の味方のATKを100%+自身の基礎ATK200ごと×18%アップ(30CT)(最大300%)

以及+4装飾品

1
2
EX2「聖なる波動」のATKの上昇値が50%+自身の基礎ATK200ごと×9%アップ/
ATKアップの最大値をさらに150%アップ/

基礎ATK==1306[Magica2026]ここあ

1
150% + floor(1306/200) * (18+9%) = 150% + 162% = 312%

与effectValue对的上,value也是基础倍率27%,猜一猜也能大致猜出:value2是基礎ATK的基数,value3是加攻上限,别的字段就不知道啦~

看了该SkillEffect也或许可以变相说明为什么不全一股脑塞进AtkUp。

A. 技能倍率

EXスキル倍率(A)可以通过TSKBattleCalculationManager.CaluculationNormalDamage的args[4]获取。

B. 爆伤倍率

クリティカルダメージ倍率(B)通过TSKBattleCalculationManager.CriticalOffset(...args)获取;同时该函数可以了解是否暴击: const isCritilal = args[0];;没有任何buff时是1.5。

C. 克制倍率

属性ダメージ倍率(C)通过TSKBattleCalculationManager.AttributeOffset(...args)获取。有利属性时是C=150%+有利属性ダメージ倍率(%)

D. スタンダメージ倍率

スタンダメージ倍率(D)通过TSKBattleCalculationManager.DownOffset(...args)获取。スタン時: D=200%+相手スタン時ダメージ倍率(%)

E. 易伤

被ダメージ増減倍率(E)理论是在TSKBattleNote.GetDamageRateValue的代码中,但我没找到。不过可以通过defencer(TSKBattleNote)的defencer.field("skillEffectList").value as Il2Cpp.Object;得到所有SkillEffect,其中type==SkillType.DmgUpAllyRateBit的就是易伤值,effect.field("<SkillEffectValue>k__BackingField")得到的effectValue=3000就代表30%,List中可能有多个易伤,相加就行了,别忘了最后加上1。(该SkillEffect中还有个SkillValue1=600的值,意义不明(意义明了,基础是6%,队中5个符合技能条件*5才得到的30%))

F. 特殊易伤

デバフダメージ倍率(F) 是在TSKBattleNote.GetDamageRateValue中计算的。典型的是[霹靂の射手]梨緒赋予的標的,50%额外易伤,SkillEffect的形式是SkillType.Target: effect 13: type=Target time=16 value=5000 effectValue=0,这里是存在effect.field("<SkillValue1>k__BackingField")中,和上述的易伤(E)存在class TSKBattleSkillData中不同的变量,很变态,不知道它这样做的理由。

然后各个属性的融解極冷以及各个攻撃タイプ裂傷破砕等专属易伤没仔细看,不过代码中都有,似乎是直接相加,TSKBattleNote.GetDamageRateValue中搜索TSKBattleNote.GetSkillEffect都能找到。例如TSKBattleNote.GetSkillEffect(param_1,0x1a7,0);,0x1a7=423对应SkillType.Collapse。(16进制->10进制->enum->英文->日语,要对应谁是谁太头大了,虽然可以通过上面代码的

1
2
3
if (((*(longlong *)(attacker + 0x10) != **(longlong **)(IntPtr_TypeInfo + 0xb8)) &&
    (*(longlong *)(attacker + 0x98) != 0)) &&
    (*(int *)(*(longlong *)(attacker + 0x98) + 0x34) == 5))

来定位attacker的属性和攻击类型,但也看的很累;且这里翻译完马上就忘了。

(这里去查了下,attacker + 0x98private TSKBattleUnit <UnitData>k__BackingField; //Field offset: 0x98TSKBattleUnit+0x34private int <AttrType>k__BackingField; //Field offset: 0x34,AttrType==5是什么意思呢,让我猜猜,Collapse的中文翻译是坍塌,日文翻译是崩壊,看来它是对应崩壊: 闇属性から受けるダメージAttrType==5代表是暗属性。好恶心好恶心。)

G. rush倍率

ラッシュ倍率(G)通过TSKBattleCalculationManager.RushOffset(...args)获取。一般情况的上限是RushOffset = 6.699999809265137,与wiki中的ただし、RUSH倍率はRUSH101の+570%で頭打ちになるようで、そこから先はどれだけRUSH数を伸ばしても倍率は変わらない一致。

H. BOOST倍率

ダメージBOOST(H)没找,它目前是討伐イベント特有的,一般也用不上。

I. 减伤

被ダメージカット率(I) 没找到,不过应该是在TSKBattleNote.GetDamageRateValue中之后。

测试时SkillEffect中有个effect 0: type=PassiveDamageCutType time=9963 value=7000 effectValue=0,对应70%减伤,GetDamageRateValue返回值是364474,CaluculationNormalDamage的返回值0x1ab1f==109343,刚好对应*0.3,向上取整。

J. 随机数

乱数(J)通过TSKBattleCalculationManager.FluctuationOffset获取。我测试下来也是1.00倍~1.01倍(100%~101%)

额外

ユニゾンアタック不讲,这个应该不能暴击。

总结

总之:

1
Damage = ATK * A * B * ... * I * J。

去寻找你所爱的乘区吧。

然后

虽然wiki上ABCDEFG按顺序排,但代码中不是这个顺序,

先获取damage = ATK * SkillValue * FluctuationOffset * RushOffset * AttributeOffset * CriticalOffset * DownOffset,算出理论伤害,后续再通过GetDamageRateValue去计算defencer的减伤易伤。获取GetDamageRateValue的返回值再最后计算伤害cut。

使用 Hugo 构建
主题 StackJimmy 设计