🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:WeaponInfobox
2021年8月5日 (木) 18:47時点におけるMntone (トーク | 投稿記録)による版 (リロード時間の実装を新しい外部モジュール Module:WeaponInfobox/Duration に変更)
このモジュールについての説明文ページを モジュール:WeaponInfobox/doc に作成できます
require('Module:Utility/mw.html Extensions') local p = {} local cfg = mw.loadData('Module:WeaponInfobox/configuration') local aw = require('Module:Utility/Library') local iu = require('Module:Utility/Image') local nu = require('Module:Utility/Name') local proto = require('Module:Utility/Prototypes') local formatter -- lazily initialized local getArgs -- lazily initialized local function calcBurstAverageRPS(stat, delay) delay = delay or stat.firerate.burst_delay return stat.mode.burst / ((stat.mode.burst - 1) / stat.firerate.burst + delay) end local function calcRechamberRPS(firerate, rechamber) rechamber = rechamber or firerate.single_rechamber return 1 / (1 / firerate.single + rechamber) end local function createCellInRow(tbl, name) return tbl:tag('tr') :tag('th') :wikitext(name) :done() :tag('td') end local function renderRow(tbl, name, item) createCellInRow(tbl, name):wikitext(item) end local function renderFormatRow(tbl, name, default, common, rare, epic, opts) opts = opts or {} opts.separator = opts.separator or ' - ' local row = tbl:tag('tr') :addClassIf(opts.class and type(opts.class) == 'string', opts.class) if name ~= nil then row:tag('th') :attrIf(opts.headerAlign and type(opts.headerAlign) == 'string', { align = opts.headerAlign }) :wikitext(name) end local first = true if default ~= nil then first = false row:tag('td') :addClass('cell-type-number') :attrIf(opts.align and type(opts.align) == 'string', { align = opts.align }) :wikitext(default) end if common ~= nil then if not first then row:tag('td'):wikitext(opts.separator) end first = false row:tag('td') :addClass('cell-type-number') :attrIf(opts.align and type(opts.align) == 'string', { align = opts.align }) :wikitext(formatter:common(common)) end if rare ~= nil then if not first then row:tag('td'):wikitext(opts.separator) end first = false row:tag('td') :addClass('cell-type-number') :attrIf(opts.align and type(opts.align) == 'string', { align = opts.align }) :wikitext(formatter:rare(rare)) end if epic ~= nil then if not first then row:tag('td'):wikitext(opts.separator) end first = false row:tag('td') :addClass('cell-type-number') :attrIf(opts.align and type(opts.align) == 'string', { align = opts.align }) :wikitext(formatter:epic(epic)) end if opts.footer ~= nil then row:tag('td') :attrIf(opts.footerAlign and type(opts.footerAlign) == 'string', { align = opts.footerAlign }, { align = 'left' }) :attrIf(opts.footerColspan and type(opts.footerColspan) == 'number', { colspan = opts.footerColspan }) :wikitext(opts.footer) end return row end local function renderReleaseDate(tbl, cfg, release) local r = os.date("*t", release) local releaseText = string.format( '<time datetime="%04d-%02d-%02dT%02d:00:00.000+0900">%d年%d月%d日 %d時</time>~', r.year, r.month, r.day, r.hour, r.year, r.month, r.day, r.hour) renderRow(tbl, cfg.name, releaseText) end local function renderCategory(tbl, cfg, stat, lang) local category = nu.type(stat, lang, 1) local item if lang == 'ja' then item = string.format('[[武器#%s|%s]][[Category:%s]]', category, category, category) else item = string.format('%s[[Category:%s]]', category, category) end renderRow(tbl, cfg.name, item) end local function renderAmmo(tbl, cfg, stat, lang) local ammo = nu.ammo(stat, lang) local classSuffix if aw.stringstarts(stat, 'special_') then classSuffix = 'special' else classSuffix = stat end local item if lang == 'ja' then item = string.format( '%s [[弾薬#%s|<span class="text-ammo text-ammo-%s">%s</span>]][[Category:%s]]', iu.ammo(stat, { size = 24 }), ammo, classSuffix, ammo, ammo) else item = string.format( '%s <span class="text-ammo text-ammo-%s">%s</span>[[Category:%s]]', iu.ammo(stat, { size = 24 }), classSuffix, ammo, ammo) end createCellInRow(tbl, cfg.name) :addClass('cell-ammo') :wikitext(item) end local function renderCost(tbl, cfg, stat, ammo) if stat == nil or aw.stringstarts(ammo, 'special_') then return end local text = formatter:format( aw.comma(stat[1]), aw.comma(stat[2]), aw.comma(stat[3]), aw.comma(stat[4]), '', ' - ') renderRow(tbl, cfg.name, cfg.header .. text) end local function renderMode(tbl, cfg, stat) local builder = require('Module:Utility/StringBuilder').new() if stat.burst > 1 then builder:appendFormat(cfg.burst, stat.burst) builder:append(cfg.burst_category) end if stat.auto then if not builder:isEmpty() then builder:append(cfg.separator) end builder:append(cfg.auto, cfg.auto_category) end if stat.single then if not builder:isEmpty() then builder:append(cfg.separator) end builder:append(cfg.single, cfg.single_category) end renderRow(tbl, cfg.name, tostring(builder)) end local function getDamageText(stat) if aw.isNumber(stat.pellet) then if aw.isNumberAndGreaterThanZero(stat.damage.charged) then return string.format( '<span class="text-type-number">%s</span> × %d → <span class="text-type-number">%s</span> × %d', stat.damage.base, stat.pellet, stat.damage.charged, stat.pellet) else return string.format( '<span class="text-type-number">%s</span> × %d', stat.damage.base, stat.pellet) end else if aw.isNumberAndGreaterThanZero(stat.damage.amped) then return string.format( '<span class="text-type-number">%s</span> <span class="text-separator">/</span> %s <span class="text-type-number">%s</span>', stat.damage.base, iu.item('シールドセル'), stat.damage.amped) elseif aw.isNumberAndGreaterThanZero(stat.damage.charged) then return string.format( '<span class="text-type-number">%s</span> → <span class="text-type-number">%s</span>', stat.damage.base, stat.damage.charged) else return string.format('<span class="text-type-number">%s</span>', stat.damage.base) end end end local function renderHeadRow(tbl, name, head, cfg, nolist) local hlm1 = 0.2 + 0.8 * head local hlm2 = 0.4 + 0.6 * head local hlm3 = 0.5 + 0.5 * head local opts = { align = 'left', footer = cfg.unit } if nolist then opts.class = 'no-list-style' opts.headerAlign = 'right' end renderFormatRow( tbl, name, nil, hlm1, hlm2, hlm3, opts) end local function renderLegsRow(tbl, cfg, stat) local text if aw.isNumberAndGreaterThanZero(stat.legshot_charged) then text = string.format( '<span class="text-type-number">%s</span> → <span class="text-type-number">%s</span>%s', stat.legshot, stat.legshot_charged, cfg.unit) else text = string.format( '<span class="text-type-number">%s</span>%s', stat.legshot, cfg.unit) end tbl:tag('tr') :tag('th') :wikitext(cfg.legs) :done() :tag('td') :attr('align', 'left') :attr('colspan', 6) :wikitext(text) end local DamageProto = { damage = { base = proto.NumberRange(1), headshot = proto.NumberRange(1), legshot = proto.NumberRange(0, 1), }, } local ShatterCapsProto = { damage = { base = proto.NumberRange(1), headshot = proto.NumberRange(1), legshot = proto.NumberRange(0, 1), }, pellet = proto.NumberRange(1), } local damageHopups = { { name = 'anvil_receiver', proto = DamageProto, textclass = 'text-rarity-legendary', dispclass = 'disp-rarity-legendary', }, { name = 'shatter_caps', proto = ShatterCapsProto, textclass = 'text-rarity-epic', dispclass = 'disp-rarity-epic', }, } local function renderDamage(tbl, cfg, stat) if not proto.validateTypes(stat, DamageProto) then return end local cattext = string.format(cfg.head_category, stat.damage.headshot_charged or stat.damage.headshot) local cell = createCellInRow(tbl, cfg.name) cell:wikitext(cattext) :wikitext(getDamageText(stat)) -- Headshot local sprm = stat.damage.skullpiercer_rifling or 1 local hlmc = stat.damage.headshot_charged or 1 local intable = --tbl:tag('tr'):tag('td'):attr('colspan', 2) cell :tag('table') :addClass('condensedtable') :addClass('listtable') renderHeadRow(intable, cfg.head, stat.damage.headshot, cfg) if sprm > 1 then local nameS = iu.hopup('skullpiercer_rifling') .. ' ' renderHeadRow(intable, nameS, sprm, cfg, true) elseif hlmc > 1 then local nameC = '→ ' renderHeadRow(intable, nameC, hlmc, cfg, true) end -- Legsshot renderLegsRow(intable, cfg, stat.damage) -- [Hop-Up] Anvil Receiver & Shatter Caps for _, v in ipairs(damageHopups) do if proto.validateTypes(stat[v.name], v.proto) then local intblS = cell:tag('div') :addClass('tpl-weapon-inbox') :addClass(v.dispclass) :wikitext(iu.hopup(v.name) .. ' ') :tag('span') :addClass('text-rarity') :addClass(v.textclass) :wikitext(getDamageText(stat[v.name])) :done() :tag('table') :addClass('condensedtable') :addClass('listtable') renderHeadRow(intblS, cfg.head, stat[v.name].damage.headshot, cfg) renderLegsRow(intblS, cfg, stat[v.name].damage) end end end local function renderMultipleFirerateRow(intbl, name, cfg, rps, opts) opts = opts or {} renderFormatRow( intbl, name .. cfg.rps.name, string.format(cfg.rps.format, aw.roundx(rps[1], 2)), string.format(cfg.rps.format, aw.roundx(rps[2], 2)), string.format(cfg.rps.format, aw.roundx(rps[3], 2)), string.format(cfg.rps.format, aw.roundx(rps[4], 2)), { class = opts.rpsClass or '', separator = cfg.rps.separator, footer = cfg.rps.unit }) renderFormatRow( intbl, cfg.rpm.name, string.format(cfg.rpm.format, aw.comma(aw.roundx(60 * rps[1], 1))), string.format(cfg.rpm.format, aw.comma(aw.roundx(60 * rps[2], 1))), string.format(cfg.rpm.format, aw.comma(aw.roundx(60 * rps[3], 1))), string.format(cfg.rpm.format, aw.comma(aw.roundx(60 * rps[4], 1))), { class = opts.rpmClass and 'all-secondary text-smaller ' .. opts.rpmClass or 'all-secondary text-smaller', headerAlign = 'right', separator = cfg.rpm.separator, footer = cfg.rpm.unit }) end local function renderVariableFirerateRow(intbl, name, cfg, rps1, rps2, opts) opts = opts or {} intbl :tag('tr') :addClassIf(type(opts.rarity) == 'string', 'row-rarity-first disp-rarity-' .. (opts.rarity or 'common')) :addClassIf(type(opts.class) == 'string', opts.class) :tag('th') :wikitext(name) :done() :tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(string.format(cfg.rps.format, rps1)) :done() :tag('td') :wikitext(' → ') :done() :tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(string.format(cfg.rps.format, rps2)) :done() :tag('td') :wikitext(cfg.rps.unit) :done() :done() :tag('tr') :addClassIf(type(opts.rarity) == 'string', 'row-rarity-last disp-rarity-' .. (opts.rarity or 'common')) :addClass('no-list-style') :addClass('text-secondary') :addClass('text-smaller') :tag('th') :attr('align', 'right') :wikitext(cfg.rpm.name) :done() :tag('td') :addClass('cell-type-number') :wikitext(aw.comma(aw.roundx(60 * rps1, 1))) :done() :tag('td') :wikitext(' → ') :done() :tag('td') :addClass('cell-type-number') :wikitext(aw.comma(aw.roundx(60 * rps2, 1))) :done() :tag('td') :wikitext(cfg.rpm.unit) end local function renderFirerateRow(intbl, name, cfg, rps, opts) opts = opts or {} intbl:tag('tr') :addClassIf(type(opts.rarity) == 'string', 'row-rarity-one disp-rarity-' .. (opts.rarity or 'common')) :addClassIf(opts.class and type(opts.class) == 'string', opts.class) :tag('th') :wikitext(name) :done() :tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(string.format(cfg.rps.format, rps)) :done() :tag('td') :wikitext(cfg.rps.unit) :done() :tag('td') :tag('small') :addClass('text-secondary') :wikitext(cfg.rpm.name) :done() :done() :tag('td') :addClass('cell-type-number') :attr('align', 'right') :tag('small') :addClass('text-secondary') :wikitext(aw.comma(0.1 * aw.round(600 * rps))) :done() :done() :tag('td') :tag('small') :addClass('text-secondary') :wikitext(cfg.rpm.unit) end local function renderFirerateCell(cell, cfg, rps, opts) opts = opts or {} opts.header = opts.header or '' cell:wikitext(string.format( opts.header .. '<span class="text-type-number">' .. cfg.rps.format .. '</span>' .. cfg.rps.unit .. '<span class="text-secondary"><small>(<span class="text-type-number">%s</span>' .. cfg.rpm.unit .. '</small></span>', rps, aw.comma(0.1 * aw.round(600 * rps)))) end local MultipleNumberProto = { proto.NumberRange(0), proto.NumberRange(0), proto.NumberRange(0), proto.NumberRange(0), } local AnvilReceiverProto = { firerate = { single = proto.NumberRange(0), }, } local DeadeyesTempoWithChargeProto = { firerate = { single_charged = proto.NumberRange(0), }, } local DeadeyesTempoWithRechamberProto = { firerate = { single_rechamber = proto.NumberRange(0), }, } local function renderFirerate(tbl, cfg, stat) local firerate = stat.firerate if firerate == nil then return end local mode = stat.mode local cell = createCellInRow(tbl, cfg.name) local rps if mode.auto then if mode.single then local hasAnvil = proto.validateTypes(stat.anvil_receiver, AnvilReceiverProto) if hasAnvil or firerate.auto ~= firerate.single then local intbl if firerate.auto ~= firerate.single then intbl = cell:tag('table') :addClass('condensedtable') :addClass('listtable') local singleRPS if aw.isNumberAndGreaterThanZero(firerate.single_rechamber) then singleRPS = calcRechamberRPS(firerate) else singleRPS = firerate.single end renderFirerateRow(intbl, cfg.auto, cfg, firerate.auto) renderFirerateRow(intbl, cfg.single, cfg, singleRPS) else intbl = cell:tag('table') :addClass('condensedtable') renderFirerateRow(intbl, '', cfg, firerate.auto) end if hasAnvil then intbl:addClass('raritytable') renderFirerateRow(intbl, iu.hopup('anvil_receiver') .. ' ', cfg, stat.anvil_receiver.firerate.single, { rarity = 'legendary' }) end return end elseif mode.burst > 1 then if type(firerate.auto) == 'table' then local newcell = tbl:tag('tr') :tag('td') :attr('colspan', 2) renderFirerateCell(newcell:tag('ul'):tag('li'), cfg, firerate.burst, { header = cfg.burst }) local intbl = newcell:tag('table') :addClass('condensedtable') :addClass('listtable') local average = { calcBurstAverageRPS(stat, firerate.burst_delay[1]), calcBurstAverageRPS(stat, firerate.burst_delay[2]), calcBurstAverageRPS(stat, firerate.burst_delay[3]), calcBurstAverageRPS(stat, firerate.burst_delay[4]), } renderMultipleFirerateRow(intbl, cfg.burst_average, cfg, average, { rpsClass = 'no-list-style', rpmClass = 'no-list-style' }) renderMultipleFirerateRow(intbl, cfg.auto, cfg, firerate.auto, { rpmClass = 'no-list-style' }) else local intbl = cell:tag('table') :addClass('condensedtable') :addClass('listtable') local average = calcBurstAverageRPS(stat) renderFirerateRow(intbl, cfg.burst, cfg, firerate.burst) renderFirerateRow(intbl, cfg.burst_average, cfg, average, { class = 'no-list-style' }) renderFirerateRow(intbl, cfg.auto, cfg, firerate.auto) end return elseif aw.isNumberAndGreaterThanZero(firerate.auto_start) then local intbl = cell:tag('table') :addClass('condensedtable') renderVariableFirerateRow(intbl, '', cfg, firerate.auto_start, firerate.auto) if aw.isNumberAndGreaterThanZero(firerate.auto_start_turbocharger) then intbl:addClass('raritytable') renderVariableFirerateRow(intbl, iu.hopup('turbocharger') .. ' ', cfg, firerate.auto_start_turbocharger, firerate.auto, { rarity = 'legendary' }) end return end rps = firerate.auto elseif mode.single then if mode.burst > 1 then local intbl = cell:tag('table') :addClass('condensedtable') :addClass('listtable') local average = calcBurstAverageRPS(stat) renderFirerateRow(intbl, cfg.burst, cfg, firerate.burst) renderFirerateRow(intbl, cfg.burst_average, cfg, average, { class = 'no-list-style' }) local singleRPS if aw.isNumberAndGreaterThanZero(firerate.single_rechamber) then singleRPS = calcRechamberRPS(firerate) else singleRPS = firerate.single end renderFirerateRow(intbl, cfg.single, cfg, singleRPS) return end if proto.validateTypes(firerate.single_rechamber, MultipleNumberProto) then local calcRPS = { calcRechamberRPS(firerate, firerate.single_rechamber[1]), calcRechamberRPS(firerate, firerate.single_rechamber[2]), calcRechamberRPS(firerate, firerate.single_rechamber[3]), calcRechamberRPS(firerate, firerate.single_rechamber[4]), } local intbl = cell:tag('table'):addClass('condensedtable') renderMultipleFirerateRow(intbl, '', cfg, calcRPS) return elseif aw.isNumberAndGreaterThanZero(firerate.single_charged) then local minimum local maximum if aw.isNumberAndGreaterThanZero(firerate.single_charged_minimum) then minimum = calcRechamberRPS(firerate, firerate.single_charged_minimum) maximum = calcRechamberRPS(firerate, firerate.single_charged) elseif aw.isNumberAndGreaterThanZero(firerate.single_rechamber) then minimum = calcRechamberRPS(firerate, firerate.single_rechamber) maximum = calcRechamberRPS(firerate, firerate.single_rechamber + firerate.single_charged) else minimum = firerate maximum = calcRechamberRPS(firerate, firerate.single_charged) end local intbl = cell:tag('table'):addClass('condensedtable') renderVariableFirerateRow(intbl, '', cfg, minimum, maximum) if proto.validateTypes(stat.deadeyes_tempo, DeadeyesTempoWithChargeProto) then intbl:addClass('raritytable') local mintempo = calcRechamberRPS(firerate, aw.getAsNumber(stat.deadeyes_tempo.firerate.single_charged_minimum, 0)) local maxtempo = calcRechamberRPS(firerate, stat.deadeyes_tempo.firerate.single_charged) renderVariableFirerateRow(intbl, iu.hopup('deadeyes_tempo') .. ' ', cfg, mintempo, maxtempo, { rarity = 'epic' }) end return elseif aw.isNumberAndGreaterThanZero(firerate.single_rechamber) then if proto.validateTypes(stat.deadeyes_tempo, DeadeyesTempoWithRechamberProto) then local normal = calcRechamberRPS(firerate, firerate.single_rechamber) local tempo = calcRechamberRPS(firerate, stat.deadeyes_tempo.firerate.single_rechamber) local intbl = cell:tag('table') :addClass('condensedtable') :addClass('raritytable') renderFirerateRow(intbl, '', cfg, normal) renderFirerateRow(intbl, iu.hopup('deadeyes_tempo') .. ' ', cfg, tempo, { rarity = 'epic' }) return else rps = calcRechamberRPS(firerate) end else rps = firerate.single end else return end if type(rps) == 'table' then local intbl = cell:tag('table'):addClass('condensedtable') renderMultipleFirerateRow(intbl, '', cfg, rps) else renderFirerateCell(cell, cfg, rps) end end local function renderProjectileSpeed(tbl, cfg, projectile_speed, projectile_speed_charged) if projectile_speed == nil then return end local text if projectile_speed == math.huge then text = cfg.hitscan elseif projectile_speed_charged ~= nil then text = string.format( '<span class="text-type-number">%s</span> → <span class="text-type-number">%s</span>%s', string.format(cfg.format, aw.comma(aw.roundx(0.0254 * projectile_speed, 2))), string.format(cfg.format, aw.comma(aw.roundx(0.0254 * projectile_speed_charged, 2))), cfg.unit) else text = string.format( '<span class="text-type-number">%s</span>%s', string.format(cfg.format, aw.comma(aw.roundx(0.0254 * projectile_speed, 2))), cfg.unit) end renderRow(tbl, cfg.name, text) end local function renderDPS(tbl, cfg, stat, lang) if stat.firerate == nil then return end local sld = require('Module:Stat/Shield')['removelowprofile'] local node = require('Module:WeaponInfobox/DPS').renderDPS(stat, sld, lang) createCellInRow(tbl, cfg.name) tbl:tag('tr'):tag('td'):attr('colspan', 2):node(node) end local function renderMagazineRow(intbl, name, mag, rsvmag, cfg, opts) opts = opts or {} intbl:tag('tr') :addClassIf(opts.class and type(opts.class) == 'string', opts.class) :tag('th') :wikitext(name) :done() :tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(mag) :done() :tag('td') :wikitext(cfg.unit) :done() :tag('td') :addClass('text-secondary') :wikitext(' / ') :done() :tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(rsvmag == math.huge and cfg.infinity or rsvmag) :done() :tag('td') :wikitext(cfg.unit) end local function calcVirtualMagSize(overheat, firerate, moddedLoader) if moddedLoader then return 1 + math.floor(1.15 * overheat * firerate) else return 1 + math.floor(overheat * firerate) end end local function renderMagazine(tbl, cfg, stat, isModdedLoaderAttachable) local magazine = stat.magazine local typename = type(magazine) if typename == 'table' then if isModdedLoaderAttachable then local intable = createCellInRow(tbl, cfg.name) :tag('table') :addClass('condensedtable') renderFormatRow( intable, '', magazine[1], magazine[2], magazine[3], magazine[4], { footer = cfg.unit }) renderFormatRow( intable, iu.passive('modded_loader') .. ' ', aw.round(1.15 * magazine[1]), aw.round(1.15 * magazine[2]), aw.round(1.15 * magazine[3]), aw.round(1.15 * magazine[4]), { footer = cfg.unit }) else local text = formatter:format(magazine[1], magazine[2], magazine[3], magazine[4], cfg.unit, ' - ') renderRow(tbl, cfg.name, text) end elseif typename == 'number' then local text if magazine == math.huge then if stat.firerate and stat.firerate.auto then if proto.validateTypes(stat.overheat, MultipleNumberProto) then local intable = createCellInRow(tbl, cfg.name) :tag('table') :addClass('condensedtable') renderFormatRow( intable, '', calcVirtualMagSize(stat.overheat[1], stat.firerate.auto), calcVirtualMagSize(stat.overheat[2], stat.firerate.auto), calcVirtualMagSize(stat.overheat[3], stat.firerate.auto), calcVirtualMagSize(stat.overheat[4], stat.firerate.auto), { footer = cfg.unit }) renderFormatRow( intable, cfg.seconds.name, string.format(cfg.seconds.format, stat.overheat[1]), string.format(cfg.seconds.format, stat.overheat[2]), string.format(cfg.seconds.format, stat.overheat[3]), string.format(cfg.seconds.format, stat.overheat[4]), { class = 'no-list-style all-secondary text-smaller', headerAlign = 'right', footer = cfg.seconds.unit }) if isModdedLoaderAttachable then renderFormatRow( intable, iu.passive('modded_loader') .. ' ', calcVirtualMagSize(stat.overheat[1], stat.firerate.auto, true), calcVirtualMagSize(stat.overheat[2], stat.firerate.auto, true), calcVirtualMagSize(stat.overheat[3], stat.firerate.auto, true), calcVirtualMagSize(stat.overheat[4], stat.firerate.auto, true), { footer = cfg.unit }) renderFormatRow( intable, cfg.seconds.name, string.format(cfg.seconds.format, 1.15 * stat.overheat[1]), string.format(cfg.seconds.format, 1.15 * stat.overheat[2]), string.format(cfg.seconds.format, 1.15 * stat.overheat[3]), string.format(cfg.seconds.format, 1.15 * stat.overheat[4]), { class = 'no-list-style all-secondary text-smaller', headerAlign = 'right', footer = cfg.seconds.unit }) end return elseif aw.isNumber(stat.overheat) then text = string.format( '%s (<span class="text-type-number">%d</span>%s <span class="text-separator">/</span> %s <span class="text-type-number">%d</span>%s)', cfg.infinity, 1 + math.floor(stat.overheat * stat.firerate.auto), cfg.unit, iu.passive('modded_loader'), 1 + math.floor(1.15 * stat.overheat * stat.firerate.auto), cfg.unit) else text = cfg.infinity end else text = cfg.infinity end elseif stat.rounds_per_shot and stat.rounds_per_shot.single and stat.rounds_per_shot.single > 1 then local times = magazine / stat.rounds_per_shot.single local timesText if type(cfg.times.format) == 'table' then if times > 2 then timesText = string.format(cfg.times.format[3], times) else timesText = cfg.times.format[times] end else timesText = string.format(cfg.times.format, times) end text = string.format( '<span class="text-type-number">%d</span>%s <span class="text-secondary"><small>(%s)</small></span>', magazine, cfg.unit, timesText) elseif aw.isNumber(stat.magazine_reserve) then if isModdedLoaderAttachable then local intbl = createCellInRow(tbl, cfg.name) :tag('table') :addClass('condensedtable') renderMagazineRow(intbl, '', magazine, stat.magazine_reserve, cfg) renderMagazineRow(intbl, iu.passive('modded_loader') .. ' ', aw.round(1.15 * magazine), stat.magazine_reserve, cfg) return else text = string.format( '<span class="text-type-number">%d</span>%s <span class="text-separator">/</span> <span class="text-type-number">%s</span>%s', magazine, cfg.unit, stat.magazine_reserve == math.huge and cfg.infinity or stat.magazine_reserve, cfg.unit) end else text = string.format('<span class="text-type-number">%d</span>%s', magazine, cfg.unit) end renderRow(tbl, cfg.name, text) end end local function renderDuration(tbl, cfg, stat, lang) local node, isSimple = require('Module:WeaponInfobox/Duration').renderDuration(stat, lang) local cell = createCellInRow(tbl, cfg.name) if isSimple then cell:node(node) else tbl:tag('tr'):tag('td'):attr('colspan', 2):node(node) end end local function renderDraw(tbl, cfg, draw, quickdraw_holster, attachments, ammo) if draw == nil then return end local muls if ammo == 'heavy' or ammo == 'special_heavy' then muls = { level2 = 0.92, level3 = 0.87 } else muls = { level2 = 0.95, level3 = 0.9 } end local incompatible = not attachments.stock if incompatible or aw.stringstarts(ammo, "special_") then local time if incompatible or ammo == 'special_sniper' then time = draw else time = 0.75 * draw end local text if quickdraw_holster > 0 then text = string.format( cfg.format .. cfg.unit .. ' <span class="text-separator">/</span> %s ' .. formatter:epic(cfg.format .. cfg.unit), time, iu.hopup('quickdraw_holster'), quickdraw_holster * time) else text = string.format(cfg.format, time) .. cfg.unit end renderRow(tbl, cfg.name, text) elseif quickdraw_holster > 0 then local intable = createCellInRow(tbl, cfg.name) :tag('table') :addClass('condensedtable') renderFormatRow( intable, '', string.format(cfg.format, draw), string.format(cfg.format, 0.85 * draw), string.format(cfg.format, 0.80 * draw), string.format(cfg.format, 0.75 * draw), { footer = cfg.unit }) renderFormatRow( intable, iu.hopup('quickdraw_holster') .. ' ', string.format(cfg.format, quickdraw_holster * draw), string.format(cfg.format, 0.85 * quickdraw_holster * draw), string.format(cfg.format, 0.80 * quickdraw_holster * draw), string.format(cfg.format, 0.75 * quickdraw_holster * draw), { footer = cfg.unit }) else local text = formatter:format( string.format(cfg.format, draw), string.format(cfg.format, 0.85 * draw), string.format(cfg.format, 0.80 * draw), string.format(cfg.format, 0.75 * draw), cfg.unit, ' - ') renderRow(tbl, cfg.name, text) end end local function renderSpread(tbl, cfg, stat, lang) local node = require('Module:WeaponInfobox/Spread').renderSpread(stat.spread, stat.quickdraw_holster and stat.quickdraw_holster.spread, lang) local cell = createCellInRow(tbl, cfg.name) if node.tagName == 'span' then cell:node(node) else tbl:tag('tr'):tag('td'):attr('colspan', 2):node(node) end end local function createTable(cfg, stat, lang) local isModdedLoaderAttachable = stat.category == 'light_machine_gun' or stat.ammo == 'minigun' local tbl = mw.html.create('table') renderReleaseDate(tbl, cfg.release, stat.release) renderCategory(tbl, cfg.category, stat.category, lang) renderAmmo(tbl, cfg.ammo, stat.ammo, lang) renderCost(tbl, cfg.cost, stat.cost, stat.ammo) renderMode(tbl, cfg.mode, stat.mode) renderDamage(tbl, cfg.damage, stat) renderFirerate(tbl, cfg.firerate, stat) renderProjectileSpeed(tbl, cfg.projectilespeed, stat.projectile_speed, stat.projectile_speed_charged) renderMagazine(tbl, cfg.magazine, stat, isModdedLoaderAttachable) if stat.time then if stat.time.draw then renderDraw(tbl, cfg.draw, stat.time.draw, stat.time.quickdraw_holster or 0, stat.attachments, stat.ammo) end renderDuration(tbl, cfg.duration, stat, lang) end renderDPS(tbl, cfg.dps, stat, lang) renderSpread(tbl, cfg.spread, stat, lang) return tbl end local function renderInfobox(args) local lang = args and args.lang or 'ja' local cfglang = cfg[lang] local stat = mw.loadData('Module:Stat/Weapon')[args.name] local div = mw.html.create('div') :addClass('tpl-infobox-right') :addClass('tpl-weapon') if aw.stringstarts(stat.ammo, "special_") then div:addClass('tpl-weapon-special') else div:addClass('tpl-weapon-' .. stat.ammo) end div:tag('div') :addClass('tpl-weapon-header') :wikitext(args.name .. iu.ammo(stat.ammo, { size = 40 })) div:node(createTable(cfglang, stat, lang)) return div end function p._main(args, frame) formatter = require('Module:Utility/Formatter').new(frame) return tostring(renderInfobox(args)) end function p.main(frame) if not getArgs then getArgs = require('Module:Arguments').getArgs end args = getArgs(frame) return p._main(args, frame) end return p