🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:WeaponInfobox/Duration」の版間の差分
ナビゲーションに移動
検索に移動
(単一の値を表示する際の初回の武器を構える時間に対応) |
(物資投下の際にホップアップ「デュアルシェル」を自動で有効化) |
||
(同じ利用者による、間の10版が非表示) | |||
4行目: | 4行目: | ||
local cfg = mw.loadData('Module:WeaponInfobox/configuration') | local cfg = mw.loadData('Module:WeaponInfobox/configuration') | ||
local attachment = mw.loadData('Module:Stat/Attachment') | local attachment = mw.loadData('Module:Stat/Attachment') | ||
local Hopup = mw.loadData('Module:Stat/Hopup') | |||
local aw = require('Module:Utility/Library') | local aw = require('Module:Utility/Library') | ||
43行目: | 44行目: | ||
overheat_cooldown = proto.NumberRange(0), | overheat_cooldown = proto.NumberRange(0), | ||
overheat_cooldown_delay = proto.NumberRange(0), | overheat_cooldown_delay = proto.NumberRange(0), | ||
} | |||
local DualShellProto = { | |||
dual_shell = { | |||
ammo_size_segmented_reload = proto.NumberRange(1), | |||
}, | |||
} | } | ||
144行目: | 150行目: | ||
:addClass('intable') | :addClass('intable') | ||
local rootOpts = { colspan = 2 } | local hasCooldown = proto.validateTypes(stat.time, CooldownProto) | ||
local hasDualShell = Hopup.dual_shell.enabled and proto.validateTypes(stat, DualShellProto) | |||
local colspan, rootOpts, secondOpts, thirdOpts | |||
if hasCooldown or hasDualShell or canModdedLoader then | |||
colspan = 3 | |||
rootOpts = { colspan = 3 } | |||
secondOpts = { colspan = 2, offset = 1 } | |||
thirdOpts = { offset = 2, offsetStyles = { nil, { leftBorder = true } } } | |||
else | |||
colspan = 2 | |||
rootOpts = { colspan = 2 } | |||
secondOpts = { offset = 1 } | |||
end | |||
-- Header | -- Header | ||
151行目: | 168行目: | ||
tbl:tag('tr') | tbl:tag('tr') | ||
:tag('th') | :tag('th') | ||
:attr('colspan', | :attr('colspan', colspan) | ||
:wikitext(name) | :wikitext(name) | ||
:done() | :done() | ||
197行目: | 214行目: | ||
reloadSegmentConfig, | reloadSegmentConfig, | ||
secondOpts) | secondOpts) | ||
-- [Hop-up] Dual Shell | |||
if hasDualShell then | |||
local virtualBaseAmmoSize = math.ceil(stat.magazine[1] / stat.dual_shell.ammo_size_segmented_reload) | |||
local dualShellBaseTime = calcSegmentedReloadTime(virtualBaseAmmoSize, stat.time) | |||
createMultipleRow( | |||
iu.hopup('dual_shell'), | |||
dualShellBaseTime, | |||
reloadSegmentConfig, | |||
secondOpts) | |||
local virtualLvl1AmmoSize = math.ceil(stat.magazine[2] / stat.dual_shell.ammo_size_segmented_reload) | |||
local dualShellLvl1Time = calcSegmentedReloadTime(virtualLvl1AmmoSize, stat.time) | |||
createMultipleRow( | |||
iu.attachment(magName, 1), | |||
dualShellLvl1Time, | |||
reloadSegmentConfig, | |||
thirdOpts) | |||
local virtualLvl2AmmoSize = math.ceil(stat.magazine[3] / stat.dual_shell.ammo_size_segmented_reload) | |||
local dualShellLvl2Time = calcSegmentedReloadTime(virtualLvl2AmmoSize, stat.time) | |||
createMultipleRow( | |||
iu.attachment(magName, 2), | |||
dualShellLvl2Time, | |||
reloadSegmentConfig, | |||
thirdOpts) | |||
local virtualLvl3AmmoSize = math.ceil(stat.magazine[4] / stat.dual_shell.ammo_size_segmented_reload) | |||
local dualShellLvl3Time = calcSegmentedReloadTime(virtualLvl3AmmoSize, stat.time) | |||
createMultipleRow( | |||
iu.attachment(magName, 3) .. iu.attachment(magName, 4), | |||
dualShellLvl3Time, | |||
reloadSegmentConfig, | |||
thirdOpts) | |||
end | |||
local reloadSegmentConfigOne = { | local reloadSegmentConfigOne = { | ||
213行目: | 265行目: | ||
-- Cooldown | -- Cooldown | ||
elseif | elseif hasCooldown then | ||
local cooldownOverheatConfig = { | local cooldownOverheatConfig = { | ||
fmt = duration.cooldownoverheat.format, | fmt = duration.cooldownoverheat.format, | ||
226行目: | 278行目: | ||
cooldownOverheatConfig, | cooldownOverheatConfig, | ||
rootOpts) | rootOpts) | ||
-- [Passive] Modded Loader | |||
if canModdedLoader then | |||
local moddedLoaderOverheatedTime = stat.time.overheat_cooldown * 0.75 + stat.time.overheat_cooldown_delay | |||
createMultipleRow( | |||
iu.passive('modded_loader'), | |||
moddedLoaderOverheatedTime, | |||
cooldownOverheatConfig, | |||
secondOpts) | |||
end | |||
local cooldownConfig = { | local cooldownConfig = { | ||
234行目: | 296行目: | ||
} | } | ||
local baseTime = stat.time.cooldown + stat.time.cooldown_delay | local baseTime = stat.time.cooldown + stat.time.cooldown_delay | ||
local moddedLoaderTime = stat.time.cooldown * 0.75 + stat.time.cooldown_delay | |||
for _, rate in ipairs(duration.cooldown.rates) do | for _, rate in ipairs(duration.cooldown.rates) do | ||
createMultipleRow( | createMultipleRow( | ||
240行目: | 303行目: | ||
cooldownConfig, | cooldownConfig, | ||
secondOpts) | secondOpts) | ||
-- [Passive] Modded Loader | |||
if canModdedLoader then | |||
createMultipleRow( | |||
iu.passive('modded_loader'), | |||
rate * moddedLoaderTime, | |||
cooldownConfig, | |||
thirdOpts) | |||
end | |||
end | end | ||
270行目: | 342行目: | ||
} | } | ||
createMultipleRow( | createMultipleRow( | ||
iu.hopup('boosted_loader') | iu.hopup('boosted_loader'), | ||
stat.boosted_loader.reloadfast, | stat.boosted_loader.reloadfast, | ||
reloadFastConfig, | reloadFastConfig, | ||
secondOpts) | secondOpts) | ||
end | |||
-- [Hop-up] Splatter Rounds | |||
local reloadSplatterConfig = { | |||
fmt = duration.reload.format, | |||
tbl = tbl, | |||
res = duration, | |||
isLegendary = true, | |||
} | |||
createMultipleRow( | |||
iu.hopup('splatter_rounds'), | |||
stat.time.reload * stock.reload[3] * 0.75, | |||
reloadSplatterConfig, | |||
secondOpts) | |||
-- [Passive] Modded Loader & [Hop-up] Splatter Rounds | |||
if canModdedLoader then | |||
createMultipleRow( | |||
iu.passive('modded_loader'), | |||
stat.time.reload * stock.reload[3] * 0.5625, | |||
reloadSplatterConfig, | |||
thirdOpts) | |||
end | end | ||
293行目: | 387行目: | ||
reloadEmptyConfig, | reloadEmptyConfig, | ||
secondOpts) | secondOpts) | ||
end | |||
-- [Hop-up] Splatter Rounds | |||
local reloadEmptySplatterConfig = { | |||
fmt = duration.reloadempty.format, | |||
tbl = tbl, | |||
res = duration, | |||
isLegendary = true, | |||
} | |||
createMultipleRow( | |||
iu.hopup('splatter_rounds'), | |||
stat.time.reloadempty * stock.reload[3] * 0.75, | |||
reloadEmptySplatterConfig, | |||
secondOpts) | |||
-- [Passive] Modded Loader & [Hop-up] Splatter Rounds | |||
if canModdedLoader then | |||
createMultipleRow( | |||
iu.passive('modded_loader'), | |||
stat.time.reloadempty * stock.reload[3] * 0.5625, | |||
reloadEmptySplatterConfig, | |||
thirdOpts) | |||
end | end | ||
end | end | ||
528行目: | 644行目: | ||
local row = tbl:tag('tr') | local row = tbl:tag('tr') | ||
:addClassIf(opts.class and type(opts.class) == 'string', opts.class) | :addClassIf(opts.class and type(opts.class) == 'string', opts.class) | ||
:attr('role', 'listitem') | |||
:tag('th') | :tag('th') | ||
:attrIf(opts.headerAlign and type(opts.headerAlign) == 'string', { align = opts.headerAlign }) | :attrIf(opts.headerAlign and type(opts.headerAlign) == 'string', { align = opts.headerAlign }) | ||
549行目: | 666行目: | ||
:addClass('condensedtable') | :addClass('condensedtable') | ||
:addClass('listtable') | :addClass('listtable') | ||
:attr('role', 'list') | |||
-- Segmented Reload | -- Segmented Reload | ||
567行目: | 685行目: | ||
lvl3Time, | lvl3Time, | ||
reloadSegmentConfig) | reloadSegmentConfig) | ||
-- [Hop-up] Dual Shell | |||
if (Hopup.dual_shell.enabled or isSpecial) and proto.validateTypes(stat, DualShellProto) then | |||
local lvl3VirtualAmmoSize = math.ceil(stat.magazine[4] / stat.dual_shell.ammo_size_segmented_reload) | |||
local lvl3DualShellTime = calcSegmentedReloadTime(lvl3VirtualAmmoSize, stat.time) | |||
renderRow( | |||
tbl, | |||
iu.hopup('dual_shell') .. ' ', | |||
lvl3DualShellTime, | |||
reloadSegmentConfig, | |||
secondOpts) | |||
end | |||
local oneTime = calcSegmentedReloadTime(1, stat.time) | local oneTime = calcSegmentedReloadTime(1, stat.time) | ||
583行目: | 713行目: | ||
baseTime, | baseTime, | ||
reloadSegmentConfig) | reloadSegmentConfig) | ||
-- [Hop-up] Dual Shell | |||
if (Hopup.dual_shell.enabled or isSpecial) and proto.validateTypes(stat, DualShellProto) then | |||
local virtualAmmoSize = math.ceil(stat.magazine / stat.dual_shell.ammo_size_segmented_reload) | |||
local dualShellTime = calcSegmentedReloadTime(virtualAmmoSize, stat.time) | |||
renderRow( | |||
tbl, | |||
iu.hopup('dual_shell') .. ' ', | |||
dualShellTime, | |||
reloadSegmentConfig, | |||
secondOpts) | |||
end | |||
local oneTime = calcSegmentedReloadTime(1, stat.time) | local oneTime = calcSegmentedReloadTime(1, stat.time) | ||
619行目: | 761行目: | ||
stat.boosted_loader.reloadfast, | stat.boosted_loader.reloadfast, | ||
reloadConfig, | reloadConfig, | ||
secondOpts) | |||
end | |||
if not isSpecial then | |||
-- [Hop-up] Splatter Rounds | |||
local reloadSplatterConfig = { | |||
fmt = duration.reload.format, | |||
unit = duration.reload.unit, | |||
} | |||
renderRow( | |||
tbl, | |||
iu.hopup('splatter_rounds') .. ' ', | |||
stat.time.reload * 0.75, | |||
reloadSplatterConfig, | |||
secondOpts) | secondOpts) | ||
end | end | ||
641行目: | 797行目: | ||
stat.time.reloadempty * 0.75, | stat.time.reloadempty * 0.75, | ||
reloademptyConfig, | reloademptyConfig, | ||
secondOpts) | |||
end | |||
if not isSpecial then | |||
-- [Hop-up] Splatter Rounds | |||
local reloademptySplatterConfig = { | |||
fmt = duration.reloadempty.format, | |||
unit = duration.reloadempty.unit, | |||
} | |||
renderRow( | |||
tbl, | |||
iu.hopup('splatter_rounds') .. ' ', | |||
stat.time.reloadempty * 0.75, | |||
reloademptySplatterConfig, | |||
secondOpts) | secondOpts) | ||
end | end | ||
736行目: | 906行目: | ||
-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat | -- 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 | if proto.validateTypes(stat.time.hcog_classic, ZoomProto) and stat.time.hcog_classic.zoom_in ~= stat.time.zoom_in then | ||
local label | local label | ||
if proto.validateTypes(stat.time.threat, ZoomProto) then | if proto.validateTypes(stat.time.threat, ZoomProto) then | ||
label = label .. iu.scope(' | label = duration.without_standard_scope | ||
else | |||
label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト') | |||
end | end | ||
830行目: | 1,002行目: | ||
-- HCOG Classic/Bruiser, Holosight, 1x Digital Threat | -- 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 | if proto.validateTypes(stat.time.hcog_classic, ZoomProto) and stat.time.hcog_classic.zoom_out ~= stat.time.zoom_out then | ||
local label | local label | ||
if proto.validateTypes(stat.time.threat, ZoomProto) then | if proto.validateTypes(stat.time.threat, ZoomProto) then | ||
label = label .. iu.scope(' | label = duration.without_standard_scope | ||
else | |||
label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト') | |||
end | end | ||
2022年5月19日 (木) 12:45時点における最新版
このモジュールについての説明文ページを モジュール: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 Hopup = mw.loadData('Module:Stat/Hopup') 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), } local DualShellProto = { dual_shell = { ammo_size_segmented_reload = proto.NumberRange(1), }, } -- 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 not cfg.isLegendary then row :tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(string.format(cfg.fmt, default)) :done() if cfg.muls then row :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('disabled') :attr('align', 'center') :attr('colspan', 3) :wikitext(cfg.res.na) end 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 hasCooldown = proto.validateTypes(stat.time, CooldownProto) local hasDualShell = Hopup.dual_shell.enabled and proto.validateTypes(stat, DualShellProto) local colspan, rootOpts, secondOpts, thirdOpts if hasCooldown or hasDualShell or canModdedLoader then colspan = 3 rootOpts = { colspan = 3 } secondOpts = { colspan = 2, offset = 1 } thirdOpts = { offset = 2, offsetStyles = { nil, { leftBorder = true } } } else colspan = 2 rootOpts = { colspan = 2 } secondOpts = { offset = 1 } end -- Header local stockName = isSniper and 'スナイパーストック' or '標準ストック' tbl:tag('tr') :tag('th') :attr('colspan', colspan) :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, res = duration, } 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) -- [Hop-up] Dual Shell if hasDualShell then local virtualBaseAmmoSize = math.ceil(stat.magazine[1] / stat.dual_shell.ammo_size_segmented_reload) local dualShellBaseTime = calcSegmentedReloadTime(virtualBaseAmmoSize, stat.time) createMultipleRow( iu.hopup('dual_shell'), dualShellBaseTime, reloadSegmentConfig, secondOpts) local virtualLvl1AmmoSize = math.ceil(stat.magazine[2] / stat.dual_shell.ammo_size_segmented_reload) local dualShellLvl1Time = calcSegmentedReloadTime(virtualLvl1AmmoSize, stat.time) createMultipleRow( iu.attachment(magName, 1), dualShellLvl1Time, reloadSegmentConfig, thirdOpts) local virtualLvl2AmmoSize = math.ceil(stat.magazine[3] / stat.dual_shell.ammo_size_segmented_reload) local dualShellLvl2Time = calcSegmentedReloadTime(virtualLvl2AmmoSize, stat.time) createMultipleRow( iu.attachment(magName, 2), dualShellLvl2Time, reloadSegmentConfig, thirdOpts) local virtualLvl3AmmoSize = math.ceil(stat.magazine[4] / stat.dual_shell.ammo_size_segmented_reload) local dualShellLvl3Time = calcSegmentedReloadTime(virtualLvl3AmmoSize, stat.time) createMultipleRow( iu.attachment(magName, 3) .. iu.attachment(magName, 4), dualShellLvl3Time, reloadSegmentConfig, thirdOpts) end local reloadSegmentConfigOne = { fmt = duration.reloadsegmentone.format, tbl = tbl, muls = stock.reload_segment, res = duration, } local oneTime = calcSegmentedReloadTime(1, stat.time) createMultipleRow( duration.reloadsegmentone.name, oneTime, reloadSegmentConfigOne, rootOpts) end -- Cooldown elseif hasCooldown then local cooldownOverheatConfig = { fmt = duration.cooldownoverheat.format, tbl = tbl, muls = stock.reload, res = duration, } local overheatedTime = stat.time.overheat_cooldown + stat.time.overheat_cooldown_delay createMultipleRow( duration.cooldownoverheat.name, overheatedTime, cooldownOverheatConfig, rootOpts) -- [Passive] Modded Loader if canModdedLoader then local moddedLoaderOverheatedTime = stat.time.overheat_cooldown * 0.75 + stat.time.overheat_cooldown_delay createMultipleRow( iu.passive('modded_loader'), moddedLoaderOverheatedTime, cooldownOverheatConfig, secondOpts) end local cooldownConfig = { fmt = duration.cooldown.format, tbl = tbl, muls = stock.reload, res = duration, } local baseTime = stat.time.cooldown + stat.time.cooldown_delay local moddedLoaderTime = stat.time.cooldown * 0.75 + stat.time.cooldown_delay for _, rate in ipairs(duration.cooldown.rates) do createMultipleRow( string.format(duration.cooldown.name, 100 * rate), rate * baseTime, cooldownConfig, secondOpts) -- [Passive] Modded Loader if canModdedLoader then createMultipleRow( iu.passive('modded_loader'), rate * moddedLoaderTime, cooldownConfig, thirdOpts) end end -- Reload elseif aw.isNumber(stat.time.reload) then local reloadConfig = { fmt = duration.reload.format, tbl = tbl, muls = stock.reload, res = duration, } 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, res = duration, isLegendary = true, } createMultipleRow( iu.hopup('boosted_loader'), stat.boosted_loader.reloadfast, reloadFastConfig, secondOpts) end -- [Hop-up] Splatter Rounds local reloadSplatterConfig = { fmt = duration.reload.format, tbl = tbl, res = duration, isLegendary = true, } createMultipleRow( iu.hopup('splatter_rounds'), stat.time.reload * stock.reload[3] * 0.75, reloadSplatterConfig, secondOpts) -- [Passive] Modded Loader & [Hop-up] Splatter Rounds if canModdedLoader then createMultipleRow( iu.passive('modded_loader'), stat.time.reload * stock.reload[3] * 0.5625, reloadSplatterConfig, thirdOpts) 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, res = duration, } 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 -- [Hop-up] Splatter Rounds local reloadEmptySplatterConfig = { fmt = duration.reloadempty.format, tbl = tbl, res = duration, isLegendary = true, } createMultipleRow( iu.hopup('splatter_rounds'), stat.time.reloadempty * stock.reload[3] * 0.75, reloadEmptySplatterConfig, secondOpts) -- [Passive] Modded Loader & [Hop-up] Splatter Rounds if canModdedLoader then createMultipleRow( iu.passive('modded_loader'), stat.time.reloadempty * stock.reload[3] * 0.5625, reloadEmptySplatterConfig, thirdOpts) end end end -- Deploy if aw.isNumber(stat.time.draw) then local deployConfig = { fmt = duration.deploy.format, tbl = tbl, muls = stock.change, res = duration, } createMultipleRow(duration.deploy.name, stat.time.draw, deployConfig, rootOpts) if aw.isNumber(stat.time.deployfirst) then local deployFirstConfig = { fmt = duration.deploy.format, tbl = tbl, muls = nil, res = duration, } createMultipleRow(duration.deployfirst.name, stat.time.deployfirst, deployFirstConfig, secondOpts) end end -- Holster if aw.isNumber(stat.time.holster) then local holsterConfig = { fmt = duration.holster.format, tbl = tbl, muls = stock.change, res = duration, } createMultipleRow(duration.holster.name, stat.time.holster, holsterConfig, rootOpts) end -- Raise if aw.isNumber(stat.time.upper) then local raiseConfig = { fmt = duration.raise.format, tbl = tbl, muls = stock.raise, res = duration, } createMultipleRow(duration.raise.name, stat.time.upper, raiseConfig, rootOpts) end -- Lower if aw.isNumber(stat.time.lower) then local lowerConfig = { fmt = duration.lower.format, tbl = tbl, muls = stock.lower, res = duration, } createMultipleRow(duration.lower.name, stat.time.lower, lowerConfig, rootOpts) end -- Zoom In if aw.isNumber(stat.time.zoom_in) then local zoomInConfig = { fmt = duration.zoomin.format, tbl = tbl, muls = stock.zoom, res = duration, } 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, res = duration, } 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 and cfg.muls then num = num * cfg.muls[3] end local row = tbl:tag('tr') :addClassIf(opts.class and type(opts.class) == 'string', opts.class) :attr('role', 'listitem') :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') :attr('role', 'list') -- 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 .. ' ', lvl3Time, reloadSegmentConfig) -- [Hop-up] Dual Shell if (Hopup.dual_shell.enabled or isSpecial) and proto.validateTypes(stat, DualShellProto) then local lvl3VirtualAmmoSize = math.ceil(stat.magazine[4] / stat.dual_shell.ammo_size_segmented_reload) local lvl3DualShellTime = calcSegmentedReloadTime(lvl3VirtualAmmoSize, stat.time) renderRow( tbl, iu.hopup('dual_shell') .. ' ', lvl3DualShellTime, reloadSegmentConfig, secondOpts) end local oneTime = calcSegmentedReloadTime(1, stat.time) renderRow( tbl, duration.reloadsegmentone.name .. ' ', oneTime, reloadSegmentConfig) -- without Mags elseif aw.isNumber(stat.magazine) then local baseTime = calcSegmentedReloadTime(stat.magazine, stat.time) renderRow( tbl, duration.reload.name .. ' ', baseTime, reloadSegmentConfig) -- [Hop-up] Dual Shell if (Hopup.dual_shell.enabled or isSpecial) and proto.validateTypes(stat, DualShellProto) then local virtualAmmoSize = math.ceil(stat.magazine / stat.dual_shell.ammo_size_segmented_reload) local dualShellTime = calcSegmentedReloadTime(virtualAmmoSize, stat.time) renderRow( tbl, iu.hopup('dual_shell') .. ' ', dualShellTime, reloadSegmentConfig, secondOpts) end local oneTime = calcSegmentedReloadTime(1, stat.time) renderRow( tbl, duration.reloadsegmentone.name .. ' ', 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 .. ' ', stat.time.reload, reloadConfig) if canModdedLoader then renderRow( tbl, iu.passive('modded_loader') .. ' ', 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') .. ' ', stat.boosted_loader.reloadfast, reloadConfig, secondOpts) end if not isSpecial then -- [Hop-up] Splatter Rounds local reloadSplatterConfig = { fmt = duration.reload.format, unit = duration.reload.unit, } renderRow( tbl, iu.hopup('splatter_rounds') .. ' ', stat.time.reload * 0.75, reloadSplatterConfig, 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 .. ' ', stat.time.reloadempty, reloademptyConfig) if canModdedLoader then renderRow( tbl, iu.passive('modded_loader') .. ' ', stat.time.reloadempty * 0.75, reloademptyConfig, secondOpts) end if not isSpecial then -- [Hop-up] Splatter Rounds local reloademptySplatterConfig = { fmt = duration.reloadempty.format, unit = duration.reloadempty.unit, } renderRow( tbl, iu.hopup('splatter_rounds') .. ' ', stat.time.reloadempty * 0.75, reloademptySplatterConfig, 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 .. ' ', stat.time.draw, deployConfig) if aw.isNumber(stat.time.deployfirst) then local deployFirstConfig = { fmt = duration.deployfirst.format, unit = duration.deployfirst.unit, isSpecial = isSpecial, } renderRow( tbl, duration.deployfirst.name .. ' ', stat.time.deployfirst, deployFirstConfig, secondOpts) end 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 .. ' ', stat.time.holster, holsterConfig) end -- Raise if aw.isNumber(stat.time.upper) then local raiseConfig = { fmt = duration.raise.format, muls = stock.raise, unit = duration.raise.unit, isSpecial = isSpecial, } renderRow( tbl, duration.raise.name .. ' ', stat.time.upper, raiseConfig) end -- Lower if aw.isNumber(stat.time.lower) then local lowerConfig = { fmt = duration.lower.format, muls = stock.lower, unit = duration.lower.unit, isSpecial = isSpecial, } renderRow( tbl, duration.lower.name .. ' ', stat.time.lower, lowerConfig) 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 .. ' ', 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 if proto.validateTypes(stat.time.threat, ZoomProto) then label = duration.without_standard_scope else label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト') end renderRow( tbl, 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 renderRow( tbl, iu.scope('3倍HCOG\'レンジャー\'') .. ' ', stat.time.hcog_ranged.zoom_in, zoominConfig, secondOpts) renderRow( tbl, iu.scope('2~4倍可変式AOG') .. ' ', stat.time.aog_variable.zoom_in, zoominConfig, secondOpts) else renderRow( tbl, iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG') .. ' ', 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\'レンジャー\'') .. ' ', 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倍スナイパー') .. ' ', 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倍可変式スナイパー') .. ' ', 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倍デジタルスレット') .. ' ', 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 .. ' ', 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 if proto.validateTypes(stat.time.threat, ZoomProto) then label = duration.without_standard_scope else label = iu.scope('1倍HCOG\'クラシック\'') .. iu.scope('2倍HCOG\'ブルーザー\'') .. iu.scope('1倍ホロサイト') .. iu.scope('1~2倍可変式ホロサイト') end renderRow( tbl, 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 renderRow( tbl, iu.scope('3倍HCOG\'レンジャー\'') .. ' ', stat.time.hcog_ranged.zoom_out, zoomoutConfig, secondOpts) renderRow( tbl, iu.scope('2~4倍可変式AOG') .. ' ', stat.time.aog_variable.zoom_out, zoomoutConfig, secondOpts) else renderRow( tbl, iu.scope('3倍HCOG\'レンジャー\'') .. iu.scope('2~4倍可変式AOG') .. ' ', 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\'レンジャー\'') .. ' ', 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倍スナイパー') .. ' ', 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倍可変式スナイパー') .. ' ', 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倍デジタルスレット') .. ' ', 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