|
|
(3 intermediate revisions by 2 users not shown) |
Line 1: |
Line 1: |
| local p = {}
| |
|
| |
|
| local Constants = require('Module:Constants')
| |
| local Shared = require('Module:Shared')
| |
| local Icons = require('Module:Icons')
| |
| local Items = require('Module:Items')
| |
| local Monsters = require('Module:Monsters')
| |
| local Magic = require('Module:Magic')
| |
| local Attacks = require('Module:AuronTest')
| |
|
| |
| function p._getSpecialAttackTable(effectDefn, categories, sourceHeaderLabel, includeSource)
| |
| local spAttTable = {}
| |
| local attacks = Attacks.getAttacks(function(attack)
| |
| if effectDefn == nil then
| |
| return true
| |
| else
| |
| return Attacks.attackHasEffect(attack, effectDefn)
| |
| end
| |
| end)
| |
| local includeCat = {}
| |
| for i, category in ipairs(categories) do
| |
| includeCat[category] = true
| |
| end
| |
|
| |
| -- Compile a list of monsters, items, spells, etc. for each included attack
| |
| for i, spAtt in ipairs(attacks) do
| |
| -- Monsters
| |
| if includeCat['Monster'] then
| |
| for j, monsterID in ipairs(spAtt.monsters) do
| |
| local monster = Monsters.getMonsterByID(monsterID)
| |
| local overrideChance = (monster.overrideSpecialChances ~= nil and Shared.tableCount(monster.overrideSpecialChances) > 0)
| |
| local attChance = spAtt.defaultChance
| |
| if overrideChance then
| |
| local attIdx = nil
| |
| for k, monsterAttack in ipairs(monster.specialAttacks) do
| |
| local attID = (type(monsterAttack) == 'table' and monsterAttack.id) or monsterAttack
| |
| if spAtt.id == attID then
| |
| attIdx = k
| |
| break
| |
| end
| |
| end
| |
| if attIdx ~= nil then
| |
| attChance = monster.overrideSpecialChances[attIdx]
| |
| end
| |
| end
| |
|
| |
| table.insert(spAttTable, { idx = i, source = 'Monster', sourceSort = monster.name, sourceText = Icons.Icon({ monster.name, type = 'monster' }), chance = attChance, descType = 'monster' })
| |
| end
| |
| end
| |
|
| |
| -- Items/Weapons
| |
| if includeCat['Item'] then
| |
| for j, itemID in ipairs(spAtt.items) do
| |
| 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' })
| |
| end
| |
| end
| |
|
| |
| -- Spells
| |
| if includeCat['Spell'] then
| |
| for j, spellID in ipairs(spAtt.spells) do
| |
| 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' })
| |
| end
| |
| end
| |
| end
| |
|
| |
| -- 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
| |
| if includeCat['Familiar'] then
| |
| local famIdx = Shared.tableCount(attacks) + 1
| |
| local familiars = Items.getItems(function(item)
| |
| 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 } } }
| |
| if effectDefn == nil then
| |
| return Shared.tableCount(Attacks.getAttackEffects(famAttack)) > 0
| |
| else
| |
| return Attacks.attackHasEffect(famAttack, effectDefn)
| |
| end
| |
| end
| |
| return false
| |
| end)
| |
| for j, familiar in ipairs(familiars) do
| |
| -- For chance, assume the first modifier we come across has the chance, which is pretty lazy
| |
| local famChance, famDesc = 0, ''
| |
| for modName, modVal in pairs(familiar.modifiers) do
| |
| if type(modVal) == 'table' and type(modVal[1]) == 'number' then
| |
| famChance = modVal[1]
| |
| elseif type(modVal) == 'number' then
| |
| famChance = modVal
| |
| else
| |
| famChance = 0
| |
| end
| |
| famDesc = Constants._getModifierText(modName, modVal, false)
| |
| break
| |
| end
| |
|
| |
| 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
| |
| attacks[famIdx] = { name = familiar.name .. ' (Familiar)', description = { player = famDesc } }
| |
| famIdx = famIdx + 1
| |
| end
| |
| end
| |
|
| |
| -- Nothing to output if there are no row definitions
| |
| if Shared.tableCount(spAttTable) == 0 then
| |
| return ''
| |
| end
| |
|
| |
| -- 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.)
| |
| table.sort(spAttTable, function (a, b)
| |
| local sortKeys = { 'idx', 'descType', 'chance', 'source', 'sourceSort' }
| |
| for i, key in ipairs(sortKeys) do
| |
| if a[key] ~= b[key] then
| |
| return a[key] < b[key]
| |
| end
| |
| end
| |
| return false
| |
| end)
| |
| -- Determine row counts for grouping/rowspans
| |
| local rowCounts = {}
| |
| for i, rowDefn in ipairs(spAttTable) do
| |
| local idx, dt, chance = rowDefn.idx, rowDefn.descType, rowDefn.chance
| |
| if rowCounts[idx] == nil then
| |
| rowCounts[idx] = { rows = 0 }
| |
| end
| |
| if rowCounts[idx][dt] == nil then
| |
| rowCounts[idx][dt] = { rows = 0 }
| |
| end
| |
| if rowCounts[idx][dt][chance] == nil then
| |
| rowCounts[idx][dt][chance] = 0
| |
| end
| |
| rowCounts[idx]['rows'] = rowCounts[idx]['rows'] + 1
| |
| rowCounts[idx][dt]['rows'] = rowCounts[idx][dt]['rows'] + 1
| |
| rowCounts[idx][dt][chance] = rowCounts[idx][dt][chance] + 1
| |
| end
| |
|
| |
| -- Generate output table
| |
| local resultPart = {}
| |
| table.insert(resultPart, '{|class="wikitable sortable stickyHeader"')
| |
| 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')
| |
|
| |
| local firstRow = { idx = true, descType = true, chance = true }
| |
| local prevRowVal = { idx = 0, descType = '', chance = 0 }
| |
| local resetOnChange = {
| |
| idx = { 'idx', 'descType', 'chance' },
| |
| descType = { 'descType', 'chance' },
| |
| chance = { 'chance' }
| |
| }
| |
| local rowSuffix = ''
| |
| for i, spAttRow in ipairs(spAttTable) do
| |
| local spIdx = spAttRow.idx
| |
| local spAtt = attacks[spIdx]
| |
| -- Determine if it's the first row for any of our groupings
| |
| local resetKeys = {}
| |
| for key, val in pairs(prevRowVal) do
| |
| if spAttRow[key] ~= prevRowVal[key] then
| |
| for j, keyName in ipairs(resetOnChange[key]) do
| |
| resetKeys[keyName] = true
| |
| end
| |
| end
| |
| prevRowVal[key] = spAttRow[key]
| |
| end
| |
| for key, val in pairs(firstRow) do
| |
| firstRow[key] = (resetKeys[key] ~= nil)
| |
| end
| |
|
| |
| table.insert(resultPart, '\r\n|-')
| |
| if firstRow.idx then
| |
| rowSuffix = (rowCounts[spIdx]['rows'] > 1 and '|rowspan="' .. rowCounts[spIdx]['rows'] .. '"') or ''
| |
| table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt.name)
| |
| end
| |
| table.insert(resultPart, '\r\n|data-sort-value="' .. spAttRow.sourceSort .. '"| ' .. spAttRow.sourceText)
| |
| if includeSource then
| |
| table.insert(resultPart, '\r\n| ' .. spAttRow.source)
| |
| end
| |
| if firstRow.chance then
| |
| 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) .. '%')
| |
| end
| |
| if firstRow.descType then
| |
| rowSuffix = (rowCounts[spIdx][spAttRow.descType]['rows'] > 1 and '|rowspan="' .. rowCounts[spIdx][spAttRow.descType]['rows'] .. '"') or ''
| |
| table.insert(resultPart, '\r\n' .. rowSuffix .. '| ' .. spAtt['description'][spAttRow.descType])
| |
| end
| |
| end
| |
| table.insert(resultPart, '\r\n|}')
| |
|
| |
| return table.concat(resultPart)
| |
| end
| |
|
| |
| function p.getSpecialAttackTable(frame)
| |
| local args = frame.args ~= nil and frame.args or frame
| |
| local tableCategories = {'Monster', 'Item', 'Spell', 'Familiar'}
| |
| if args[1] ~= nil and args[1] ~= '' then
| |
| tableCategories = Shared.splitString(args[1], ',')
| |
| end
| |
| local effectName = args['effect']
| |
| local sourceHeaderLabel = args['sourceHeader'] or 'Source'
| |
| local includeSource = true
| |
| if args['includeSource'] ~= nil and string.lower(args['includeSource']) == 'false' then
| |
| includeSource = false
| |
| end
| |
| local effectDefn = nil
| |
|
| |
| if effectName ~= nil and effectName ~= '' then
| |
| effectDefn = Attacks.effectDefinition[effectName]
| |
| if effectDefn == nil then
| |
| local validEffectNames = {}
| |
| for k, v in pairs(Attacks.effectDefinition) do
| |
| table.insert(validEffectNames, k)
| |
| 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]]'
| |
| end
| |
| end
| |
|
| |
| return p._getSpecialAttackTable(effectDefn, tableCategories, sourceHeaderLabel, includeSource)
| |
| end
| |
|
| |
| return p
| |