🌟現在、鉄壁 鉄壁ヘッドショットには対応済みです。
鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。

「モジュール:WeaponInfobox/Duration」の版間の差分

提供:Apex Data
ナビゲーションに移動 検索に移動
(冷却時間の表示形式の変更)
(表形式の行生成をリファクタリング)
46行目: 46行目:


-- Duration for multiple value
-- Duration for multiple value
local function createMultipleRow(tbl, name, default, common, rare, epic, opts)
local function createMultipleRow(name, default, cfg, opts)
opts = opts or {}
opts = opts or {}
local row = tbl:tag('tr')
local row = cfg.tbl:tag('tr')
if aw.isNumberAndGreaterThanZero(opts.offset) then
if aw.isNumberAndGreaterThanZero(opts.offset) then
71行目: 71行目:
:wikitext(name)
:wikitext(name)
if common then
if cfg.muls then
row
row
:tag('td')
:tag('td')
:addClass('cell-type-number')
:addClass('cell-type-number')
:attr('align', 'right')
:attr('align', 'right')
:wikitext(default)
:wikitext(string.format(cfg.fmt, default))
:done()
:done()
:tag('td')
:tag('td')
84行目: 84行目:
:addClass('text-rarity')
:addClass('text-rarity')
:addClass('text-rarity-common')
:addClass('text-rarity-common')
:wikitext(common)
:wikitext(string.format(cfg.fmt, cfg.muls[1] * default))
:done()
:done()
:done()
:done()
93行目: 93行目:
:addClass('text-rarity')
:addClass('text-rarity')
:addClass('text-rarity-rare')
:addClass('text-rarity-rare')
:wikitext(rare)
:wikitext(string.format(cfg.fmt, cfg.muls[2] * default))
:done()
:done()
:done()
:done()
102行目: 102行目:
:addClass('text-rarity')
:addClass('text-rarity')
:addClass('text-rarity-epic')
:addClass('text-rarity-epic')
:wikitext(epic)
:wikitext(string.format(cfg.fmt, cfg.muls[3] * default))
:done()
:done()
:done()
:done()
114行目: 114行目:
:addClass('text-rarity')
:addClass('text-rarity')
:addClass('text-rarity-legendary')
:addClass('text-rarity-legendary')
:wikitext(default)
:wikitext(string.format(cfg.fmt, default))
:done()
:done()
:done()
:done()
151行目: 151行目:
-- Segmented Reload
-- Segmented Reload
if proto.validateTypes(stat.time, SegmentReloadProto) then
if proto.validateTypes(stat.time, SegmentReloadProto) then
local reloadSegmentConfig = {
fmt  = duration.reload.format,
tbl  = tbl,
muls = stock.reload_segment,
}
if proto.validateTypes(stat.magazine, MagazineProto) then
if proto.validateTypes(stat.magazine, MagazineProto) then
local magName  = nu.extmag(stat.ammo, 'ja')
local magName  = nu.extmag(stat.ammo, 'ja')
local baseTime = calcSegmentedReloadTime(stat.magazine[1], stat.time)
local baseTime = calcSegmentedReloadTime(stat.magazine[1], stat.time)
createMultipleRow(
createMultipleRow(
tbl,
duration.reload.name,
duration.reload.name,
string.format(duration.reload.format, baseTime),
baseTime,
string.format(duration.reload.format, baseTime * stock.reload_segment[1]),
reloadSegmentConfig,
string.format(duration.reload.format, baseTime * stock.reload_segment[2]),
string.format(duration.reload.format, baseTime * stock.reload_segment[3]),
rootOpts)
rootOpts)
local lvl1Time = calcSegmentedReloadTime(stat.magazine[2], stat.time)
local lvl1Time = calcSegmentedReloadTime(stat.magazine[2], stat.time)
createMultipleRow(
createMultipleRow(
tbl,
iu.attachment(magName, 1),
iu.attachment(magName, 1),
string.format(duration.reload.format, lvl1Time),
lvl1Time,
string.format(duration.reload.format, lvl1Time * stock.reload_segment[1]),
reloadSegmentConfig,
string.format(duration.reload.format, lvl1Time * stock.reload_segment[2]),
string.format(duration.reload.format, lvl1Time * stock.reload_segment[3]),
secondOpts)
secondOpts)
local lvl2Time = calcSegmentedReloadTime(stat.magazine[3], stat.time)
local lvl2Time = calcSegmentedReloadTime(stat.magazine[3], stat.time)
createMultipleRow(
createMultipleRow(
tbl,
iu.attachment(magName, 2),
iu.attachment(magName, 2),
string.format(duration.reload.format, lvl2Time),
lvl2Time,
string.format(duration.reload.format, lvl2Time * stock.reload_segment[1]),
reloadSegmentConfig,
string.format(duration.reload.format, lvl2Time * stock.reload_segment[2]),
string.format(duration.reload.format, lvl2Time * stock.reload_segment[3]),
secondOpts)
secondOpts)
local lvl3Time = calcSegmentedReloadTime(stat.magazine[4], stat.time)
local lvl3Time = calcSegmentedReloadTime(stat.magazine[4], stat.time)
createMultipleRow(
createMultipleRow(
tbl,
iu.attachment(magName, 3) .. iu.attachment(magName, 4),
iu.attachment(magName, 3) .. iu.attachment(magName, 4),
string.format(duration.reload.format, lvl3Time),
lvl3Time,
string.format(duration.reload.format, lvl3Time * stock.reload_segment[1]),
reloadSegmentConfig,
string.format(duration.reload.format, lvl3Time * stock.reload_segment[2]),
string.format(duration.reload.format, lvl3Time * stock.reload_segment[3]),
secondOpts)
secondOpts)
local reloadSegmentConfigOne = {
fmt  = duration.reloadsegmentone.format,
tbl  = tbl,
muls = stock.reload_segment,
}
local oneTime = calcSegmentedReloadTime(1, stat.time)
local oneTime = calcSegmentedReloadTime(1, stat.time)
createMultipleRow(
createMultipleRow(
tbl,
duration.reloadsegmentone.name,
duration.reloadsegmentone.name,
string.format(duration.reloadsegmentone.format, oneTime),
oneTime,
string.format(duration.reloadsegmentone.format, oneTime * stock.reload_segment[1]),
reloadSegmentConfigOne,
string.format(duration.reloadsegmentone.format, oneTime * stock.reload_segment[2]),
string.format(duration.reloadsegmentone.format, oneTime * stock.reload_segment[3]),
rootOpts)
rootOpts)
end
end
-- Cooldown
-- Cooldown
elseif proto.validateTypes(stat.time, CooldownProto) then
elseif proto.validateTypes(stat.time, CooldownProto) then
local cooldownOverheatConfig = {
fmt  = duration.cooldownoverheat.format,
tbl  = tbl,
muls = stock.reload,
}
local overheatedTime = stat.time.overheat_cooldown + stat.time.overheat_cooldown_delay
local overheatedTime = stat.time.overheat_cooldown + stat.time.overheat_cooldown_delay
createMultipleRow(
createMultipleRow(
tbl,
duration.cooldownoverheat.name,
duration.cooldownoverheat.name,
string.format(duration.cooldownoverheat.format, overheatedTime),
overheatedTime,
string.format(duration.cooldownoverheat.format, overheatedTime * stock.reload[1]),
cooldownOverheatConfig,
string.format(duration.cooldownoverheat.format, overheatedTime * stock.reload[2]),
string.format(duration.cooldownoverheat.format, overheatedTime * stock.reload[3]),
rootOpts)
rootOpts)
local cooldownConfig = {
fmt  = duration.cooldown.format,
tbl  = tbl,
muls = stock.reload,
}
local baseTime = stat.time.cooldown + stat.time.cooldown_delay
local baseTime = stat.time.cooldown + stat.time.cooldown_delay
for _, rate in ipairs(duration.cooldown.rates) do
for _, rate in ipairs(duration.cooldown.rates) do
createMultipleRow(
createMultipleRow(
tbl,
string.format(duration.cooldown.name, 100 * rate),
string.format(duration.cooldown.name, 100 * rate),
string.format(duration.cooldown.format, rate * baseTime),
rate * baseTime,
string.format(duration.cooldown.format, rate * baseTime * stock.reload[1]),
cooldownConfig,
string.format(duration.cooldown.format, rate * baseTime * stock.reload[2]),
string.format(duration.cooldown.format, rate * baseTime * stock.reload[3]),
secondOpts)
secondOpts)
end
end
230行目: 230行目:
-- Reload
-- Reload
elseif aw.isNumber(stat.time.reload) then
elseif aw.isNumber(stat.time.reload) then
createMultipleRow(
local reloadConfig = {
tbl,
fmt  = duration.reload.format,
duration.reload.name,
tbl  = tbl,
string.format(duration.reload.format, stat.time.reload),
muls = stock.reload,
string.format(duration.reload.format, stat.time.reload * stock.reload[1]),
}
string.format(duration.reload.format, stat.time.reload * stock.reload[2]),
createMultipleRow(duration.reload.name, stat.time.reload, reloadConfig, rootOpts)
string.format(duration.reload.format, stat.time.reload * stock.reload[3]),
rootOpts)
-- [Passive] Modded Loader
if canModdedLoader then
if canModdedLoader then
createMultipleRow(
createMultipleRow(
tbl,
iu.passive('modded_loader'),
iu.passive('modded_loader'),
string.format(duration.reload.format, stat.time.reload * 0.75),
stat.time.reload * 0.75,
string.format(duration.reload.format, stat.time.reload * 0.75 * stock.reload[1]),
reloadConfig,
string.format(duration.reload.format, stat.time.reload * 0.75 * stock.reload[2]),
string.format(duration.reload.format, stat.time.reload * 0.75 * stock.reload[3]),
secondOpts)
secondOpts)
end
end
-- [Hop-up] Boosted Loader
if stat.boosted_loader and aw.isNumberAndGreaterThanZero(stat.boosted_loader.reloadfast) then
if stat.boosted_loader and aw.isNumberAndGreaterThanZero(stat.boosted_loader.reloadfast) then
local reloadFastConfig = {
fmt  = duration.reload.format,
tbl  = tbl,
}
createMultipleRow(
createMultipleRow(
tbl,
iu.hopup('boosted_loader') .. ' ',
iu.hopup('boosted_loader') .. ' ',
string.format(duration.reload.format, stat.boosted_loader.reloadfast),
stat.boosted_loader.reloadfast,
nil,
reloadFastConfig,
nil,
nil,
secondOpts)
secondOpts)
end
end
261行目: 261行目:
-- Reload (Empty)
-- Reload (Empty)
if aw.isNumber(stat.time.reloadempty) and stat.time.reload ~= stat.time.reloadempty then
if aw.isNumber(stat.time.reloadempty) and stat.time.reload ~= stat.time.reloadempty then
createMultipleRow(
local reloadEmptyConfig = {
tbl,
fmt  = duration.reloadempty.format,
duration.reloadempty.name,
tbl  = tbl,
string.format(duration.reloadempty.format, stat.time.reloadempty),
muls = stock.reload,
string.format(duration.reloadempty.format, stat.time.reloadempty * stock.reload[1]),
}
string.format(duration.reloadempty.format, stat.time.reloadempty * stock.reload[2]),
createMultipleRow(duration.reloadempty.name, stat.time.reloadempty, reloadEmptyConfig, rootOpts)
string.format(duration.reloadempty.format, stat.time.reloadempty * stock.reload[3]),
rootOpts)
-- [Passive] Modded Loader
if canModdedLoader then
if canModdedLoader then
createMultipleRow(
createMultipleRow(
tbl,
iu.passive('modded_loader'),
iu.passive('modded_loader'),
string.format(duration.reloadempty.format, stat.time.reloadempty * 0.75),
stat.time.reloadempty * 0.75,
string.format(duration.reloadempty.format, stat.time.reloadempty * 0.75 * stock.reload[1]),
reloadEmptyConfig,
string.format(duration.reloadempty.format, stat.time.reloadempty * 0.75 * stock.reload[2]),
string.format(duration.reloadempty.format, stat.time.reloadempty * 0.75 * stock.reload[3]),
secondOpts)
secondOpts)
end
end
284行目: 281行目:
-- Deploy
-- Deploy
if aw.isNumber(stat.time.draw) then
if aw.isNumber(stat.time.draw) then
createMultipleRow(
local deployConfig = {
tbl,
fmt  = duration.deploy.format,
duration.deploy.name,
tbl  = tbl,
string.format(duration.deploy.format, stat.time.draw),
muls = stock.change,
string.format(duration.deploy.format, stat.time.draw * stock.change[1]),
}
string.format(duration.deploy.format, stat.time.draw * stock.change[2]),
createMultipleRow(duration.deploy.name, stat.time.draw, deployConfig, rootOpts)
string.format(duration.deploy.format, stat.time.draw * stock.change[3]),
rootOpts)
end
end
-- Deploy
-- Holster
if aw.isNumber(stat.time.holster) then
if aw.isNumber(stat.time.holster) then
createMultipleRow(
local holsterConfig = {
tbl,
fmt  = duration.holster.format,
duration.holster.name,
tbl  = tbl,
string.format(duration.holster.format, stat.time.holster),
muls = stock.change,
string.format(duration.holster.format, stat.time.holster * stock.change[1]),
}
string.format(duration.holster.format, stat.time.holster * stock.change[2]),
createMultipleRow(duration.holster.name, stat.time.holster, holsterConfig, rootOpts)
string.format(duration.holster.format, stat.time.holster * stock.change[3]),
rootOpts)
end
end
-- Zoom In
-- Zoom In
if aw.isNumber(stat.time.zoom_in) then
if aw.isNumber(stat.time.zoom_in) then
createMultipleRow(
local zoomInConfig = {
tbl,
fmt  = duration.zoomin.format,
duration.zoomin.name,
tbl  = tbl,
string.format(duration.zoomin.format, stat.time.zoom_in),
muls = stock.zoom,
string.format(duration.zoomin.format, stat.time.zoom_in * stock.zoom[1]),
}
string.format(duration.zoomin.format, stat.time.zoom_in * stock.zoom[2]),
createMultipleRow(duration.zoomin.name, stat.time.zoom_in, zoomInConfig, rootOpts)
string.format(duration.zoomin.format, stat.time.zoom_in * stock.zoom[3]),
rootOpts)
-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat
-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat
326行目: 317行目:
end
end
createMultipleRow(
createMultipleRow(label, stat.time.hcog_classic.zoom_in, zoomInConfig, secondOpts)
tbl,
label,
string.format(duration.zoomin.format, stat.time.hcog_classic.zoom_in),
string.format(duration.zoomin.format, stat.time.hcog_classic.zoom_in * stock.zoom[1]),
string.format(duration.zoomin.format, stat.time.hcog_classic.zoom_in * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.hcog_classic.zoom_in * stock.zoom[3]),
secondOpts)
end
end
341行目: 325行目:
if stat.time.hcog_ranged.zoom_in ~= stat.time.aog_variable.zoom_in then
if stat.time.hcog_ranged.zoom_in ~= stat.time.aog_variable.zoom_in then
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('3倍HCOG\'レンジャー\''),
iu.scope('3倍HCOG\'レンジャー\''),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in),
stat.time.hcog_ranged.zoom_in,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[1]),
zoomInConfig,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[3]),
secondOpts)
secondOpts)
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('2~4倍可変式AOG'),
iu.scope('2~4倍可変式AOG'),
string.format(duration.zoomin.format, stat.time.aog_variable.zoom_in),
stat.time.aog_variable.zoom_in,
string.format(duration.zoomin.format, stat.time.aog_variable.zoom_in * stock.zoom[1]),
zoomInConfig,
string.format(duration.zoomin.format, stat.time.aog_variable.zoom_in * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.aog_variable.zoom_in * stock.zoom[3]),
secondOpts)
secondOpts)
else
else
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG'),
iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG'),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in),
stat.time.hcog_ranged.zoom_in,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[1]),
zoomInConfig,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
else
else
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('3倍HCOG\'レンジャー\''),
iu.scope('3倍HCOG\'レンジャー\''),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in),
stat.time.hcog_ranged.zoom_in,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[1]),
zoomInConfig,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_in * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
381行目: 353行目:
if proto.validateTypes(stat.time.sniper, ZoomProto) then
if proto.validateTypes(stat.time.sniper, ZoomProto) then
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('6倍スナイパー'),
iu.scope('6倍スナイパー'),
string.format(duration.zoomin.format, stat.time.sniper.zoom_in),
stat.time.sniper.zoom_in,
string.format(duration.zoomin.format, stat.time.sniper.zoom_in * stock.zoom[1]),
zoomInConfig,
string.format(duration.zoomin.format, stat.time.sniper.zoom_in * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.sniper.zoom_in * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
393行目: 362行目:
if proto.validateTypes(stat.time.sniper_variable, ZoomProto) then
if proto.validateTypes(stat.time.sniper_variable, ZoomProto) then
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('4~8倍可変式スナイパー'),
iu.scope('4~8倍可変式スナイパー'),
string.format(duration.zoomin.format, stat.time.sniper_variable.zoom_in),
stat.time.sniper_variable.zoom_in,
string.format(duration.zoomin.format, stat.time.sniper_variable.zoom_in * stock.zoom[1]),
zoomInConfig,
string.format(duration.zoomin.format, stat.time.sniper_variable.zoom_in * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.sniper_variable.zoom_in * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
405行目: 371行目:
if proto.validateTypes(stat.time.sniper_threat, ZoomProto) then
if proto.validateTypes(stat.time.sniper_threat, ZoomProto) then
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('4~10倍デジタルスレット'),
iu.scope('4~10倍デジタルスレット'),
string.format(duration.zoomin.format, stat.time.sniper_threat.zoom_in),
stat.time.sniper_threat.zoom_in,
string.format(duration.zoomin.format, stat.time.sniper_threat.zoom_in * stock.zoom[1]),
zoomInConfig,
string.format(duration.zoomin.format, stat.time.sniper_threat.zoom_in * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.sniper_threat.zoom_in * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
417行目: 380行目:
-- Zoom Out
-- Zoom Out
if aw.isNumber(stat.time.zoom_out) then
if aw.isNumber(stat.time.zoom_out) then
createMultipleRow(
local zoomOutConfig = {
tbl,
fmt  = duration.zoomout.format,
duration.zoomout.name,
tbl  = tbl,
string.format(duration.zoomout.format, stat.time.zoom_out),
muls = stock.zoom,
string.format(duration.zoomout.format, stat.time.zoom_out * stock.zoom[1]),
}
string.format(duration.zoomout.format, stat.time.zoom_out * stock.zoom[2]),
createMultipleRow(duration.zoomout.name, stat.time.zoom_out, zoomOutConfig, rootOpts)
string.format(duration.zoomout.format, stat.time.zoom_out * stock.zoom[3]),
rootOpts)
-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat
-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat
436行目: 397行目:
createMultipleRow(
createMultipleRow(
tbl,
label,
label,
string.format(duration.zoomin.format, stat.time.hcog_classic.zoom_out),
stat.time.hcog_classic.zoom_out,
string.format(duration.zoomin.format, stat.time.hcog_classic.zoom_out * stock.zoom[1]),
zoomOutConfig,
string.format(duration.zoomin.format, stat.time.hcog_classic.zoom_out * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.hcog_classic.zoom_out * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
450行目: 408行目:
if stat.time.hcog_ranged.zoom_out ~= stat.time.aog_variable.zoom_out then
if stat.time.hcog_ranged.zoom_out ~= stat.time.aog_variable.zoom_out then
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('3倍HCOG\'レンジャー\''),
iu.scope('3倍HCOG\'レンジャー\''),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out),
stat.time.hcog_ranged.zoom_out,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[1]),
zoomOutConfig,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[3]),
secondOpts)
secondOpts)
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('2~4倍可変式AOG'),
iu.scope('2~4倍可変式AOG'),
string.format(duration.zoomin.format, stat.time.aog_variable.zoom_out),
stat.time.aog_variable.zoom_out,
string.format(duration.zoomin.format, stat.time.aog_variable.zoom_out * stock.zoom[1]),
zoomOutConfig,
string.format(duration.zoomin.format, stat.time.aog_variable.zoom_out * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.aog_variable.zoom_out * stock.zoom[3]),
secondOpts)
secondOpts)
else
else
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG'),
iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG'),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out),
stat.time.hcog_ranged.zoom_out,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[1]),
zoomOutConfig,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
else
else
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('3倍HCOG\'レンジャー\''),
iu.scope('3倍HCOG\'レンジャー\''),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out),
stat.time.hcog_ranged.zoom_out,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[1]),
zoomOutConfig,
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.hcog_ranged.zoom_out * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
490行目: 436行目:
if proto.validateTypes(stat.time.sniper, ZoomProto) then
if proto.validateTypes(stat.time.sniper, ZoomProto) then
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('6倍スナイパー'),
iu.scope('6倍スナイパー'),
string.format(duration.zoomin.format, stat.time.sniper.zoom_out),
stat.time.sniper.zoom_out,
string.format(duration.zoomin.format, stat.time.sniper.zoom_out * stock.zoom[1]),
zoomOutConfig,
string.format(duration.zoomin.format, stat.time.sniper.zoom_out * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.sniper.zoom_out * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
502行目: 445行目:
if proto.validateTypes(stat.time.sniper_variable, ZoomProto) then
if proto.validateTypes(stat.time.sniper_variable, ZoomProto) then
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('4~8倍可変式スナイパー'),
iu.scope('4~8倍可変式スナイパー'),
string.format(duration.zoomin.format, stat.time.sniper_variable.zoom_out),
stat.time.sniper_variable.zoom_out,
string.format(duration.zoomin.format, stat.time.sniper_variable.zoom_out * stock.zoom[1]),
zoomOutConfig,
string.format(duration.zoomin.format, stat.time.sniper_variable.zoom_out * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.sniper_variable.zoom_out * stock.zoom[3]),
secondOpts)
secondOpts)
end
end
514行目: 454行目:
if proto.validateTypes(stat.time.sniper_threat, ZoomProto) then
if proto.validateTypes(stat.time.sniper_threat, ZoomProto) then
createMultipleRow(
createMultipleRow(
tbl,
iu.scope('4~10倍デジタルスレット'),
iu.scope('4~10倍デジタルスレット'),
string.format(duration.zoomin.format, stat.time.sniper_threat.zoom_out),
stat.time.sniper_threat.zoom_out,
string.format(duration.zoomin.format, stat.time.sniper_threat.zoom_out * stock.zoom[1]),
zoomOutConfig,
string.format(duration.zoomin.format, stat.time.sniper_threat.zoom_out * stock.zoom[2]),
string.format(duration.zoomin.format, stat.time.sniper_threat.zoom_out * stock.zoom[3]),
secondOpts)
secondOpts)
end
end

