🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:WeaponInfobox
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール:WeaponInfobox/doc に作成できます
require('Module:Utility/mw.html Extensions') local p = {} 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') :tag('td') :attrIf(opts.headerAlign and type(opts.headerAlign) == 'string', { aling = opts.headerAlign }) :wikitext(name) :done() :tag('td') :addClass('cell-type-number') :wikitext(default) :done() 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 CategoryDict = { assault_rifle = "アサルトライフル", sub_machine_gun = "サブマシンガン", light_machine_gun = "ライトマシンガン", sniper = "スナイパーライフル", shotgun = "ショットガン", pistol = "ピストル", } local function renderCategory(tbl, name, stat) local category = CategoryDict[stat] local item = string.format('[[武器#%s|%s]][[Category:%s]]', category, category, category) renderRow(tbl, name, item) end local AmmoDict = { light = "ライトアモ", heavy = "ヘビーアモ", energy = "エネルギーアモ", sniper = "スナイパーアモ", shotgun = "ショットガンアモ", special_light = "専用ライトアモ", special_heavy = "専用ヘビーアモ", special_energy = "専用エネルギーアモ", special_sniper = "専用スナイパーアモ", special_shotgun = "専用ショットガンアモ", } local function renderAmmo(tbl, name, stat) local ammo = AmmoDict[stat] local page = '弾による武器一覧#' .. ammo local item = formatter:ammo(ammo, 28, page) .. string.format(' [[%s|%s]][[Category:%s]]', page, ammo, ammo) renderRow(tbl, 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, name, stat) local mode = nil if stat.burst > 1 then mode = stat.burst .. '点バースト' end if stat.auto then if mode == nil then mode = 'オート' else mode = mode .. '・オート' end end if stat.single then if mode == nil then mode = '単発' else mode = mode .. '・単発' end end renderRow(tbl, name, mode) end local function renderDamage(tbl, name, stat, ammo, pellet) local base = stat.base local typename = type(base) if pellet ~= nil then local item = tostring(base) .. ' × ' .. tostring(pellet) .. '片' renderRow(tbl, name, item) elseif typename == 'table' then renderRow(tbl, name, table.concat(base, ' - ')) elseif typename == 'number' then local damageText if stat.anvil_receiver ~= nil then damageText = base .. ' - ' .. iu.hopup('アンビルレシーバー') .. ' ' .. formatter:legendary(stat.anvil_receiver.base) else damageText = tostring(base) end renderRow(tbl, name, damageText) else return end 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 = '[[Category:ヘッドショット倍率が' .. stat.headshot .. '倍の武器]]' local ul = mw.html.create('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, '頭', head, hlm1, hlm2, hlm3, { footer = '倍' .. cattext }) renderFormatRow( intable, iu.hopup('スカルピアサーライフリング') .. ' ', spr0, spr1, spr2, spr3, { footer = '倍' }) else local headText = '頭 ' .. formatter:format(head, hlm1, hlm2, hlm3, '倍', ' - ') .. cattext ul:tag('li'):wikitext(headText) end local legText if stat.anvil_receiver ~= nil then local anvilleg = convertDecimalToFractional(stat.anvil_receiver.legshot) legText = '脚 ' .. leg .. ' - ' .. iu.hopup('アンビルレシーバー') .. ' ' .. formatter:legendary(anvilleg) .. '倍' else legText = '脚 ' .. leg .. '倍' end ul:tag('li'):wikitext(legText) tbl:tag('tr') :tag('td') :attr('colspan', 2) :node(ul) end local function renderFirerate(tbl, name, firerate, mode) if firerate == nil then return end local cell = createCellInRow(tbl, name) if mode.auto then if mode.single then if firerate.anvil_receiver then local ul = tbl:tag('tr'):tag('td'):attr('colspan', 2):tag('ul') ul:tag('li'):wikitext('オート: ' .. firerate.auto .. ' rps <small>(' .. (60 * firerate.auto) .. ' rpm)</small>') if firerate.auto ~= firerate.single then ul:tag('li'):wikitext('単発: ' .. firerate.single .. ' rps <small>(' .. (60 * firerate.single) .. ' rpm)</small>') end if firerate.anvil_receiver then ul:tag('li') :wikitext( iu.hopup('アンビルレシーバー') .. ': ' .. firerate.anvil_receiver .. ' rps <small>(' .. (60 * firerate.anvil_receiver) .. ' rpm)</small>') end elseif firerate.auto ~= firerate.single then tbl:tag('tr') :tag('td') :attr('colspan', 2) :tag('ul') :tag('li') :wikitext('オート: ' .. firerate.auto .. ' rps <small>(' .. (60 * firerate.auto) .. ' rpm)</small>') :done() :tag('li') :wikitext('単発: ' .. firerate.single .. ' rps <small>(' .. (60 * firerate.single) .. ' rpm)</small>') else local rps = firerate.auto cell:wikitext(rps .. ' rps <small>(' .. (60 * rps) .. ' rpm)</small>') end else local rps = firerate.auto cell:wikitext(rps .. ' rps <small>(' .. (60 * rps) .. ' rpm)</small>') end elseif mode.single then local rps = firerate.single cell:wikitext(rps .. ' rps <small>(' .. (60 * rps) .. ' rpm)</small>') 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 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(table, name, stat, islmg) local typename = type(stat) if typename == 'table' then if islmg then local intable = createCellInRow(table, name) :tag('table') :addClass('condensedtable') renderFormatRow( intable, '', stat[1], stat[2], stat[3], stat[4]) renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', stat['modded0'], stat['modded1'], stat['modded2'], stat['modded3']) else local text = formatter:format(stat[1], stat[2], stat[3], stat[4], '', ' - ') renderRow(table, name, text) end elseif typename == 'number' then if stat == math.huge then renderRow(table, name, '∞') else renderRow(table, name, stat) end else return end end local reloadFormat = '%.2f' local function renderReload(tbl, name, 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, name) :tag('table') :addClass('condensedtable') :addClass('listtable') renderFormatRow( intable, 'タクティカル ', string.format(reloadFormat, reload.tactical), nil, nil, nil, { footer = '秒'}) if islmg then renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', string.format(reloadFormat, 0.75 * reload.tactical), nil, nil, nil, { headerAlign = 'right', footer = '秒' }) end renderFormatRow( intable, 'フル', string.format(reloadFormat, reload.full), nil, nil, nil, { footer = '秒'}) if islmg then renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', string.format(reloadFormat, 0.75 * reload.full), nil, nil, nil, { headerAlign = 'right', footer = '秒' }) end elseif islmg then local intable = createCellInRow(tbl, name) :tag('table') :addClass('condensedtable') renderFormatRow( intable, '', string.format(reloadFormat, muls.level3 * reload.full), nil, nil, nil, { footer = '秒'}) renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', string.format(reloadFormat, 0.75 * muls.level3 * reload.full), nil, nil, nil, { headerAlign = 'right', footer = '秒' }) else local time if incompatible or ammo == 'special_sniper' then time = reload.full else time = muls.level3 * reload.full end renderRow(tbl, name, string.format(reloadFormat .. '秒', time)) end elseif reload.tactical ~= nil and reload.tactical ~= reload.full then renderRow(tbl, name, '') local intable = tbl:tag('tr') :tag('td') :attr('colspan', 2) :tag('table') :addClass('condensedtable') :addClass('listtable') renderFormatRow( intable, 'タクティカル ', string.format(reloadFormat, reload.tactical), nil, string.format(reloadFormat, muls.level2 * reload.tactical), string.format(reloadFormat, muls.level3 * reload.tactical), { footer = '秒'}) if islmg then renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', string.format(reloadFormat, 0.75 * reload.tactical), nil, string.format(reloadFormat, 0.75 * muls.level2 * reload.tactical), string.format(reloadFormat, 0.75 * muls.level3 * reload.tactical), { headerAlign = 'right', footer = '秒' }) end renderFormatRow( intable, 'フル', string.format(reloadFormat, reload.full), nil, string.format(reloadFormat, muls.level2 * reload.full), string.format(reloadFormat, muls.level3 * reload.full), { footer = '秒'}) if islmg then renderFormatRow( intable, formatter:hopup('改造ローダー') .. ' ', string.format(reloadFormat, 0.75 * reload.full), nil, string.format(reloadFormat, 0.75 * muls.level2 * reload.full), string.format(reloadFormat, 0.75 * muls.level3 * reload.full), { headerAlign = 'right', footer = '秒' }) end else local text = formatter:format( string.format(reloadFormat, reload.full), nil, string.format(reloadFormat, muls.level2 * reload.full), string.format(reloadFormat, muls.level3 * reload.full), '秒', ' - ') renderRow(tbl, name, text) end end local function renderReleaseDate(tbl, name, 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, name, releaseText) end local function renderTable(args, stat) stat = stat or mw.loadData('Module:Stat/Weapon')[args.name] local category = stat.category local islmg = category == 'light_machine_gun' local table = mw.html.create('table') renderReleaseDate(table, 'リリース日', stat.release) renderCategory(table, '種類', category) renderAmmo(table, '弾薬', stat.ammo) renderMode(table, '射撃モード', stat.mode) renderDamage(table, 'ダメージ', stat.damage, stat.ammo, stat.pellet) renderFirerate(table, '射撃速度', stat.firerate, stat.mode) renderDPS(table, 'DPS', stat) renderMagazine(table, '装填数', stat.magazine, islmg) if stat.time and stat.time.reload then renderReload(table, 'リロード', stat.time.reload, stat.attachments, stat.ammo, islmg) end return table end function p.getNode(stat, formatter2) formatter = formatter2 or require('Module:Utility/Formatter').new() return renderTable(nil, stat) end function p._main(args, frame) formatter = require('Module:Utility/Formatter').new(frame) return tostring(renderTable(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