| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:WeaponInfobox/Firerate
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール:WeaponInfobox/Firerate/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 proto = require('Module:Utility/Prototypes')
local Hopup = mw.loadData('Module:Stat/Hopup')
-- Protos
local MultipleNumberProto = {
proto.NumberRange(0),
proto.NumberRange(0),
proto.NumberRange(0),
proto.NumberRange(0),
}
local Eva8AutoProto = {
firerate = MultipleNumberProto,
double_tap_trigger = {
burst_count = proto.NumberRange(2),
burst_delay = MultipleNumberProto,
firerate = proto.NumberRange(0),
},
}
local PeacekeeperProto = {
firerate = proto.NumberRange(0),
rechamber = MultipleNumberProto,
}
local AltfireProto = {
firerate = proto.NumberRange(0),
}
local SelectfireReceiverProto = {
firerate = proto.NumberRange(0),
}
local DevotionProto = {
firerate = proto.NumberRange(0),
firerate_maximum = proto.NumberRange(0),
}
local AnvilReceiverProto = {
firerate = proto.NumberRange(0),
}
local DoubleTapTrigggerProto = {
burst_count = proto.NumberRange(2),
burst_delay = proto.NumberRange(0),
firerate = proto.NumberRange(0),
}
local DeadeyesTempoWithChargeProto = {
charge = proto.NumberRange(0),
}
local DeadeyesTempoWithRechamberProto = {
rechamber = proto.NumberRange(0),
}
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
row
:tag('td')
:addClass('cell-type-number')
:attrIf(opts.align and type(opts.align) == 'string', { align = opts.align })
:wikitext(default)
:done()
:tag('td'):wikitext(opts.separator):done()
: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)
:done()
:done()
:tag('td'):wikitext(opts.separator):done()
: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)
:done()
:done()
:tag('td'):wikitext(opts.separator):done()
: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)
:done()
:done()
:tag('td')
:attr('align', 'left')
:wikitext(opts.footer)
return row
end
-- Render variable firerate
local function renderVariableFirerateRow(intbl, name, cfg, rps1, rps2, opts)
opts = opts or {}
intbl
:tag('tr')
:addClassIf(type(opts.rarity) == 'string', 'row-rarity-first disp-rarity-' .. (opts.rarity or 'common'))
:addClassIf(type(opts.class) == 'string', opts.class)
:tag('th')
:wikitext(name)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(string.format(cfg.rps.format, rps1))
:done()
:tag('td')
:wikitext(' → ')
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(string.format(cfg.rps.format, rps2))
:done()
:tag('td')
:wikitext(cfg.rps.unit)
:done()
:done()
:tag('tr')
:addClassIf(type(opts.rarity) == 'string', 'row-rarity-last disp-rarity-' .. (opts.rarity or 'common'))
:addClass('no-list-style')
:addClass('text-secondary')
:addClass('text-smaller')
:tag('th')
:attr('align', 'right')
:wikitext(cfg.rpm.name)
:done()
:tag('td')
:addClass('cell-type-number')
:wikitext(aw.comma(aw.roundx(60 * rps1, 1)))
:done()
:tag('td')
:wikitext(' → ')
:done()
:tag('td')
:addClass('cell-type-number')
:wikitext(aw.comma(aw.roundx(60 * rps2, 1)))
:done()
:tag('td')
:wikitext(cfg.rpm.unit)
end
-- Render multiple firerates in table
local function renderMultipleFirerateRow(intbl, name, cfg, rps, opts)
opts = opts or {}
renderFormatRow(
intbl,
name .. cfg.rps.name,
string.format(cfg.rps.format, aw.roundx(rps[1], 2)),
string.format(cfg.rps.format, aw.roundx(rps[2], 2)),
string.format(cfg.rps.format, aw.roundx(rps[3], 2)),
string.format(cfg.rps.format, aw.roundx(rps[4], 2)),
{ class = opts.rpsClass or '', separator = cfg.rps.separator, footer = cfg.rps.unit })
renderFormatRow(
intbl,
cfg.rpm.name,
string.format(cfg.rpm.format, aw.comma(aw.roundx(60 * rps[1], 1))),
string.format(cfg.rpm.format, aw.comma(aw.roundx(60 * rps[2], 1))),
string.format(cfg.rpm.format, aw.comma(aw.roundx(60 * rps[3], 1))),
string.format(cfg.rpm.format, aw.comma(aw.roundx(60 * rps[4], 1))),
{ class = opts.rpmClass and 'text-secondary text-smaller ' .. opts.rpmClass or 'text-secondary text-smaller', headerAlign = 'right', separator = cfg.rpm.separator, footer = cfg.rpm.unit })
end
-- Render a firerate in table
local function renderFirerateRow(intbl, name, cfg, rps, opts)
opts = opts or {}
local row = intbl:tag('tr')
:addClassIf(opts.class and type(opts.class) == 'string', opts.class)
if type(opts.rarity) == 'string' then
row:addClass(string.format('row-rarity-%s disp-rarity-%s', opts.rarityRowStyle or 'one', opts.rarity))
end
row
: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('text-secondary')
:addClass('text-smaller')
:wikitext(cfg.rpm.name)
:done()
:tag('td')
:addClass('cell-type-number')
:addClass('text-secondary')
:addClass('text-smaller')
:attr('align', 'right')
:wikitext(aw.comma(aw.roundx(60 * rps, 1)))
:done()
:tag('td')
:addClass('text-secondary')
:addClass('text-smaller')
:wikitext(cfg.rpm.unit)
end
-- Render a firerate
local function renderFirerateText(name, cfg, rps)
return string.format(
'%s<span class="text-type-number">' .. cfg.rps.format .. '</span>' .. cfg.rps.unit .. '<span class="text-secondary text-smaller">(<span class="text-type-number">%s</span>' .. cfg.rpm.unit .. '</span>',
name,
rps,
aw.comma(aw.roundx(60 * rps, 1)))
end
-- Render
function p.renderFirerate(stat, lang)
local isSpecial = aw.stringstarts(stat.ammo, "special_")
local cfg2 = cfg[lang].firerate
local tbl = mw.html.create('table'):addClass('condensedtable')
-- ディヴォーションLMG
if proto.validateTypes(stat, DevotionProto) then
renderVariableFirerateRow(tbl, '', cfg2, stat.firerate, stat.firerate_maximum)
if stat.turbocharger and aw.isNumberAndGreaterThanZero(stat.turbocharger.firerate) then
tbl:addClass('raritytable')
renderVariableFirerateRow(
tbl,
iu.hopup('turbocharger') .. ' ',
cfg2,
stat.turbocharger.firerate or stat.firerate,
stat.turbocharger.firerate_maximum or stat.firerate_maximum,
{ rarity = Hopup.turbocharger.rarity })
end
-- ショットガン
elseif stat.ammo == 'shotgun' then
-- EVA-8オート
if (Hopup.double_tap_trigger.enabled or isSpecial) and proto.validateTypes(stat, Eva8AutoProto) then
renderMultipleFirerateRow(tbl, '', cfg2, stat.firerate)
local burstAverage = {
apex.calcBurstAverageFirerate(stat.double_tap_trigger.burst_count, stat.double_tap_trigger.burst_delay[1], stat.double_tap_trigger.firerate),
apex.calcBurstAverageFirerate(stat.double_tap_trigger.burst_count, stat.double_tap_trigger.burst_delay[2], stat.double_tap_trigger.firerate),
apex.calcBurstAverageFirerate(stat.double_tap_trigger.burst_count, stat.double_tap_trigger.burst_delay[3], stat.double_tap_trigger.firerate),
apex.calcBurstAverageFirerate(stat.double_tap_trigger.burst_count, stat.double_tap_trigger.burst_delay[4], stat.double_tap_trigger.firerate),
}
local label = string.format('%s %s ', iu.hopup('double_tap_trigger'), cfg2.burst_average)
tbl:addClass('raritytable')
renderMultipleFirerateRow(tbl, label, cfg2, burstAverage, {
rpsClass = 'row-rarity-first disp-rarity-epic',
rpmClass = 'row-rarity-last disp-rarity-epic',
})
return tbl, true
-- ピースキーパー
elseif proto.validateTypes(stat, PeacekeeperProto) then
local calcRPS = {
apex.calcRechamberFirerate(stat.firerate, stat.rechamber[1]),
apex.calcRechamberFirerate(stat.firerate, stat.rechamber[2]),
apex.calcRechamberFirerate(stat.firerate, stat.rechamber[3]),
apex.calcRechamberFirerate(stat.firerate, stat.rechamber[4]),
}
renderMultipleFirerateRow(tbl, '', cfg2, calcRPS)
-- マスティフショットガン・モザンビークショットガン
elseif proto.validateTypes(stat.firerate, MultipleNumberProto) then
renderMultipleFirerateRow(tbl, '', cfg2, stat.firerate)
end
-- mode: Burst
elseif aw.isNumberAndGreaterThanOrEqualToX(stat.burst_count, 2) then
local average = apex.calcBurstAverageFirerate(stat.burst_count, stat.burst_delay, stat.firerate)
-- w/Altfire
if proto.validateTypes(stat.altfire, AltfireProto) then
tbl:addClass('listtable')
renderFirerateRow(tbl, cfg2.burst, cfg2, stat.firerate)
renderFirerateRow(tbl, cfg2.burst_average, cfg2, average, { class = 'no-list-style' })
local label = (stat.altfire.is_semi_auto == true or stat.is_semi_auto) and cfg2.single or cfg2.auto
renderFirerateRow(tbl, label, cfg2, stat.altfire.firerate)
return tbl, true
-- w/o Altfire
else
renderFirerateRow(tbl, '', cfg2, stat.firerate)
renderFirerateRow(tbl, cfg2.burst_average, cfg2, average)
-- プラウラーバーストPDW
if (Hopup.selectfire_receiver.enabled or isSpecial) and proto.validateTypes(stat.selectfire_receiver, SelectfireReceiverProto) then
tbl:addClass('raritytable')
local label = iu.hopup('selectfire_receiver') .. ' '
renderFirerateRow(tbl, label, cfg2, stat.selectfire_receiver.firerate, { rarity = Hopup.selectfire_receiver.rarity })
end
end
-- w/charge
elseif aw.isNumberAndGreaterThanZero(stat.charge) then
local minimum, maximum
if aw.isNumberAndGreaterThanZero(stat.charge_minimum) then
minimum = apex.calcRechamberFirerate(stat.firerate, stat.charge_minimum)
maximum = apex.calcRechamberFirerate(stat.firerate, stat.charge)
elseif aw.isNumberAndGreaterThanZero(stat.rechamber) then
minimum = apex.calcRechamberFirerate(stat.firerate, stat.rechamber)
maximum = apex.calcRechamberFirerate(stat.firerate, stat.rechamber + stat.charge)
else
minimum = stat.firerate
maximum = apex.calcRechamberFirerate(stat.firerate, stat.charge)
end
renderVariableFirerateRow(tbl, '', cfg2, minimum, maximum)
if (Hopup.deadeyes_tempo.enabled or isSpecial) and proto.validateTypes(stat.deadeyes_tempo, DeadeyesTempoWithChargeProto) then
tbl:addClass('raritytable')
local mintempo = apex.calcRechamberFirerate(stat.firerate, aw.getAsNumber(stat.deadeyes_tempo.charge_minimum, 0))
local maxtempo = apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.charge)
local label = iu.hopup('deadeyes_tempo') .. ' '
renderVariableFirerateRow(tbl, label, cfg2, mintempo, maxtempo, { rarity = Hopup.deadeyes_tempo.rarity })
end
-- mode: Auto/Single
else
local isRarity = false
local hasRevvedUp = aw.isNumberAndGreaterThanZero(stat.firerate_revvedup)
local hasAnvilReceiver = (Hopup.anvil_receiver.enabled or isSpecial) and proto.validateTypes(stat.anvil_receiver, AnvilReceiverProto)
local hasDoubleTapTrigger = (Hopup.double_tap_trigger.enabled or isSpecial) and proto.validateTypes(stat.double_tap_trigger, DoubleTapTrigggerProto)
local hasDeadeyesTempo = (Hopup.deadeyes_tempo.enabled or isSpecial) and proto.validateTypes(stat.deadeyes_tempo, DeadeyesTempoWithRechamberProto)
-- w/Altfire
if proto.validateTypes(stat.altfire, AltfireProto) and stat.firerate ~= stat.altfire.firerate then
renderFirerateRow(tbl, cfg2.auto, cfg2, calcFirerate)
if aw.isNumberAndGreaterThanZero(stat.rechamber) then
local calcFirerate = apex.calcRechamberFirerate(stat.firerate, stat.rechamber)
renderFirerateRow(tbl, cfg2.single, cfg2, calcFirerate)
else
renderFirerateRow(tbl, cfg2.single, cfg2, stat.altfire.firerate)
end
-- single w/o Altfire
elseif stat.is_semi_auto and aw.isNumberAndGreaterThanZero(stat.rechamber) then
local calcFirerate = apex.calcRechamberFirerate(stat.firerate, stat.rechamber)
renderFirerateRow(tbl, '', cfg2, calcFirerate)
-- auto w/o Altfire
else
if hasRevvedUp or hasAnvilReceiver or hasDoubleTapTrigger or hasDeadeyesTempo then
renderFirerateRow(tbl, '', cfg2, stat.firerate)
else
return renderFirerateText('', cfg2, stat.firerate), false
end
end
-- Revved Up
if hasRevvedUp then
if not isRarity then
tbl:addClass('raritytable')
end
local label = iu.grenade('テルミットグレネード') .. ' '
renderFirerateRow(tbl, label, cfg2, stat.firerate_revvedup)
end
-- Anvil Receiver
if hasAnvilReceiver then
if not isRarity then
tbl:addClass('raritytable')
end
local label = iu.hopup('anvil_receiver') .. ' '
renderFirerateRow(tbl, label, cfg2, stat.anvil_receiver.firerate, { rarity = Hopup.anvil_receiver.rarity })
end
-- Double Tap Trigger
if hasDoubleTapTrigger then
if not isRarity then
tbl:addClass('raritytable')
end
local average = apex.calcBurstAverageFirerate(stat.double_tap_trigger.burst_count, stat.double_tap_trigger.burst_delay, stat.double_tap_trigger.firerate)
local label = iu.hopup('double_tap_trigger') .. ' '
renderFirerateRow(tbl, label, cfg2, stat.double_tap_trigger.firerate, { rarity = Hopup.double_tap_trigger.rarity, rarityRowStyle = 'first' })
renderFirerateRow(tbl, cfg2.burst_average, cfg2, average , { rarity = Hopup.double_tap_trigger.rarity, rarityRowStyle = 'last' })
end
-- Deadeyes Tempo
if hasDeadeyesTempo then
if not isRarity then
tbl:addClass('raritytable')
end
local label = iu.hopup('deadeyes_tempo') .. ' '
local calcFirerate = apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.rechamber)
renderFirerateRow(tbl, label, cfg2, calcFirerate, { rarity = Hopup.deadeyes_tempo.rarity })
end
end
return tbl, false
end
function p._main(name, lang)
lang = lang or 'ja'
stats = {
['VK-47フラットライン'] = {
ammo = "heavy",
firerate = 10,
is_semi_auto = false,
altfire = {
is_semi_auto = true,
},
anvil_receiver = {
firerate = 2.9,
is_semi_auto = true,
},
},
['ヘムロックバーストAR'] = {
ammo = "heavy",
burst_count = 3,
burst_delay = 0.28,
firerate = 15.5,
is_semi_auto = true,
altfire = {
burst_count = 0,
burst_delay = 0,
firerate = 6.4,
},
},
['30-30リピーター'] = {
ammo = "heavy",
charge = 0.35,
firerate = 3.85,
is_semi_auto = true,
rechamber = 0.685,
},
['ボセックコンパウンドボウ'] = {
ammo = "arrows",
charge = 0.56,
charge_minimum = 0.084,
firerate = 3,
is_semi_auto = true,
deadeyes_tempo = {
charge = 0.38,
charge_minimum = 0.057,
},
},
['R-99 SMG'] = {
ammo = "light",
firerate = 18,
is_semi_auto = false,
},
['プラウラーバーストPDW'] = {
ammo = "heavy",
burst_count = 5,
burst_delay = 0.24,
firerate = 21,
is_semi_auto = true,
selectfire_receiver = {
burst_count = 0,
burst_delay = 0,
firerate = 13.25,
is_semi_auto = false,
},
},
['ディヴォーションLMG'] = {
ammo = "energy",
firerate = 5,
firerate_maximum = 15,
firerate_maximum_duration = 1.75,
firerate_maximum_count = 17,
is_semi_auto = false,
turbocharger = {
firerate = 6.8,
firerate_maximum_duration = 0.85,
firerate_maximum_count = 9,
},
},
['センチネル'] = {
ammo = "sniper",
firerate = 3.1,
is_semi_auto = true,
rechamber = 1.6,
deadeyes_tempo = {
rechamber = 1.25,
},
},
['ピースキーパー'] = {
ammo = "shotgun",
firerate = 4,
is_semi_auto = true,
rechamber = { 1.1, 1.0175, 0.957, 0.924 },
},
['EVA-8オート'] = {
ammo = "shotgun",
firerate = { 2.1, 2.31, 2.415, 2.52 },
is_semi_auto = false,
double_tap_trigger = {
burst_count = 2,
burst_delay = { 0.8, 0.74, 0.7, 0.66 },
firerate = 6,
},
},
}
local builder = require('Module:Utility/StringBuilder').new()
for name, stat in pairs(stats) do
local cell = mw.html.create('div')
:addClass('tpl-infobox-right')
:addClass('tpl-weapon')
:addClass('tpl-weapon-' .. stat.ammo)
:tag('div')
:addClass('tpl-weapon-header')
:wikitext(name .. iu.ammo(stat.ammo, { size = 40 }))
:done()
:tag('table')
:tag('tr')
:tag('th'):wikitext(cfg[lang].firerate.name):done()
:tag('td')
local node, newcell = p.renderFirerate(stat, lang)
if newcell then
cell = cell:done():done():tag('tr'):tag('td'):attr('colspan', 2)
end
cell:node(node)
builder:append(tostring(cell:allDone()))
end
return tostring(builder)
end
return p