🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁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:_getTtk(left) return (left - 1) / self.firerate end 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:_getVariableFirerateTtkInOneMagazine(left) local ttk = 0 -- The first left = left - 1 -- To the last while left > 0 do left = left - 1 local current = self.start + (self.firerate - self.start) * math.min(1, ttk / self.duration) local time = 1 / current ttk = ttk + time 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 -- 可変オート elseif self.start > 0 and self.duration > 0 then local first = true local virtualMagazine = magazine - self.maximum if magazine > 0 then if self.startMaximum and shot > virtualMagazine then local shotTTK = self:_getTtk(virtualMagazine) ttk = ttk + self.raise + shotTTK + self.reload shot = shot - virtualMagazine first = false end while shot > magazine do local shotTTK = self:_getVariableFirerateTtkInOneMagazine(magazine) ttk = ttk + self.raise + shotTTK + self.reload shot = shot - magazine end end local shotTTK if self.startMaximum and first then shotTTK = self:_getTtk(shot) else shotTTK = self:_getVariableFirerateTtkInOneMagazine(shot) end ttk = ttk + self.raise + shotTTK -- 非バースト (オート・単発) else if magazine > 0 then while shot > magazine do local shotTTK = self:_getTtk(magazine) ttk = ttk + self.raise + shotTTK + self.reload shot = shot - magazine end end local shotTTK = self:_getTtk(shot) ttk = ttk + self.raise + shotTTK end return ttk end function TTKCalculator:getAsLevel(shot, level) self:setLevel(level) return self:get(shot) 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, start = opts.start or 0, duration = opts.duration or 0, maximum = opts.maximum or 0, startMaximum = opts.startMaximum or false, 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 opts2 = opts2 or {} local firerate, magazine, reload local opts = { startMaximum = opts2.startMaximum or false } local isModdedLoader = stat.category == 'light_machine_gun' and opts2.useModdedLoader -- バースト 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 if opts2.useTurbocharger then opts.raise = stat.firerate.auto_raise_turbocharger or 0 opts.start = stat.firerate.auto_start_turbocharger or 0 opts.duration = stat.firerate.auto_duration_turbocharger or 0 opts.maximum = stat.firerate.auto_maximum_turbocharger or 0 else opts.raise = stat.firerate.auto_raise or 0 opts.start = stat.firerate.auto_start or 0 opts.duration = stat.firerate.auto_duration or 0 opts.maximum = stat.firerate.auto_maximum or 0 end 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