Anonymous

Module:Attacks/Tables: Difference between revisions

From Melvor Idle
Fix for unknown items
(Adding notes to the Special Attack table with the delay between each attack)
(Fix for unknown items)
(4 intermediate revisions by 2 users not shown)
Line 10: Line 10:


function p._getSpecialAttackTable(effectDefn, categories, sourceHeaderLabel, includeSource)
function p._getSpecialAttackTable(effectDefn, categories, sourceHeaderLabel, includeSource)
    local spAttTable = {}
local spAttTable = {}
    local attacks = Attacks.getAttacks(function(attack)
local attacks = Attacks.getAttacks(function(attack)
                                          if effectDefn == nil then
if effectDefn == nil then
                                              return true
return true
                                          else
else
                                              return Attacks.attackHasEffect(attack, effectDefn)
return Attacks.attackHasEffect(attack, effectDefn)
                                          end
end
                                      end)
end)
    local includeCat = {}
local includeCat = {}
    for i, category in ipairs(categories) do
for i, category in ipairs(categories) do
        includeCat[category] = true
includeCat[category] = true
    end
end


    -- Compile a list of monsters, items, spells, etc. for each included attack
-- Compile a list of monsters, items, spells, etc. for each included attack
    for i, spAtt in ipairs(attacks) do
for i, spAtt in ipairs(attacks) do
        -- Monsters
-- Monsters
        if includeCat['Monster'] then
if includeCat['Monster'] then
            for j, monsterID in ipairs(spAtt.monsters) do
for j, monsterID in ipairs(spAtt.monsters) do
                local monster = Monsters.getMonsterByID(monsterID)
local monster = Monsters.getMonsterByID(monsterID)
                local overrideChance = (monster.overrideSpecialChances ~= nil and Shared.tableCount(monster.overrideSpecialChances) > 0)
local overrideChance = (monster.overrideSpecialChances ~= nil and Shared.tableCount(monster.overrideSpecialChances) > 0)
                local attChance = spAtt.defaultChance
local attChance = spAtt.defaultChance
                if overrideChance then
if overrideChance then
                    local attIdx = nil
local attIdx = nil
                    for k, monsterAttack in ipairs(monster.specialAttacks) do
for k, monsterAttack in ipairs(monster.specialAttacks) do
                        local attID = (type(monsterAttack) == 'table' and monsterAttack.id) or monsterAttack
local attID = (type(monsterAttack) == 'table' and monsterAttack.id) or monsterAttack
                        if spAtt.id == attID then
if spAtt.id == attID then
                            attIdx = k
attIdx = k
                            break
break
                        end
end
                    end
end
                    if attIdx ~= nil then
if attIdx ~= nil then
                        attChance = monster.overrideSpecialChances[attIdx]
attChance = monster.overrideSpecialChances[attIdx]
                    end
end
                end
end


                table.insert(spAttTable, { idx = i, source = 'Monster', sourceSort = monster.name, sourceText = Icons.Icon({ monster.name, type = 'monster' }), chance = attChance, descType = 'monster' })
table.insert(spAttTable, { idx = i, source = 'Monster', sourceSort = monster.name, sourceText = Icons.Icon({ monster.name, type = 'monster' }), chance = attChance, descType = 'monster' })
            end
end
        end
end


        -- Items/Weapons
-- Items/Weapons
        if includeCat['Item'] then
if includeCat['Item'] then
            for j, itemID in ipairs(spAtt.items) do
for j, itemID in ipairs(spAtt.items) do
                local item = Items.getItemByID(itemID)
local item = Items.getItemByID(itemID)
                table.insert(spAttTable, { idx = i, source = 'Weapon', sourceSort = item.name, sourceText = Icons.Icon({ item.name, type = 'item' }), chance = spAtt.defaultChance, descType = 'player' })
if item ~= nil then
            end
table.insert(spAttTable, { idx = i, source = 'Weapon', sourceSort = item.name, sourceText = Icons.Icon({ item.name, type = 'item' }), chance = spAtt.defaultChance, descType = 'player' })
        end
