🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:WeaponInfobox/DPS
< モジュール:WeaponInfobox
ナビゲーションに移動
検索に移動
2021年8月23日 (月) 11:04時点におけるMntone (トーク | 投稿記録)による版 (rechamber時間の計算に Module:Utility/ApexLibrary の関数を使用)
このモジュールについての説明文ページを モジュール:WeaponInfobox/DPS/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') -- Constants local leftBorder = { ['border-left-width'] = '1px', ['border-left-style'] = 'solid', } local leftBorderWithoutTopRightBorder = { ['border-top'] = '0 none transparent', ['border-right'] = '0 none transparent', ['border-left-width'] = '1px', ['border-left-style'] = 'solid', } -- Protos local MinMaxProto = { proto.NumberRange(0), proto.NumberRange(0), } local MultipleFirerateProto = { proto.NumberRange(0), proto.NumberRange(0), proto.NumberRange(0), proto.NumberRange(0), } local SelectfireReceiverProto = { damage = { base = proto.NumberRange(1), headshot = proto.NumberRange(1, 10), legshot = proto.NumberRange(0, 1), }, firerate = proto.NumberRange(0), raise = proto.NumberRange(0), } local AnvilReceiverProto = { damage = { base = proto.NumberRange(1), headshot = proto.NumberRange(1, 10), legshot = proto.NumberRange(0, 1), }, firerate = proto.NumberRange(0), } local ShatterCapsProto = { damage = { base = proto.NumberRange(1), headshot = proto.NumberRange(1, 10), legshot = proto.NumberRange(0, 1), }, pellet = proto.NumberRange(1), } local DeadeyesTempoWithRechamberProto = { rechamber = proto.NumberRange(0), } local function calcBurstRPS(stat, delay) delay = delay or stat.burst_delay return stat.burst_count / ((stat.burst_count - 1) / stat.firerate + delay) end local function getStats(stat1, stat2) local ret if stat2 then local semi if stat2.is_semi_auto ~= nil then semi = stat2.is_semi_auto else semi = stat1.is_semi_auto end ret = { base = stat2.damage.base or stat1.damage.base, head = stat2.damage.headshot or stat1.damage.headshot or 1.75, legs = stat2.damage.legshot or stat1.damage.legshot or 0.75, semi = semi, } else ret = { base = stat1.damage.base, head = stat1.damage.headshot or 1.75, legs = stat1.damage.legshot or 0.75, semi = stat1.is_semi_auto, } end return ret end local function getDamages(stat, helmets) local helmet = helmets.level0.disabled and helmets.level1 or helmets.level0 local ret if stat.legs > 0 and stat.legs < 1 then ret = { aw.round(stat.legs * stat.base), stat.base, { aw.round(helmets.level3.func(stat.head) * stat.base), aw.round(helmet.func(stat.head) * stat.base), }, } else ret = { stat.base, { aw.round(helmets.level3.func(stat.head) * stat.base), aw.round(helmet.func(stat.head) * stat.base), }, } end return ret end local function getDPSs(damages, perk, pellets, firerate, useRound) local ret = {} for _, damage in ipairs(damages) do if proto.validateTypes(damage, MinMaxProto) then local minPerked = apex.calcPassiveDamage(damage[1], perk, { round = useRound }) local maxPerked = apex.calcPassiveDamage(damage[2], perk, { round = useRound }) table.insert(ret, { minPerked * firerate, pellets * maxPerked * firerate }) elseif pellets > 1 then local perked = apex.calcPassiveDamage(damage, perk, { round = useRound }) table.insert(ret, { perked * firerate, pellets * perked * firerate }) else local perked = apex.calcPassiveDamage(damage, perk, { round = useRound }) table.insert(ret, pellets * perked * firerate) end end return ret end local function toDPSText(value, format) if proto.validateTypes(value, MinMaxProto) then return string.format(format, string.format("%.1f", value[1]), string.format("%.1f", value[2])) else return string.format("%.1f", value) end end local function renderDPSRow(tbl, name, format, data, opts) local row = tbl:tag('tr') if aw.isNumberAndGreaterThanZero(opts.offset) then for i = 1, opts.offset do local hasLeftBorder = opts.offsetStyles and opts.offsetStyles[i] and opts.offsetStyles[i].leftBorder if hasLeftBorder then row:tag('th') :css(leftBorderWithoutTopRightBorder) :wikitext(' ') else row:tag('th') :css('border', '0 none transparent') :wikitext(' ') end end end row:tag('th') :attrIf(aw.isNumber(opts.colspan), { colspan = opts.colspan }) :cssIf(aw.isNumberAndGreaterThanZero(opts.offset), leftBorder) :wikitext(name) if #data >= 3 then if data[1] == nil then row:tag('td') :attr('align', 'center') :addClass('disabled') :wikitext('–') else row:tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(toDPSText(data[1], format)) end row :tag('td') :addClass('cell-type-number') :attr('align', 'right') :wikitext(toDPSText(data[2], format)) :done() :tag('td') :attr('align', 'right') :wikitext(toDPSText(data[3], format)) else row :tag('td') :addClass('cell-type-number') :attr('align', 'right') :attrIf(opts.hideLegs, { colspan = 2 }) :wikitext(toDPSText(data[1], format)) :done() :tag('td') :attr('align', 'right') :wikitext(toDPSText(data[2], format)) end end function p.renderDPS(stat, shieldinfo, lang) local cfg = cfg[lang].dps local basic = getStats(stat) local damages = getDamages(basic, shieldinfo.helmets) local pellet = aw.getAsNumber(stat.pellet, 1) local useRound = aw.getAsBoolean(stat.damage.round, false) local hasSlct = proto.validateTypes(stat.selectfire_receiver, SelectfireReceiverProto) local hasAnvil = proto.validateTypes(stat.anvil_receiver, AnvilReceiverProto) local hasShat = proto.validateTypes(stat.shatter_caps, ShatterCapsProto) local hasTempo = proto.validateTypes(stat.deadeyes_tempo, DeadeyesTempoWithRechamberProto) local hasTrmts = aw.isNumberAndGreaterThanZero(stat.firerate_revvedup) local hasHopup = hasSlct or hasAnvil or hasShat or hasTempo or hasTrmts local hasAmped = aw.isNumberAndGreaterThanZero(stat.damage.amped) local hasChgd = aw.isNumberAndGreaterThanZero(stat.damage.charged) local hasExtra = hasAmped or hasChgd -- Load firerate local firerate if aw.isNumberAndGreaterThanOrEqualToX(stat.burst_count, 2) then firerate = calcBurstRPS(stat) elseif proto.validateTypes(stat.rechamber, MultipleFirerateProto) then firerate = { 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]), } elseif aw.isNumberAndGreaterThanZero(stat.rechamber) then firerate = apex.calcRechamberFirerate(stat.firerate, stat.rechamber) else firerate = stat.firerate end local hasMultiple = proto.validateTypes(firerate, MultipleFirerateProto) local headerColspan local defopts, mpopts, huopts, exopts, ex2opts if hasMultiple then if hasExtra then headerColspan = 3 defopts = { colspan = 3 } muopts = { offset = 1, colspan = 2 } exopts = { offset = 2 } ex2opts = { offset = 2, offsetStyles = { nil, { leftBorder = true } } } else headerColspan = 2 defopts = { colspan = 2 } muopts = { offset = 1 } exopts = {} ex2opts = {} end huopts = {} elseif hasHopup then if hasExtra then local hideLegs = damages.legs ~= 1 headerColspan = 3 defopts = { colspan = 3 } huopts = { offset = 1, colspan = 2, hideLegs = hideLegs } exopts = { offset = 2 } ex2opts = { offset = 2, offsetStyles = { nil, { leftBorder = true } }, hideLegs = hideLegs } else headerColspan = 2 defopts = { colspan = 2 } huopts = { offset = 1, hideLegs = damages.legs ~= 1 } exopts = {} ex2opts = {} end muopts = {} elseif hasExtra then headerColspan = 1 defopts = { colspan = 2 } muopts = {} huopts = {} exopts = {} ex2opts = { offset = 1 } else headerColspan = 1 defopts = {} muopts = {} huopts = {} exopts = {} ex2opts = {} end -- Hop-ups local damages2, pellet2, firerate2, label if hasSlct then local slct = getStats(stat, stat.selectfire_receiver) damages2 = getDamages(slct, shieldinfo.helmets) pellet2 = pellet firerate2 = slct.semi and apex.calcRechamberFirerate(stat.selectfire_receiver.firerate, stat.selectfire_receiver.raise) or stat.selectfire_receiver.firerate label = iu.hopup('selectfire_receiver') elseif hasAnvil then local anvil = getStats(stat, stat.anvil_receiver) damages2 = getDamages(anvil, shieldinfo.helmets) pellet2 = pellet firerate2 = stat.anvil_receiver.firerate label = iu.hopup('anvil_receiver') elseif hasShat then local shat = getStats(stat, stat.shatter_caps) damages2 = getDamages(shat, shieldinfo.helmets) pellet2 = stat.shatter_caps.pellet firerate2 = firerate label = iu.hopup('shatter_caps') elseif hasTempo then damages2 = damages pellet2 = pellet firerate2 = apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.rechamber) label = string.format(cfg.hopup.deadeyes_tempo, iu.hopup('deadeyes_tempo')) elseif hasTrmts then damages2 = damages pellet2 = pellet firerate2 = stat.firerate_revvedup label = iu.grenade('テルミットグレネード') end -- Extra damages local damagesE, labelE, damages2E if hasAmped then local extra = aw.shallowCopy(basic) extra.base = stat.damage.amped damagesE = getDamages(extra, shieldinfo.helmets) labelE = iu.item('シールドセル') elseif hasChgd then local extra = aw.shallowCopy(basic) extra.base = stat.damage.charged damagesE = getDamages(extra, shieldinfo.helmets) labelE = iu.scope('スロット') if hasShat then local shat2 = getStats(stat, stat.shatter_caps) shat2.base = stat.shatter_caps.damage.charged if aw.isNumberAndGreaterThanZero(stat.shatter_caps.damage.headshot_charged) then shat2.head = stat.shatter_caps.damage.headshot_charged end if aw.isNumberAndGreaterThanZero(stat.shatter_caps.damage.legshot_charged) then local legs = stat.shatter_caps.damage.legshot_charged shat2.legs = legs if legs == 1 then ex2opts.hideLegs = true end end damages2E = getDamages(shat2, shieldinfo.helmets) end end local tbl = mw.html.create('table'):addClass('intable') -- Header local header = tbl:tag('tr'):tag('th') :attrIf(headerColspan > 1, { colspan = headerColspan }) :wikitext('') :done() if #damages >= 3 then header :tag('th') :wikitext(cfg.part.legs) :tag('th') :wikitext(cfg.part.body) else header:tag('th') :wikitext(cfg.part.bodylegs) end header:tag('th') :wikitext(cfg.part.head) -- Normal if hasMultiple then local normalDPS0 = getDPSs(damages, 1, pellet, firerate[1], useRound) local normalDPS1 = getDPSs(damages, 1, pellet, firerate[2], useRound) local normalDPS2 = getDPSs(damages, 1, pellet, firerate[3], useRound) local normalDPS3 = getDPSs(damages, 1, pellet, firerate[4], useRound) renderDPSRow(tbl, cfg.perk.normal, cfg.complex, normalDPS0, defopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 1), cfg.complex, normalDPS1, muopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 2), cfg.complex, normalDPS2, muopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 3), cfg.complex, normalDPS3, muopts) else local normalDPS = getDPSs(damages, 1, pellet, firerate, useRound) renderDPSRow(tbl, cfg.perk.normal, cfg.complex, normalDPS, defopts) end --- Extra if hasExtra then local extraDPS = getDPSs(damagesE, 1, pellet, firerate, useRound) renderDPSRow(tbl, labelE, cfg.complex, extraDPS, exopts) end --- Hop-up if hasHopup then local hopupDPS = getDPSs(damages2, 1, pellet2, firerate2, useRound) renderDPSRow(tbl, label, cfg.complex, hopupDPS, huopts) ---- Extra if hasTempo and hasAmped then local tempoExtraDPS = getDPSs(damagesE, 1, pellet2, firerate2, useRound) renderDPSRow(tbl, labelE, cfg.complex, tempoExtraDPS, ex2opts) elseif hasShat and hasChgd then local shatChargedDPS = getDPSs(damages2E, 1, pellet2, firerate2, useRound) renderDPSRow(tbl, labelE, cfg.complex, shatChargedDPS, ex2opts) end end -- Low Profile if aw.isNumber(shieldinfo.lowprofile) and shieldinfo.lowprofile > 1 then if hasMultiple then local normalDPS0 = getDPSs(damages, shieldinfo.lowprofile, pellet, firerate[1], useRound) local normalDPS1 = getDPSs(damages, shieldinfo.lowprofile, pellet, firerate[2], useRound) local normalDPS2 = getDPSs(damages, shieldinfo.lowprofile, pellet, firerate[3], useRound) local normalDPS3 = getDPSs(damages, shieldinfo.lowprofile, pellet, firerate[4], useRound) renderDPSRow(tbl, cfg.perk.lowprofile, cfg.complex, normalDPS0, defopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 1), cfg.complex, normalDPS1, muopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 2), cfg.complex, normalDPS2, muopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 3), cfg.complex, normalDPS3, muopts) else local lowprofileDPS = getDPSs(damages, shieldinfo.lowprofile, pellet, firerate, useRound) renderDPSRow(tbl, cfg.perk.lowprofile, cfg.complex, lowprofileDPS, defopts) end --- Extra if hasExtra then local extraLowProfileDPS = getDPSs(damagesE, shieldinfo.lowprofile, pellet, firerate, useRound) renderDPSRow(tbl, labelE, cfg.complex, extraLowProfileDPS, exopts) end --- Hop-up if hasHopup then local hopupLowProfileDPS = getDPSs(damages2, shieldinfo.lowprofile, pellet2, firerate2, useRound) renderDPSRow(tbl, label, cfg.complex, hopupLowProfileDPS, huopts) ---- Extra if hasTempo and hasAmped then local tempoAmpedLowProfileDPS = getDPSs(damagesE, shieldinfo.lowprofile, pellet2, firerate2, useRound) renderDPSRow(tbl, labelE, cfg.complex, tempoAmpedLowProfileDPS, ex2opts) elseif hasShat and hasChgd then local shatChargedLowProfileDPS = getDPSs(damages2E, shieldinfo.lowprofile, pellet2, firerate2, useRound) renderDPSRow(tbl, labelE, cfg.complex, shatChargedLowProfileDPS, ex2opts) end end end -- Fortified if aw.isNumber(shieldinfo.fortified) and shieldinfo.fortified < 1 then if hasMultiple then local normalDPS0 = getDPSs(damages, shieldinfo.fortified, pellet, firerate[1], useRound) local normalDPS1 = getDPSs(damages, shieldinfo.fortified, pellet, firerate[2], useRound) local normalDPS2 = getDPSs(damages, shieldinfo.fortified, pellet, firerate[3], useRound) local normalDPS3 = getDPSs(damages, shieldinfo.fortified, pellet, firerate[4], useRound) renderDPSRow(tbl, cfg.perk.fortified, cfg.complex, normalDPS0, defopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 1), cfg.complex, normalDPS1, muopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 2), cfg.complex, normalDPS2, muopts) renderDPSRow(tbl, iu.attachment('ショットガンボルト', 3), cfg.complex, normalDPS3, muopts) else local lowprofileDPS = getDPSs(damages, shieldinfo.fortified, pellet, firerate, useRound) renderDPSRow(tbl, cfg.perk.fortified, cfg.complex, lowprofileDPS, defopts) end --- Extra if hasExtra then local extraFortifiedDPS = getDPSs(damagesE, shieldinfo.fortified, pellet, firerate, useRound) renderDPSRow(tbl, labelE, cfg.complex, extraFortifiedDPS, exopts) end --- Hop-up if hasHopup then local hopupFortifiedDPS = getDPSs(damages2, shieldinfo.fortified, pellet2, firerate2, useRound) renderDPSRow(tbl, label, cfg.complex, hopupFortifiedDPS, huopts) ---- Extra if hasTempo and hasAmped then local tempoAmpedFortifiedDPS = getDPSs(damagesE, shieldinfo.fortified, pellet2, firerate2, useRound) renderDPSRow(tbl, labelE, cfg.complex, tempoAmpedFortifiedDPS, ex2opts) elseif hasShat and hasChgd then local shatChargedFortifiedDPS = getDPSs(damages2E, shieldinfo.fortified, pellet2, firerate2, useRound) renderDPSRow(tbl, labelE, cfg.complex, shatChargedFortifiedDPS, ex2opts) end end end return tbl end function p._main(name, lang) lang = lang or 'ja' local stat = mw.loadData('Module:Stat/Weapon')[name] local sld = require('Module:Stat/Shield')['removelowprofile'] local node = p.renderDPS(stat, sld, lang) local div = mw.html.create('div') :addClass('tpl-infobox-right') :addClass('tpl-weapon') if aw.stringstarts(stat.ammo, "special_") then div:addClass('tpl-weapon-special') else div:addClass('tpl-weapon-' .. stat.ammo) end div :tag('div') :addClass('tpl-weapon-header') :wikitext(name .. iu.ammo(stat.ammo, { size = 40 })) :done() :tag('table') :tag('tr') :tag('th'):wikitext('DPS'):done() :tag('td'):done() :tag('tr') :tag('td'):attr('colspan', 2):node(node) return tostring(div) end return p