2021年8月13日 (金) 11:48時点における版

このモジュールについての説明文ページを モジュール:WeaponInfobox/Duration/doc に作成できます

require('Module:Utility/mw.html Extensions')

local p = {}
local cfg = mw.loadData('Module:WeaponInfobox/configuration')
local attachment = mw.loadData('Module:Stat/Attachment')

local aw = require('Module:Utility/Library')
local iu = require('Module:Utility/Image')
local nu = require('Module:Utility/Name')
local proto = require('Module:Utility/Prototypes')

-- Constants
local leftBorder = {
	['border-left-width'] = '1px',
	['border-left-style'] = 'solid',
}
local leftBorderWithoutTopRightBorder = {
	['border-top'] = '0 none transparent',
	['border-right'] = '0 none transparent',
	['border-left-width'] = '1px',
	['border-left-style'] = 'solid',
}

-- Protos
local ZoomProto = {
	zoom_in  = proto.NumberRange(0),
	zoom_out = proto.NumberRange(0),
}
local MagazineProto = {
	proto.NumberRange(0),
	proto.NumberRange(0),
	proto.NumberRange(0),
	proto.NumberRange(0),
}
local SegmentReloadProto = {
	reload_segment_loop = proto.NumberRange(0),
	reload_segment_end  = proto.NumberRange(0),
	reload_segment_one  = proto.NumberRange(0),
}
local CooldownProto = {
	cooldown                = proto.NumberRange(0),
	cooldown_delay          = proto.NumberRange(0),
	overheat_cooldown       = proto.NumberRange(0),
	overheat_cooldown_delay = proto.NumberRange(0),
}