end
end
end


        -- Spells
-- Spells
        if includeCat['Spell'] then
if includeCat['Spell'] then
            for j, spellID in ipairs(spAtt.spells) do
for j, spellID in ipairs(spAtt.spells) do
                local spell = Magic.getSpellByID(spellID[1], spellID[2])
local spell = Magic.getSpellByID(spellID[1], spellID[2])
                table.insert(spAttTable, { idx = i, source = 'Spell', sourceSort = spell.name, sourceText = Icons.Icon({ spell.name, type = 'spell' }), chance = spAtt.defaultChance, descType = 'player' })
table.insert(spAttTable, { idx = i, source = 'Spell', sourceSort = spell.name, sourceText = Icons.Icon({ spell.name, type = 'spell' }), chance = spAtt.defaultChance, descType = 'player' })
            end
end
        end
end
    end
end


    -- Summoning familiars. Any effects inflicted by combat familiars aren't actually special
-- Summoning familiars. Any effects inflicted by combat familiars aren't actually special
    -- attacks, therefore the handling here is a bit different and outside of the above attack loop
-- attacks, therefore the handling here is a bit different and outside of the above attack loop
    if includeCat['Familiar'] then
if includeCat['Familiar'] then
        local famIdx = Shared.tableCount(attacks) + 1
local famIdx = Shared.tableCount(attacks) + 1
        local familiars = Items.getItems(function(item)
local familiars = Items.getItems(function(item)
                                            if item.type == 'Familiar' and Items._getItemStat(item, 'summoningMaxhit') ~= nil and item.modifiers ~= nil then
if item.type == 'Familiar' and Items._getItemStat(item, 'summoningMaxhit') ~= nil and item.modifiers ~= nil then
                                                local famAttack = { prehitEffects = {}, onhitEffects = { { type = 'Modifier', subtype = 'Familiar', modifiers = item.modifiers } } }
local famAttack = { prehitEffects = {}, onhitEffects = { { type = 'Modifier', subtype = 'Familiar', modifiers = item.modifiers } } }
                                                if effectDefn == nil then
if effectDefn == nil then
                                                    return Shared.tableCount(Attacks.getAttackEffects(famAttack)) > 0
return Shared.tableCount(Attacks.getAttackEffects(famAttack)) > 0
                                                else
else
                                                    return Attacks.attackHasEffect(famAttack, effectDefn)
return Attacks.attackHasEffect(famAttack, effectDefn)
                                                end
end
                                            end
end
                                            return false
return false
                                        end)
end)
        for j, familiar in ipairs(familiars) do
for j, familiar in ipairs(familiars) do
            -- For chance, assume the first modifier we come across has the chance, which is pretty lazy
-- For chance, assume the first modifier we come across has the chance, which is pretty lazy
            local famChance, famDesc = 0, ''
local famChance, famDesc = 0, ''
            for modName, modVal in pairs(familiar.modifiers) do
for modName, modVal in pairs(familiar.modifiers) do
                if type(modVal) == 'table' and type(modVal[1]) == 'number' then
if type(modVal) == 'table' and type(modVal[1]) == 'number' then
                    famChance = modVal[1]
famChance = modVal[1]
                elseif type(modVal) == 'number' then
elseif type(modVal) == 'number' then
                    famChance = modVal
famChance = modVal
                else
else
                    famChance = 0
famChance = 0
                end
end
                famDesc = Constants._getModifierText(modName, modVal, false)
famDesc = Constants._getModifierText(modName, modVal, false)
                break
break
            end
end


            table.insert(spAttTable, { idx = famIdx, source = 'Familiar', sourceSort = familiar.name, sourceText = Icons.Icon({ familiar.name, type = 'item' }), chance = famChance or 0, descType = 'player' })
table.insert(spAttTable, { idx = famIdx, source = 'Familiar', sourceSort = familiar.name, sourceText = Icons.Icon({ familiar.name, type = 'item' }), chance = famChance or 0, descType = 'player' })
            -- Slap a dummy entry into the attacks table for this familiar
