| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:DamageTable
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール:DamageTable/doc に作成できます
require('Module:Utility/mw.html Extensions')
local p = {}
local table = require('Module:TableExtensions')
local aw = require('Module:Utility/Library')
local apex = require('Module:Utility/ApexLibrary')
local Color = require('Module:Color')
local STKCalculator = require('Module:Apex/STKCalculator')
local getArgs -- lazily initialized
local function getShotCount(part, health, shield, info, gunshield)
local damages = apex.calcShotCount(info.damage, part, info.mul, health, shield, gunshield or 0, info.opts)
return #damages, damages
end
local function renderHeader(tbl, mul, colspan, shields, res)
tbl:tag('tr')
:tag('th')
:attr('colspan', colspan)
:attr('rowspan', 2)
:wikitextIf(
mul == 1,
res.targets.caption,
function()
return string.format(res.targets.caption_format, mul)
end)
:done()
:tag('th')
:attr('rowspan', 2)
:wikitext(res.damages.caption)
:done()
:tag('th')
:attr('colspan', #shields)
:wikitext(res.shotstokill)
local row = tbl:tag('tr')
for _, shield in ipairs(shields) do
row:tag('th')
:attrIf(
shield.tooltip ~= nil,
{ ['data-tooltip'] = shield.tooltip })
:wikitext(shield.label)
end
end
local function renderCell(row, part, health, shield, info, gunshield, rowspan)
local shotCount, damages = getShotCount(part, health, shield, info, gunshield)
local ratio = (shotCount - info.minCount) / info.diffCount
local tooltip = { aw.stringifyRepeatingArray(damages, '→') }
if info.ttkCalculator then
local template = '<tr><th>%s </th><td class="cell-type-number" style="font-weight:bold">%d</td><td> ミリ秒</td></tr>'
local ttkc = info.ttkCalculator
local ttk0 = aw.round(1000 * ttkc:getAsLevel(shotCount, 0))
local ttk1 = aw.round(1000 * ttkc:getAsLevel(shotCount, 1))
local ttk2 = aw.round(1000 * ttkc:getAsLevel(shotCount, 2))
local ttk3 = aw.round(1000 * ttkc:getAsLevel(shotCount, 3))
if ttk2 ~= ttk3 then
table.insert(tooltip, '<br><br>キルタイム:<table class="condensedtable listtable">')
if ttk0 == ttk1 then
table.insert(tooltip, string.format(template, 'なし・Lv.1', ttk0))
table.insert(tooltip, string.format(template, 'Lv.2', ttk2))
else
table.insert(tooltip, string.format(template, 'なし', ttk0))
table.insert(tooltip, string.format(template, 'Lv.1', ttk1))
table.insert(tooltip, string.format(template, 'Lv.2', ttk2))
end
table.insert(tooltip, string.format(template, 'Lv.3', ttk3))
table.insert(tooltip, '</table>')
elseif ttk1 ~= ttk2 then
table.insert(tooltip, '<br><br>キルタイム:<table class="condensedtable listtable">')
if ttk0 == ttk1 then
table.insert(tooltip, string.format(template, 'なし・Lv.1', ttk0))
else
table.insert(tooltip, string.format(template, 'なし', ttk0))
table.insert(tooltip, string.format(template, 'Lv.1', ttk1))
end
table.insert(tooltip, string.format(template, 'Lv.2, 3', ttk2))
table.insert(tooltip, '</table>')
elseif ttk0 ~= ttk1 then
table.insert(tooltip, '<br><br>キルタイム:<table class="condensedtable listtable">')
table.insert(tooltip, string.format(template, 'なし', ttk0))
table.insert(tooltip, string.format(template, 'Lv.1, 2, 3', ttk1))
table.insert(tooltip, '</table>')
else
table.insert(tooltip, string.format('<br>キルタイム: <span class="text-style-number" style="font-weight:bold">%d</span> ミリ秒', ttk0))
end
end
local hue = (info.diffCount < 5 and 0.65 or 0.85) * ratio
local color = Color.HSL(hue, 0.91, 0.89):toRGB()
row:tag('td')
:attrIf(rowspan > 1, { rowspan = rowspan })
:attr('data-tooltip', table.concat(tooltip))
:css('background-color', tostring(color))
:wikitext(shotCount)
end
local function renderHeaderCell(row, name, tooltip, rowinfo)
for i = 1, #rowinfo do
local cellinfo = rowinfo[i]
local colspan = cellinfo.colspan or 1
local rowspan = cellinfo.rowspan or 1
local cell = row:tag('th')
if colspan > 1 then
cell:attr('colspan', colspan)
end
if rowspan > 1 then
cell:attr('rowspan', rowspan)
end
if cellinfo.breaktop then
cell:css('border-top', '0 none transparent')
end
if cellinfo.breakbottom then
cell:css('border-bottom', '0 none transparent')
end
--if cellinfo.showbottom then
-- cell:css({
-- ['border-bottom-style'] = 'solid',
-- ['border-bottom-width'] = '1px',
-- })
--end
if cellinfo.verticalAlign then
cell:css('vertical-align', cellinfo.verticalAlign)
end
if i == #rowinfo then
if tooltip ~= nil then
cell:attr('data-tooltip', tooltip)
end
cell:wikitext(name)
elseif cellinfo.content then
if cellinfo.vertical then
cell:addClass('vertical-cell')
:tag('span')
:wikitext(cellinfo.content)
else
cell:wikitext(cellinfo.content)
end
else
cell:wikitext(' ')
end
end
end
local function renderRow(tbl, name, tooltip, part, weaponinfo, rowinfo, res, gunshield)
local row = tbl:tag('tr')
renderHeaderCell(row, name, tooltip, rowinfo)
local damage
local opts2 = aw.shallowCopy(weaponinfo.opts)
table.removeKey(opts2, 'beamdamage')
table.removeKey(opts2, 'beamticks')
if gunshield then
table.removeKey(opts2, 'disruptorRounds')
table.removeKey(opts2, 'hammerpointRounds')
damage = apex.calcDamage(weaponinfo.damage, 1, 1, opts2)
else
damage = apex.calcDamage(weaponinfo.damage, part, weaponinfo.mul, opts2)
end
local text
if not gunshield and weaponinfo.opts.disruptorRounds > 1 then
local optsD = aw.shallowCopy(weaponinfo.opts)
table.removeKey(optsD, 'disruptorRounds')
local defaultDamage = apex.calcDamage(weaponinfo.damage, part, weaponinfo.mul, optsD)
if weaponinfo.opts.pellets > 1 then
text = string.format(
res.damages.pelletsWithDisruptor,
damage * weaponinfo.opts.pellets,
damage,
weaponinfo.opts.pellets,
defaultDamage * weaponinfo.opts.pellets)
else
text = string.format(res.damages.disruptor, damage, defaultDamage)
end
elseif not gunshield and weaponinfo.opts.hammerpointRounds > 1 then
local optsH = aw.shallowCopy(weaponinfo.opts)
table.removeKey(optsH, 'hammerpointRounds')
local defaultDamage = apex.calcDamage(weaponinfo.damage, part, weaponinfo.mul, optsH)
if weaponinfo.opts.pellets > 1 then
text = string.format(
res.damages.pelletsWithHammerpoint,
defaultDamage * weaponinfo.opts.pellets,
damage * weaponinfo.opts.pellets,
damage,
weaponinfo.opts.pellets)
else
text = string.format(res.damages.hammerpoint, defaultDamage, damage)
end
elseif weaponinfo.opts.pellets > 1 then
text = string.format(
res.damages.pellets,
damage * weaponinfo.opts.pellets,
damage,
weaponinfo.opts.pellets)
elseif weaponinfo.opts.beamticks > 1 then
local beamdamage = apex.calcDamageFromPartAndPassive(weaponinfo.opts.beamdamage, part, weaponinfo.mul, opts2)
local alldamage = beamdamage * weaponinfo.opts.beamticks + damage
text = string.format(
res.damages.ticks,
alldamage,
beamdamage,
weaponinfo.opts.beamticks,
damage)
else
text = tostring(damage)
end
row:tag('td'):wikitext(text)
for _, shield in ipairs(weaponinfo.shields) do
renderCell(row, part, shield.health, shield.shield, weaponinfo, gunshield, 1)
end
end
local function getTTKCalculator(args)
if args.rps <= 0 then
return nil
end
-- 射撃レート
local firerate
if args.rpsratio1 > 1 then
if args.rpsratio2 > args.rpsratio1 then
if args.rpsratio3 > args.rpsratio2 then
firerate = {
args.rps,
args.rpsratio1 * args.rps,
args.rpsratio2 * args.rps,
args.rpsratio3 * args.rps,
}
else
local rps2 = args.rpsratio2 * args.rps
firerate = {
args.rps,
args.rpsratio1 * args.rps,
rps2,
rps2,
}
end
else
local rps1 = args.rpsratio1 * args.rps
firerate = {
args.rps,
rps1,
rps1,
rps1,
}
end
else
firerate = args.rps
end
-- 装填数
local magazine
if args.extmag0 > 0 then
if args.extmag1 > args.extmag0 then
if args.extmag2 > args.extmag1 then
if args.extmag3 > args.extmag2 then
magazine = { args.extmag0, args.extmag1, args.extmag2, args.extmag3 }
else
magazine = { args.extmag0, args.extmag1, args.extmag2, args.extmag2 }
end
else
magazine = { args.extmag0, args.extmag1, args.extmag1, args.extmag1 }
end
else
magazine = args.extmag0
end
else
magazine = math.huge
end
-- リロード時間
local reload
if args.reloadratio2 > 0 and args.reloadratio2 < 1 then
if args.reloadratio3 > 0 and args.reloadratio3 < args.reloadratio2 then
if args.reloadratio1 > 0 and args.reloadratio1 < 1 and args.reloadratio1 > args.reloadratio2 then
reload = {
args.reload,
args.reloadratio1 * args.reload,
args.reloadratio2 * args.reload,
args.reloadratio3 * args.reload
}
else
reload = {
args.reload,
args.reload,
args.reloadratio2 * args.reload,
args.reloadratio3 * args.reload
}
end
else
local reload2 = args.reloadratio2 * args.reload
reload = {
args.reload,
args.reload,
reload2,
reload2
}
end
else
reload = args.reload
end
local ttkc = require('Module:Apex/TTKCalculator').new(firerate, magazine, reload, {
raiseTime = args.raise,
})
return ttkc
end
local function getContentLanguage(lang)
local language = lang or mw.language.getContentLanguage().code
return language == 'en' and 'en' or 'ja'
end
-- Calc all base damages
local function calcBaseDamages(damage, headScale, legsScale, helmets, opts)
local headLv1Scale = helmets.level1.func(headScale)
local headLv2Scale = helmets.level2.func(headScale)
local headLv3Scale = helmets.level3.func(headScale)
local ret = {
scale_hed0 = headScale,
scale_hed1 = headLv1Scale,
scale_hed2 = headLv2Scale,
scale_hed3 = headLv3Scale,
scale_body = 1,
scale_legs = legsScale,
}
if opts.beamdamage > 0 then
ret.dschrg_hed0 = aw.round(headScale * opts.beamdamage)
ret.dschrg_hed1 = aw.round(headLv1Scale * opts.beamdamage)
ret.dschrg_hed2 = aw.round(headLv2Scale * opts.beamdamage)
ret.dschrg_hed3 = aw.round(headLv3Scale * opts.beamdamage)
ret.dschrg_body = opts.beamdamage
if legsScale < 1 then
ret.dschrg_legs = aw.round(legsScale * opts.beamdamage)
else
ret.dschrg_legs = opts.beamdamage
end
end
-- Amped Cover
if opts.ampedCover then
damage = aw.round(1.2 * damage)
end
-- Additional Scale
if opts.charged > 1 then
damage = aw.round(opts.charged * damage)
end
-- Unshield Scale
if opts.hammerpointRounds > 1 then
local shieldDamage = damage
local unshldDamage = apex.calcHammerpointDamage(damage, opts.hammerpointRounds)
-- Passthrough
if opts.passthrough < 1 then
shieldDamage = apex.calcPassthroughDamage(shieldDamage, opts.passthrough)
unshldDamage = apex.calcPassthroughDamage(unshldDamage, opts.passthrough)
end
local shieldLegs, unshldLegs
if legsScale < 1 then
shieldLegs = aw.round(legsScale * shieldDamage)
unshldLegs = aw.round(legsScale * unshldDamage)
else
shieldLegs = shieldDamage
unshldLegs = unshldDamage
end
ret.shield_hed0 = aw.round(headScale * shieldDamage)
ret.shield_hed1 = aw.round(headLv1Scale * shieldDamage)
ret.shield_hed2 = aw.round(headLv2Scale * shieldDamage)
ret.shield_hed3 = aw.round(headLv3Scale * shieldDamage)
ret.shield_body = shieldDamage
ret.shield_legs = shieldLegs
ret.unshld_hed0 = aw.round(headScale * unshldDamage)
ret.unshld_hed1 = aw.round(headLv1Scale * unshldDamage)
ret.unshld_hed2 = aw.round(headLv2Scale * unshldDamage)
ret.unshld_hed3 = aw.round(headLv3Scale * unshldDamage)
ret.unshld_body = unshldDamage
ret.unshld_legs = unshldLegs
-- Other
else
-- Passthrough
if opts.passthrough < 1 then
damage = apex.calcPassthroughDamage(damage, opts.passthrough)
end
local legs
if legsScale < 1 then
legs = aw.round(legsScale * damage)
else
legs = damage
end
ret.shield_hed0 = aw.round(headScale * damage)
ret.shield_hed1 = aw.round(headLv1Scale * damage)
ret.shield_hed2 = aw.round(headLv2Scale * damage)
ret.shield_hed3 = aw.round(headLv3Scale * damage)
ret.shield_body = damage
ret.shield_legs = legs
ret.unshld_hed0 = ret.shield_hed0
ret.unshld_hed1 = ret.shield_hed1
ret.unshld_hed2 = ret.shield_hed2
ret.unshld_hed3 = ret.shield_hed3
ret.unshld_body = ret.shield_body
ret.unshld_legs = ret.shield_legs
end
return ret
end
-- Apply perk/shield scale to damages
local function applyPerkAndShieldScaleToDamages(damages, perkScale, ignorePerkScaleForHS, opts)
if perkScale ~= 1 then
if opts.disruptorRounds > 1 then
return table.map(damages, function(key, val)
if ignorePerkScaleForHS and (aw.stringstarts(key, 'shield_hed') or aw.stringstarts(key, 'unshld_hed') or aw.stringstarts(key, 'dschrg_hed')) then
if aw.stringstarts(key, 'shield_') then
return apex.calcDisruptorDamage(val, opts.disruptorRounds)
else
return val
end
elseif aw.stringstarts(key, 'shield_') or aw.stringstarts(key, 'unshld_') or aw.stringstarts(key, 'dschrg_') then
local perkedDamage = apex.calcPassiveDamage(val, perkScale, { round = opts.round })
if aw.stringstarts(key, 'shield_') then
return apex.calcDisruptorDamage(perkedDamage, opts.disruptorRounds)
else
return perkedDamage
end
else
return val
end
end)
else
return table.map(damages, function(key, val)
if ignorePerkScaleForHS and (aw.stringstarts(key, 'shield_hed') or aw.stringstarts(key, 'unshld_hed') or aw.stringstarts(key, 'dschrg_hed')) then
return val
elseif aw.stringstarts(key, 'shield_') or aw.stringstarts(key, 'unshld_') or aw.stringstarts(key, 'dschrg_') then
return apex.calcPassiveDamage(val, perkScale, { round = opts.round })
else
return val
end
end)
end
elseif opts.disruptorRounds > 1 then
return table.map(damages, function(key, val)
if aw.stringstarts(key, 'shield_') then
return apex.calcDisruptorDamage(val, opts.disruptorRounds)
else
return val
end
end)
else
return damages
end
end
-- Compare damage
local function equalPartDamage(damages, part0, part1)
if damages['dschrg_' .. part0] and damages['dschrg_' .. part1] then
return damages['shield_' .. part0] == damages['shield_' .. part1] and damages['unshld_' .. part0] == damages['unshld_' .. part1] and damages['dschrg_' .. part0] == damages['dschrg_' .. part1]
else
return damages['shield_' .. part0] == damages['shield_' .. part1] and damages['unshld_' .. part0] == damages['unshld_' .. part1]
end
end
-- Render the damage row
local function renderRow2(tbl, name, tooltip, damages, partname, weaponinfo, rowinfo, res, rowspan, gunshield)
rowspan = rowspan or 1
local scale = damages['scale_' .. partname]
local shieldDamage = damages['shield_' .. partname]
local unshldDamage = damages['unshld_' .. partname]
local dschrgDamage = damages['dschrg_' .. partname]
local row = tbl:tag('tr')
renderHeaderCell(row, name, tooltip, rowinfo)
local text
if shieldDamage > unshldDamage then
if weaponinfo.opts.pellets > 1 then
text = string.format(
res.damages.pelletsWithDisruptor,
shieldDamage * weaponinfo.opts.pellets,
shieldDamage,
weaponinfo.opts.pellets,
unshldDamage * weaponinfo.opts.pellets)
else
text = string.format(res.damages.disruptor, shieldDamage, unshldDamage)
end
elseif shieldDamage < unshldDamage then
if weaponinfo.opts.pellets > 1 then
text = string.format(
res.damages.pelletsWithHammerpoint,
shieldDamage * weaponinfo.opts.pellets,
unshldDamage * weaponinfo.opts.pellets,
unshldDamage,
weaponinfo.opts.pellets)
else
text = string.format(res.damages.hammerpoint, shieldDamage, unshldDamage)
end
elseif dschrgDamage and weaponinfo.opts.beamticks >= 1 then
text = string.format(
res.damages.ticks,
dschrgDamage * weaponinfo.opts.beamticks + shieldDamage,
dschrgDamage,
weaponinfo.opts.beamticks,
shieldDamage)
else
if weaponinfo.opts.pellets > 1 then
text = string.format(
res.damages.pellets,
shieldDamage * weaponinfo.opts.pellets,
shieldDamage,
weaponinfo.opts.pellets)
else
text = tostring(shieldDamage)
end
end
row:tag('td')
:attr('rowspan', rowspan)
:wikitext(text)
for _, shield in ipairs(weaponinfo.shields) do
renderCell(row, scale, shield.health, shield.shield, weaponinfo, gunshield, rowspan)
end
end
-- Render the helmet damage
local function renderHelmetSection(tbl, damages, res, weaponinfo, helmets, info)
local skipLvl1 = false
local skipLvl2 = false
local hed1Label = string.format(res.targets.helmet1, damages.scale_hed1)
local hed2Label = string.format(res.targets.helmet2, damages.scale_hed2)
local hed3Label = string.format(res.targets.helmet3, damages.scale_hed3)
local hed1Tooltip = string.format(helmets.level1.text, damages.scale_hed0)
local hed2Tooltip = string.format(helmets.level2.text, damages.scale_hed0)
local hed3Tooltip = string.format(helmets.level3.text, damages.scale_hed0)
if not helmets.level0.disabled then
local hed0Rowspan
if equalPartDamage(damages, 'hed0', 'hed1') then
if equalPartDamage(damages, 'hed0', 'hed2') then
if equalPartDamage(damages, 'hed0', 'hed3') then
hed0Rowspan = 4
else
hed0Rowspan = 3
end
else
hed0Rowspan = 2
end
else
hed0Rowspan = 1
end
local hed0Label = string.format(res.targets.head_format, damages.scale_hed0)
renderRow2(tbl, hed0Label, nil, damages, 'hed0', weaponinfo, info.level1top, res, hed0Rowspan)
if hed0Rowspan >= 4 then
renderHeaderCell(tbl:tag('tr'), hed1Label, hed1Tooltip, info.level2first)
renderHeaderCell(tbl:tag('tr'), hed2Label, hed2Tooltip, info.level2)
renderHeaderCell(tbl:tag('tr'), hed3Label, hed3Tooltip, info.level2)
return
elseif hed0Rowspan == 3 then
renderHeaderCell(tbl:tag('tr'), hed1Label, hed1Tooltip, info.level2first)
renderHeaderCell(tbl:tag('tr'), hed2Label, hed2Tooltip, info.level2)
skipLvl1 = true
skipLvl2 = true
elseif hed0Rowspan == 2 then
renderHeaderCell(tbl:tag('tr'), hed1Label, hed1Tooltip, info.level2first)
skipLvl1 = true
end
end
-- Lvl 1
if not skipLvl1 then
local hed1Rowspan
if equalPartDamage(damages, 'hed1', 'hed2') then
if equalPartDamage(damages, 'hed1', 'hed3') then
hed1Rowspan = 3
else
hed1Rowspan = 2
end
else
hed1Rowspan = 1
end
renderRow2(tbl, hed1Label, hed1Tooltip, damages, 'hed1', weaponinfo, info.level2first, res, hed1Rowspan)
if hed1Rowspan >= 3 then
renderHeaderCell(tbl:tag('tr'), hed2Label, hed2Tooltip, info.level2)
renderHeaderCell(tbl:tag('tr'), hed3Label, hed3Tooltip, info.level2)
return
elseif hed1Rowspan == 2 then
renderHeaderCell(tbl:tag('tr'), hed2Label, hed2Tooltip, info.level2)
skipLvl2 = true
end
end
-- Lvl 2
if not skipLvl2 then
local hed2Rowspan
if equalPartDamage(damages, 'hed2', 'hed3') then
hed2Rowspan = 2
else
hed2Rowspan = 1
end
renderRow2(tbl, hed2Label, hed2Tooltip, damages, 'hed2', weaponinfo, info.level2, res, hed2Rowspan)
if hed2Rowspan >= 2 then
renderHeaderCell(tbl:tag('tr'), hed3Label, hed3Tooltip, info.level2)
return
end
end
-- Lvl 3
renderRow2(tbl, hed3Label, hed3Tooltip, damages, 'hed3', weaponinfo, info.level2, res, 1)
end
local function renderTable(args)
local lang = getContentLanguage(args.lang)
local res = mw.loadData('Module:DamageTable/configuration')[lang]
local shieldinfo = args.shieldinfo or require('Module:Stat/Shield')[args.shieldpreset]
local skullpiercer = args.skullpiercer or 1
local headMul = args.head or 2
local hideNoHelmets = shieldinfo.helmets.level0.disabled
local minHead
if hideNoHelmets then
minHead = shieldinfo.helmets.level1.func(args.headmax)
else
minHead = args.headmax
end
if shieldinfo.sameHeadshotDamageToNormalOnFortified then
args.mul2 = shieldinfo.fortified
end
local hasSecond = args.mul2 > 0 and args.mul2 ~= 1
local noLegsShot = args.leg < 0 or args.leg >= 1 or (shieldinfo.legAsBodyOnLowProfile and args.mul > 1)
local noLegsShot2 = args.leg < 0 or args.leg >= 1 or (shieldinfo.legAsBodyOnLowProfile and args.mul2 > 1)
-- Get/calc min count
local minCount
if args.mincount > 0 then
minCount = args.mincount
else
minCount, _ = getShotCount(
minHead,
100,
0,
{
damage = math.max(args.damage, args.damagemax),
mul = math.max(args.mul, args.mulmax),
opts = {
ampedCover = true,
beamdamage = math.max(args.beamdamage, args.beamdamagemax),
beamticks = math.max(args.ticks, args.ticksmax),
charged = math.max(args.charged, args.chargedmax),
disruptorRounds = math.max(args.disruptor, args.disruptorsup),
gunshieldBleedthrough = shieldinfo.gunshieldBleedthrough,
hammerpointRounds = math.max(args.hammerpoint, args.hammerpointsup),
ignorePassiveForHeadshot = shieldinfo.sameHeadshotDamageToNormalOnFortified,
passthrough = 1,
pellets = math.max(args.pellet, args.pelletmax),
round = args.round,
}
})
end
-- Get/calc max count
local maxCount
if args.maxcount < 250 then
maxCount = args.maxcount
else
local damagemin = math.min(args.damage, args.damagemin)
local mininfo = {
damage = damagemin,
mul = math.min(args.mul, args.mulmin),
opts = {
ampedCover = false,
beamdamage = math.min(args.beamdamage, args.beamdamagemin),
beamticks = math.min(args.ticks, args.ticksmin),
charged = 1,
disruptorRounds = 1,
gunshieldBleedthrough = shieldinfo.gunshieldBleedthrough,
hammerpointRounds = 1,
ignorePassiveForHeadshot = shieldinfo.sameHeadshotDamageToNormalOnFortified,
passthrough = math.min(args.passthrough, args.passthroughsup),
pellets = math.min(args.pellet, args.pelletmin),
round = args.round,
}
}
local maxshield = shieldinfo.shields[#shieldinfo.shields]
local legCount, _ = getShotCount(math.min(args.leg, args.legmin), maxshield.health, maxshield.shield, mininfo)
local bodyWithGunSheild, _ = getShotCount(1, maxshield.health, maxshield.shield, mininfo, shieldinfo.gunshield)
maxCount = math.max(legCount, bodyWithGunSheild)
end
local ttkCalculator = getTTKCalculator(args)
-- Define weapon info
local weaponinfo = {
damage = args.damage,
mul = args.mul,
minCount = minCount,
diffCount = maxCount - minCount,
shields = shieldinfo.shields,
helmets = shieldinfo.helmets,
ttkCalculator = ttkCalculator,
opts = {
ampedCover = args.amped,
beamdamage = args.beamdamage,
beamticks = args.ticks,
charged = args.charged,
disruptorRounds = args.disruptor,
gunshieldBleedthrough = shieldinfo.gunshieldBleedthrough,
hammerpointRounds = args.hammerpoint,
ignorePassiveForHeadshot = shieldinfo.sameHeadshotDamageToNormalOnFortified,
passthrough = args.passthrough,
pellets = args.pellet,
round = args.round,
},
}
local colspan, info
if skullpiercer > 1 then
colspan = 3
info = {
level1 = {
{ breaktop = false, breakbottom = false, colspan = 3 },
},
level1top = {
{ breaktop = true, breakbottom = true, colspan = 3 },
},
level1gunshiled = {
{ breaktop = false, breakbottom = true, colspan = 3 },
},
level2 = {
{ breaktop = true, breakbottom = false, colspan = 2 },
},
level2gunshiled = {
{ breaktop = true, breakbottom = false },
{ breaktop = false, breakbottom = false, colspan = 2 },
},
level3 = {
{ breaktop = false, breakbottom = true },
{ breaktop = false, breakbottom = false, showbottom = true },
},
level3first = {
hideNoHelmets and { breaktop = false, breakbottom = false, rowspan = 6, content = res.targets.head, vertical = res.targets.head_vertical, verticalAlign = res.targets.head_verticalalign } or { breaktop = true, breakbottom = false, rowspan = 6 },
{ breaktop = false, breakbottom = true },
{ breaktop = false, breakbottom = false, showbottom = true },
},
level3top = {
{ breaktop = false, breakbottom = true, colspan = 2 },
{ breaktop = false, breakbottom = false, showbottom = true },
},
}
info.level2first = info.level2
if hasSecond and not noLegsShot2 then
info.level1gunshiled = nil
info.level2gunshiled = {
{ breaktop = false, breakbottom = false, rowspan = 3, content = res.targets.fortified, vertical = res.targets.fortified_vertical, verticalAlign = res.targets.fortified_verticalalign },
{ breaktop = false, breakbottom = true, colspan = 2 },
}
info.level3gunshiled = {
{ breaktop = true, breakbottom = false },
{ breaktop = false, breakbottom = false },
}
end
elseif hasSecond and not noLegsShot2 then
colspan = 3
info = {
level1 = {
{ breaktop = false, breakbottom = false, colspan = 3 },
},
level1top = {
{ breaktop = false, breakbottom = true, colspan = 3 },
},
level2 = {
{ breaktop = false, breakbottom = false, colspan = 2 },
},
level2first = {
hideNoHelmets and { breaktop = false, breakbottom = false, rowspan = 3, content = res.targets.head, vertical = res.targets.head_vertical, verticalAlign = res.targets.head_verticalalign } or { breaktop = true, breakbottom = false, rowspan = 3 },
{ breaktop = false, breakbottom = false, colspan = 2 },
},
level2gunshiled = {
{ breaktop = false, breakbottom = false, rowspan = 3, content = res.targets.fortified, vertical = res.targets.fortified_vertical, verticalAlign = res.targets.fortified_verticalalign },
{ breaktop = false, breakbottom = true, colspan = 2 },
},
level3 = {
{ breaktop = false, breakbottom = false },
},
level3gunshiled = {
{ breaktop = true, breakbottom = false },
{ breaktop = false, breakbottom = false },
},
}
else
colspan = 2
info = {
level1 = {
{ breaktop = false, breakbottom = false, colspan = 2 },
},
level1gunshiled = {
{ breaktop = false, breakbottom = true, colspan = 2 },
},
level2 = {
{ breaktop = false, breakbottom = false },
},
level2first = {
hideNoHelmets and { breaktop = false, breakbottom = false, rowspan = 3, content = res.targets.head, vertical = res.targets.head_vertical, verticalAlign = res.targets.head_verticalalign } or { breaktop = true, breakbottom = false, rowspan = 3 },
{ breaktop = false, breakbottom = false },
},
level2gunshiled = {
{ breaktop = true, breakbottom = false },
{ breaktop = false, breakbottom = false },
},
}
info.level1top = info.level1gunshiled
end
local table = mw.html.create('table')
:addClass('wikitable')
:addClass('numbertable')
:addClass('damagetable')
if args.caption ~= nil then
table:tag('caption')
:wikitext(args.caption)
end
local baseDamages = calcBaseDamages(weaponinfo.damage, headMul, args.leg, weaponinfo.helmets, weaponinfo.opts)
local perkedDamages = applyPerkAndShieldScaleToDamages(baseDamages, weaponinfo.mul, shieldinfo.sameHeadshotDamageToNormalOnFortified, weaponinfo.opts)
renderHeader(table, args.mul, colspan, shieldinfo.shields, res)
-- Headshot damage
if headMul > 1 then
-- w/Skullpiercer Rifling
if skullpiercer > 1 then
if not hideNoHelmets then
renderRow(
table,
string.format(res.targets.skullpiercer0, args.skullpiercerrarity, skullpiercer),
nil,
skullpiercer, weaponinfo, info.level3top, res)
renderRow2(
table,
string.format(res.targets.head_format, perkedDamages.scale_hed0),
nil,
perkedDamages,
'hed0',
weaponinfo, info.level1top, res)
end
local skullpiercerLv1Mul = shieldinfo.helmets.level1.func(skullpiercer)
renderRow(
table,
string.format(res.targets.skullpiercer1, args.skullpiercerrarity, skullpiercerLv1Mul),
string.format(shieldinfo.helmets.level1.text, skullpiercer),
skullpiercerLv1Mul, weaponinfo, info.level3first, res)
renderRow2(
table,
string.format(res.targets.helmet1, perkedDamages.scale_hed1),
string.format(shieldinfo.helmets.level1.text, headMul),
perkedDamages,
'hed1',
weaponinfo, info.level2first, res)
local skullpiercerLv2Mul = shieldinfo.helmets.level2.func(skullpiercer)
renderRow(
table,
string.format(res.targets.skullpiercer2, args.skullpiercerrarity, skullpiercerLv2Mul),
string.format(shieldinfo.helmets.level2.text, skullpiercer),
skullpiercerLv2Mul, weaponinfo, info.level3, res)
renderRow2(
table,
string.format(res.targets.helmet2, perkedDamages.scale_hed2),
string.format(shieldinfo.helmets.level2.text, headMul),
perkedDamages,
'hed2',
weaponinfo, info.level2, res)
local skullpiercerLv3Mul = shieldinfo.helmets.level3.func(skullpiercer)
renderRow(
table,
string.format(res.targets.skullpiercer3, args.skullpiercerrarity, skullpiercerLv3Mul),
string.format(shieldinfo.helmets.level3.text, skullpiercer),
skullpiercerLv3Mul, weaponinfo, info.level3, res)
renderRow2(
table,
string.format(res.targets.helmet3, perkedDamages.scale_hed3),
string.format(shieldinfo.helmets.level3.text, headMul),
perkedDamages,
'hed3',
weaponinfo, info.level2, res)
-- w/o Skullpiercer Rifling
else
renderHelmetSection(table, perkedDamages, res, weaponinfo, shieldinfo.helmets, info)
end
end
-- Body shot damage
local label
if headMul <= 1 then
if noLegsShot then
label = res.targets.all
else
label = res.targets.headbody
end
elseif noLegsShot then
label = res.targets.bodylegs
else
label = res.targets.body
end
if args.mul < 1 or args.forcegunshield then
renderRow2(table, label, nil, perkedDamages, 'body', weaponinfo, info.level1gunshiled, res)
renderRow(
table,
res.targets.gunshield,
shieldinfo.gunshieldLabel,
1, weaponinfo, info.level2gunshiled, res, shieldinfo.gunshield)
else
renderRow2(table, label, nil, perkedDamages, 'body', weaponinfo, info.level1, res)
end
-- Legs shot damage
if not noLegsShot then
local legsLabel = string.format(res.targets.legs, args.leg)
renderRow2(table, legsLabel, nil, perkedDamages, 'legs', weaponinfo, info.level1, res)
end
-- the 2nd place of damages
if hasSecond then
local rowinfoSecondTop, rowinfoSecondGunShield, label2
if not noLegsShot2 then
rowinfoSecondTop = info.level2gunshiled
rowinfoSecondGunShield = info.level3gunshiled
label2 = label
elseif args.mul2 < 1 then
rowinfoSecondTop = info.level1gunshiled
rowinfoSecondGunShield = info.level2gunshiled
label2 = string.format(res.targets.fortified_prefix, args.mul2, label)
else
rowinfoSecondTop = info.level1
rowinfoSecondGunShield = nil
label2 = string.format(res.targets.fortified_prefix, args.mul2, label)
end
local weaponinfo2 = aw.shallowCopy(weaponinfo)
weaponinfo2.mul = args.mul2
local perkedDamages2 = applyPerkAndShieldScaleToDamages(baseDamages, weaponinfo2.mul, shieldinfo.sameHeadshotDamageToNormalOnFortified, weaponinfo2.opts)
if args.mul2 < 1 then
renderRow2(table, label2, nil, perkedDamages2, 'body', weaponinfo2, rowinfoSecondTop, res)
renderRow(
table,
res.targets.gunshield,
shieldinfo.gunshieldLabel,
1, weaponinfo2, rowinfoSecondGunShield, res, shieldinfo.gunshield)
else
renderRow2(table, label2, nil, perkedDamages2, 'body', weaponinfo2, info.level2, res)
end
-- Legs shot damage
if not noLegsShot2 then
local legsLabel = string.format(res.targets.legs, args.leg)
renderRow2(table, legsLabel, nil, perkedDamages2, 'legs', weaponinfo2, info.level2, res)
end
end
return table
end
function p._main(args, frame)
-- init value
local initValues = {
mincount = 0,
maxcount = 250,
damage = 20,
damagemin = 1000,
damagemax = 0,
beamdamage = 0,
beamdamagemin = 0,
beamdamagemax = 0,
ticks = 0,
ticksmin = math.huge,
ticksmax = 0,
pellet = 1,
pelletmin = 0,
pelletmax = 0,
head = 2,
headmax = -1,
leg = 0.8,
legmin = 0,
mul = 1,
mul2 = 0,
mulmin = 0.85,
mulmax = 1,
charged = 1,
chargedmax = 1,
skullpiercer = 1,
disruptor = 1,
disruptorsup = 1,
hammerpoint = 1,
hammerpointsup = 1,
passthrough = 1,
passthroughsup = 1,
rps = 0,
rpsratio1 = 0,
rpsratio2 = 0,
rpsratio3 = 0,
raise = 0,
reload = 0,
reloadratio1 = 0.963,
reloadratio2 = 0.933,
reloadratio3 = 0.9,
extmag0 = 0,
extmag1 = 0,
extmag2 = 0,
extmag3 = 0,
}
-- fix arguments
for key, value in pairs(initValues) do
args[key] = aw.getAsNumber(args[key], value)
end
if args.pelletmin == 0 then
args.pelletmin = args.pellet
end
if args.pelletmax == 0 then
args.pelletmax = args.pellet
end
if args.headmax == -1 then
args.headmax = math.max(args.head, args.skullpiercer)
end
if args.legmin == 0 then
args.legmin = args.leg
end
if args.beamdamagemin == 0 then
args.beamdamagemin = args.beamdamage
end
if args.beamdamagemax == 0 then
args.beamdamagemax = args.beamdamage
end
args.round = aw.getAsBoolean(args.round, false)
args.amped = aw.getAsBoolean(args.amped, false)
args.forcegunshield = aw.getAsBoolean(args.forcegunshield, false)
args.rarity = args.rarity or 'epic'
args.skullpiercerrarity = args.skullpiercerrarity or 'legendary'
args.shieldpreset = args.shieldpreset or 'reinforcehelmets'
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