🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:WeaponInfobox
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール: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 renderReload(tbl, cfg, reload, attachments, ammo, isModdedLoaderAttachable) if reload.full == nil then return end local muls = { level1 = 0.963, level2 = 0.933, level3 = 0.9 } --if ammo == 'heavy' or ammo == 'special_heavy' then -- muls = { level1 = 1, level2 = 0.92, level3 = 0.87 } --else -- muls = { level1 = 1, level2 = 0.95, level3 = 0.9 } --end local incompatible = not attachments.stock if incompatible or ammo == 'shotgun' then if reload.tactical ~= nil and reload.tactical ~= reload.full then local tacticalText, fullText if incompatible then tacticalText = tostring(reload.tactical) fullText = tostring(reload.full) else tacticalText = tostring(muls.level3 * reload.tactical) fullText = tostring(muls.level3 * reload.full) end local intable = createCellInRow(tbl, cfg.name) :tag('table') :addClass('condensedtable') :addClass('listtable') renderFormatRow( intable, cfg.tactical.name .. ' ', string.format(cfg.tactical.format, reload.tactical), nil, nil, nil, { footer = cfg.tactical.unit }) if isModdedLoaderAttachable then renderFormatRow( intable, iu.passive('modded_loader') .. ' ', string.format(cfg.tactical.format, 0.75 * reload.tactical), nil, nil, nil, { class = 'no-list-style', headerAlign = 'right', footer = cfg.tactical.unit }) end renderFormatRow( intable, cfg.full.name .. ' ', string.format(cfg.full.format, reload.full), nil, nil, nil, { footer = cfg.full.unit }) if isModdedLoaderAttachable then renderFormatRow( intable, iu.passive('modded_loader') .. ' ', string.format(cfg.full.format, 0.75 * reload.full), nil, nil, nil, { class = 'no-list-style', headerAlign = 'right', footer = cfg.full.unit }) end elseif isModdedLoaderAttachable then local time if incompatible then time = reload.full else time = muls.level3 * reload.full end local text = string.format( cfg.full.format .. cfg.full.unit .. ' <span class="text-separator">/</span> %s ' .. cfg.full.format .. cfg.full.unit, time, iu.passive('modded_loader'), 0.75 * time) renderRow(tbl, cfg.name, text) else local time if incompatible then time = reload.full else time = muls.level3 * reload.full end renderRow(tbl, cfg.name, string.format(cfg.full.format, time) .. cfg.full.unit) end elseif reload.tactical ~= nil and reload.full ~= nil then renderRow(tbl, cfg.name, '') local intable = tbl:tag('tr') :tag('td') :attr('colspan', 2) :tag('table') :addClass('condensedtable') :addClass('listtable') local level1 if muls.level1 < 1 then level1 = string.format(cfg.tactical.format, muls.level1 * reload.tactical) else level1 = nil end renderFormatRow( intable, cfg.tactical.name .. ' ', string.format(cfg.tactical.format, reload.tactical), level1, string.format(cfg.tactical.format, muls.level2 * reload.tactical), string.format(cfg.tactical.format, muls.level3 * reload.tactical), { footer = cfg.tactical.unit }) if isModdedLoaderAttachable then local level1modded if muls.level1 < 1 then level1modded = string.format(cfg.tactical.format, 0.75 * muls.level1 * reload.tactical) else level1modded = nil end renderFormatRow( intable, iu.passive('modded_loader') .. ' ', string.format(cfg.tactical.format, 0.75 * reload.tactical), level1modded, string.format(cfg.tactical.format, 0.75 * muls.level2 * reload.tactical), string.format(cfg.tactical.format, 0.75 * muls.level3 * reload.tactical), { class = 'no-list-style', headerAlign = 'right', footer = cfg.tactical.unit }) end local level1empty if muls.level1 < 1 then level1empty = string.format(cfg.tactical.format, muls.level1 * reload.full) else level1empty = nil end renderFormatRow( intable, cfg.full.name .. ' ', string.format(cfg.full.format, reload.full), level1empty, string.format(cfg.full.format, muls.level2 * reload.full), string.format(cfg.full.format, muls.level3 * reload.full), { footer = cfg.full.unit }) if isModdedLoaderAttachable then local level1emptymodded if muls.level1 ~= 1 then level1emptymodded = string.format(cfg.tactical.format, 0.75 * muls.level1 * reload.full) else level1emptymodded = nil end renderFormatRow( intable, iu.passive('modded_loader') .. ' ', string.format(cfg.full.format, 0.75 * reload.full), level1emptymodded, string.format(cfg.full.format, 0.75 * muls.level2 * reload.full), string.format(cfg.full.format, 0.75 * muls.level3 * reload.full), { class = 'no-list-style', headerAlign = 'right', footer = cfg.full.unit }) end 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) createCellInRow(tbl, cfg.name) tbl:tag('tr'):tag('td'):attr('colspan', 2):node(node) 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 if stat.time.reload then renderReload(tbl, cfg.reload, stat.time.reload, stat.attachments, stat.ammo, isModdedLoaderAttachable) end 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