-- Slap a dummy entry into the attacks table for this familiar
            attacks[famIdx] = { name = familiar.name .. ' (Familiar)', description = { player = famDesc } }
attacks[famIdx] = { name = familiar.name .. ' (Familiar)', description = { player = famDesc } }
            famIdx = famIdx + 1
famIdx = famIdx + 1
        end
end
    end
end


    -- Nothing to output if there are no row definitions
-- Nothing to output if there are no row definitions
    if Shared.tableCount(spAttTable) == 0 then
if Shared.tableCount(spAttTable) == 0 then
    return ''
return ''
    end
end


    -- Sort entries into desired order and generate stats to determine row spans:
-- Sort entries into desired order and generate stats to determine row spans:
    -- By attack index, description type (monster/player), chance, source, then source name (weapon/item/etc.)
-- By attack index, description type (monster/player), chance, source, then source name (weapon/item/etc.)
    table.sort(spAttTable, function (a, b)
table.sort(spAttTable, function (a, b)
                              local sortKeys = { 'idx', 'descType', 'chance', 'source', 'sourceSort' }
local sortKeys = { 'idx', 'descType', 'chance', 'source', 'sourceSort' }
                              for i, key in ipairs(sortKeys) do
for i, key in ipairs(sortKeys) do
                                  if a[key] ~= b[key] then
if a[key] ~= b[key] then
                                      return a[key] < b[key]
return a[key] < b[key]
                                  end
end
                              end
end
                              return false
return false
                          end)
end)
    -- Determine row counts for grouping/rowspans
-- Determine row counts for grouping/rowspans
    local rowCounts = {}
local rowCounts = {}
    for i, rowDefn in ipairs(spAttTable) do
for i, rowDefn in ipairs(spAttTable) do
        local idx, dt, chance = rowDefn.idx, rowDefn.descType, rowDefn.chance
local idx, dt, chance = rowDefn.idx, rowDefn.descType, rowDefn.chance
        if rowCounts[idx] == nil then
if rowCounts[idx] == nil then
            rowCounts[idx] = { rows = 0 }
rowCounts[idx] = { rows = 0 }
        end
end
        if rowCounts[idx][dt] == nil then
if rowCounts[idx][dt] == nil then
            rowCounts[idx][dt] = { rows = 0 }
rowCounts[idx][dt] = { rows = 0 }
        end
end
        if rowCounts[idx][dt][chance] == nil then
if rowCounts[idx][dt][chance] == nil then
            rowCounts[idx][dt][chance] = 0
rowCounts[idx][dt][chance] = 0
        end
end
        rowCounts[idx]['rows'] = rowCounts[idx]['rows'] + 1
rowCounts[idx]['rows'] = rowCounts[idx]['rows'] + 1
        rowCounts[idx][dt]['rows'] = rowCounts[idx][dt]['rows'] + 1
rowCounts[idx][dt]['rows'] = rowCounts[idx][dt]['rows'] + 1
        rowCounts[idx][dt][chance] = rowCounts[idx][dt][chance] + 1
rowCounts[idx][dt][chance] = rowCounts[idx][dt][chance] + 1
    end
end


    -- Generate output table
-- Generate output table
    local resultPart = {}
local resultPart = {}
    table.insert(resultPart, '{|class="wikitable sortable stickyHeader"')
table.insert(resultPart, '{|class="wikitable sortable stickyHeader"')
    table.insert(resultPart, '\r\n|- class="headerRow-0"')
table.insert(resultPart, '\r\n|- class="headerRow-0"')
    table.insert(resultPart, '\r\n!Name!!style="min-width:225px"| ' .. sourceHeaderLabel .. (includeSource and '!!Type' or '') .. '!!Chance!!Effect')
table.insert(resultPart, '\r\n!Name!!style="min-width:225px"| ' .. sourceHeaderLabel .. (includeSource and '!!Type' or '') .. '!!Chance!!Effect')


    local firstRow = { idx = true, descType = true, chance = true }
local firstRow = { idx = true, descType = true, chance = true }
    local prevRowVal = { idx = 0, descType = '', chance = 0 }
