🌟 | 現在、 鉄壁ヘッドショットには対応済みです。 鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。 |
「モジュール:DamageTable」の版間の差分
ナビゲーションに移動
検索に移動
(強制的にガンシールドを印字する機能を実装) |
(ガンシールドに対する回数計算の判定を改善) |
||
135行目: | 135行目: | ||
local function _getShotCountForDefault(part, health, info, gunshield) | local function _getShotCountForDefault(part, health, info, gunshield) | ||
local damage = getDamage(part, info) | local damage = getDamage(part, info) | ||
if gunshield then | if gunshield > 0 then | ||
local gunshieldcount, damages = _getShotCountForGunShield(info, gunshield) | local gunshieldcount, damages = _getShotCountForGunShield(info, gunshield) | ||
local count, damages2 = _getShotCount(damage, health, info) | local count, damages2 = _getShotCount(damage, health, info) |
2021年2月4日 (木) 23:49時点における版
このモジュールについての説明文ページを モジュール: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, _ = getShotCount(math.min(args.leg, args.legmin), 100, 125, mininfo) local bodyWithGunSheild, _ = getShotCount(1, 100, 125, mininfo, args.gunshield) 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