| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:Apex/STKCalculator」の版間の差分
ナビゲーションに移動
検索に移動
(calcShotCountのガンシールド貫通状態に変更に対応) |
(ヘッドショットに対するパッシブ倍率を無効化する機能をフラグで有効・無効にできるように変更) |
||
| (同じ利用者による、間の7版が非表示) | |||
| 59行目: | 59行目: | ||
end | end | ||
function STKCalculator:_calcShotToKill(base, passive, points, cond, isLast, forcePart) | 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 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 | local beamdamage | ||
| 88行目: | 105行目: | ||
partmul = self:_getPartMultiplier(forcePart) | partmul = self:_getPartMultiplier(forcePart) | ||
damage = | damage = calcDamage(base, self.passthrough, partmul, passive, self.opts, finalfunc) | ||
if hasBeam then | if hasBeam then | ||
beamdamage = apex.calcDamageFromPartAndPassive(self.beamdamage, partmul, passive, self.opts) | beamdamage = apex.calcDamageFromPartAndPassive(self.beamdamage, partmul, passive, self.opts) | ||
| 153行目: | 170行目: | ||
self.patternIndex = 1 -- 強制的に first パターンに戻す | self.patternIndex = 1 -- 強制的に first パターンに戻す | ||
end | 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) | shield = self:_calcShotToKill(self.damage, passive, shield, isGreaterThanOrEqualToDamage) | ||
| 165行目: | 209行目: | ||
local baseMergedDamage | local baseMergedDamage | ||
if shield < self.damage then | if shield < self.damage then | ||
baseMergedDamage = shield + | baseMergedDamage = shield + apex.calcHammerpointDamage(self.damage - shield, self.hammerpointRounds) | ||
else | else | ||
baseMergedDamage = self.damage | baseMergedDamage = self.damage | ||
| 180行目: | 224行目: | ||
-- 体力 | -- 体力 | ||
local hammerpointDamage = apex.calcHammerpointDamage(self.damage, self.hammerpointRounds) | |||
health = self:_calcShotToKill(hammerpointDamage, passive, health, isEqualToZero, true) | |||
-- ボディーシールド | -- ボディーシールド | ||
| 218行目: | 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, | gunshieldBleedthrough = opts.gunshieldBleedthrough ~= false, | ||
| 235行目: | 287行目: | ||
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 }) | ||
| 242行目: | 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 | ||
| 273行目: | 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, | ||
hammerpointRounds = opts.useHammerpointRounds and | 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 | ||
| 287行目: | 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.disruptorRounds = opts.disruptorRounds or 0 | ||
opts.gunshieldBleedthrough = opts.gunshieldBleedthrough ~= false | opts.hammerpointRounds = opts.hammerpointRounds or 0 | ||
opts.pellets | opts.gunshieldBleedthrough = opts.gunshieldBleedthrough ~= false | ||
opts.round | 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) | ||
| 298行目: | 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