🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
モジュール:DamageTable
ナビゲーションに移動
検索に移動
このモジュールについての説明文ページを モジュール:DamageTable/doc に作成できます
local p = {} local aw = require('Module:Utility/Library') local getArgs -- lazily initialized local function round(num) return math.floor(tonumber(string.format("%.4f", num)) + 0.5) end local function roundover(num) return math.ceil(tonumber(string.format("%.4f", num)) - 0.5) end local function selectiveRound(num, useRound) useRound = useRound or false if useRound then return round(num) else return roundover(num) end end 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 = round(1.2 * damage) end -- ハンマーポイント弾 if info.hammerpoint > 1 then damage = round(info.hammerpoint * damage) end -- 部位倍率 if part ~= 1 then damage = round(part * damage) end -- 小柄・鉄壁 if info.mul == 1.05 and not info.amped then damage = selectiveRound(info.mul * damage, info.useRound) elseif info.mul ~= 1 then damage = round(info.mul * damage) end return damage end local function getDamageForPartAndPassive(damage, part, info) -- 部位倍率 if part ~= 1 then damage = round(part * damage) end -- 小柄・鉄壁 if info.mul == 1.05 and not info.amped then damage = selectiveRound(info.mul * damage, info.useRound) elseif info.mul ~= 1 then damage = 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) local gunshieldinfo = aw.shallowCopy(info) gunshieldinfo.mul = 1 gunshieldinfo.hammerpoint = 1 local damage = getDamage(1, gunshieldinfo) return _getShotCount(damage, 50, gunshieldinfo) end local function _getShotCountForDefault(part, health, info, gunshield) local damage = getDamage(part, info) if gunshield then local gunshieldcount, damages = _getShotCountForGunShield(info) 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 then count, damages = _getShotCountForGunShield(info) 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(round(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 false if info.hammerpoint > 1 then local damage if info.amped then damage = 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) 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>') row:tag('th'):wikitext('<span class="text-rarity text-rarity-legendary">120<small> HP</small></span>') 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>') row:tag('th'):wikitext('<span class="text-rarity text-rarity-heirloom">225<small> HP</small></span>') 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('align', 'right') :attr('title', 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 = round(1.2 * weaponinfo.damage) else damage = weaponinfo.damage end else damage = getDamage(part, weaponinfo) end if weaponinfo.pellet > 1 then row:tag('td'):attr('align', 'right'):wikitext((damage * weaponinfo.pellet) .. ' <span style="white-space:nowrap"><small>(' .. damage .. ' × ' .. weaponinfo.pellet .. ')</small></span>') else row:tag('td'):attr('align', 'right'):wikitext(damage) end renderCell(row, part, 100, 0, weaponinfo, gunshield) renderCell(row, part, 70, 50, weaponinfo, gunshield) renderCell(row, part, 100, 50, weaponinfo, gunshield) renderCell(row, part, 100, 75, weaponinfo, gunshield) renderCell(row, part, 100, 100, weaponinfo, gunshield) renderCell(row, part, 100, 125, weaponinfo, gunshield) 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 = 1.05, 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 = 0.85, pellet = args.pellet, amped = false, hammerpoint = 1, } local legCount, _ = getShotCount(args.leg, 100, 125, mininfo) local bodyWithGunSheild, _ = getShotCount(1, 100, 125, mininfo, true) local maxCount = math.max(legCount, bodyWithGunSheild) local weaponinfo = { damage = args.damage, mul = args.mul, pellet = args.pellet, amped = args.amped, hammerpoint = args.hammerpoint, minCount = minCount, maxCount = maxCount, } 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 = { "スカルピアサーライフリング" }} .. ' ' 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) 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 legMul == 1 then if args.mul == 0.85 then renderRow(table, "胴・脚", 1, weaponinfo, info.level1gunshiled) renderRow(table, '+ガンシールド', 1, weaponinfo, info.level2gunshiled, true) 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 == 0.85 then renderRow(table, "胴", 1, weaponinfo, info.level1gunshiled) renderRow(table, '+ガンシールド', 1, weaponinfo, info.level2gunshiled, true) 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, mul = 1, skullpiercer = 1, hammerpoint = 1, hammerpointsup = 1, } -- fix arguments for key, value in pairs(initValues) do args[key] = aw.getAsNumber(args[key], value) end args.round = aw.getAsBoolean(args.round, false) args.amped = aw.getAsBoolean(args.amped, false) 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