local prevRowVal = { idx = 0, descType = '', chance = 0 }
    local resetOnChange = {
local resetOnChange = {
        idx = { 'idx', 'descType', 'chance' },
idx = { 'idx', 'descType', 'chance' },
        descType = { 'descType', 'chance' },
descType = { 'descType', 'chance' },
        chance = { 'chance' }
chance = { 'chance' }
    }
}
    local rowSuffix = ''
local rowSuffix = ''
    for i, spAttRow in ipairs(spAttTable) do
for i, spAttRow in ipairs(spAttTable) do
        local spIdx = spAttRow.idx
local spIdx = spAttRow.idx
        local spAtt = attacks[spIdx]
local spAtt = attacks[spIdx]
        -- Determine if it's the first row for any of our groupings
-- Determine if it's the first row for any of our groupings
        local resetKeys = {}
local resetKeys = {}
        for key, val in pairs(prevRowVal) do
for key, val in pairs(prevRowVal) do
            if spAttRow[key] ~= prevRowVal[key] then
if spAttRow[key] ~= prevRowVal[key] then
                for j, keyName in ipairs(resetOnChange[key]) do
for j, keyName in ipairs(resetOnChange[key]) do
                    resetKeys[keyName] = true
resetKeys[keyName] = true
                end
end
            end
end
            prevRowVal[key] = spAttRow[key]
prevRowVal[key] = spAttRow[key]
        end
end
        for key, val in pairs(firstRow) do
for key, val in pairs(firstRow) do
            firstRow[key] = (resetKeys[key] ~= nil)
firstRow[key] = (resetKeys[key] ~= nil)
        end
end


        table.insert(resultPart, '\r\n|-')
table.insert(resultPart, '\r\n|-')
        if firstRow.idx then
if firstRow.idx then
            rowSuffix = (rowCounts[spIdx]['rows'] > 1 and '|rowspan="' .. rowCounts[spIdx]['rows'] .. '"') or ''
rowSuffix = (rowCounts[spIdx]['rows'] > 1 and '|rowspan="' .. rowCounts[spIdx]['rows'] .. '"') or ''
            table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.name)
table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.name)
        end
end
        table.insert(resultPart, '\r\n|data-sort-value="' .. spAttRow.sourceSort .. '"| ' .. spAttRow.sourceText)
table.insert(resultPart, '\r\n|data-sort-value="' .. spAttRow.sourceSort .. '"| ' .. spAttRow.sourceText)
        if includeSource then
if includeSource then
            table.insert(resultPart, '\r\n| ' .. spAttRow.source)
table.insert(resultPart, '\r\n| ' .. spAttRow.source)
        end
end
        if firstRow.chance then
if firstRow.chance then
            rowSuffix = (rowCounts[spIdx][spAttRow.descType][spAttRow.chance] > 1 and 'rowspan="' .. rowCounts[spIdx][spAttRow.descType][spAttRow.chance] .. '" ') or ''
rowSuffix = (rowCounts[spIdx][spAttRow.descType][spAttRow.chance] > 1 and 'rowspan="' .. rowCounts[spIdx][spAttRow.descType][spAttRow.chance] .. '" ') or ''
            table.insert(resultPart, '\r\n|' .. rowSuffix .. 'data-sort-value="' .. spAttRow.chance .. '" style="text-align:right;"| ' .. Shared.round(spAttRow.chance, 2, 0) .. '%')
table.insert(resultPart, '\r\n|' .. rowSuffix .. 'data-sort-value="' .. spAttRow.chance .. '" style="text-align:right;"| ' .. Shared.round(spAttRow.chance, 2, 0) .. '%')
        end
end
        if firstRow.descType then
if firstRow.descType then
            rowSuffix = (rowCounts[spIdx][spAttRow.descType]['rows'] > 1 and '|rowspan="' .. rowCounts[spIdx][spAttRow.descType]['rows'] .. '"') or ''
rowSuffix = (rowCounts[spIdx][spAttRow.descType]['rows'] > 1 and '|rowspan="' .. rowCounts[spIdx][spAttRow.descType]['rows'] .. '"') or ''
            local spAttDesc = spAtt['description'][spAttRow.descType]