-- Duration for multiple value
local function createMultipleRow(name, default, cfg, opts)
	opts = opts or {}
	
	local row = cfg.tbl:tag('tr')
	
	if aw.isNumberAndGreaterThanZero(opts.offset) then
		for i = 1, opts.offset do
			local hasLeftBorder = opts.offsetStyles and opts.offsetStyles[i] and opts.offsetStyles[i].leftBorder
			if hasLeftBorder then
				row:tag('th')
					:css(leftBorderWithoutTopRightBorder)
					:wikitext(' ')
			else
				row:tag('th')
					:css('border', '0 none transparent')
					:wikitext(' ')
			end
		end
	end
	
	row:tag('th')
		:attrIf(aw.isNumber(opts.colspan), { colspan = opts.colspan })
		:cssIf(aw.isNumberAndGreaterThanZero(opts.offset), leftBorder)
		:wikitext(name)
	
	if cfg.muls then
		row
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
					:wikitext(string.format(cfg.fmt, default))
				:done()
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:tag('span')
					:addClass('text-rarity')
					:addClass('text-rarity-common')
					:wikitext(string.format(cfg.fmt, cfg.muls[1] * default))
					:done()
				:done()
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:tag('span')
					:addClass('text-rarity')
					:addClass('text-rarity-rare')
					:wikitext(string.format(cfg.fmt, cfg.muls[2] * default))
					:done()
				:done()
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:tag('span')
					:addClass('text-rarity')
					:addClass('text-rarity-epic')
					:wikitext(string.format(cfg.fmt, cfg.muls[3] * default))
					:done()
				:done()
	else
		row
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:attr('colspan', 4)
				:tag('span')
					:addClass('text-rarity')
					:addClass('text-rarity-legendary')
					:wikitext(string.format(cfg.fmt, default))
					:done()
				:done()
	end
	
	return row
