🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁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 iu = require('Module:Utility/Image') local proto = require('Module:Utility/Prototypes') -- 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 DeadeyesTempoWithChargeProto = { charge = proto.NumberRange(0), } local DeadeyesTempoWithRechamberProto = { rechamber = proto.NumberRange(0), } -- Define functions local function calcBurstAverageRPS(stat, delay) delay = delay or stat.burst_delay return stat.burst_count / ((stat.burst_count - 1) / stat.firerate + delay) end local function calcRechamberRPS(firerate, rechamber) return 1 / (1 / firerate + rechamber) 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(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 'all-secondary text-smaller ' .. opts.rpmClass or 'all-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 {} intbl:tag('tr') :addClassIf(type(opts.rarity) == 'string', 'row-rarity-one disp-rarity-' .. (opts.rarity or 'common')) :addClassIf(opts.class and 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, 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 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 = 'legendary' }) end -- ショットガン elseif stat.ammo == 'shotgun' then -- EVA-8オート if proto.validateTypes(stat, Eva8AutoProto) then renderMultipleFirerateRow(tbl, '', cfg2, stat.firerate) local burstAverage = { calcBurstAverageRPS(stat.double_tap_trigger, stat.double_tap_trigger.burst_delay[1]), calcBurstAverageRPS(stat.double_tap_trigger, stat.double_tap_trigger.burst_delay[2]), calcBurstAverageRPS(stat.double_tap_trigger, stat.double_tap_trigger.burst_delay[3]), calcBurstAverageRPS(stat.double_tap_trigger, stat.double_tap_trigger.burst_delay[4]), } 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 = { calcRechamberRPS(stat.firerate, stat.rechamber[1]), calcRechamberRPS(stat.firerate, stat.rechamber[2]), calcRechamberRPS(stat.firerate, stat.rechamber[3]), calcRechamberRPS(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 = calcBurstAverageRPS(stat) -- 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 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 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 = 'epic' }) end end -- w/charge elseif aw.isNumberAndGreaterThanZero(stat.charge) then local minimum, maximum if aw.isNumberAndGreaterThanZero(stat.charge_minimum) then minimum = calcRechamberRPS(stat.firerate, stat.charge_minimum) maximum = calcRechamberRPS(stat.firerate, stat.charge) elseif aw.isNumberAndGreaterThanZero(stat.rechamber) then minimum = calcRechamberRPS(stat.firerate, stat.rechamber) maximum = calcRechamberRPS(stat.firerate, stat.rechamber + stat.charge) else minimum = stat.firerate maximum = calcRechamberRPS(stat.firerate, stat.charge) end renderVariableFirerateRow(tbl, '', cfg2, minimum, maximum) if proto.validateTypes(stat.deadeyes_tempo, DeadeyesTempoWithChargeProto) then tbl:addClass('raritytable') local mintempo = calcRechamberRPS(stat.firerate, aw.getAsNumber(stat.deadeyes_tempo.charge_minimum, 0)) local maxtempo = calcRechamberRPS(stat.firerate, stat.deadeyes_tempo.charge) local label = iu.hopup('deadeyes_tempo') .. ' ' renderVariableFirerateRow(tbl, label, cfg2, mintempo, maxtempo, { rarity = 'epic' }) end -- mode: Auto/Single else local isRarity = false local hasRevvedUp = aw.isNumberAndGreaterThanZero(stat.firerate_revvedup) local hasAnvilReceiver = proto.validateTypes(stat.anvil_receiver, AnvilReceiverProto) local hasDeadeyesTempo = 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 = calcRechamberRPS(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 = calcRechamberRPS(stat.firerate, stat.rechamber) renderFirerateRow(tbl, '', cfg2, calcFirerate) -- auto w/o Altfire else if hasRevvedUp or hasAnvilReceiver 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, { rarity = 'common' }) 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 = 'legendary' }) end -- Deadeyes Tempo if hasDeadeyesTempo then if not isRarity then tbl:addClass('raritytable') end local label = iu.hopup('deadeyes_tempo') .. ' ' local calcFirerate = calcRechamberRPS(stat.firerate, stat.deadeyes_tempo.rechamber) renderFirerateRow(tbl, label, cfg2, calcFirerate, { rarity = 'epic' }) 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 node = p.renderFirerate(stat, lang) builder:appendFormat('<h1>%s</h1>', name) builder:append(tostring(node)) end return tostring(builder) end return p