local spAttDesc = spAtt['description'][spAttRow.descType]
            --Adding the time between hits as a note at the end of the special attack description
--Adding the time between hits and total duration as a note at the end of the special attack description
            local spAttInterval = spAtt.attackInterval ~= nil and spAtt.attackInterval or -1
local spAttInterval = spAtt.attackInterval ~= nil and spAtt.attackInterval or -1
            if(spAttInterval ~= -1) then
if(spAttInterval ~= -1 and spAtt.damage ~= nil and Shared.tableCount(spAtt.damage) > 0) then
            spAttDesc = spAttDesc..'<br/>'..'('..Shared.round(spAttInterval / 1000, 1, 1)..'s delay between attacks)'
spAttDesc = spAttDesc..'<br/>('
            end
local spAttDuration = spAttInterval * (spAtt.attackCount - 1)
            table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAttDesc)
spAttDesc = spAttDesc..Shared.round(spAttInterval / 1000, 2, 2)..'s delay between attacks.'
        end
if spAtt.attackCount ~= nil and spAtt.attackCount > 2 then
    end
spAttDesc = spAttDesc..' '..Shared.round(spAttDuration / 1000, 2, 2)..'s total duration'
    table.insert(resultPart, '\r\n|}')
end
spAttDesc = spAttDesc..')'
end
table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAttDesc)
end
end
table.insert(resultPart, '\r\n|}')


    return table.concat(resultPart)
return table.concat(resultPart)
end
end


function p.getSpecialAttackTable(frame)
function p.getSpecialAttackTable(frame)
    local args = frame.args ~= nil and frame.args or frame
local args = frame.args ~= nil and frame.args or frame
    local tableCategories = {'Monster', 'Item', 'Spell', 'Familiar'}
local tableCategories = {'Monster', 'Item', 'Spell', 'Familiar'}
    if args[1] ~= nil and args[1] ~= '' then
if args[1] ~= nil and args[1] ~= '' then
        tableCategories = Shared.splitString(args[1], ',')
tableCategories = Shared.splitString(args[1], ',')
    end
end
    local effectName = args['effect']
local effectName = args['effect']
    local sourceHeaderLabel = (args['sourceHeader'] ~= '' and args['sourceHeader']) or 'Source'
local sourceHeaderLabel = (args['sourceHeader'] ~= '' and args['sourceHeader']) or 'Source'
    local includeSource = true
local includeSource = true
    if args['includeSource'] ~= nil and string.lower(args['includeSource']) == 'false' then
if args['includeSource'] ~= nil and string.lower(args['includeSource']) == 'false' then
        includeSource = false
includeSource = false
    end
end
    local effectDefn = nil
local effectDefn = nil


    if effectName ~= nil and effectName ~= '' then
if effectName ~= nil and effectName ~= '' then
        effectDefn = Attacks.effectDefinition[effectName]
effectDefn = Attacks.effectDefinition[effectName]
        if effectDefn == nil then
if effectDefn == nil then
            local validEffectNames = {}
local validEffectNames = {}
            for k, v in pairs(Attacks.effectDefinition) do
for k, v in pairs(Attacks.effectDefinition) do
                table.insert(validEffectNames, k)
table.insert(validEffectNames, k)
            end
end
            table.sort(validEffectNames, function(a, b) return a < b end)
table.sort(validEffectNames, function(a, b) return a < b end)


            return 'ERROR: Invalid effect name "' .. effectName .. '", must be one of: ' .. table.concat(validEffectNames, ', ') .. '[[Category:Pages with script errors]]'
return 'ERROR: Invalid effect name "' .. effectName .. '", must be one of: ' .. table.concat(validEffectNames, ', ') .. '[[Category:Pages with script errors]]'
        end
end
    end
end


    return p._getSpecialAttackTable(effectDefn, tableCategories, sourceHeaderLabel, includeSource)
return p._getSpecialAttackTable(effectDefn, tableCategories, sourceHeaderLabel, includeSource)
end
end