🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:WeaponInfobox」の版間の差分
ナビゲーションに移動
検索に移動
(アンビルレシーバーのダメージ倍率の表記漏れの追加) |
(アンビルレシーバーのレジェンダリーハイライトを「倍」まで行うように変更) |
||
230行目: | 230行目: | ||
local anvilleg = convertDecimalToFractional(stat.anvil_receiver.legshot) | local anvilleg = convertDecimalToFractional(stat.anvil_receiver.legshot) | ||
legText = string.format( | legText = string.format( | ||
'脚 %s <span class="text-separator">/</span> %s %s | '脚 %s <span class="text-separator">/</span> %s %s', | ||
leg, | leg, | ||
iu.hopup('アンビルレシーバー'), | iu.hopup('アンビルレシーバー'), | ||
formatter:legendary(anvilleg)) | formatter:legendary(anvilleg .. ' 倍')) | ||
else | else | ||
legText = '脚 ' .. leg .. ' 倍' | legText = '脚 ' .. leg .. ' 倍' |
2021年2月17日 (水) 11:37時点における版
このモジュールについての説明文ページを モジュール: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') :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 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, 24, 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 = string.format( '%s <span class="text-separator">/</span> %s %s', 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 = string.format( '脚 %s <span class="text-separator">/</span> %s %s', 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 rpsFormat = '%.2f' local rpmFormat = '%.0f' local function renderFirerate(tbl, name, firerate, mode) if firerate == nil then return end local cell = createCellInRow(tbl, name) local rps 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 return else rps = firerate.auto end elseif mode.single then rps = firerate.single else return end if type(rps) == 'table' then local intable = cell:tag('table'):addClass('condensedtable') renderFormatRow( intable, '', string.format(rpsFormat, rps[1]), string.format(rpsFormat, rps[2]), string.format(rpsFormat, rps[3]), string.format(rpsFormat, rps[4]), { separator = ' - ', footer = ' rps ' }) renderFormatRow( intable, '(', string.format(rpmFormat, 60 * rps[1]), string.format(rpmFormat, 60 * rps[2]), string.format(rpmFormat, 60 * rps[3]), string.format(rpmFormat, 60 * rps[4]), { separator = ' - ', footer = ' rpm)' }) else cell:wikitext(string.format( rpsFormat .. ' rps <small>(' .. rpmFormat .. ' rpm)</small>', rps, 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(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], { footer = ' 発' }) 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 = ' 発' }) 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, { class = 'no-list-style', 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, { class = 'no-list-style', headerAlign = 'right', footer = ' 秒' }) end elseif islmg then local text = string.format( reloadFormat .. ' 秒 <span class="text-separator">/</span> %s ' .. reloadFormat .. ' 秒', muls.level3 * reload.full, formatter:hopup('改造ローダー'), 0.75 * muls.level3 * reload.full) renderRow(tbl, name, text) 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), { class = 'no-list-style', 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), { class = 'no-list-style', 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 drawFormat = '%.2f' local function renderDraw(tbl, name, 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( drawFormat .. ' 秒 <span class="text-separator">/</span> %s ' .. formatter:epic(drawFormat .. ' 秒'), time, iu.hopup('クイックドローホルスター'), quickdraw_holster * time) else text = string.format(drawFormat .. ' 秒', time) end renderRow(tbl, name, text) elseif quickdraw_holster > 0 then local intable = createCellInRow(tbl, name) :tag('table') :addClass('condensedtable') renderFormatRow( intable, '', string.format(reloadFormat, draw), string.format(reloadFormat, 0.85 * draw), string.format(reloadFormat, 0.80 * draw), string.format(reloadFormat, 0.75 * draw), { footer = ' 秒' }) renderFormatRow( intable, iu.hopup('クイックドローホルスター') .. ' ', string.format(reloadFormat, quickdraw_holster * draw), string.format(reloadFormat, 0.85 * quickdraw_holster * draw), string.format(reloadFormat, 0.80 * quickdraw_holster * draw), string.format(reloadFormat, 0.75 * quickdraw_holster * draw), { footer = ' 秒' }) else local text = formatter:format( string.format(drawFormat, draw), string.format(drawFormat, 0.85 * draw), string.format(drawFormat, 0.80 * draw), string.format(drawFormat, 0.75 * draw), ' 秒', ' - ') 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 tbl = mw.html.create('table') renderReleaseDate(tbl, 'リリース日', stat.release) renderCategory(tbl, '種類', category) renderAmmo(tbl, '弾薬', stat.ammo) renderMode(tbl, '射撃モード', stat.mode) renderDamage(tbl, 'ダメージ', stat.damage, stat.ammo, stat.pellet) renderDPS(tbl, 'DPS', stat) renderFirerate(tbl, '射撃速度', stat.firerate, stat.mode) renderMagazine(tbl, '装填数', stat.magazine, islmg) if stat.time then if stat.time.draw then renderDraw(tbl, '据銃時間', stat.time.draw, stat.time.quickdraw_holster or 0, stat.attachments, stat.ammo) end if stat.time.reload then renderReload(tbl, 'リロード', stat.time.reload, stat.attachments, stat.ammo, islmg) end end return tbl 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