🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:WeaponInfobox」の版間の差分
ナビゲーションに移動
検索に移動
(連射間隔のrpmフォーマットをcomma付与関数に変更) |
(連射間隔の一行のrpmフォーマットをcomma付与関数に変更) |
||
323行目: | 323行目: | ||
else | else | ||
cell:wikitext(string.format( | cell:wikitext(string.format( | ||
'<span class="text-type-number">' .. cfg.rps.format .. '</span>' .. cfg.rps.unit .. '<span class="text-secondary"><small>(<span class="text-type-number"> | '<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, | rps, | ||
60 * rps)) | aw.comma(60 * rps))) | ||
end | end | ||
end | end |
2021年2月17日 (水) 15:58時点における版
このモジュールについての説明文ページを モジュール: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 formatter -- lazily initialized local getArgs -- lazily initialized local function stringStarts(str, start) return string.sub(str, 1, string.len(start)) == start 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 row:tag('td') :addClass('cell-type-number') :wikitext(default) if common ~= nil then row:tag('td'):wikitext(opts.separator):done() :tag('td') :addClass('cell-type-number') :wikitext(formatter:common(common)) end if rare ~= nil then row:tag('td'):wikitext(opts.separator):done() :tag('td') :addClass('cell-type-number') :wikitext(formatter:rare(rare)) end if epic ~= nil then row:tag('td'):wikitext(opts.separator):done() :tag('td') :addClass('cell-type-number') :wikitext(formatter:epic(epic)) end if opts.footer ~= nil then row:tag('td'):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) local category = cfg[stat] local item = string.format('[[武器#%s|%s]][[Category:%s]]', category, category, category) renderRow(tbl, cfg.name, item) end local function renderAmmo(tbl, cfg, stat) local ammo = cfg[stat] local page = '弾薬#' .. ammo local item = formatter:ammo(ammo, 24, page) .. string.format(' [[%s|%s]][[Category:%s]]', page, ammo, ammo) renderRow(tbl, cfg.name, item) end local function convertDecimalToFractional(num) local integer = math.floor(num) local decimal = tonumber(string.format("%.3f", num - integer)) local decimalText if decimal == 0.125 then decimalText = '⅛' elseif decimal == 0.2 then decimalText = '⅕' elseif decimal == 0.25 then decimalText = '¼' elseif decimal == 1/3 then decimalText = '⅓' elseif decimal == 0.375 then decimalText = '⅜' elseif decimal == 0.4 then decimalText = '⅖' elseif decimal == 0.5 then decimalText = '½' elseif decimal == 0.6 then decimalText = '⅗' elseif decimal == 0.625 then decimalText = '⅝' elseif decimal == 2/3 then decimalText = '⅔' elseif decimal == 0.75 then decimalText = '¾' elseif decimal == 0.8 then decimalText = '⅘' elseif decimal == 0.875 then decimalText = '⅞' else decimalText = '' end if decimalText == '' then return tostring(num) elseif integer == 0 then return decimalText else return tostring(integer) .. decimalText end end local function renderMode(tbl, cfg, stat) local mode = nil if stat.burst > 1 then mode = string.format(cfg.burst, stat.burst) .. cfg.burst_category end if stat.auto then if mode == nil then mode = cfg.auto .. cfg.auto_category else mode = mode .. cfg.separator .. cfg.auto .. cfg.auto_category end end if stat.single then if mode == nil then mode = cfg.single .. cfg.single_category else mode = mode .. cfg.separator .. cfg.single .. cfg.single_category end end renderRow(tbl, cfg.name, mode) end local function renderDamage(tbl, cfg, stat, ammo, pellet) local base = stat.base local typename = type(base) local damageText if pellet ~= nil then damageText = string.format(cfg.shotgun, base, pellet) elseif typename == 'table' then damageText = table.concat(base, ' - ') elseif typename == 'number' then if stat.anvil_receiver ~= nil then damageText = string.format( '%s <span class="text-separator">/</span> %s %s', base, iu.hopup('アンビルレシーバー'), formatter:legendary(stat.anvil_receiver.base)) else damageText = tostring(base) end else return end renderRow(tbl, cfg.name, damageText) local head = convertDecimalToFractional(stat.headshot) local hlm1 = convertDecimalToFractional(0.2 + 0.8 * stat.headshot) local hlm2 = convertDecimalToFractional(0.4 + 0.6 * stat.headshot) local hlm3 = convertDecimalToFractional(0.5 + 0.5 * stat.headshot) local leg = convertDecimalToFractional(stat.legshot) local sprm = stat.skullpiercer_rifling or 1 local cattext = string.format(cfg.head_category, stat.headshot) local ul = tbl:tag('tr') :tag('td') :attr('colspan', 2) :tag('ul') if sprm > 1 then local spr0 = convertDecimalToFractional(sprm) local spr1 = convertDecimalToFractional(0.2 + 0.8 * sprm) local spr2 = convertDecimalToFractional(0.4 + 0.6 * sprm) local spr3 = convertDecimalToFractional(0.5 + 0.5 * sprm) local intable = ul:tag('li') :tag('table') :addClass('condensedtable') renderFormatRow( intable, cfg.head, head, hlm1, hlm2, hlm3, { footer = cfg.unit .. cattext }) renderFormatRow( intable, iu.hopup('スカルピアサーライフリング') .. ' ', spr0, spr1, spr2, spr3, { footer = cfg.unit }) else local headText = cfg.head .. formatter:format(head, hlm1, hlm2, hlm3, cfg.unit, ' - ') .. cattext ul:tag('li'):wikitext(headText) end local legText if stat.anvil_receiver ~= nil then local anvilleg = convertDecimalToFractional(stat.anvil_receiver.legshot) legText = string.format( cfg.legs .. ' %s' .. cfg.unit .. ' <span class="text-separator">/</span> %s %s', leg, iu.hopup('アンビルレシーバー'), formatter:legendary(anvilleg .. cfg.unit)) else legText = cfg.legs .. ' ' .. leg .. cfg.unit end ul:tag('li'):wikitext(legText) end local function renderFirerateRow(intbl, name, cfg, rps) intbl:tag('tr') :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') :addClass('all-secondary') :tag('small') :wikitext(cfg.rpm.name) :done() :done() :tag('td') :addClass('all-secondary') :addClass('cell-type-number') :attr('align', 'right') :tag('small') :wikitext(aw.comma(60 * rps)) :done() :done() :tag('td') :addClass('all-secondary') :tag('small') :wikitext(cfg.rpm.unit) end local function renderFirerate(tbl, cfg, firerate, mode) if firerate == nil then return end local cell = createCellInRow(tbl, cfg.name) local rps if mode.auto then if mode.single then if firerate.anvil_receiver then local intbl = cell:tag('table') :addClass('condensedtable') :addClass('listtable') renderFirerateRow(intbl, cfg.auto, cfg, firerate.auto) if firerate.auto ~= firerate.single then renderFirerateRow(intbl, cfg.single, cfg, firerate.single) end if firerate.anvil_receiver then renderFirerateRow(intbl, iu.hopup('アンビルレシーバー'), cfg, firerate.anvil_receiver) end return elseif firerate.auto ~= firerate.single then local intbl = cell:tag('table') :addClass('condensedtable') :addClass('listtable') renderFirerateRow(intbl, cfg.auto, cfg, firerate.auto) renderFirerateRow(intbl, cfg.single, cfg, firerate.single) return end end rps = firerate.auto elseif mode.single then rps = firerate.single else return end if type(rps) == 'table' then local intable = cell:tag('table'):addClass('condensedtable') renderFormatRow( intable, cfg.rps.name, string.format(cfg.rps.format, rps[1]), string.format(cfg.rps.format, rps[2]), string.format(cfg.rps.format, rps[3]), string.format(cfg.rps.format, rps[4]), { separator = cfg.rps.separator, footer = cfg.rps.unit }) renderFormatRow( intable, cfg.rpm.name, string.format(cfg.rpm.format, 60 * rps[1]), string.format(cfg.rpm.format, 60 * rps[2]), string.format(cfg.rpm.format, 60 * rps[3]), string.format(cfg.rpm.format, 60 * rps[4]), { class = 'all-secondary', separator = cfg.rpm.separator, footer = cfg.rpm.unit }) else cell:wikitext(string.format( '<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(60 * rps))) end end local function renderRowDPS(tbl, name, leg, body, head, skullpiercer, tag) tag = tag or 'td' local row = tbl:tag('tr') row:tag('th'):wikitext(name) if leg == '' then row:tag(tag) :attr('align', 'center') :addClass('disabled') :wikitext('–') elseif leg ~= nil and leg ~= body then row:tag(tag):wikitext(leg) end row :tag(tag):wikitext(body):done() :tag(tag):wikitext(head) if skullpiercer ~= nil then row:tag(tag):wikitext(skullpiercer) end end local function toDPSText(dps) return string.format("%.1f", dps) end local function renderDPSTable(cell, name, pellet, base, damages, firerate, useRound) local headDamage = aw.round(damages.headshot * base) local legDamage = aw.round(damages.legshot * base) local skullpiercer = damages.skullpiercer_rifling local skullpiercerHeader = nil local commonSkullpiercerDPS = nil local lowprofileSkullpiercerDPS = nil local fortifiedSkullpiercerDPS = nil if skullpiercer ~= nil then skullpiercerHeader = iu.hopup('スカルピアサーライフリング') local skullpiercerDamage = aw.round(skullpiercer * base) commonSkullpiercerDPS = toDPSText(pellet * skullpiercerDamage * firerate) lowprofileSkullpiercerDPS = toDPSText(pellet * aw.selectiveRound(1.05 * skullpiercerDamage, useRound) * firerate) fortifiedSkullpiercerDPS = toDPSText(pellet * aw.round(0.85 * skullpiercerDamage) * firerate) end if type(firerate) == 'table' then firerate = firerate[1] end local intable = cell:tag('table') :addClass('intable') :addClass('numbertable') local lowprofileLegDamagePlaceholder if damages.legshot == 1 then lowprofileLegDamagePlaceholder = nil renderRowDPS(intable, name, nil, '胴', '頭', skullpiercerHeader, 'th') else lowprofileLegDamagePlaceholder = '' renderRowDPS(intable, name, '脚', '胴', '頭', skullpiercerHeader, 'th') end renderRowDPS( intable, '通常', toDPSText(pellet * legDamage * firerate), toDPSText(pellet * base * firerate), toDPSText(pellet * headDamage * firerate), commonSkullpiercerDPS) renderRowDPS( intable, '小柄', lowprofileLegDamagePlaceholder, toDPSText(pellet * aw.selectiveRound(1.05 * base, useRound) * firerate), toDPSText(pellet * aw.selectiveRound(1.05 * headDamage, useRound) * firerate), lowprofileSkullpiercerDPS) renderRowDPS( intable, '鉄壁', toDPSText(pellet * aw.round(0.85 * legDamage) * firerate), toDPSText(pellet * aw.round(0.85 * base) * firerate), toDPSText(pellet * aw.round(0.85 * headDamage) * firerate), fortifiedSkullpiercerDPS) end local function renderDPS(tbl, name, stat) if stat.firerate == nil then return end local damage = stat.damage.base renderRow(tbl, name, '') local pellet = stat.pellet or 1 local useRound = stat.damage.round or false local cell = tbl:tag('tr'):tag('td'):attr('colspan', 2) if type(damage) == 'table' then for _, damage in ipairs(damage) do if stat.mode.single then renderDPSTable( cell, '', pellet, damage, stat.damage, stat.firerate.single, useRound) end end else if stat.mode.auto then renderDPSTable( cell, '', pellet, stat.damage.base, stat.damage, stat.firerate.auto, useRound) end if stat.mode.single and stat.firerate.auto ~= stat.firerate.single then renderDPSTable( cell, '', pellet, stat.damage.base, stat.damage, stat.firerate.single, useRound) end if stat.damage.anvil_receiver and stat.firerate.anvil_receiver then renderDPSTable( cell, iu.hopup('アンビルレシーバー'), pellet, stat.damage.anvil_receiver.base, stat.damage.anvil_receiver, stat.firerate.anvil_receiver, useRound) end end end local function renderMagazine(tbl, cfg, stat, islmg) local typename = type(stat) if typename == 'table' then if islmg then local intable = createCellInRow(tbl, cfg.name) :tag('table') :addClass('condensedtable') renderFormatRow( intable, '', stat[1], stat[2], stat[3], stat[4], { footer = cfg.units }) renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', aw.round(1.15 * stat[1]), aw.round(1.15 * stat[2]), aw.round(1.15 * stat[3]), aw.round(1.15 * stat[4]), { footer = cfg.units }) else local text = formatter:format(stat[1], stat[2], stat[3], stat[4], cfg.units, ' - ') renderRow(tbl, cfg.name, text) end elseif typename == 'number' then local text if stat == math.huge then text = cfg.infinity else text = stat .. cfg.unit end renderRow(tbl, cfg.name, text) end end local function renderReload(tbl, cfg, reload, attachments, ammo, islmg) if reload.full == 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.extended_mag_or_shotgun_bolt if incompatible or ammo == 'shotgun' or stringStarts(ammo, "special_") then if reload.tactical ~= nil and reload.tactical ~= reload.full then local tacticalText, fullText if incompatible or ammo == 'special_sniper' 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 islmg then renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', 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 islmg then renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', string.format(cfg.full.format, 0.75 * reload.full), nil, nil, nil, { class = 'no-list-style', headerAlign = 'right', footer = cfg.full.unit }) end elseif islmg then local text = string.format( cfg.full.format .. cfg.full.unit .. ' <span class="text-separator">/</span> %s ' .. cfg.full.format .. cfg.full.unit, muls.level3 * reload.full, formatter:hopup('改造ローダー'), 0.75 * muls.level3 * reload.full) renderRow(tbl, cfg.name, text) else local time if incompatible or ammo == 'special_sniper' 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.tactical ~= reload.full then renderRow(tbl, cfg.name, '') local intable = tbl:tag('tr') :tag('td') :attr('colspan', 2) :tag('table') :addClass('condensedtable') :addClass('listtable') renderFormatRow( intable, cfg.tactical.name .. ' ', string.format(cfg.tactical.format, reload.tactical), nil, string.format(cfg.tactical.format, muls.level2 * reload.tactical), string.format(cfg.tactical.format, muls.level3 * reload.tactical), { footer = cfg.tactical.unit }) if islmg then renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', string.format(cfg.tactical.format, 0.75 * reload.tactical), nil, 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 renderFormatRow( intable, cfg.full.name .. ' ', string.format(cfg.full.format, reload.full), nil, string.format(cfg.full.format, muls.level2 * reload.full), string.format(cfg.full.format, muls.level3 * reload.full), { footer = cfg.full.unit }) if islmg then renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', string.format(cfg.full.format, 0.75 * reload.full), nil, 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 else local text = formatter:format( string.format(cfg.full.format, reload.full), nil, string.format(cfg.full.format, muls.level2 * reload.full), string.format(cfg.full.format, muls.level3 * reload.full), cfg.full.unit, ' - ') renderRow(tbl, cfg.name, text) 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 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 * 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('クイックドローホルスター') .. ' ', 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 createTable(cfg, stat) local islmg = stat.category == 'light_machine_gun' local tbl = mw.html.create('table') renderReleaseDate(tbl, cfg.release, stat.release) renderCategory(tbl, cfg.category, stat.category) renderAmmo(tbl, cfg.ammo, stat.ammo) renderMode(tbl, cfg.mode, stat.mode) renderDamage(tbl, cfg.damage, stat.damage, stat.ammo, stat.pellet) renderDPS(tbl, 'DPS', stat) renderFirerate(tbl, cfg.firerate, stat.firerate, stat.mode) renderMagazine(tbl, cfg.magazine, stat.magazine, islmg) 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, islmg) end end return tbl end local function renderInfobox(args) local cfglang = cfg[args and args.lang or 'ja'] local stat = mw.loadData('Module:Stat/Weapon')[args.name] local ammolang = cfglang.ammo[stat.ammo] local page = '弾による武器一覧#' .. ammolang local div = mw.html.create('div') :addClass('tpl-infobox-right') :addClass('tpl-weapon') if 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 .. formatter:ammo(ammolang, 40, page)) div:node(createTable(cfglang, stat)) 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