| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:Apex/STKCalculator
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール:Apex/STKCalculator/doc に作成できます
local STKCalculator = {}
local aw = require('Module:Utility/Library')
local apex = require('Module:Utility/ApexLibrary')
local STKCalculator = {}
function STKCalculator:reset()
self.damages = {}
self.damageStack = 0
self.currentPellets = self.pellets
self.patternIndex = 1
end
function STKCalculator:_getPartMultiplier(forcePart)
local part
if self.patternIndex <= #self.pattern.first then
part = self.pattern.first[self.patternIndex]
else
part = self.pattern.loop[self.patternIndex - #self.pattern.first]
end
if forcePart and part ~= apex.SKY then
part = forcePart
end
local mul
if part == apex.BODY then
mul = self.bodyshot
elseif part == apex.LEGS then
mul = self.legsshot
elseif part == apex.SKY then
mul = self.skyshot
else
mul = apex.calcHeadshotMultiplier(self.headshot, part)
end
return mul
end
function STKCalculator:_nextPart()
if self.patternIndex == #self.pattern.first + #self.pattern.loop then
self.patternIndex = 1 + #self.pattern.first
else
self.patternIndex = self.patternIndex + 1
end
end
function STKCalculator:_saveState(damage)
self.damageStack = self.damageStack + damage
self.currentPellets = self.currentPellets - 1
if self.currentPellets <= 0 then
self.currentPellets = self.pellets
table.insert(self.damages, self.damageStack)
self.damageStack = 0
self:_nextPart()
end
end
local function calcDamage(base, passthrough, partmul, passive, opts, finalfunc)
-- 貫通減衰倍率
if passthrough < 1 then
base = apex.calcPassthroughDamage(base, passthrough)
end
-- 部位倍率、小柄・鉄壁
base = apex.calcDamageFromPartAndPassive(base, partmul, passive, opts)
-- 最終関数
if finalfunc then
base = finalfunc(base)
end
return base
end
function STKCalculator:_calcShotToKill(base, passive, points, cond, isLast, forcePart, finalfunc)
local partmul = self:_getPartMultiplier(forcePart)
local damage = calcDamage(base, self.passthrough, partmul, passive, self.opts, finalfunc)
local hasBeam = self.beamdamage > 0 and self.beamticks > 0
local beamdamage
if hasBeam then
beamdamage = apex.calcDamageFromPartAndPassive(self.beamdamage, partmul, passive, self.opts)
else
beamdamage = 0
end
repeat
if hasBeam then
for t = 1, self.beamticks do
if not cond(points, damage) then
break
end
points = points - beamdamage
self.damageStack = self.damageStack + beamdamage
end
end
if not cond(points, damage) then
break
end
points = points - damage
self:_saveState(damage)
partmul = self:_getPartMultiplier(forcePart)
damage = calcDamage(base, self.passthrough, partmul, passive, self.opts, finalfunc)
if hasBeam then
beamdamage = apex.calcDamageFromPartAndPassive(self.beamdamage, partmul, passive, self.opts)
end
until not cond(points, damage)
if isLast then
if self.damageStack > 0 then
self.currentPellets = self.pellets
table.insert(self.damages, self.damageStack)
self.damageStack = 0
self:_nextPart()
end
end
return points
end
-- ポイントが0かどうか確認する関数
local function isEqualToZero(points, _)
return points > 0
end
-- ポイントがダメージ以上かどうか確認する関数
local function isGreaterThanOrEqualToDamage(points, damage)
return points >= damage
end
function STKCalculator:calcShotToKill(health, shield, gunshield, passive)
legend = legend or 1
-- ガンシールド
if gunshield > 0 then
local cond
if self.gunshieldBleedthrough then
cond = isGreaterThanOrEqualToDamage
else
cond = isEqualToZero
end
self.patternIndex = 1 + #self.pattern.first -- 強制的に loop パターンの呼び出し
gunshield = self:_calcShotToKill(self.damage, 1, gunshield, cond, not self.gunshieldBleedthrough, apex.BODY)
-- ガンシールドとシールド/体力の混合
while gunshield > 0 do
local mul = self:_getPartMultiplier(apex.BODY)
if mul > 0 then
local leftDamage = apex.calcDamageFromPartAndPassive(self.damage - gunshield, mul, passive, self.opts)
if shield >= leftDamage then
shield = shield - leftDamage
elseif shield > 0 then
health = health - (leftDamage - shield)
shield = 0
else
health = health - leftDamage
end
self:_saveState(gunshield + leftDamage)
gunshield = 0
else
self:_saveState(0)
end
end
self.patternIndex = 1 -- 強制的に first パターンに戻す
end
-- ディスラプター弾
if self.disruptorRounds > 1 then
-- シールド
local finalfunc = function(damage)
return apex.calcDisruptorDamage(damage, self.disruptorRounds)
end
shield = self:_calcShotToKill(self.damage, passive, shield, isGreaterThanOrEqualToDamage, false, nil, finalfunc)
-- シールドと体力の混合
while shield > 0 do
local mul = self:_getPartMultiplier(apex.BODY)
if mul > 0 then
local partDamage = apex.calcPartDamage(self.damage, mul)
local minDamage = apex.calcPassiveDamage(partDamage, passive, self.opts)
local maxDamage = apex.calcPassiveDamage(apex.calcDisruptorDamage(partDamage, self.disruptorRounds), passive, self.opts)
local mergedDamage = aw.clamp(maxDamage, minDamage, math.max(minDamage, shield))
health = health - (mergedDamage - shield)
shield = 0
self:_saveState(mergedDamage)
else
self:_saveState(0)
end
end
-- 体力
health = self:_calcShotToKill(self.damage, passive, health, isEqualToZero, true)
-- ハンマーポイント弾
elseif self.hammerpointRounds > 1 then
-- シールド
shield = self:_calcShotToKill(self.damage, passive, shield, isGreaterThanOrEqualToDamage)
-- シールドと体力の混合
while shield > 0 do
local mul = self:_getPartMultiplier(apex.BODY)
if mul > 0 then
local baseMergedDamage
if shield < self.damage then
baseMergedDamage = shield + apex.calcHammerpointDamage(self.damage - shield, self.hammerpointRounds)
else
baseMergedDamage = self.damage
end
local mergedDamage = apex.calcDamageFromPartAndPassive(baseMergedDamage, mul, passive, self.opts)
health = health - (mergedDamage - shield)
shield = 0
self:_saveState(mergedDamage)
else
self:_saveState(0)
end
end
-- 体力
local hammerpointDamage = apex.calcHammerpointDamage(self.damage, self.hammerpointRounds)
health = self:_calcShotToKill(hammerpointDamage, passive, health, isEqualToZero, true)
-- ボディーシールド
else
self:_calcShotToKill(self.damage, passive, health + shield, isEqualToZero, true)
end
end
function STKCalculator:getTable()
return self.damages
end
function STKCalculator:get()
return #self.damages
end
function STKCalculator:setPattern(pattern)
if pattern then
pattern.first = pattern.first or {}
pattern.loop = pattern.loop or { apex.BODY }
self.pattern = pattern
else
self.pattern = { first = {}, loop = { apex.BODY }}
end
end
function STKCalculator.new(damage, opts)
opts = opts or {}
if opts.pattern then
opts.pattern.first = opts.pattern.first or {}
opts.pattern.loop = opts.pattern.loop or { apex.BODY }
else
opts.pattern = { first = {}, loop = { apex.BODY }}
end
-- 増幅バリケードが有効
if opts.ampedCover then
damage = aw.round(1.2 * damage)
end
-- チャージ倍率が有効
if opts.charged then
damage = aw.round(opts.charged * damage)
end
local obj = setmetatable({
damage = damage,
bodyshot = opts.bodyshot or 1,
headshot = opts.headshot or 2,
legsshot = opts.legsshot or 0.75,
skyshot = opts.skyshot or 0,
passthrough = opts.passthrough or 1,
pattern = opts.pattern,
pellets = opts.pellets or 1,
beamdamage = opts.beamdamage or 0,
beamticks = opts.beamticks or 0,
disruptorRounds = opts.disruptorRounds or 0,
hammerpointRounds = opts.hammerpointRounds or 0,
gunshieldBleedthrough = opts.gunshieldBleedthrough ~= false,
opts = {
ampedCover = opts.ampedCover or false,
round = opts.round or false,
ignorePassiveForHeadshot = opts.ignorePassiveForHeadshot ~= false,
},
}, { __index = STKCalculator })
obj:reset()
return obj
end
function STKCalculator.newFromStat(stat, opts)
local stat2, damagestat, pellets
if stat.anvil_receiver and opts.useAnvilReceiver then
stat2 = stat.anvil_receiver
damagestat = stat.anvil_receiver.damage or stat.damage
pellets = opts.pellets or stat.anvil_receiver.pellet or stat.pellet
elseif stat.shatter_caps and opts.useShatterCaps then
stat2 = stat.shatter_caps
damagestat = stat.shatter_caps.damage or stat.damage
pellets = opts.pellets or stat.shatter_caps.pellet or stat.pellet
else
stat2 = stat
damagestat = stat.damage
pellets = opts.pellets or stat.pellet
end
local damage
if opts.useAmpedMode then
damage = damagestat.amped or damagestat.base
elseif opts.useCharged then
damage = damagestat.charged or damagestat.base
else
damage = damagestat.base
end
local beamdamage, beamticks
if damagestat.beam then
beamdamage = damagestat.beam.base
if opts.ticks then
beamticks = math.min(opts.ticks, damagestat.beam.ticks)
else
beamticks = damagestat.beam.ticks
end
else
beamdamage = 0
beamticks = 0
end
return STKCalculator.new(damage, {
bodyshot = opts.bodyshot,
headshot = stat2.damage_head_scale or stat.damage_head_scale,
legsshot = stat2.damage_legs_scale or stat.damage_legs_scale,
skyshot = opts.skyshot,
passthrough = opts.passthrough,
pattern = opts.pattern,
pellets = pellets,
beamdamage = beamdamage,
beamticks = beamticks,
disruptorRounds = opts.useDisruptorRounds and stat.disruptor_rounds and stat.disruptor_rounds.damage_shield_scale or 0,
hammerpointRounds = opts.useHammerpointRounds and stat.hammerpoint_rounds and stat.hammerpoint_rounds.damage_unshielded_scale or 0,
})
end
function apex.calcShotCount(base, part, passive, health, shield, gunshield, opts)
opts = opts or {}
opts.ampedCover = opts.ampedCover or false
opts.bodyshot = part or opts.bodyshot or 1
opts.disruptorRounds = opts.disruptorRounds or 0
opts.hammerpointRounds = opts.hammerpointRounds or 0
opts.gunshieldBleedthrough = opts.gunshieldBleedthrough ~= false
opts.ignorePassiveForHeadshot = opts.ignorePassiveForHeadshot ~= false
opts.passthrough = opts.passthrough or 1
opts.pellets = opts.pellets or 1
opts.round = opts.round or false
local stkc = STKCalculator.new(base, opts)
stkc:calcShotToKill(health, shield, gunshield, passive)
return stkc:getTable()
end
STKCalculator.calcShotCount = apex.calcShotCount
return STKCalculator