| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:WeaponInfobox」の版間の差分
ナビゲーションに移動
検索に移動
(外部ファイルからテキストリソースを読み込むように改善) |
(装填数が単一の数字のケースの不具合を修正) |
||
| 473行目: | 473行目: | ||
text = cfg.infinity | text = cfg.infinity | ||
else | else | ||
text = stat .. cfg. | text = stat .. cfg.unit | ||
end | end | ||
renderRow(tbl, cfg.name, text) | renderRow(tbl, cfg.name, text) | ||
2021年2月17日 (水) 12:28時点における版
このモジュールについての説明文ページを モジュール:WeaponInfobox/doc に作成できます
require('Module:Utility/mw.html Extensions')
local p = {}
local cfg = mw.loadData('Module:Utility/WeaponTable/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)
end
if stat.auto then
if mode == nil then
mode = cfg.auto
else
mode = mode .. cfg.separator .. cfg.auto
end
end
if stat.single then
if mode == nil then
mode = cfg.single
else
mode = mode .. cfg.separator .. cfg.single
end
end
renderRow(tbl, cfg.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 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 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
return
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) .. cfg.rpm.unit .. ')</small>')
:done()
:tag('li')
:wikitext('単発: ' .. firerate.single .. ' rps <small>(' .. (60 * firerate.single) .. cfg.rpm.unit .. ')</small>')
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]),
{ separator = cfg.rpm.separator, footer = cfg.rpm.unit })
else
cell:wikitext(string.format(
cfg.rps.format .. cfg.rps.unit .. '<small>(' .. cfg.rpm.format .. cfg.rpm.unit .. '</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(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, 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 renderTable(args, stat)
stat = stat or mw.loadData('Module:Stat/Weapon')[args.name]
local cfglang = cfg.ja
local islmg = stat.category == 'light_machine_gun'
local tbl = mw.html.create('table')
renderReleaseDate(tbl, cfglang.release, stat.release)
renderCategory(tbl, cfglang.category, stat.category)
renderAmmo(tbl, cfglang.ammo, stat.ammo)
renderMode(tbl, cfglang.mode, stat.mode)
renderDamage(tbl, 'ダメージ', stat.damage, stat.ammo, stat.pellet)
renderDPS(tbl, 'DPS', stat)
renderFirerate(tbl, cfglang.firerate, stat.firerate, stat.mode)
renderMagazine(tbl, cfglang.magazine, stat.magazine, islmg)
if stat.time then
if stat.time.draw then
renderDraw(tbl, cfglang.draw, stat.time.draw, stat.time.quickdraw_holster or 0, stat.attachments, stat.ammo)
end
if stat.time.reload then
renderReload(tbl, cfglang.reload, 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