| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:Apex/STKCalculator」の版間の差分
ナビゲーションに移動
検索に移動
(ペレット周りの部位パターン実装の不具合を修正) |
(ガンシールド貫通に対応(一部複合ダメージの不具合も修正済み)) |
||
| 47行目: | 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() | self:_nextPart() | ||
end | end | ||
| 81行目: | 84行目: | ||
end | end | ||
points | points = points - damage | ||
self:_saveState(damage) | |||
self: | |||
partmul = self:_getPartMultiplier(forcePart) | partmul = self:_getPartMultiplier(forcePart) | ||
| 104行目: | 104行目: | ||
return points | return points | ||
end | |||
-- ポイントが0かどうか確認する関数 | |||
local function isEqualToZero(points, _) | |||
return points > 0 | |||
end | |||
-- ポイントがダメージ以上かどうか確認する関数 | |||
local function isGreaterThanOrEqualToDamage(points, damage) | |||
return points >= damage | |||
end | end | ||
| 111行目: | 121行目: | ||
-- ガンシールド | -- ガンシールド | ||
if gunshield > 0 then | if gunshield > 0 then | ||
local cond = | local cond | ||
if self.gunshieldBleedthrough then | |||
cond = isGreaterThanOrEqualToDamage | |||
else | |||
cond = isEqualToZero | |||
end | end | ||
self.patternIndex = 1 + #self.pattern.first -- 強制的に loop パターンの呼び出し | self.patternIndex = 1 + #self.pattern.first -- 強制的に loop パターンの呼び出し | ||
self:_calcShotToKill(self.damage, 1, gunshield, cond, | gunshield = self:_calcShotToKill(self.damage, 1, gunshield, cond, not self.gunshieldBleedthrough, apex.BODY) | ||
self.patternIndex = 1 | |||
-- ガンシールドとシールド/体力の混合 | |||
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 | end | ||
| 122行目: | 157行目: | ||
if self.hammerpointRounds > 1 then | if self.hammerpointRounds > 1 then | ||
-- シールド | -- シールド | ||
shield = self:_calcShotToKill(self.damage, passive, shield, isGreaterThanOrEqualToDamage) | |||
shield = self:_calcShotToKill(self.damage, passive, shield, | |||
-- シールドと体力の混合 | -- シールドと体力の混合 | ||
while shield > 0 do | |||
local | local mul = self:_getPartMultiplier(apex.BODY) | ||
if shield < self.damage then | if mul > 0 then | ||
local baseMergedDamage | |||
if shield < self.damage then | |||
baseMergedDamage = shield + math.floor(self.hammerpointRounds * (self.damage - shield)) | |||
else | |||
baseMergedDamage = self.damage | |||
end | |||
local mergedDamage = apex.calcDamageFromPartAndPassive(baseMergedDamage, mul, passive, self.opts) | |||
health = health - (mergedDamage - shield) | |||
shield = 0 | |||
self:_saveState(mergedDamage) | |||
else | else | ||
self:_saveState(0) | |||
end | end | ||
end | end | ||
-- 体力 | -- 体力 | ||
health = self:_calcShotToKill(math.floor(self.hammerpointRounds * self.damage), passive, health, isEqualToZero, true) | |||
health = self:_calcShotToKill(math.floor(self.hammerpointRounds * self.damage), passive, health, | |||
-- ボディーシールド | -- ボディーシールド | ||
else | else | ||
self:_calcShotToKill(self.damage, passive, health + shield, isEqualToZero, true) | |||
self:_calcShotToKill(self.damage, passive, health + shield, | |||
end | end | ||
end | end | ||
| 200行目: | 231行目: | ||
beamticks = opts.beamticks or 0, | beamticks = opts.beamticks or 0, | ||
hammerpointRounds = opts.hammerpointRounds or 0, | hammerpointRounds = opts.hammerpointRounds or 0, | ||
gunshieldBleedthrough = opts.gunshieldBleedthrough or true, | |||
opts = { | opts = { | ||
ampedCover = opts.ampedCover or false, | ampedCover = opts.ampedCover or false, | ||
round = opts.round or false, | round = opts.round or false, | ||
}, | }, | ||
}, { __index = STKCalculator }) | }, { __index = STKCalculator }) | ||
2021年3月16日 (火) 11:03時点における版
このモジュールについての説明文ページを モジュール: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
function STKCalculator:_calcShotToKill(base, passive, points, cond, isLast, forcePart)
local partmul = self:_getPartMultiplier(forcePart)
local damage = apex.calcDamageFromPartAndPassive(base, partmul, passive, self.opts)
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 = apex.calcDamageFromPartAndPassive(base, partmul, passive, self.opts)
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.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 + math.floor(self.hammerpointRounds * (self.damage - shield))
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
-- 体力
health = self:_calcShotToKill(math.floor(self.hammerpointRounds * self.damage), 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
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,
pattern = opts.pattern,
pellets = opts.pellets or 1,
beamdamage = opts.beamdamage or 0,
beamticks = opts.beamticks or 0,
hammerpointRounds = opts.hammerpointRounds or 0,
gunshieldBleedthrough = opts.gunshieldBleedthrough or true,
opts = {
ampedCover = opts.ampedCover or false,
round = opts.round or false,
},
}, { __index = STKCalculator })
obj:reset()
return obj
end
function STKCalculator.newFromStat(stat, opts)
local damagestat
if opts.useAnvilReceiver then
damagestat = stat.damage.anvil_receiver or stat.damage
else
damagestat = stat.damage
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 = damagestat.headshot,
legsshot = damagestat.legshot,
skyshot = opts.skyshot,
pattern = opts.pattern,
pellets = opts.pellets or stat.pellet,
beamdamage = beamdamage,
beamticks = beamticks,
hammerpointRounds = opts.useHammerpointRounds and damagestat.hammerpoint_rounds 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.hammerpointRounds = opts.hammerpointRounds or 0
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
return STKCalculator