| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:StatTable/ShotTime
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール:StatTable/ShotTime/doc に作成できます
local aw = require('Module:Utility/Library')
local apex = require('Module:Utility/ApexLibrary')
local iu = require('Module:Utility/Image')
local tableutil = require('Module:Utility/TableUtil/Apex')
local TTKCalculator = require('Module:Apex/TTKCalculator')
local Hopup = mw.loadData('Module:Stat/Hopup')
local configuration = mw.loadData('Module:StatTable/configuration')
local getArgs -- lazily initialized
local function calcBurstDuration(data, firerate, magazine, delay)
local groupCount = math.floor(math.floor(magazine / data.ammopershot) / data.burstcount)
local duration = groupCount * ((data.burstcount - 1) / firerate + delay) - delay
return duration
end
local function calcDurationBase(data, firerate, shotCount, rechamber)
local duration = shotCount / firerate
if data.raise > 0 then
if data.semiauto then
duration = duration + shotCount * data.raise
else
duration = duration + data.raise
end
end
if data.charge > 0 then
duration = duration + shotCount * data.charge
end
if rechamber > 0 then
duration = duration + shotCount * rechamber
end
return duration
end
local function calcDuration(data, firerate, magazine, rechamber)
local shotCount = math.floor(magazine / data.ammopershot) - 1
if aw.isNumberAndGreaterThanOrEqualToX(data.tempomaxcount, 1) and shotCount > data.tempomaxcount and aw.isNumberAndGreaterThanZero(data.temporechamber) then
local duration = calcDurationBase(data, firerate, data.tempomaxcount, rechamber)
duration = duration + calcDurationBase(data, firerate, shotCount - data.tempomaxcount, data.temporechamber)
return duration
else
return calcDurationBase(data, firerate, shotCount, rechamber)
end
end
local function addFlatData(dataset, data, special)
local fireratesType = type(data.firerates)
local magazinesType = type(data.magazines)
local rechambersType = type(data.rechambers)
-- バーストの場合
if aw.isNumberAndGreaterThanOrEqualToX(data.burstcount, 2) and fireratesType == 'number' then
local delaysType = type(data.burstdelay)
-- ショットガンボルトがつく場合(バースト遅延が可変)
if delaysType == 'table' then
if special then
data.duration = calcBurstDuration(data, data.firerates, data.magazines, data.burstdelay[4])
table.insert(dataset, data)
else
for level, delay in ipairs(data.burstdelay) do
local data2 = aw.shallowCopy(data)
data2.duration = calcBurstDuration(data, data.firerates, data.magazines, delay)
data2.level = level - 1
table.insert(dataset, data2)
end
end
elseif delaysType == 'number' and data.burstdelay > 0 then
-- 拡張マガジンがつく場合
if magazinesType == 'table' then
if special then
data.duration = calcBurstDuration(data, data.firerates, data.magazines[4], data.burstdelay)
table.insert(dataset, data)
else
for level, magazine in ipairs(data.magazines) do
local data2 = aw.shallowCopy(data)
data2.duration = calcBurstDuration(data, data.firerates, magazine, data.burstdelay)
data2.level = level - 1
table.insert(dataset, data2)
end
end
else
data.duration = calcBurstDuration(data, data.firerates, data.magazines, data.burstdelay)
table.insert(dataset, data)
end
end
-- ショットガンボルトがつく場合 (ファイアレートが可変)
elseif fireratesType == 'table' and magazinesType == 'number' then
if special then
data.duration = calcDuration(data, data.firerates[4], data.magazines, data.rechambers)
table.insert(dataset, data)
else
for level, firerate in ipairs(data.firerates) do
local data2 = aw.shallowCopy(data)
data2.duration = calcDuration(data, firerate, data.magazines, data.rechambers)
data2.level = level - 1
table.insert(dataset, data2)
end
end
-- ショットガンボルトがつく場合 (リチャンバーが可変)
elseif fireratesType == 'number' and magazinesType == 'number' and rechambersType == 'table' then
if special then
data.duration = calcDuration(data, data.firerates, data.magazines, data.rechambers[4])
table.insert(dataset, data)
else
for level, rechamber in ipairs(data.rechambers) do
local data2 = aw.shallowCopy(data)
data2.duration = calcDuration(data, data.firerates, data.magazines, rechamber)
data2.level = level - 1
table.insert(dataset, data2)
end
end
-- 拡張マガジンがつく場合
elseif fireratesType == 'number' and magazinesType == 'table' then
if special then
data.duration = calcDuration(data, data.firerates, data.magazines[4], data.rechambers)
table.insert(dataset, data)
else
for level, magazine in ipairs(data.magazines) do
local data2 = aw.shallowCopy(data)
data2.duration = calcDuration(data, data.firerates, magazine, data.rechambers)
data2.level = level - 1
table.insert(dataset, data2)
end
end
-- 拡張マガジンとショットガンボルトの両方ともがつかない場合
elseif fireratesType == 'number' and magazinesType == 'number' then
data.duration = calcDuration(data, data.firerates, data.magazines, data.rechambers)
table.insert(dataset, data)
end
end
local function createDataset(dataset, stats, res, addData, __debug)
for name, stat in pairs(stats) do
local baseData = {
ammo = stat.ammo,
ammoicon = stat.ammo,
ammopershot = stat.ammo_per_shot or 1,
charge = -1,
duration = -1,
firerates = stat.firerate,
level = -1,
magazines = stat.magazine,
name = name,
semiauto = stat.is_semi_auto,
raise = stat.raise or 0,
rechambers = stat.rechamber or 0,
shortname = stat.localization['Japanese_Short'],
}
local special = aw.stringstarts(stat.ammo, 'special_')
-- Use TTKCalculator
if name == 'ディヴォーションLMG' then
local ttkc = TTKCalculator.newFromStat(stat)
for level, magazine in ipairs(stat.magazine) do
local data2 = aw.shallowCopy(baseData)
data2.duration = ttkc:getAsLevel(magazine, level - 1)
data2.level = level - 1
table.insert(dataset, data2)
end
ttkc = TTKCalculator.newFromStat(stat, { useTurbocharger = true })
for level, magazine in ipairs(stat.magazine) do
local data2 = aw.shallowCopy(baseData)
data2.duration = ttkc:getAsLevel(magazine, level - 1)
data2.hopup = { 'turbocharger' }
data2.level = level - 1
table.insert(dataset, data2)
end
local moddedLoaderMagazines = apex.getMagazineWithModdedLoader(stat.magazine)
ttkc = TTKCalculator.newFromStat(stat, { useModdedLoader = true })
for level, magazine in ipairs(moddedLoaderMagazines) do
local data2 = aw.shallowCopy(baseData)
data2.duration = ttkc:getAsLevel(magazine, level - 1)
data2.hopup = { 'modded_loader' }
data2.level = level - 1
table.insert(dataset, data2)
end
ttkc = TTKCalculator.newFromStat(stat, { useTurbocharger = true, useModdedLoader = true })
for level, magazine in ipairs(moddedLoaderMagazines) do
local data2 = aw.shallowCopy(baseData)
data2.duration = ttkc:getAsLevel(magazine, level - 1)
data2.hopup = { 'turbocharger', 'modded_loader' }
data2.level = level - 1
table.insert(dataset, data2)
end
-- Mag is inf
elseif stat.magazine == math.huge then
local overheatsType = type(stat.overheat)
if overheatsType == 'table' then
local virtualMagazines = {
math.ceil(stat.overheat[1] * stat.firerate),
math.ceil(stat.overheat[2] * stat.firerate),
math.ceil(stat.overheat[3] * stat.firerate),
math.ceil(stat.overheat[4] * stat.firerate),
}
baseData.magazines = virtualMagazines
addData(dataset, baseData, special)
-- Modded Loader
if stat.category == 'light_machine_gun' then
local moddedLoaderVirtualMagazines = {
math.ceil(1.15 * stat.overheat[1] * stat.firerate),
math.ceil(1.15 * stat.overheat[2] * stat.firerate),
math.ceil(1.15 * stat.overheat[3] * stat.firerate),
math.ceil(1.15 * stat.overheat[4] * stat.firerate),
}
local moddedLoaderData = aw.shallowCopy(baseData)
moddedLoaderData.hopup = { 'modded_loader' }
moddedLoaderData.magazines = moddedLoaderVirtualMagazines
addData(dataset, moddedLoaderData, special)
end
elseif overheatsType == 'number' then
baseData.magazines = math.ceil(stat.overheat * stat.firerate)
addData(dataset, baseData, special)
-- Modded Loader
if stat.category == 'light_machine_gun' then
local moddedLoaderData = aw.shallowCopy(baseData)
moddedLoaderData.hopup = { 'modded_loader' }
moddedLoaderData.magazines = math.ceil(1.15 * stat.overheat * stat.firerate)
addData(dataset, moddedLoaderData, special)
end
end
-- Other
else
-- Altfire mode
if type(stat.altfire) == 'table' and aw.isNumberAndGreaterThanZero(stat.altfire.firerate) then
local burstfireData = aw.shallowCopy(baseData)
burstfireData.burstcount = stat.burst_count
burstfireData.burstdelay = stat.burst_delay
burstfireData.option = res.burst
addData(dataset, burstfireData, special)
local altfireData = aw.shallowCopy(baseData)
altfireData.firerates = stat.altfire.firerate
altfireData.semiauto = stat.altfire.is_semi_auto == nil and stat.is_semi_auto or stat.altfire.is_semi_auto
altfireData.option = altfireData.semiauto and res.single or res.auto
addData(dataset, altfireData, special)
-- Burst mode
elseif aw.isNumberAndGreaterThanOrEqualToX(stat.burst_count, 2) then
local burstfireData = aw.shallowCopy(baseData)
burstfireData.burstcount = stat.burst_count
burstfireData.burstdelay = stat.burst_delay
addData(dataset, burstfireData, special)
-- Chargefire
elseif aw.isNumberAndGreaterThanZero(stat.charge) then
baseData.option = res.mincharge
addData(dataset, baseData, special)
local maxData = aw.shallowCopy(baseData)
maxData.charge = stat.charge
maxData.option = res.maxcharge
addData(dataset, maxData, special)
-- Charge Rifle
elseif aw.isNumberAndGreaterThanZero(stat.sustained_discharge_duration) then
baseData.raise = stat.sustained_discharge_duration
addData(dataset, baseData, special)
-- Other
else
addData(dataset, baseData, special)
end
-- Modded Loader
if stat.category == 'light_machine_gun' or stat.ammo == 'minigun' then
local moddedLoaderData = aw.shallowCopy(baseData)
moddedLoaderData.hopup = { 'modded_loader' }
moddedLoaderData.magazines = apex.getMagazineWithModdedLoader(stat.magazine)
addData(dataset, moddedLoaderData, special)
-- Revved Up mode
if aw.isNumberAndGreaterThanOrEqualToX(stat.firerate_revvedup, stat.firerate) then
local revvedUpData = aw.shallowCopy(baseData)
revvedUpData.ammoicon = stat.ammo .. '_revved_up'
revvedUpData.firerates = stat.firerate_revvedup
revvedUpData.option = res.revvedup
addData(dataset, revvedUpData, special)
local moddedLoaderRevvedUpData = aw.shallowCopy(moddedLoaderData)
moddedLoaderRevvedUpData.ammoicon = stat.ammo .. '_revved_up'
moddedLoaderRevvedUpData.firerates = stat.firerate_revvedup
moddedLoaderRevvedUpData.option = res.revvedup
addData(dataset, moddedLoaderRevvedUpData, special)
end
end
-- Turbocharger
if (__debug or Hopup.turbocharger.enabled) and type(stat.turbocharger) == 'table' and aw.isNumberAndGreaterThanZero(stat.turbocharger.raise) then
local turbochargerData = aw.shallowCopy(baseData)
turbochargerData.hopup = { 'turbocharger' }
turbochargerData.raise = stat.turbocharger.raise or stat.raise or 0
addData(dataset, turbochargerData, special)
end
-- Selectfire Receiver
if (__debug or Hopup.selectfire_receiver.enabled) and type(stat.selectfire_receiver) == 'table' and aw.isNumberAndGreaterThanZero(stat.selectfire_receiver.firerate) then
local semiauto
if stat.selectfire_receiver.semiauto then
semiauto = stat.selectfire_receiver.semiauto
else
semiauto = stat.semiauto
end
local selectfireReceiverData = aw.shallowCopy(baseData)
selectfireReceiverData.ammopershot = stat.selectfire_receiver.ammo_per_shot or stat.ammo_per_shot or 1
selectfireReceiverData.firerates = stat.selectfire_receiver.firerate
selectfireReceiverData.hopup = { 'selectfire_receiver' }
selectfireReceiverData.raise = stat.selectfire_receiver.raise or stat.raise or 0
selectfireReceiverData.semiauto = semiauto
addData(dataset, selectfireReceiverData, special)
end
-- Anvil Receiver
if (__debug or Hopup.anvil_receiver.enabled) and type(stat.anvil_receiver) == 'table' and aw.isNumberAndGreaterThanZero(stat.anvil_receiver.firerate) then
local anvilReceiverData = aw.shallowCopy(baseData)
anvilReceiverData.ammopershot = stat.anvil_receiver.ammo_per_shot or 2
anvilReceiverData.firerates = stat.anvil_receiver.firerate
anvilReceiverData.hopup = { 'anvil_receiver' }
addData(dataset, anvilReceiverData, special)
end
-- Double Tap Trigger
if (__debug or Hopup.double_tap_trigger.enabled) and type(stat.double_tap_trigger) == 'table' and aw.isNumberAndGreaterThanOrEqualToX(stat.double_tap_trigger.burst_count, 2) then
local doubleTapTriggerData = aw.shallowCopy(baseData)
doubleTapTriggerData.burstcount = stat.double_tap_trigger.burst_count
doubleTapTriggerData.burstdelay = stat.double_tap_trigger.burst_delay
doubleTapTriggerData.firerates = stat.double_tap_trigger.firerate
doubleTapTriggerData.hopup = { 'double_tap_trigger' }
addData(dataset, doubleTapTriggerData, special)
end
-- Deadeye's Tempo
if (__debug or Hopup.deadeyes_tempo.enabled) and type(stat.deadeyes_tempo) == 'table' and aw.isNumberAndGreaterThanZero(stat.deadeyes_tempo.rechamber) then
local deadeyesTempoData = aw.shallowCopy(baseData)
deadeyesTempoData.hopup = { 'deadeyes_tempo' }
deadeyesTempoData.tempomaxcount = stat.deadeyes_tempo.firerate_maximum_count
deadeyesTempoData.temporechamber = stat.deadeyes_tempo.rechamber
addData(dataset, deadeyesTempoData, special)
end
-- Boosted Loader
if (__debug or Hopup.boosted_loader.enabled) and type(stat.boosted_loader) == 'table' then
if type(stat.altfire) == 'table' and aw.isNumberAndGreaterThanZero(stat.altfire.firerate) then
local boostedLoaderData = aw.shallowCopy(baseData)
boostedLoaderData.burstcount = stat.burst_count
boostedLoaderData.burstdelay = stat.burst_delay
boostedLoaderData.hopup = { 'boosted_loader' }
boostedLoaderData.magazines = stat.boosted_loader.magazine
boostedLoaderData.option = res.burst
addData(dataset, boostedLoaderData, special)
local altfireBoostedLoaderData = aw.shallowCopy(baseData)
altfireBoostedLoaderData.firerates = stat.altfire.firerate
altfireBoostedLoaderData.hopup = { 'boosted_loader' }
altfireBoostedLoaderData.magazines = stat.boosted_loader.magazine
altfireBoostedLoaderData.semiauto = stat.altfire.is_semi_auto == nil and stat.is_semi_auto or stat.altfire.is_semi_auto
altfireBoostedLoaderData.option = altfireBoostedLoaderData.semiauto and res.single or res.auto
addData(dataset, altfireBoostedLoaderData, special)
else
local boostedLoaderData = aw.shallowCopy(baseData)
boostedLoaderData.hopup = { 'boosted_loader' }
boostedLoaderData.magazines = stat.boosted_loader.magazine
addData(dataset, boostedLoaderData, special)
end
end
end
end
end
local p = {}
function p._main(args, __debug)
args = args or {}
if __debug == nil then
__debug = true
end
local lang = args.lang or 'ja'
local res = configuration[lang]
local stats = mw.loadData('Module:Stat/Weapon')
local dataset = {}
createDataset(dataset, stats, res, addFlatData, __debug)
local metadata = {
tableutil.RankCell.new('', 'duration', true),
tableutil.AmmoCell.new('', 'ammoicon', {
attributes = { align = 'center' },
cellClass = 'st-desktop',
footerClass = 'st-desktop',
headerClass = 'st-desktop',
headerStyle = { width = '36px' },
}),
tableutil.WeaponNameCell.new(res.weaponname, 'name', {
ammoIndex = 'ammo',
attributes = { align = 'left' },
cellClass = 'st-dashed-right st-mobile-none-right st-mobile-padding0-right',
headerColspan = 3,
optionIndex = 'option',
shortnameIndex = 'shortname',
}),
tableutil.MagazineCell.new(res.mag, 'level', {
ammoIndex = 'ammo',
attributes = { align = 'left' },
cellClass = 'st-dashed-right st-mobile-none-right st-mobile-padding0-both',
headerColspan = 0,
}),
tableutil.HopupCell.new(res.hopup, 'hopup', {
attributes = { align = 'left' },
cellClass = 'st-mobile-padding0-both',
headerColspan = 0,
}),
tableutil.LineValueCell.new(res.duration, 'duration', {
cellClass = 'st-mobile-graph st-mobile-medium st-mobile-textshadow st-mobile-last',
footerClass = 'st-mobile-axis st-mobile-last',
format = function(val)
if val >= 10 then
return string.format('%.2f', val)
else
return string.format('%.3f', val)
end
end,
headerClass = 'st-mobile-last',
headerStyle = {
['min-width'] = '50px',
['max-width'] = '6em',
},
preferredGridCount = 3,
}),
tableutil.LineCell.new(res.graph, 'duration', {
cellClass = 'st-desktop st-desktop-graph',
footerClass = 'st-desktop',
headerClass = 'st-desktop',
headerStyle = {
['min-width'] = '200px',
},
}),
}
local node = tableutil.createTable(dataset, metadata)
return tostring(node)
--mw.logObject(dataset)
--return dataset
end
function p.main(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
args = getArgs(frame)
return p._main(args, false)
end
return p