| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:Apex/TTKCalculator
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール:Apex/TTKCalculator/doc に作成できます
local TTKCalculator = {}
local aw = require('Module:Utility/Library')
-- モード
TTKCalculator.BURST = 0
TTKCalculator.AUTO = 100
TTKCalculator.SINGLE = 200
TTKCalculator.SINGLE_ANVIL_RECEIVER = 201
-- [prop] 発射レート
function TTKCalculator:_loadFirerates()
local firerates = self.firerates
local type = type(firerates)
if type == 'table' then
self.firerate = firerates[1 + self.level]
elseif type == 'string' then
self.firerate = tonumber(firerates)
else
self.firerate = firerates
end
end
function TTKCalculator:setFirerates(firerates)
self.firerates = firerates or 1
self:_loadFirerates()
end
-- [prop] 装填数
function TTKCalculator:_loadMagazines()
local magazines = self.magazines
local type = type(magazines)
if type == 'table' then
self.magazine = magazines[1 + self.level]
elseif type == 'string' then
self.magazine = tonumber(magazines)
else
self.magazine = magazines
end
end
function TTKCalculator:setMagazines(magazines)
self.magazines = magazines or 20
self:_loadMagazines()
end
-- [prop] リロード時間
function TTKCalculator:_loadReloads()
local reloads = self.reloads
local type = type(reloads)
if type == 'table' then
self.reload = reloads[1 + self.level]
elseif type == 'string' then
self.reload = tonumber(reloads)
else
self.reload = reloads
end
end
function TTKCalculator:setReloads(reloads)
self.reloads = reloads or 0
self:_loadReloads()
end
-- [prop] レベル
function TTKCalculator:_load()
self:_loadFirerates()
self:_loadMagazines()
self:_loadReloads()
end
function TTKCalculator:setLevel(level)
self.level = level
self:_load()
end
-- [func] TTK算出関数
function TTKCalculator:_getBurstTtkInOneMagazine(left, skipLastDelay)
local ttk = 0
while left > 0 do
local current = math.min(self.burst, left)
left = left - current
if current > 1 then
ttk = ttk + (current - 1) / self.firerate
end
if left == 0 and skipLastDelay then
break
end
if current == self.burst then
ttk = ttk + self.burstDelay
end
end
return ttk
end
function TTKCalculator:get(shot)
local ttk = 0
local magazine = math.floor(self.magazine / self.roundsPerShot)
-- バースト
if self.burst > 1 and self.burst <= magazine then
local function getTtkInOneMag(left, burst, burstDelay, firerate)
end
while shot > magazine do
local shotTTK = self:_getBurstTtkInOneMagazine(magazine)
ttk = ttk + self.raise + shotTTK + self.reload
shot = shot - magazine
end
local shotTTK = self:_getBurstTtkInOneMagazine(shot, true)
ttk = ttk + self.raise + shotTTK
-- 非バースト (オート・単発)
else
while shot > magazine do
ttk = ttk + self.raise + (magazine - 1) / self.firerate + self.reload
shot = shot - magazine
end
ttk = ttk + self.raise + (shot - 1) / self.firerate
end
return ttk
end
-- コンストラクター
function TTKCalculator.new(firerates, magazines, reloads, opts)
local obj = setmetatable({
firerates = firerates or 1,
magazines = magazines or math.huge,
reloads = reloads or 0,
raise = opts.raise or 0,
burst = opts.burst or 1,
burstDelay = opts.burstDelay or 0,
roundsPerShot = opts.roundsPerShot or 1,
level = opts.level or 0,
}, { __index = TTKCalculator })
obj:_load()
return obj
end
function TTKCalculator.newFromStat(stat, mode, opts2)
mode = mode or TTKCalculator.AUTO
local firerate, magazine, reload
local opts = {}
local isModdedLoader = stat.category == 'light_machine_gun' and opts2 and opts2.moddedLoader
-- バースト
if stat.mode.burst > 1 and mode == TTKCalculator.BURST then
firerate = stat.firerate.burst
opts.burst = stat.mode.burst
opts.burstDelay = stat.firerate.burst_delay
opts.roundsPerShot = stat.rounds_per_shot and stat.rounds_per_shot.burst or 1
-- オート
elseif stat.mode.auto and (mode == TTKCalculator.AUTO or not stat.mode.single) then
firerate = stat.firerate.auto
opts.raise = stat.firerate.auto_raise or 0
opts.roundsPerShot = stat.rounds_per_shot and stat.rounds_per_shot.auto or 1
-- 単発
elseif stat.mode.single then
-- アンビルレシーバー
if mode == TTKCalculator.SINGLE_ANVIL_RECEIVER then
firerate = stat.firerate.anvil_receiver
opts.roundsPerShot = stat.rounds_per_shot and stat.rounds_per_shot.anvil_receiver or 1
-- 通常の単発
else
firerate = stat.firerate.single
opts.roundsPerShot = stat.rounds_per_shot and stat.rounds_per_shot.single or 1
end
-- プレースホルダー
else
firerate = 1
opts.roundsPerShot = 1
end
-- 装填数
if isModdedLoader then
if type(stat.magazine) == 'table' then
magazine = {
aw.round(1.15 * stat.magazine[1]),
aw.round(1.15 * stat.magazine[2]),
aw.round(1.15 * stat.magazine[3]),
aw.round(1.15 * stat.magazine[4]),
}
elseif stat.magazine == math.huge then
if aw.isNumberAndGreaterThanZero(stat.overheat) then
magazine = 1 + math.floor(1.15 * stat.overheat * firerate)
else
magazine = math.huge -- dummy
end
else
magazine = aw.round(1.15 * stat.magazine)
end
-- L-スターEMG
elseif stat.magazine == math.huge then
if aw.isNumberAndGreaterThanZero(stat.overheat) then
magazine = 1 + math.floor(stat.overheat * firerate)
else
magazine = math.huge -- dummy
end
-- 拡張マガジンがつかない場合
else
magazine = stat.magazine
end
-- ショットガンまたは拡張マガジンがつかない
if stat.ammo == 'shotgun' or stat.ammo == 'special_shotgun'
or not stat.attachments.extended_mag_or_shotgun_bolt
then
reload = stat.time.reload.full
-- 投下物資 (ヘビーアモ)
elseif stat.ammo == 'special_heavy' then
reload = 0.87 * stat.time.reload.full
-- 投下物資 (その他)
elseif aw.stringstarts(stat.ammo, 'special_') then
reload = 0.9 * stat.time.reload.full
-- ヘビー
elseif stat.ammo == 'heavy' then
local base = stat.time.reload.full
if isModdedLoader then
base = 0.75 * base
end
reload = {
base,
base,
0.92 * base,
0.87 * base,
}
-- その他
else
local base = stat.time.reload.full
if isModdedLoader then
base = 0.75 * base
end
reload = {
base,
base,
0.95 * base,
0.9 * base,
}
end
return TTKCalculator.new(firerate, magazine, reload, opts)
end
function TTKCalculator._test(name, count, opts)
local stat = mw.loadData('Module:Stat/Weapon')[name]
local mode = stat.mode.auto and TTKCalculator.AUTO or TTKCalculator.SINGLE
local ttkc = TTKCalculator.newFromStat(stat, mode, opts)
return ttkc:get(count)
end
return TTKCalculator