end

local function calcSegmentedReloadTime(rounds, time)
	if rounds <= 1 then
		return time.reload_segment_one
	else
		return (rounds - 1) * time.reload_segment_loop + time.reload_segment_end
	end
end

local function renderDurationWithStock(stat, duration, stock, canModdedLoader, isSniper)
	local tbl = mw.html.create('table')
		:addClass('intable')
	
	local rootOpts = { colspan = 2 }
	local secondOpts = { offset = 1 }
	
	-- Header
	local stockName = isSniper and 'スナイパーストック' or '標準ストック'
	tbl:tag('tr')
		:tag('th')
			:attr('colspan', 2)
			:wikitext(name)
			:done()
		:tag('th'):done()
		:tag('th'):wikitext(iu.attachment(stockName, 1)):done()
		:tag('th'):wikitext(iu.attachment(stockName, 2)):done()
		:tag('th'):wikitext(iu.attachment(stockName, 3))
	
	-- Segmented Reload
	if proto.validateTypes(stat.time, SegmentReloadProto) then
		local reloadSegmentConfig = {
			fmt  = duration.reload.format,
			tbl  = tbl,
			muls = stock.reload_segment,
		}
		
		if proto.validateTypes(stat.magazine, MagazineProto) then
			local magName  = nu.extmag(stat.ammo, 'ja')
			local baseTime = calcSegmentedReloadTime(stat.magazine[1], stat.time)
			createMultipleRow(
				duration.reload.name,
				baseTime,
				reloadSegmentConfig,
				rootOpts)
			
			local lvl1Time = calcSegmentedReloadTime(stat.magazine[2], stat.time)
			createMultipleRow(
				iu.attachment(magName, 1),
				lvl1Time,
				reloadSegmentConfig,
				secondOpts)
			
			local lvl2Time = calcSegmentedReloadTime(stat.magazine[3], stat.time)
			createMultipleRow(
				iu.attachment(magName, 2),
				lvl2Time,
				reloadSegmentConfig,
				secondOpts)
			
			local lvl3Time = calcSegmentedReloadTime(stat.magazine[4], stat.time)
			createMultipleRow(
				iu.attachment(magName, 3) .. iu.attachment(magName, 4),
				lvl3Time,
				reloadSegmentConfig,
				secondOpts)
			
			local reloadSegmentConfigOne = {
				fmt  = duration.reloadsegmentone.format,
				tbl  = tbl,
				muls = stock.reload_segment,
			}
			local oneTime = calcSegmentedReloadTime(1, stat.time)
			createMultipleRow(
				duration.reloadsegmentone.name,
				oneTime,
				reloadSegmentConfigOne,
				rootOpts)
		end
	
	-- Cooldown
	elseif proto.validateTypes(stat.time, CooldownProto) then		
		local cooldownOverheatConfig = {
			fmt  = duration.cooldownoverheat.format,
			tbl  = tbl,
			muls = stock.reload,
		}
		local overheatedTime = stat.time.overheat_cooldown + stat.time.overheat_cooldown_delay
		createMultipleRow(
			duration.cooldownoverheat.name,
			overheatedTime,
			cooldownOverheatConfig,
			rootOpts)
		
		local cooldownConfig = {
			fmt  = duration.cooldown.format,
			tbl  = tbl,
			muls = stock.reload,
		}
		local baseTime = stat.time.cooldown + stat.time.cooldown_delay
		for _, rate in ipairs(duration.cooldown.rates) do
			createMultipleRow(
				string.format(duration.cooldown.name, 100 * rate),
				rate * baseTime,
				cooldownConfig,
				secondOpts)
		end
	
	-- Reload
	elseif aw.isNumber(stat.time.reload) then
		local reloadConfig = {
			fmt  = duration.reload.format,
			tbl  = tbl,
			muls = stock.reload,
		}
		createMultipleRow(duration.reload.name, stat.time.reload, reloadConfig, rootOpts)
		
		-- [Passive] Modded Loader
		if canModdedLoader then
			createMultipleRow(
				iu.passive('modded_loader'),
				stat.time.reload * 0.75,
				reloadConfig,
				secondOpts)
		end
		
		-- [Hop-up] Boosted Loader
		if stat.boosted_loader and aw.isNumberAndGreaterThanZero(stat.boosted_loader.reloadfast) then
			local reloadFastConfig = {
				fmt  = duration.reload.format,
				tbl  = tbl,
			}
			createMultipleRow(
				iu.hopup('boosted_loader') .. '&nbsp;',
				stat.boosted_loader.reloadfast,
				reloadFastConfig,
				secondOpts)
		end
		
		-- Reload (Empty)
		if aw.isNumber(stat.time.reloadempty) and stat.time.reload ~= stat.time.reloadempty then
			local reloadEmptyConfig = {
				fmt  = duration.reloadempty.format,
				tbl  = tbl,
				muls = stock.reload,
			}
			createMultipleRow(duration.reloadempty.name, stat.time.reloadempty, reloadEmptyConfig, rootOpts)
			
			-- [Passive] Modded Loader
			if canModdedLoader then
				createMultipleRow(
					iu.passive('modded_loader'),
					stat.time.reloadempty * 0.75,
					reloadEmptyConfig,
					secondOpts)
			end
		end
	end
	
	-- Deploy
	if aw.isNumber(stat.time.draw) then
		local deployConfig = {
			fmt  = duration.deploy.format,
			tbl  = tbl,
			muls = stock.change,
		}
		createMultipleRow(duration.deploy.name, stat.time.draw, deployConfig, rootOpts)
	end
	
	-- Holster
	if aw.isNumber(stat.time.holster) then
		local holsterConfig = {
			fmt  = duration.holster.format,
			tbl  = tbl,
			muls = stock.change,
		}
		createMultipleRow(duration.holster.name, stat.time.holster, holsterConfig, rootOpts)
	end
	
	-- Zoom In
	if aw.isNumber(stat.time.zoom_in) then
		local zoomInConfig = {
			fmt  = duration.zoomin.format,
			tbl  = tbl,
			muls = stock.zoom,
		}
		createMultipleRow(duration.zoomin.name, stat.time.zoom_in, zoomInConfig, rootOpts)
		
		-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat
		if proto.validateTypes(stat.time.hcog_classic, ZoomProto) then
			local label
			if proto.validateTypes(stat.time.threat, ZoomProto) then
				label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト') .. iu.scope('1倍デジタルスレット')
			else
				label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. '<br>' .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト')
			end
			
			createMultipleRow(label, stat.time.hcog_classic.zoom_in, zoomInConfig, secondOpts)
		end
		
		-- 3x HCOG 'Ranger', 2x-4x Variable AOG
		if proto.validateTypes(stat.time.hcog_ranged, ZoomProto) then
			if proto.validateTypes(stat.time.aog_variable, ZoomProto) then
				if stat.time.hcog_ranged.zoom_in ~= stat.time.aog_variable.zoom_in then
					createMultipleRow(
						iu.scope('3倍HCOG\'レンジャー\''),
						stat.time.hcog_ranged.zoom_in,
						zoomInConfig,
						secondOpts)
					createMultipleRow(
						iu.scope('2~4倍可変式AOG'),
						stat.time.aog_variable.zoom_in,
						zoomInConfig,
						secondOpts)
				else
					createMultipleRow(
						iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG'),
						stat.time.hcog_ranged.zoom_in,
						zoomInConfig,
						secondOpts)
				end
			else
				createMultipleRow(
					iu.scope('3倍HCOG\'レンジャー\''),
					stat.time.hcog_ranged.zoom_in,
					zoomInConfig,
					secondOpts)
			end
		end
		
		-- 6x Sniper Scope
		if proto.validateTypes(stat.time.sniper, ZoomProto) then
			createMultipleRow(
				iu.scope('6倍スナイパー'),
				stat.time.sniper.zoom_in,
				zoomInConfig,
				secondOpts)
		end
		
		-- 4x-8x Variable Sniper Scope
		if proto.validateTypes(stat.time.sniper_variable, ZoomProto) then
			createMultipleRow(
				iu.scope('4~8倍可変式スナイパー'),
				stat.time.sniper_variable.zoom_in,
				zoomInConfig,
				secondOpts)
		end
		
		-- 4x-10x Digital Sniper Threat
		if proto.validateTypes(stat.time.sniper_threat, ZoomProto) then
			createMultipleRow(
				iu.scope('4~10倍デジタルスレット'),
				stat.time.sniper_threat.zoom_in,
				zoomInConfig,
				secondOpts)
		end
	end
	
	-- Zoom Out
	if aw.isNumber(stat.time.zoom_out) then
		local zoomOutConfig = {
			fmt  = duration.zoomout.format,
			tbl  = tbl,
			muls = stock.zoom,
		}
		createMultipleRow(duration.zoomout.name, stat.time.zoom_out, zoomOutConfig, rootOpts)
		
		-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat
		if proto.validateTypes(stat.time.hcog_classic, ZoomProto) then
			local label
			if proto.validateTypes(stat.time.threat, ZoomProto) then
				label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト') .. iu.scope('1倍デジタルスレット')
			else
				label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. '<br>' .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト')
			end
			
			createMultipleRow(
				label,
				stat.time.hcog_classic.zoom_out,
				zoomOutConfig,
				secondOpts)
		end
		
		-- 3x HCOG 'Ranger', 2x-4x Variable AOG
		if proto.validateTypes(stat.time.hcog_ranged, ZoomProto) then
			if proto.validateTypes(stat.time.aog_variable, ZoomProto) then
				if stat.time.hcog_ranged.zoom_out ~= stat.time.aog_variable.zoom_out then
					createMultipleRow(
						iu.scope('3倍HCOG\'レンジャー\''),
						stat.time.hcog_ranged.zoom_out,
						zoomOutConfig,
						secondOpts)
					createMultipleRow(
						iu.scope('2~4倍可変式AOG'),
						stat.time.aog_variable.zoom_out,
						zoomOutConfig,
						secondOpts)
				else
					createMultipleRow(
						iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG'),
						stat.time.hcog_ranged.zoom_out,
						zoomOutConfig,
						secondOpts)
				end
			else
				createMultipleRow(
					iu.scope('3倍HCOG\'レンジャー\''),
					stat.time.hcog_ranged.zoom_out,
					zoomOutConfig,
					secondOpts)
			end
		end
		
		-- 6x Sniper Scope
		if proto.validateTypes(stat.time.sniper, ZoomProto) then
			createMultipleRow(
				iu.scope('6倍スナイパー'),
				stat.time.sniper.zoom_out,
				zoomOutConfig,
				secondOpts)
		end
		
		-- 4x-8x Variable Sniper Scope
		if proto.validateTypes(stat.time.sniper_variable, ZoomProto) then
			createMultipleRow(
				iu.scope('4~8倍可変式スナイパー'),
				stat.time.sniper_variable.zoom_out,
				zoomOutConfig,
				secondOpts)
		end
		
		-- 4x-10x Digital Sniper Threat
		if proto.validateTypes(stat.time.sniper_threat, ZoomProto) then
			createMultipleRow(
				iu.scope('4~10倍デジタルスレット'),
				stat.time.sniper_threat.zoom_out,
				zoomOutConfig,
				secondOpts)
		end
	end
	
	return tbl
