| 🌟 | 現在、 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:DamageTable
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール:DamageTable/doc に作成できます
local p = {}
local aw = require('Module:Utility/Library')
local getArgs -- lazily initialized
local function convertHslToRgb(hue, saturation, lightness)
hue = math.max(0, math.min(1, hue))
saturation = math.max(0, math.min(1, saturation))
lightness = math.max(0, math.min(1, lightness))
if saturation == 0 then
return lightness, lightness, lightness
else
local function to(p, q, t)
if t < 0 then t = t + 1 end
if t > 1 then t = t - 1 end
if t < 1/6 then
return p + (q - p) * 6 * t
elseif t < 3/6 then
return q
elseif t < 4/6 then
return p + (q - p) * (2/3 - t) * 6
else
return p
end
end
local q
if lightness < 0.5 then
q = lightness * (1 + saturation)
else
q = lightness + saturation - lightness * saturation
end
local p = 2 * lightness - q
return to(p, q, hue + 1/3), to(p, q, hue), to(p, q, hue - 1/3)
end
end
local function getColorAsString(hue)
local r, g, b = convertHslToRgb(hue, 0.91, 0.89)
return '#'
.. string.format('%02X', 255 * r)
.. string.format('%02X', 255 * g)
.. string.format('%02X', 255 * b)
end
local function getDamage(part, info)
local damage = info.damage
-- 増幅バリケード
if info.amped then
damage = aw.round(1.2 * damage)
end
-- ハンマーポイント弾
if info.hammerpoint > 1 then
damage = math.floor(info.hammerpoint * damage)
end
-- 部位倍率
if part ~= 1 then
damage = aw.round(part * damage)
end
-- 小柄・鉄壁
if info.mul == 1.05 then
if info.amped then
damage = aw.roundover(info.mul * damage)
else
damage = aw.selectiveRound(info.mul * damage, info.useRound)
end
elseif info.mul ~= 1 then
damage = aw.round(info.mul * damage)
end
return damage
end
local function getDamageForPartAndPassive(damage, part, info)
-- 部位倍率
if part ~= 1 then
damage = aw.round(part * damage)
end
-- 小柄・鉄壁
if info.mul == 1.05 then
if info.amped then
damage = aw.roundover(info.mul * damage)
else
damage = aw.selectiveRound(info.mul * damage, info.useRound)
end
elseif info.mul ~= 1 then
damage = aw.round(info.mul * damage)
end
return damage
end
local function _getShotCount(damage, health, info)
local count = 0
local damages = {}
local damageStack = 0
local pelletCount = info.pellet
while health > 0 do
pelletCount = pelletCount - 1
health = health - damage
damageStack = damageStack + damage
if pelletCount == 0 then
count = count + 1
pelletCount = info.pellet
table.insert(damages, damageStack)
damageStack = 0
end
end
if damageStack > 0 then
count = count + 1
table.insert(damages, damageStack)
end
return count, damages
end
local function _getShotCountForGunShield(info, gunshield)
local gunshieldinfo = aw.shallowCopy(info)
gunshieldinfo.mul = 1
gunshieldinfo.hammerpoint = 1
local damage = getDamage(1, gunshieldinfo)
return _getShotCount(damage, gunshield, gunshieldinfo)
end
local function _getShotCountForDefault(part, health, info, gunshield)
local damage = getDamage(part, info)
if gunshield > 0 then
local gunshieldcount, damages = _getShotCountForGunShield(info, gunshield)
local count, damages2 = _getShotCount(damage, health, info)
for _, value in ipairs(damages2) do
table.insert(damages, value)
end
return gunshieldcount + count, damages
else
return _getShotCount(damage, health, info)
end
end
local function _getShotCountForHammerpointRounds(ampedDamage, part, health, shield, info, gunshield)
local count = 0
local damages = {}
local damageStack = 0
local pelletCount = info.pellet
if gunshield > 0 then
count, damages = _getShotCountForGunShield(info, gunshield)
end
local shieldDamage = getDamageForPartAndPassive(ampedDamage, part, info)
while shield >= shieldDamage do
pelletCount = pelletCount - 1
shield = shield - shieldDamage
damageStack = damageStack + shieldDamage
if pelletCount == 0 then
count = count + 1
pelletCount = info.pellet
table.insert(damages, damageStack)
damageStack = 0
end
end
if shield > 0 then
local mergedDamage
if shield < ampedDamage then
mergedDamage = getDamageForPartAndPassive(shield + math.floor(info.hammerpoint * (ampedDamage - shield)), part, info)
else
mergedDamage = shieldDamage
end
pelletCount = pelletCount - 1
health = health - (mergedDamage - shield)
damageStack = damageStack + mergedDamage
end
if pelletCount == 0 then
count = count + 1
pelletCount = info.pellet
table.insert(damages, damageStack)
damageStack = 0
end
local healthDamage = getDamageForPartAndPassive(math.floor(info.hammerpoint * ampedDamage), part, info)
while health > 0 do
pelletCount = pelletCount - 1
health = health - healthDamage
damageStack = damageStack + healthDamage
if pelletCount == 0 then
count = count + 1
pelletCount = info.pellet
table.insert(damages, damageStack)
damageStack = 0
end
end
if pelletCount > 0 and pelletCount < info.pellet then
count = count + 1
pelletCount = info.pellet
table.insert(damages, damageStack)
end
return count, damages
end
local function getShotCount(part, health, shield, info, gunshield)
gunshield = gunshield or 0
if info.hammerpoint > 1 then
local damage
if info.amped then
damage = aw.round(1.2 * info.damage)
else
damage = info.damage
end
return _getShotCountForHammerpointRounds(damage, part, health, shield, info, gunshield)
else
return _getShotCountForDefault(part, health + shield, info, gunshield)
end
end
local function _arrangeArray(cache, count)
if count > 1 then
return cache .. '×' .. count
else
return cache
end
end
local function arrangeArray(array, separator)
local cache = array[1]
local count = 0
local output = nil
for _, damage in ipairs(array) do
if cache == damage then
count = count + 1
else
local text = _arrangeArray(cache, count)
if output ~= nil then
output = output .. separator .. text
else
output = text
end
cache = damage
count = 1
end
end
local text = _arrangeArray(cache, count)
if output ~= nil then
output = output .. separator .. text
else
output = text
end
return output
end
local function renderHeader(table, mul, colspan, goldbackpack, redbodyshield)
local row = table:tag('tr')
local cell = row:tag('th')
:attr('colspan', colspan)
:attr('rowspan', 2)
if mul == 1 then
cell:wikitext('部位')
else
cell:wikitext('部位 (x' .. mul .. ')')
end
row:tag('th')
:attr('rowspan', 2)
:wikitext('ダメージ')
row:tag('th')
:attr('colspan', 6)
:wikitext('確殺数')
row = table:tag('tr')
row:tag('th'):wikitext('100<small> HP</small>')
if goldbackpack then
row:tag('th')
:attr('data-tooltip', '金バックパック蘇生')
:wikitext('<span class="text-rarity text-rarity-legendary">120<small> HP</small></span>')
end
row:tag('th'):wikitext('<span class="text-rarity text-rarity-common">150<small> HP</small></span>')
row:tag('th'):wikitext('<span class="text-rarity text-rarity-rare">175<small> HP</small></span>')
row:tag('th'):wikitext('<span class="text-rarity text-rarity-epic">200<small> HP</small></span>')
if redbodyshield then
row:tag('th'):wikitext('<span class="text-rarity text-rarity-heirloom">225<small> HP</small></span>')
end
end
local function renderCell(row, part, health, shield, info, gunshield)
local shotCount, damages = getShotCount(part, health, shield, info, gunshield)
local ratio = (shotCount - info.minCount) / (info.maxCount - info.minCount)
row:tag('td')
:attr('data-tooltip', arrangeArray(damages, '→'))
:css('background-color', getColorAsString(0.85 * ratio))
:wikitext(shotCount)
end
local function renderHeaderCell(row, name, rowinfo)
for i = 1, #rowinfo do
local cellinfo = rowinfo[i]
local colspan = cellinfo.colspan or 1
local cell = row:tag('th')
if colspan > 1 then
cell:attr('colspan', colspan)
end
if cellinfo.breaktop then
cell:css('border-top', '0 none')
end
if cellinfo.breakbottom then
cell:css('border-bottom', '0 none')
end
if i == #rowinfo then
cell:wikitext(name)
else
cell:wikitext(' ')
end
end
end
local function renderRow(table, name, part, weaponinfo, rowinfo, gunshield)
local row = table:tag('tr')
renderHeaderCell(row, name, rowinfo)
local damage
if gunshield then
if weaponinfo.amped then
damage = aw.round(1.2 * weaponinfo.damage)
else
damage = weaponinfo.damage
end
else
damage = getDamage(part, weaponinfo)
end
if weaponinfo.pellet > 1 then
row:tag('td'):wikitext((damage * weaponinfo.pellet) .. ' <span style="white-space:nowrap"><small>(' .. damage .. ' × ' .. weaponinfo.pellet .. ')</small></span>')
else
row:tag('td'):wikitext(damage)
end
renderCell(row, part, 100, 0, weaponinfo, gunshield)
if weaponinfo.goldbackpack then
renderCell(row, part, 70, 50, weaponinfo, gunshield)
end
renderCell(row, part, 100, 50, weaponinfo, gunshield)
renderCell(row, part, 100, 75, weaponinfo, gunshield)
renderCell(row, part, 100, 100, weaponinfo, gunshield)
if weaponinfo.redbodyshield then
renderCell(row, part, 100, 125, weaponinfo, gunshield)
end
end
local function renderTable(args, frame)
local skullpiercer = args.skullpiercer or 1
local headMul = args.head or 2
local minCount, _ = getShotCount(
math.max(headMul, skullpiercer),
100,
0,
{
damage = math.max(args.damage, args.damagemax),
mul = math.max(args.mul, args.mulmax),
pellet = args.pellet,
amped = true,
hammerpoint = math.max(args.hammerpoint, args.hammerpointsup),
})
local damagemin = math.min(args.damage, args.damagemin)
local mininfo = {
damage = damagemin,
mul = math.min(args.mul, args.mulmin),
pellet = args.pellet,
amped = false,
hammerpoint = 1,
}
local legCount, bodyWithGunSheild
if args.redbodyshield then
legCount, _ = getShotCount(math.min(args.leg, args.legmin), 100, 125, mininfo)
bodyWithGunSheild, _ = getShotCount(1, 100, 125, mininfo, args.gunshield)
else
legCount, _ = getShotCount(math.min(args.leg, args.legmin), 100, 100, mininfo)
bodyWithGunSheild, _ = getShotCount(1, 100, 100, mininfo, args.gunshield)
end
local maxCount = math.max(legCount, bodyWithGunSheild)
local weaponinfo = {
damage = args.damage,
mul = args.mul,
pellet = args.pellet,
amped = args.amped,
hammerpoint = args.hammerpoint,
useRound = args.round,
minCount = minCount,
maxCount = maxCount,
goldbackpack = args.goldbackpack,
redbodyshield = args.redbodyshield,
}
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 = true },
{ breaktop = true, breakbottom = false, colspan = 2 },
},
level2gunshiled = {
{ breaktop = true, breakbottom = false },
{ breaktop = false, breakbottom = false, colspan = 2 },
},
level3 = {
{ breaktop = true, breakbottom = true },
{ breaktop = false, breakbottom = true },
{ breaktop = false, breakbottom = false },
},
level3top = {
{ breaktop = false, breakbottom = true, colspan = 2 },
{ breaktop = false, breakbottom = false },
},
}
else
colspan = 2
info = {
level1 = {
{ breaktop = false, breakbottom = true, colspan = 2 },
},
level1gunshiled = {
{ breaktop = false, breakbottom = true, colspan = 2 },
},
level2 = {
{ breaktop = true, breakbottom = true },
{ breaktop = false, breakbottom = false },
},
level2gunshiled = {
{ breaktop = true, breakbottom = false },
{ breaktop = false, breakbottom = false },
},
}
info.level1top = info.level1
end
local skullpiercerHtml
if frame ~= nil then
skullpiercerHtml = frame:expandTemplate { title = 'Hopup', args = { "スカルピアサーライフリング", rariry = args.skullpiercerrariry }} .. ' '
else
skullpiercerHtml = ''
end
local table = mw.html.create('table')
:addClass('wikitable')
:addClass('numbertable')
if args.caption ~= nil then
table:tag('caption')
:wikitext(args.caption)
end
renderHeader(table, args.mul, colspan, args.goldbackpack, args.redbodyshield)
if skullpiercer > 1 then
renderRow(
table,
skullpiercerHtml .. '(x' .. skullpiercer .. ')',
skullpiercer, weaponinfo, info.level3top)
end
renderRow(
table,
"頭 (x" .. headMul .. ")",
headMul, weaponinfo, info.level1top)
if skullpiercer > 1 then
local skullpiercerLv1Mul = 0.2 + 0.8 * skullpiercer
renderRow(
table,
skullpiercerHtml .. '<span class="text-rarity text-rarity-common">(x' .. skullpiercerLv1Mul .. ')</span>',
skullpiercerLv1Mul, weaponinfo, info.level3)
end
local hlmLv1Mul = 0.2 + 0.8 * headMul
renderRow(
table,
'<span class="text-rarity text-rarity-common">Lv.1 (x' .. hlmLv1Mul .. ')</span>',
hlmLv1Mul, weaponinfo, info.level2)
if skullpiercer > 1 then
local skullpiercerLv2Mul = 0.4 + 0.6 * skullpiercer
renderRow(
table,
skullpiercerHtml .. '<span class="text-rarity text-rarity-rare">(x' .. skullpiercerLv2Mul .. ')</span>',
skullpiercerLv2Mul, weaponinfo, info.level3)
end
local hlmLv2Mul = 0.4 + 0.6 * headMul
renderRow(
table,
'<span class="text-rarity text-rarity-rare">Lv.2 (x' .. hlmLv2Mul .. ')</span>',
hlmLv2Mul, weaponinfo, info.level2)
if skullpiercer > 1 then
local skullpiercerLv3Mul = 0.5 + 0.5 * skullpiercer
renderRow(
table,
skullpiercerHtml .. '<span class="text-rarity text-rarity-epic">(x' .. skullpiercerLv3Mul .. ')</span>',
skullpiercerLv3Mul, weaponinfo, info.level3)
end
local hlmLv3Mul = 0.5 + 0.5 * headMul
renderRow(
table,
'<span class="text-rarity text-rarity-epic">Lv.3</span>/<span class="text-rarity text-rarity-legendary">4</span> <span class="text-rarity text-rarity-epic">(x' .. hlmLv3Mul .. ')</span>',
hlmLv3Mul, weaponinfo, info.level2)
if args.leg == 1 then
if args.mul < 1 or args.forcegunshield then
renderRow(table, "胴・脚", 1, weaponinfo, info.level1gunshiled)
renderRow(table, '+ガンシールド', 1, weaponinfo, info.level2gunshiled, args.gunshield)
else
renderRow(table, "胴・脚", 1, weaponinfo, info.level1)
end
else
if args.mul == 1.05 then
renderRow(table, "胴・脚", 1, weaponinfo, info.level1)
else
if args.mul < 1 or args.forcegunshield then
renderRow(table, "胴", 1, weaponinfo, info.level1gunshiled)
renderRow(table, '+ガンシールド', 1, weaponinfo, info.level2gunshiled, args.gunshield)
else
renderRow(table, "胴", 1, weaponinfo, info.level1)
end
renderRow(table, "脚 (x" .. args.leg .. ")", args.leg, weaponinfo, info.level1)
end
end
return table
end
function p._main(args, frame)
-- init value
local initValues = {
damage = 20,
damagemin = 1000,
damagemax = 0,
pellet = 1,
head = 2,
leg = 0.8,
legmin = 0,
mul = 1,
mulmin = 0.85,
mulmax = 1.05,
skullpiercer = 1,
hammerpoint = 1,
hammerpointsup = 1,
gunshield = 50,
}
-- fix arguments
for key, value in pairs(initValues) do
args[key] = aw.getAsNumber(args[key], value)
end
if args.legmin == 0 then
args.legmin = args.leg
end
args.round = aw.getAsBoolean(args.round, false)
args.amped = aw.getAsBoolean(args.amped, false)
args.goldbackpack = aw.getAsBoolean(args.goldbackpack, true)
args.redbodyshield = aw.getAsBoolean(args.redbodyshield, args.goldbackpack)
args.forcegunshield = aw.getAsBoolean(args.forcegunshield, false)
args.skullpiercerrariry = args.skullpiercerrariry or 'legendary'
return tostring(renderTable(args, frame))
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