🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:Apex/STKCalculator」の版間の差分
ナビゲーションに移動
検索に移動
(チャージライフルのビーム演算に対応) |
(ヘッドショットに対するパッシブ倍率を無効化する機能をフラグで有効・無効にできるように変更) |
||
(同じ利用者による、間の23版が非表示) | |||
16行目: | 16行目: | ||
function STKCalculator:_getPartMultiplier(forcePart) | function STKCalculator:_getPartMultiplier(forcePart) | ||
local part | local part | ||
if | if self.patternIndex <= #self.pattern.first then | ||
part = self.pattern.first[self.patternIndex] | part = self.pattern.first[self.patternIndex] | ||
else | else | ||
part = self.pattern.loop[self.patternIndex - #self.pattern.first] | part = self.pattern.loop[self.patternIndex - #self.pattern.first] | ||
end | |||
if forcePart and part ~= apex.SKY then | |||
part = forcePart | |||
end | end | ||
45行目: | 47行目: | ||
end | end | ||
function STKCalculator: | function STKCalculator:_saveState(damage) | ||
self.damageStack = self.damageStack + damage | |||
self.currentPellets = self.currentPellets - 1 | |||
if self.currentPellets <= 0 then | if self.currentPellets <= 0 then | ||
self.currentPellets = self.pellets | self.currentPellets = self.pellets | ||
table.insert(self.damages, self.damageStack) | table.insert(self.damages, self.damageStack) | ||
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 | end | ||
return base | |||
end | end | ||
function STKCalculator:_calcShotToKill(base, passive, points, cond, isLast, forcePart) | function STKCalculator:_calcShotToKill(base, passive, points, cond, isLast, forcePart, finalfunc) | ||
local partmul = self:_getPartMultiplier(forcePart) | local partmul = self:_getPartMultiplier(forcePart) | ||
local damage = | local damage = calcDamage(base, self.passthrough, partmul, passive, self.opts, finalfunc) | ||
local hasBeam = self.beamdamage > 0 and self.beamticks > 0 | local hasBeam = self.beamdamage > 0 and self.beamticks > 0 | ||
local beamdamage | |||
if hasBeam then | if hasBeam then | ||
beamdamage = apex.calcDamageFromPartAndPassive(self.beamdamage, partmul, passive, self.opts) | |||
else | |||
beamdamage = 0 | |||
end | 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 | end | ||
until not cond(points, damage) | |||
if isLast then | if isLast then | ||
82行目: | 116行目: | ||
table.insert(self.damages, self.damageStack) | table.insert(self.damages, self.damageStack) | ||
self.damageStack = 0 | self.damageStack = 0 | ||
self:_nextPart() | |||
end | end | ||
end | end | ||
return points | return points | ||
end | |||
-- ポイントが0かどうか確認する関数 | |||
local function isEqualToZero(points, _) | |||
return points > 0 | |||
end | |||
-- ポイントがダメージ以上かどうか確認する関数 | |||
local function isGreaterThanOrEqualToDamage(points, damage) | |||
return points >= damage | |||
end | end | ||
93行目: | 138行目: | ||
-- ガンシールド | -- ガンシールド | ||
if gunshield > 0 then | if gunshield > 0 then | ||
local cond = | 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 | end | ||
self.patternIndex = 1 -- 強制的に first パターンに戻す | |||
end | end | ||
-- | -- ディスラプター弾 | ||
if self. | if self.disruptorRounds > 1 then | ||
-- シールド | -- シールド | ||
local | local finalfunc = function(damage) | ||
return | return apex.calcDisruptorDamage(damage, self.disruptorRounds) | ||
end | end | ||
shield = self:_calcShotToKill(self.damage, passive, shield, | shield = self:_calcShotToKill(self.damage, passive, shield, isGreaterThanOrEqualToDamage, false, nil, finalfunc) | ||
-- シールドと体力の混合 | -- シールドと体力の混合 | ||
while shield > 0 do | |||
local | local mul = self:_getPartMultiplier(apex.BODY) | ||
if | 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 | else | ||
self:_saveState(0) | |||
end | end | ||
end | end | ||
-- 体力 | -- 体力 | ||
local | 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 | end | ||
-- 体力 | |||
local hammerpointDamage = apex.calcHammerpointDamage(self.damage, self.hammerpointRounds) | |||
health = self:_calcShotToKill(hammerpointDamage, passive, health, isEqualToZero, true) | |||
-- ボディーシールド | -- ボディーシールド | ||
else | else | ||
self:_calcShotToKill(self.damage, passive, health + shield, isEqualToZero, true) | |||
self:_calcShotToKill(self.damage, passive, health + shield, | |||
end | end | ||
end | end | ||
149行目: | 244行目: | ||
if pattern then | if pattern then | ||
pattern.first = pattern.first or {} | pattern.first = pattern.first or {} | ||
pattern.loop = pattern.loop or {} | pattern.loop = pattern.loop or { apex.BODY } | ||
self.pattern = pattern | self.pattern = pattern | ||
else | else | ||
160行目: | 255行目: | ||
if opts.pattern then | if opts.pattern then | ||
opts.pattern.first = opts.pattern.first or {} | opts.pattern.first = opts.pattern.first or {} | ||
opts.pattern.loop = opts.pattern.loop or {} | opts.pattern.loop = opts.pattern.loop or { apex.BODY } | ||
else | else | ||
opts.pattern = { first = {}, loop = { apex.BODY }} | opts.pattern = { first = {}, loop = { apex.BODY }} | ||
168行目: | 263行目: | ||
if opts.ampedCover then | if opts.ampedCover then | ||
damage = aw.round(1.2 * damage) | damage = aw.round(1.2 * damage) | ||
end | |||
-- チャージ倍率が有効 | |||
if opts.charged then | |||
damage = aw.round(opts.charged * damage) | |||
end | end | ||
local obj = setmetatable({ | local obj = setmetatable({ | ||
damage | damage = damage, | ||
bodyshot | bodyshot = opts.bodyshot or 1, | ||
headshot | headshot = opts.headshot or 2, | ||
legsshot | legsshot = opts.legsshot or 0.75, | ||
skyshot | skyshot = opts.skyshot or 0, | ||
pattern | passthrough = opts.passthrough or 1, | ||
pellets | pattern = opts.pattern, | ||
beamdamage = opts.beamdamage or 0, | pellets = opts.pellets or 1, | ||
beamticks | beamdamage = opts.beamdamage or 0, | ||
beamticks = opts.beamticks or 0, | |||
disruptorRounds = opts.disruptorRounds or 0, | |||
hammerpointRounds = opts.hammerpointRounds or 0, | hammerpointRounds = opts.hammerpointRounds or 0, | ||
gunshieldBleedthrough = opts.gunshieldBleedthrough ~= false, | |||
opts = { | opts = { | ||
ampedCover = opts.ampedCover or false, | ampedCover = opts.ampedCover or false, | ||
round = opts.round or false, | round = opts.round or false, | ||
ignorePassiveForHeadshot = opts.ignorePassiveForHeadshot ~= false, | |||
}, | }, | ||
}, { __index = STKCalculator }) | }, { __index = STKCalculator }) | ||
191行目: | 295行目: | ||
function STKCalculator.newFromStat(stat, opts) | function STKCalculator.newFromStat(stat, opts) | ||
local damagestat | local stat2, damagestat, pellets | ||
if opts.useAnvilReceiver then | if stat.anvil_receiver and opts.useAnvilReceiver then | ||
damagestat = stat.damage.anvil_receiver or stat.damage | 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 | else | ||
stat2 = stat | |||
damagestat = stat.damage | damagestat = stat.damage | ||
pellets = opts.pellets or stat.pellet | |||
end | end | ||
local damage | local damage | ||
if opts.useAmpedMode then | if opts.useAmpedMode then | ||
damage = | damage = damagestat.amped or damagestat.base | ||
elseif opts.useCharged then | |||
damage = damagestat.charged or damagestat.base | |||
else | else | ||
damage = | damage = damagestat.base | ||
end | end | ||
local beamdamage, beamticks | local beamdamage, beamticks | ||
if | if damagestat.beam then | ||
beamdamage = | beamdamage = damagestat.beam.base | ||
if opts.ticks then | if opts.ticks then | ||
beamticks = math.min(opts.ticks, | beamticks = math.min(opts.ticks, damagestat.beam.ticks) | ||
else | else | ||
beamticks = | beamticks = damagestat.beam.ticks | ||
end | end | ||
else | else | ||
220行目: | 334行目: | ||
return STKCalculator.new(damage, { | return STKCalculator.new(damage, { | ||
bodyshot | bodyshot = opts.bodyshot, | ||
headshot | headshot = stat2.damage_head_scale or stat.damage_head_scale, | ||
legsshot | legsshot = stat2.damage_legs_scale or stat.damage_legs_scale, | ||
skyshot | skyshot = opts.skyshot, | ||
pattern | passthrough = opts.passthrough, | ||
pellets | pattern = opts.pattern, | ||
beamdamage = beamdamage, | pellets = pellets, | ||
beamticks | 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 | end | ||
234行目: | 350行目: | ||
function apex.calcShotCount(base, part, passive, health, shield, gunshield, opts) | function apex.calcShotCount(base, part, passive, health, shield, gunshield, opts) | ||
opts = opts or {} | opts = opts or {} | ||
opts.ampedCover | opts.ampedCover = opts.ampedCover or false | ||
opts.bodyshot | opts.bodyshot = part or opts.bodyshot or 1 | ||
opts.hammerpointRounds = opts.hammerpointRounds or 0 | opts.disruptorRounds = opts.disruptorRounds or 0 | ||
opts.pellets | opts.hammerpointRounds = opts.hammerpointRounds or 0 | ||
opts.round | 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) | local stkc = STKCalculator.new(base, opts) | ||
244行目: | 364行目: | ||
return stkc:getTable() | return stkc:getTable() | ||
end | end | ||
STKCalculator.calcShotCount = apex.calcShotCount | |||
return STKCalculator | return STKCalculator |
2022年5月25日 (水) 08:11時点における最新版
このモジュールについての説明文ページを モジュール: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