end

-- Duration for single value
local function renderRow(tbl, name, num, cfg, opts)
	opts = opts or {}
	
	if cfg.isSpecial then
		num = num * cfg.muls[3]
	end
	
	local row = tbl:tag('tr')
		:addClassIf(opts.class and type(opts.class) == 'string', opts.class)
		:tag('th')
			:attrIf(opts.headerAlign and type(opts.headerAlign) == 'string', { align = opts.headerAlign })
			:wikitext(name)
			:done()
		:tag('td')
			:addClass('cell-type-number')
			:attr('align', 'left')
			:wikitext(string.format(cfg.fmt, num))
			:done()
		:tag('td')
			:attr('align', 'left')
			:wikitext(cfg.unit)
			:done()
	return row
end

local function renderDurationWithoutStock(stat, duration, stock, canModdedLoader, isSpecial)
	local secondOpts = { class = 'no-list-style', headerAlign = 'right' }
	local tbl = mw.html.create('table')
		:addClass('condensedtable')
		:addClass('listtable')
	
	-- Segmented Reload
	if proto.validateTypes(stat.time, SegmentReloadProto) then
		local reloadSegmentConfig = {
			fmt  = duration.reload.format,
			muls = stock.reload_segment,
			unit = duration.reload.unit,
			isSpecial = isSpecial,
		}
		
		-- with Mags
		if proto.validateTypes(stat.magazine, MagazineProto) then
			local lvl3Time = calcSegmentedReloadTime(stat.magazine[4], stat.time)
			renderRow(
				tbl,
				duration.reload.name .. '&nbsp;',
				lvl3Time,
				reloadSegmentConfig)
			
			local oneTime = calcSegmentedReloadTime(1, stat.time)
			renderRow(
				tbl,
				duration.reloadsegmentone.name .. '&nbsp;',
				oneTime,
				reloadSegmentConfig)
		
		-- without Mags
		elseif aw.isNumber(stat.magazine) then
			local baseTime = calcSegmentedReloadTime(stat.magazine, stat.time)
			renderRow(
				tbl,
				duration.reload.name .. '&nbsp;',
				baseTime,
				reloadSegmentConfig)
			
			local oneTime = calcSegmentedReloadTime(1, stat.time)
			renderRow(
				tbl,
				duration.reloadsegmentone.name .. '&nbsp;',
				oneTime,
				reloadSegmentConfig)
		end
	
	-- Reload
	elseif aw.isNumber(stat.time.reload) then
		local reloadConfig = {
			fmt  = duration.reload.format,
			muls = stock.reload,
			unit = duration.reload.unit,
			isSpecial = isSpecial,
		}
		renderRow(
			tbl,
			duration.reload.name .. '&nbsp;',
			stat.time.reload,
			reloadConfig)
		if canModdedLoader then
			renderRow(
				tbl,
				iu.passive('modded_loader') .. '&nbsp;',
				stat.time.reload * 0.75,
				reloadConfig,
				secondOpts)
		end
		if stat.boosted_loader and aw.isNumberAndGreaterThanZero(stat.boosted_loader.reloadfast) then
			renderRow(
				tbl,
				iu.hopup('boosted_loader') .. '&nbsp;',
				stat.boosted_loader.reloadfast,
				reloadConfig,
				secondOpts)
		end
		
		-- Reload (Empty)
		if aw.isNumber(stat.time.reloadempty) and stat.time.reload ~= stat.time.reloadempty then
			local reloademptyConfig = {
				fmt  = duration.reloadempty.format,
				muls = stock.reload,
				unit = duration.reloadempty.unit,
				isSpecial = isSpecial,
			}
			renderRow(
				tbl,
				duration.reloadempty.name .. '&nbsp;',
				stat.time.reloadempty,
				reloademptyConfig)
			if canModdedLoader then
				renderRow(
					tbl,
					iu.passive('modded_loader') .. '&nbsp;',
					stat.time.reloadempty * 0.75,
					reloademptyConfig,
					secondOpts)
			end
		end
	end
	
	-- Deploy
	if aw.isNumber(stat.time.draw) then
		local deployConfig = {
			fmt  = duration.deploy.format,
			muls = stock.change,
			unit = duration.deploy.unit,
			isSpecial = isSpecial,
		}
		renderRow(
			tbl,
			duration.deploy.name .. '&nbsp;',
			stat.time.draw,
			deployConfig)
	end
	
	-- Holster
	if aw.isNumber(stat.time.holster) then
		local holsterConfig = {
			fmt  = duration.holster.format,
			muls = stock.change,
			unit = duration.holster.unit,
			isSpecial = isSpecial,
		}
		renderRow(
			tbl,
			duration.holster.name .. '&nbsp;',
			stat.time.holster,
			holsterConfig)
	end
	
	-- Zoom In
	if aw.isNumber(stat.time.zoom_in) then
		local zoominConfig = {
			fmt  = duration.zoomin.format,
			muls = stock.zoom,
			unit = duration.zoomin.unit,
			isSpecial = isSpecial,
		}
		renderRow(
			tbl,
			duration.zoomin.name .. '&nbsp;',
			stat.time.zoom_in,
			zoominConfig)
		
		-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat
		if proto.validateTypes(stat.time.hcog_classic, ZoomProto) and stat.time.hcog_classic.zoom_in ~= stat.time.zoom_in then
			local label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト')
			if proto.validateTypes(stat.time.threat, ZoomProto) then
				label = label .. iu.scope('1倍デジタルスレット')
			end
			
			renderRow(
				tbl,
				label .. '&nbsp;',
				stat.time.hcog_classic.zoom_in,
				zoominConfig,
				secondOpts)
		end
		
		-- 3x HCOG 'Ranger', 2x-4x Variable AOG
		if proto.validateTypes(stat.time.hcog_ranged, ZoomProto) then
			if proto.validateTypes(stat.time.aog_variable, ZoomProto) then
				if stat.time.hcog_ranged.zoom_in ~= stat.time.aog_variable.zoom_in then
					renderRow(
						tbl,
						iu.scope('3倍HCOG\'レンジャー\'') .. '&nbsp;',
						stat.time.hcog_ranged.zoom_in,
						zoominConfig,
						secondOpts)
					renderRow(
						tbl,
						iu.scope('2~4倍可変式AOG') .. '&nbsp;',
						stat.time.aog_variable.zoom_in,
						zoominConfig,
						secondOpts)
				else
					renderRow(
						tbl,
						iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG') .. '&nbsp;',
						stat.time.hcog_ranged.zoom_in,
						zoominConfig,
						secondOpts)
				end
			elseif stat.time.hcog_ranged.zoom_in ~= stat.time.zoom_in then
				renderRow(
					tbl,
					iu.scope('3倍HCOG\'レンジャー\'') .. '&nbsp;',
					stat.time.hcog_ranged.zoom_in,
					zoominConfig,
					secondOpts)
			end
		end
		
		-- 6x Sniper Scope
		if proto.validateTypes(stat.time.sniper, ZoomProto) then
			renderRow(
				tbl,
				iu.scope('6倍スナイパー') .. '&nbsp;',
				stat.time.sniper.zoom_in,
				zoominConfig,
				secondOpts)
		end
		
		-- 4x-8x Variable Sniper Scope
		if proto.validateTypes(stat.time.sniper_variable, ZoomProto) then
			renderRow(
				tbl,
				iu.scope('4~8倍可変式スナイパー') .. '&nbsp;',
				stat.time.sniper_variable.zoom_in,
				zoominConfig,
				secondOpts)
		end
		
		-- 4x-10x Digital Sniper Threat
		if proto.validateTypes(stat.time.sniper_threat, ZoomProto) then
			renderRow(
				tbl,
				iu.scope('4~10倍デジタルスレット') .. '&nbsp;',
				stat.time.sniper_threat.zoom_in,
				zoominConfig,
				secondOpts)
		end
	end
	
	-- Zoom Out
	if aw.isNumber(stat.time.zoom_out) then
		local zoomoutConfig = {
			fmt  = duration.zoomout.format,
			muls = stock.zoom,
			unit = duration.zoomout.unit,
			isSpecial = isSpecial,
		}
		renderRow(
			tbl,
			duration.zoomout.name .. '&nbsp;',
			stat.time.zoom_out,
			zoomoutConfig)
		
		-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat
		if proto.validateTypes(stat.time.hcog_classic, ZoomProto) and stat.time.hcog_classic.zoom_out ~= stat.time.zoom_out then
			local label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト')
			if proto.validateTypes(stat.time.threat, ZoomProto) then
				label = label .. iu.scope('1倍デジタルスレット')
			end
			
			renderRow(
				tbl,
				label .. '&nbsp;',
				stat.time.hcog_classic.zoom_out,
				zoomoutConfig,
				secondOpts)
		end
		
		-- 3x HCOG 'Ranger', 2x-4x Variable AOG
		if proto.validateTypes(stat.time.hcog_ranged, ZoomProto) then
			if proto.validateTypes(stat.time.aog_variable, ZoomProto) then
				if stat.time.hcog_ranged.zoom_out ~= stat.time.aog_variable.zoom_out then
					renderRow(
						tbl,
						iu.scope('3倍HCOG\'レンジャー\'') .. '&nbsp;',
						stat.time.hcog_ranged.zoom_out,
						zoomoutConfig,
						secondOpts)
					renderRow(
						tbl,
						iu.scope('2~4倍可変式AOG') .. '&nbsp;',
						stat.time.aog_variable.zoom_out,
						zoomoutConfig,
						secondOpts)
				else
					renderRow(
						tbl,
						iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG') .. '&nbsp;',
						stat.time.hcog_ranged.zoom_out,
						zoomoutConfig,
						secondOpts)
				end
			elseif stat.time.hcog_ranged.zoom_out ~= stat.time.zoom_out then
				renderRow(
					tbl,
					iu.scope('3倍HCOG\'レンジャー\'') .. '&nbsp;',
					stat.time.hcog_ranged.zoom_out,
					zoomoutConfig,
					secondOpts)
			end
		end
		
		-- 6x Sniper Scope
		if proto.validateTypes(stat.time.sniper, ZoomProto) then
			renderRow(
				tbl,
				iu.scope('6倍スナイパー') .. '&nbsp;',
				stat.time.sniper.zoom_out,
				zoomoutConfig,
				secondOpts)
		end
		
		-- 4x-8x Variable Sniper Scope
		if proto.validateTypes(stat.time.sniper_variable, ZoomProto) then
			renderRow(
				tbl,
				iu.scope('4~8倍可変式スナイパー') .. '&nbsp;',
				stat.time.sniper_variable.zoom_out,
				zoomoutConfig,
				secondOpts)
		end
		
		-- 4x-10x Digital Sniper Threat
		if proto.validateTypes(stat.time.sniper_threat, ZoomProto) then
			renderRow(
				tbl,
				iu.scope('4~10倍デジタルスレット') .. '&nbsp;',
				stat.time.sniper_threat.zoom_out,
				zoomoutConfig,
				secondOpts)
		end
	end
	
	return tbl
end

function p.renderDuration(stat, lang)
	local duration = cfg[lang].duration
	local isSniper = stat.category == 'sniper' or stat.category == 'marksman_weapon'
	local stock
	if isSniper then
		stock = attachment.sniper_stock
	else
		stock = attachment.standard_stock
	end
	local canModdedLoader = stat.category == 'light_machine_gun' or stat.ammo == 'minigun'
	local isSpecial = aw.stringstarts(stat.ammo, 'special_') and not (stat.ammo == 'special_sniper')
	
	local isSimple = not stat.attachments.stock or isSpecial
	local node
	if isSimple then
		node = renderDurationWithoutStock(stat, duration, stock, canModdedLoader, isSpecial)
	else
		node = renderDurationWithStock(stat, duration, stock, canModdedLoader, isSniper)
	end
	
	return node, isSimple
end

function p._main(name, lang)
	lang = lang or 'ja'
	
	local stat = mw.loadData('Module:Stat/Weapon')[name]
	local node, _ = p.renderDuration(stat, lang)
	return tostring(node)
end

return p