2,869
edits
(Fix for unknown items) |
No edit summary |
||
(9 intermediate revisions by one other user not shown) | |||
Line 3: | Line 3: | ||
local Constants = require('Module:Constants') | local Constants = require('Module:Constants') | ||
local Shared = require('Module:Shared') | local Shared = require('Module:Shared') | ||
local GameData = require('Module:GameData') | |||
local Icons = require('Module:Icons') | local Icons = require('Module:Icons') | ||
local Items = require('Module:Items') | local Items = require('Module:Items') | ||
local Attacks = require('Module:Attacks') | local Attacks = require('Module:Attacks') | ||
local Num = require('Module:Number') | |||
function p._getSpecialAttackTable(effectDefn, categories, sourceHeaderLabel, includeSource) | function p._getSpecialAttackTable(effectDefn, categories, sourceHeaderLabel, includeSource) | ||
-- TODO needs fixing for V1.3 | |||
-- Is going to be incredibly broken following combat effects & modifiers overhaul | |||
return '' | |||
--[==[ | |||
local spAttTable = {} | local spAttTable = {} | ||
local attacks = Attacks.getAttacks(function(attack) | local attacks = Attacks.getAttacks(function(attack) | ||
Line 22: | Line 27: | ||
includeCat[category] = true | includeCat[category] = true | ||
end | end | ||
-- Build index so we can tell which to include later | |||
local includedAttacks = {} | |||
for i, attack in ipairs(attacks) do | |||
includedAttacks[attack.id] = true | |||
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 | ||
-- Monsters | |||
if includeCat['Monster'] then | |||
for i, monster in ipairs(GameData.rawData.monsters) do | |||
if monster.specialAttacks ~= nil and not Shared.tableIsEmpty(monster.specialAttacks) then | |||
local overrideChance = (monster.overrideSpecialChances ~= nil and not Shared.tableIsEmpty(monster.overrideSpecialChances)) | |||
for j, spAttID in ipairs(monster.specialAttacks) do | |||
if includedAttacks[spAttID] then | |||
local spAtt = GameData.getEntityByID('attacks', spAttID) | |||
if spAtt ~= nil then | |||
local attChance = (overrideChance and monster.overrideSpecialChances[j]) or spAtt.defaultChance | |||
table.insert(spAttTable, { id = spAttID, source = 'Monster', sourceSort = monster.name, sourceText = Icons.Icon({ monster.name, type = 'monster' }), chance = attChance, descType = 'monster' }) | |||
end | |||
end | |||
end | |||
end | |||
end | |||
end | |||
-- Items/Weapons | |||
if includeCat['Item'] then | |||
for i, item in ipairs(GameData.rawData.items) do | |||
if item.specialAttacks ~= nil and not item.golbinRaidExclusive and not Shared.tableIsEmpty(item.specialAttacks) then | |||
local overrideChance = (item.overrideSpecialChances ~= nil and not Shared.tableIsEmpty(item.overrideSpecialChances)) | |||
for j, spAttID in ipairs(item.specialAttacks) do | |||
if includedAttacks[spAttID] then | |||
local spAtt = GameData.getEntityByID('attacks', spAttID) | |||
if spAtt ~= nil then | |||
local attChance = (overrideChance and item.overrideSpecialChances[j]) or spAtt.defaultChance | |||
table.insert(spAttTable, { id = spAttID, source = 'Weapon', sourceSort = item.name, sourceText = Icons.Icon({ item.name, type = 'item' }), chance = attChance, descType = 'player' }) | |||
end | |||
end | |||
end | |||
end | |||
end | |||
end | |||
-- Spells | |||
if includeCat['Spell'] then | |||
local spellCats = { 'ancientSpells', 'archaicSpells' } | |||
for i, spellCat in ipairs(spellCats) do | |||
for j, spell in ipairs(GameData.rawData[spellCat]) do | |||
local spAttID = spell.specialAttack or spell.specialAttackID | |||
if spAttID ~= nil and includedAttacks[spAttID] then | |||
local spAtt = GameData.getEntityByID('attacks', spAttID) | |||
if spAtt ~= nil then | |||
table.insert(spAttTable, {id = spAtt.id, source = 'Spell', sourceSort = spell.name, sourceText = Icons.Icon({ spell.name, type = 'spell' }), chance = spAtt.defaultChance, descType = 'player' }) | |||
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 | -- attacks, therefore the handling here is a bit different | ||
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 item.modifiers ~= nil and Items._getItemStat(item, 'summoningMaxhit') ~= nil then | |||
local famAttack = { prehitEffects = {}, onhitEffects = { { type = 'Modifier', subtype = 'Familiar', modifiers = item.modifiers } } } | |||
if effectDefn == nil then | |||
return Shared.tableIsEmpty(Attacks.getAttackEffects(famAttack)) | |||
else | |||
return Attacks.attackHasEffect(famAttack, effectDefn) | |||
end | |||
end | |||
return false | |||
for | end) | ||
for i, 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, '' | ||
Line 98: | Line 118: | ||
end | end | ||
table.insert(spAttTable, { | table.insert(spAttTable, { id = familiar.id, 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 | attacks[famIdx] = { id = familiar.id, name = familiar.name .. ' (Familiar)', description = famDesc } | ||
famIdx = famIdx + 1 | famIdx = famIdx + 1 | ||
end | end | ||
Line 106: | Line 126: | ||
-- Nothing to output if there are no row definitions | -- Nothing to output if there are no row definitions | ||
if Shared. | if Shared.tableIsEmpty(spAttTable) then | ||
return '' | return '' | ||
end | end | ||
Line 113: | Line 133: | ||
-- 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 = { ' | local sortKeys = { 'id', '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 | ||
Line 124: | Line 144: | ||
local rowCounts = {} | local rowCounts = {} | ||
for i, rowDefn in ipairs(spAttTable) do | for i, rowDefn in ipairs(spAttTable) do | ||
local | local id, dt, chance = rowDefn.id, rowDefn.descType, rowDefn.chance | ||
if rowCounts[ | if rowCounts[id] == nil then | ||
rowCounts[ | rowCounts[id] = { rows = 0 } | ||
end | end | ||
if rowCounts[ | if rowCounts[id][dt] == nil then | ||
rowCounts[ | rowCounts[id][dt] = { rows = 0 } | ||
end | end | ||
if rowCounts[ | if rowCounts[id][dt][chance] == nil then | ||
rowCounts[ | rowCounts[id][dt][chance] = 0 | ||
end | end | ||
rowCounts[ | rowCounts[id]['rows'] = rowCounts[id]['rows'] + 1 | ||
rowCounts[ | rowCounts[id][dt]['rows'] = rowCounts[id][dt]['rows'] + 1 | ||
rowCounts[ | rowCounts[id][dt][chance] = rowCounts[id][dt][chance] + 1 | ||
end | end | ||
Line 145: | Line 165: | ||
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 = { | local firstRow = { id = true, descType = true, chance = true } | ||
local prevRowVal = { | local prevRowVal = { id = 0, descType = '', chance = 0 } | ||
local resetOnChange = { | local resetOnChange = { | ||
id = { 'id', 'descType', 'chance' }, | |||
descType = { 'descType', 'chance' }, | descType = { 'descType', 'chance' }, | ||
chance = { 'chance' } | chance = { 'chance' } | ||
Line 154: | Line 174: | ||
local rowSuffix = '' | local rowSuffix = '' | ||
for i, spAttRow in ipairs(spAttTable) do | for i, spAttRow in ipairs(spAttTable) do | ||
local spIdx = spAttRow. | local spIdx = spAttRow.id | ||
local spAtt = attacks | local spAtt = GameData.getEntityByID(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 = {} | ||
Line 171: | Line 191: | ||
table.insert(resultPart, '\r\n|-') | table.insert(resultPart, '\r\n|-') | ||
if firstRow. | if firstRow.id 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) | ||
Line 181: | Line 201: | ||
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;"| ' .. | table.insert(resultPart, '\r\n|' .. rowSuffix .. 'data-sort-value="' .. spAttRow.chance .. '" style="text-align:right;"| ' .. Num.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 | local spAttDesc = spAtt.description | ||
--Adding the time between hits and total duration 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 | ||
Line 191: | Line 211: | ||
spAttDesc = spAttDesc..'<br/>(' | spAttDesc = spAttDesc..'<br/>(' | ||
local spAttDuration = spAttInterval * (spAtt.attackCount - 1) | local spAttDuration = spAttInterval * (spAtt.attackCount - 1) | ||
spAttDesc = spAttDesc.. | spAttDesc = spAttDesc..Num.round(spAttInterval / 1000, 2, 2)..'s delay between attacks.' | ||
if spAtt.attackCount ~= nil and spAtt.attackCount > 2 then | if spAtt.attackCount ~= nil and spAtt.attackCount > 2 then | ||
spAttDesc = spAttDesc..' '.. | spAttDesc = spAttDesc..' '..Num.round(spAttDuration / 1000, 2, 2)..'s total duration' | ||
end | end | ||
spAttDesc = spAttDesc..')' | spAttDesc = spAttDesc..')' | ||
Line 203: | Line 223: | ||
return table.concat(resultPart) | return table.concat(resultPart) | ||
--]==] | |||
end | end | ||
Line 228: | Line 249: | ||
table.sort(validEffectNames, function(a, b) return a < b end) | table.sort(validEffectNames, function(a, b) return a < b end) | ||
return ' | return Shared.printError('Invalid effect name "' .. effectName .. '", must be one of: ' .. table.concat(validEffectNames, ', ')) | ||
end | end | ||
end | end | ||
Line 237: | Line 258: | ||
-- Generates a table showing the damage/DR multipliers for each combat triangle | -- Generates a table showing the damage/DR multipliers for each combat triangle | ||
function p.getCombatTriangleTable() | function p.getCombatTriangleTable() | ||
local triangleAttributes = { | -- TODO needs fixing for V1.3 | ||
return '' | |||
--[==[local triangleAttributes = { | |||
{ | { | ||
["name"] = 'damageModifier', | ["name"] = 'damageModifier', | ||
Line 258: | Line 281: | ||
} | } | ||
local gameMode = { | local gameMode = { | ||
{ 'Standard', 'Standard' }, | { 'Standard Mode', 'Standard' }, | ||
{ 'Hardcore', Icons.Icon({ 'Hardcore' }) } | { 'Hardcore Mode', Icons.Icon({ 'Hardcore' }) } | ||
} | } | ||
local attrCount = Shared.tableCount(triangleAttributes) | local attrCount = Shared.tableCount(triangleAttributes) | ||
Line 307: | Line 330: | ||
table.insert(resultPart, '\r\n|}') | table.insert(resultPart, '\r\n|}') | ||
return table.concat(resultPart) | return table.concat(resultPart) | ||
--]==] | |||
end | end | ||
return p | return p |
edits