🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:WeaponInfobox」の版間の差分
ナビゲーションに移動
検索に移動
(ディスラプター弾のダメージ表記に対応) |
(シャッターキャップのダメージ表示のタグが正しく指定されていない問題の修正) |
||
176行目: | 176行目: | ||
if aw.isNumberAndGreaterThanZero(damage.charged) then | if aw.isNumberAndGreaterThanZero(damage.charged) then | ||
return string.format( | return string.format( | ||
'<span class="text-type-number">%s</span> × %d → span class="text-type-number">%s</span> × %d', | '<span class="text-type-number">%s</span> × %d → <span class="text-type-number">%s</span> × %d', | ||
damage.base, | damage.base, | ||
stat.pellet, | stat.pellet, |
2021年9月3日 (金) 22:54時点における版
このモジュールについての説明文ページを モジュール:WeaponInfobox/doc に作成できます
require('Module:Utility/mw.html Extensions') local p = {} local cfg = mw.loadData('Module:WeaponInfobox/configuration') local aw = require('Module:Utility/Library') local apex = require('Module:Utility/ApexLibrary') local iu = require('Module:Utility/Image') local inu = require('Module:Utility/ImageWithName') local nu = require('Module:Utility/Name') local proto = require('Module:Utility/Prototypes') local formatter -- lazily initialized local getArgs -- lazily initialized 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(type(opts.class) == 'string', opts.class) :addClassIf(type(opts.rarity) == 'string', 'row-rarity-one disp-rarity-' .. (opts.rarity or 'common')) 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 }) :tag('span') :addClass('text-rarity') :addClass('text-rarity-common') :wikitext(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 }) :tag('span') :addClass('text-rarity') :addClass('text-rarity-rare') :wikitext(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 }) :tag('span') :addClass('text-rarity') :addClass('text-rarity-epic') :wikitext(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) createCellInRow(tbl, cfg.name) :addClass('cell-ammo') :wikitext(inu.ammo(stat, { lang = lang, size = 24 })) 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 appendMode(builder, cfg, stat, base) if stat.is_semi_auto or (stat.is_semi_auto == nil and base.is_semi_auto) then local burstCount = stat.burst_count or (base and base.burst_count) or 1 if aw.isNumberAndGreaterThanOrEqualToX(burstCount, 2) then builder:appendFormat(cfg.burst, burstCount) builder:append(cfg.burst_category) else builder:append(cfg.single, cfg.single_category) end else builder:append(cfg.auto, cfg.auto_category) end end local function renderMode(tbl, cfg, stat) local builder = require('Module:Utility/StringBuilder').new() appendMode(builder, cfg, stat) if stat.altfire then builder:append(cfg.separator) appendMode(builder, cfg, stat.altfire, stat) end if stat.selectfire_receiver then builder:append(cfg.separator, '<span class="block-rarity disp-rarity-epic">', iu.hopup('selectfire_receiver'), ' ') appendMode(builder, cfg, stat.selectfire_receiver, stat) builder:append('</span>') end if stat.double_tap_trigger then builder:append(cfg.separator, '<span class="block-rarity disp-rarity-epic">', iu.hopup('double_tap_trigger'), ' ') appendMode(builder, cfg, stat.double_tap_trigger, stat) builder:append('</span>') end renderRow(tbl, cfg.name, tostring(builder)) end local function getDamageText(stat, root) local damage = stat.damage or root.damage if aw.isNumber(stat.pellet) then if aw.isNumberAndGreaterThanZero(damage.charged) then return string.format( '<span class="text-type-number">%s</span> × %d → <span class="text-type-number">%s</span> × %d', damage.base, stat.pellet, damage.charged, stat.pellet) else return string.format( '<span class="text-type-number">%s</span> × %d', damage.base, stat.pellet) end else if aw.isNumberAndGreaterThanZero(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>', damage.base, iu.item('シールドセル'), damage.amped) elseif aw.isNumberAndGreaterThanZero(damage.charged) then return string.format( '<span class="text-type-number">%s</span> → <span class="text-type-number">%s</span>', damage.base, damage.charged) elseif aw.isNumberAndGreaterThanZero(stat.damage_shield_scale) then return string.format( '<span class="text-type-number">%s</span> → <span class="text-type-number">%s</span>', math.floor(damage.base * stat.damage_shield_scale), damage.base) else return string.format('<span class="text-type-number">%s</span>', damage.base) end end end local function renderHeadRow(tbl, name, stat, root, cfg, nolist) local head = stat.damage_head_scale or root.damage_head_scale local opts = { align = 'left', footer = cfg.unit } if nolist then opts.class = 'no-list-style' opts.headerAlign = 'right' end renderFormatRow( tbl, name, nil, apex.calcHeadshotMultiplier(head, apex.HEAD_HLMLV1), apex.calcHeadshotMultiplier(head, apex.HEAD_HLMLV2), apex.calcHeadshotMultiplier(head, apex.HEAD_HLMLV3), opts) end local function renderHeadEffectiveRange(tbl, cfg, stat, root) local headDist = stat.damage_head_distance or root.damage_head_distance if aw.isNumberAndGreaterThanZero(headDist) then local text = string.format(cfg.head_effective_range, 0.0254 * headDist) tbl:tag('tr') :addClass('no-list-style') :tag('td') :attr('align', 'left') :attr('colspan', 7) :wikitext(text) end end local function renderLegsRow(tbl, cfg, stat, root) local legs = stat.damage_legs_scale or root.damage_legs_scale 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', legs, stat.legshot_charged, cfg.unit) else text = string.format( '<span class="text-type-number">%s</span>%s', legs, 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 = 'selectfire_receiver', proto = DamageProto, textclass = 'text-rarity-epic', dispclass = 'disp-rarity-epic', }, { name = 'disruptor_rounds', proto = { damage_shield_scale = proto.NumberRange(1), }, textclass = 'text-rarity-epic', dispclass = 'disp-rarity-epic', }, { 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) local specialOnly = stat.attachments.disruptor_rounds_only if not specialOnly then cell: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, stat, 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 renderHeadEffectiveRange(intable, cfg, stat, stat) -- Legsshot renderLegsRow(intable, cfg, stat, stat) end -- [Hop-Up] Selectfire Receiver, Disruptor Rounds, 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(specialOnly and 'disp-rarity-heirloom' or v.dispclass) :wikitext(iu.hopup(v.name) .. ' ') :tag('span') :addClass('text-rarity') :addClass(specialOnly and 'text-rarity-heirloom' or v.textclass) :wikitext(getDamageText(stat[v.name], stat)) :done() :tag('table') :addClass('condensedtable') :addClass('listtable') renderHeadRow(intblS, cfg.head, stat[v.name], stat, cfg) renderHeadEffectiveRange(intblS, cfg, stat[v.name], stat) renderLegsRow (intblS, cfg, stat[v.name], stat) end end end local function renderFirerate(tbl, cfg, stat, lang) local cell = createCellInRow(tbl, cfg.name) local node, newcell = require('Module:WeaponInfobox/Firerate').renderFirerate(stat, lang) if newcell then tbl:tag('tr'):tag('td'):attr('colspan', 2):node(node) else cell:node(node) end end local function renderProjectileSpeed(tbl, cfg, projectile_speed, projectile_speed_charged) if not aw.isNumberAndGreaterThanZero(projectile_speed) then return end local text if projectile_speed == math.huge then text = cfg.hitscan elseif aw.isNumberAndGreaterThanZero(move_speed_charged) 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 renderMoveSpeed(tbl, cfg, move_speed, move_speed_charged) if not aw.isNumberAndGreaterThanZero(move_speed) then return end local text if aw.isNumberAndGreaterThanZero(move_speed_charged) then text = string.format( '<span class="text-type-number">%s</span> → <span class="text-type-number">%s</span>%s', string.format(cfg.format, 100 * (move_speed - 1)), string.format(cfg.format, 100 * (move_speed_charged - 1)), cfg.unit) else text = string.format( '<span class="text-type-number">%s</span>%s', string.format(cfg.format, 100 * (move_speed - 1)), cfg.unit) end renderRow(tbl, cfg.name, text) end local function renderDPS(tbl, cfg, stat, lang) 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 math.ceil(1.15 * overheat * firerate) else return math.ceil(overheat * firerate) end end local MultipleNumberProto = { proto.NumberRange(0), proto.NumberRange(0), proto.NumberRange(0), proto.NumberRange(0), } local function renderMagazine(tbl, cfg, stat, isSpecial, isModdedLoaderAttachable) local magazine = stat.magazine local typename = type(magazine) local text -- 物資投下武器 if isSpecial or stat.ammo == 'minigun' then local magazine2 if typename == 'table' then magazine2 = magazine[4] else magazine2 = magazine end if aw.isNumberAndGreaterThanZero(stat.magazine_reserve) then if isModdedLoaderAttachable then local moddedLoaderMagazine2 = apex.calcMagazineWithModdedLoader(magazine2) local moddedLoaderReserve = stat.magazine_reserve - (moddedLoaderMagazine2 - magazine2) local intbl = createCellInRow(tbl, cfg.name) :tag('table') :addClass('condensedtable') renderMagazineRow(intbl, '', magazine2, stat.magazine_reserve, cfg) renderMagazineRow(intbl, iu.passive('modded_loader') .. ' ', moddedLoaderMagazine2, moddedLoaderReserve, 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', magazine2, 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', magazine2, cfg.unit) end -- 拡張マガジンあり elseif 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], { separator = ' - ', footer = cfg.unit }) local moddedLoaderMagazine = apex.calcMagazinesWithModdedLoader(magazine) renderFormatRow( intable, iu.passive('modded_loader') .. ' ', moddedLoaderMagazine[1], moddedLoaderMagazine[2], moddedLoaderMagazine[3], moddedLoaderMagazine[4], { separator = ' - ', footer = cfg.unit }) return -- Boosted Loader elseif stat.boosted_loader and proto.validateTypes(stat.boosted_loader.magazine, MultipleNumberProto) then local intable = createCellInRow(tbl, cfg.name) :tag('table') :addClass('condensedtable') :addClass('raritytable') renderFormatRow( intable, '', magazine[1], magazine[2], magazine[3], magazine[4], { separator = ' - ', footer = cfg.unit }) renderFormatRow( intable, iu.hopup('boosted_loader') .. ' ', stat.boosted_loader.magazine[1], stat.boosted_loader.magazine[2], stat.boosted_loader.magazine[3], stat.boosted_loader.magazine[4], { rarity = 'legendary', separator = ' - ', footer = cfg.unit }) return else text = formatter:format(magazine[1], magazine[2], magazine[3], magazine[4], cfg.unit, ' - ') end -- 拡張マガジンなし elseif typename == 'number' then if magazine == math.huge then if aw.isNumberAndGreaterThanZero(stat.firerate) 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), calcVirtualMagSize(stat.overheat[2], stat.firerate), calcVirtualMagSize(stat.overheat[3], stat.firerate), calcVirtualMagSize(stat.overheat[4], stat.firerate), { separator = ' - ', 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 text-secondary text-smaller', headerAlign = 'right', separator = ' - ', footer = cfg.seconds.unit }) if isModdedLoaderAttachable then renderFormatRow( intable, iu.passive('modded_loader') .. ' ', calcVirtualMagSize(stat.overheat[1], stat.firerate, true), calcVirtualMagSize(stat.overheat[2], stat.firerate, true), calcVirtualMagSize(stat.overheat[3], stat.firerate, true), calcVirtualMagSize(stat.overheat[4], stat.firerate, true), { separator = ' - ', 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 text-secondary text-smaller', headerAlign = 'right', separator = ' - ', footer = cfg.seconds.unit }) end return elseif aw.isNumberAndGreaterThanZero(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), cfg.unit, iu.passive('modded_loader'), 1 + math.floor(1.15 * stat.overheat * stat.firerate), cfg.unit) else text = cfg.infinity end else text = cfg.infinity end elseif aw.isNumberAndGreaterThanX(stat.ammo_per_shot, 1) then local times = magazine / stat.ammo_per_shot 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) else text = string.format('<span class="text-type-number">%d</span>%s', magazine, cfg.unit) end end renderRow(tbl, cfg.name, text) 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 renderSpread(tbl, cfg, stat, lang, frame) local Spread = require('Module:WeaponInfobox/Spread') local node = 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) elseif stat.anvil_receiver and stat.anvil_receiver.spread then local node2 = Spread.renderSpread(stat.anvil_receiver.spread, nil, lang) if frame then local tabContent = string.format( '{{#tab:%s|%s}}{{#tab:%s|%s}}', cfg.normal, tostring(node), cfg.anvil_receiver, tostring(node2)) tbl:tag('tr') :tag('td') :attr('colspan', 2) :wikitext(frame:extensionTag { name = 'tabs', content = tabContent, args = { class = 'tabs-intable' }}) else tbl:tag('tr') :tag('td') :attr('colspan', 2) :tag('b') :wikitext(cfg.normal) :done() :node(node) :tag('b') :wikitext(cfg.anvil_receiver) :done() :node(node2) end else tbl:tag('tr'):tag('td'):attr('colspan', 2):node(node) end end local function renderSpreadDecayRow(intbl, name, cfg, spread, opts) opts = opts or {} intbl:tag('tr') :addClassIf(type(opts.rarity) == 'string', 'row-rarity-one disp-rarity-' .. (opts.rarity or 'common')) :tag('th') :wikitext(name) :done() :tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(string.format(cfg.rate.format, spread.decay_rate)) :done() :tag('td') :wikitext(cfg.rate.unit) :done() :tag('td') :addClass('text-smaller') :wikitext(cfg.delay.name) :done() :tag('td') :addClass('cell-type-number') :addClass('text-smaller') :attr('align', 'right') :wikitext(string.format(cfg.delay.format, spread.decay_delay)) :done() :tag('td') :addClass('text-smaller') :wikitext(cfg.delay.unit) end local function renderSpreadDecay(tbl, cfg, stat) if not (aw.isNumberAndGreaterThanZero(stat.spread.decay_rate) and aw.isNumberAndGreaterThanZero(stat.spread.decay_delay)) then return end local cell = createCellInRow(tbl, cfg.name) -- [Hop-up] Anvil Receiver if stat.anvil_receiver and stat.anvil_receiver.spread and aw.isNumberAndGreaterThanZero(stat.anvil_receiver.spread.decay_rate) and aw.isNumberAndGreaterThanZero(stat.anvil_receiver.spread.decay_delay) then local intbl = cell:tag('table') :addClass('condensedtable') :addClass('raritytable') renderSpreadDecayRow( intbl, '', cfg, stat.spread) renderSpreadDecayRow( intbl, iu.hopup('anvil_receiver') .. ' ', cfg, stat.anvil_receiver.spread, { rarity = 'legendary' }) else local text = string.format(cfg.format, stat.spread.decay_rate, stat.spread.decay_delay) cell:wikitext(text) end end local function createTable(cfg, stat, lang, frame) local isSpecial = aw.stringstarts(stat.ammo, "special_") 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) renderDamage(tbl, cfg.damage, stat) if stat.firerate then renderFirerate(tbl, cfg.firerate, stat, lang) end renderProjectileSpeed(tbl, cfg.projectilespeed, stat.projectile_speed, stat.projectile_speed_charged) renderMoveSpeed(tbl, cfg.movespeed, stat.move_speed, stat.move_speed_charged) renderMagazine(tbl, cfg.magazine, stat, isSpecial, isModdedLoaderAttachable) if stat.firerate then renderDPS(tbl, cfg.dps, stat, lang) end if stat.time then renderDuration(tbl, cfg.duration, stat, lang) end if stat.spread then renderSpread(tbl, cfg.spread, stat, lang, frame) renderSpreadDecay(tbl, cfg.spreaddecay, stat) end return tbl end local function renderInfobox(args, frame) 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, frame)) return div end function p._main(args, frame) formatter = require('Module:Utility/Formatter').new(frame) return tostring(renderInfobox(args, frame)) 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