Module:Attacks: Difference between revisions

Support Lifesteal
(Use tabs instead of spaces for indentation)
(Support Lifesteal)
 
(7 intermediate revisions by the same user not shown)
Line 3: Line 3:
local p = {}
local p = {}


local AttackData = mw.loadData('Module:Attacks/data')
local GameData = require('Module:GameData')
 
local Shared = require('Module:Shared')
local Shared = require('Module:Shared')


Line 10: Line 9:
["Burn"] = {
["Burn"] = {
{
{
["type"] = 'DOT',
["effectType"] = 'Burn'
["subtype"] = 'Burn'
},
},
-- Alternative definition specifically for familiars like Dragon
-- Alternative definition specifically for familiars like Dragon
Line 23: Line 21:
},
},
["Poison"] = {
["Poison"] = {
["type"] = 'DOT',
["effectType"] = 'Poison'
["subtype"] = 'Poison'
},
["Deadly Poison"] = {
["effectType"] = 'DeadlyPoison'
},
},
["Slow"] = {
["Slow"] = {
Line 38: Line 38:
},
},
["Frostburn"] = {
["Frostburn"] = {
["type"] = 'Modifier',
["effectType"] = 'Frostburn'
["modifiers"] = {
["include"] = { 'increasedFrostburn', 'increasedAttackIntervalPercent' }
}
},
},
["Mark of Death"] = {
["Mark of Death"] = {
Line 50: Line 47:
},
},
["Affliction"] = {
["Affliction"] = {
["type"] = 'Modifier',
{ ["effectType"] = 'Affliction' },
["modifiers"] = {
{
["include"] = { 'decreasedMaxHitpoints' }
["type"] = 'Modifier',
["modifiers"] = {
["include"] = { 'increasedAfflictionChance' }
}
}
}
},
},
["Sleep"] = {
["Sleep"] = {
["type"] = 'Sleep'
{
["type"] = 'Sleep'
},
-- Alternative definition specifically for familiars like Siren
{
["type"] = 'Modifier',
["subtype"] = 'Familiar',
["modifiers"] = {
["include"] = { 'increasedGlobalSleepChance' }
}
}
},
["Slow"] = {
["effectType"] = 'Slow'
},
},
["Freeze"] = {
["Freeze"] = {
Line 69: Line 82:
["type"] = 'DOT',
["type"] = 'DOT',
["subtype"] = 'Regen'
["subtype"] = 'Regen'
},
["Lifesteal"] = {
["attFunc"] = function(attack)
return type(attack.lifesteal) == 'number' and attack.lifesteal > 0
end
}
}
-- TODO Implement curses
}
}


function p.getAttackByID(ID)
function p.getAttackByID(ID)
return AttackData.Attacks[ID + 1]
    return GameData.getEntityByID('attacks', ID)
end
end


Line 80: Line 99:
name = string.gsub(name, "'", "'")
name = string.gsub(name, "'", "'")
name = string.gsub(name, "'", "'")
name = string.gsub(name, "'", "'")
for i, attack in ipairs(AttackData.Attacks) do
    return GameData.getEntityByName('attacks', name)
if name == attack.name then
return attack
end
end
end
end


function p.getAttacks(checkFunc)
function p.getAttacks(checkFunc)
local result = {}
    return GameData.getEntities('attacks', checkFunc)
for i, attack in ipairs(AttackData.Attacks) do
if checkFunc(attack) then
table.insert(result, attack)
end
end
return result
end
end


Line 107: Line 116:
end
end


-- Determines if attack applies the effect defined in effectDefinition
-- Convert effect definition into list of definitions to be checked
function p.attackHasEffect(attack, effectDefn)
function p.getEffectDefnList(effectDefn)
if type(attack) == 'table' and type(effectDefn) == 'table' then
-- Process pre-hit effects
for i, effect in ipairs(attack.prehitEffects) do
if p.effectMatchesDefn(effect, effectDefn) then
return true
end
end
-- Process on hit effects
for i, effect in ipairs(attack.onhitEffects) do
if p.effectMatchesDefn(effect, effectDefn) then
return true
end
end
end
return false
end
 
function p.effectMatchesDefn(effect, effectDefnIn)
-- Some effects (e.g. Burn) have multiple definitions, so handle these correctly
-- Some effects (e.g. Burn) have multiple definitions, so handle these correctly
local effectDefnList = nil
if type(effectDefn[1]) == 'table' then
if type(effectDefnIn[1]) == 'table' then
-- Definition is actually multiple definitions
-- Definition is actually multiple definitions
effectDefnList = effectDefnIn
return effectDefn
else
else
-- Definition is singular, wrap it within a table so we can iterate
-- Definition is singular, wrap it within a table so we can iterate
effectDefnList = { effectDefnIn }
return { effectDefn }
end
end
end


for i, effectDefn in pairs(effectDefnList) do
-- Determines if attack applies the effect defined in effectDefinition
if p.effectMatchesDefnSingle(effect, effectDefn) then
function p.attackHasEffect(attack, effectDefnRaw)
return true
if type(attack) == 'table' and type(effectDefnRaw) == 'table' then
local effectDefnList = p.getEffectDefnList(effectDefnRaw)
for i, effectDefn in pairs(effectDefnList) do
if effectDefn.attFunc ~= nil then
-- Attack level check, for effects like lifesteal
if effectDefn.attFunc(attack) then
return true
end
else
-- Process pre-hit effects
for i, effect in ipairs(attack.prehitEffects) do
if p.effectMatchesDefn(effect, effectDefn) then
return true
end
end
-- Process on hit effects
for i, effect in ipairs(attack.onhitEffects) do
if p.effectMatchesDefn(effect, effectDefn) then
return true
end
end
end
end
end
end
end
Line 145: Line 157:
end
end


function p.effectMatchesDefnSingle(effect, effectDefn)
function p.effectMatchesDefn(effect, effectDefn)
if effectDefn.type ~= effect.type then
if effectDefn.type ~= effect.type then
-- Effect's type doesn't match that of the effect definition
-- Effect's type doesn't match that of the effect definition
return false
elseif (effectDefn.effectType ~= nil and (effect.effectType == nil or effect.effectType ~= effectDefn.effectType)) then
return false
return false
elseif (effectDefn.subtype ~= nil and (effect.subtype == nil or effect.subtype ~= effectDefn.subtype))
elseif (effectDefn.subtype ~= nil and (effect.subtype == nil or effect.subtype ~= effectDefn.subtype))