Anonymous

Module:Attacks: Difference between revisions

From Melvor Idle
Use tabs instead of spaces for indentation
(Implement support for multiple definitions per effect)
(Use tabs instead of spaces for indentation)
Line 8: Line 8:


p.effectDefinition = {
p.effectDefinition = {
    ["Burn"] = {
["Burn"] = {
        {
{
            ["type"] = 'DOT',
["type"] = 'DOT',
            ["subtype"] = 'Burn'
["subtype"] = 'Burn'
        },
},
        -- Alternative definition specifically for familiars like Dragon
-- Alternative definition specifically for familiars like Dragon
        {
{
            ["type"] = 'Modifier',
["type"] = 'Modifier',
            ["subtype"] = 'Familiar',
["subtype"] = 'Familiar',
            ["modifiers"] = {
["modifiers"] = {
                ["include"] = { 'increasedChanceToApplyBurn' }
["include"] = { 'increasedChanceToApplyBurn' }
            }
}
        }
}
    },
},
    ["Poison"] = {
["Poison"] = {
        ["type"] = 'DOT',
["type"] = 'DOT',
        ["subtype"] = 'Poison'
["subtype"] = 'Poison'
    },
},
    ["Slow"] = {
["Slow"] = {
        ["type"] = 'Modifier',
["type"] = 'Modifier',
        ["modifiers"] = {
["modifiers"] = {
            ["include"] = { 'increasedAttackIntervalPercent' },
["include"] = { 'increasedAttackIntervalPercent' },
            ["exclude"] = { 'increasedFrostburn' }
["exclude"] = { 'increasedFrostburn' }
        }
}
    },
},
    ["Bleed"] = {
["Bleed"] = {
        ["type"] = 'DOT',
["type"] = 'DOT',
        ["subtype"] = 'Bleed'
["subtype"] = 'Bleed'
    },
},
    ["Frostburn"] = {
["Frostburn"] = {
        ["type"] = 'Modifier',
["type"] = 'Modifier',
        ["modifiers"] = {
["modifiers"] = {
            ["include"] = { 'increasedFrostburn', 'increasedAttackIntervalPercent' }
["include"] = { 'increasedFrostburn', 'increasedAttackIntervalPercent' }
        }
}
    },
},
    ["Mark of Death"] = {
["Mark of Death"] = {
        ["type"] = 'Stacking',
["type"] = 'Stacking',
        ["modifiers"] = {
["modifiers"] = {
            ["include"] = { 'decreasedDamageReductionPercent' }
["include"] = { 'decreasedDamageReductionPercent' }
        }
}
    },
},
    ["Affliction"] = {
["Affliction"] = {
        ["type"] = 'Modifier',
["type"] = 'Modifier',
        ["modifiers"] = {
["modifiers"] = {
            ["include"] = { 'decreasedMaxHitpoints' }
["include"] = { 'decreasedMaxHitpoints' }
        }
}
    },
},
    ["Sleep"] = {
["Sleep"] = {
        ["type"] = 'Sleep'
["type"] = 'Sleep'
    },
},
    ["Freeze"] = {
["Freeze"] = {
        ["type"] = 'Stun',
["type"] = 'Stun',
        ["flavour"] = 'Freeze'
["flavour"] = 'Freeze'
    },
},
    ["Stun"] = {
["Stun"] = {
        ["type"] = 'Stun',
["type"] = 'Stun',
        ["flavour"] = 'Stun'
["flavour"] = 'Stun'
    },
},
    ["Regen"] = {
["Regen"] = {
        ["type"] = 'DOT',
["type"] = 'DOT',
        ["subtype"] = 'Regen'
["subtype"] = 'Regen'
    }
}
}
}


function p.getAttackByID(ID)
function p.getAttackByID(ID)
    return AttackData.Attacks[ID + 1]
return AttackData.Attacks[ID + 1]
end
end


function p.getAttack(name)
function p.getAttack(name)
    name = string.gsub(name, "%%27", "'")
name = string.gsub(name, "%%27", "'")
    name = string.gsub(name, "'", "'")
name = string.gsub(name, "'", "'")
    name = string.gsub(name, "'", "'")
name = string.gsub(name, "'", "'")
    for i, attack in ipairs(AttackData.Attacks) do
for i, attack in ipairs(AttackData.Attacks) do
        if name == attack.name then
if name == attack.name then
            return attack
return attack
        end
end
    end
end
end
end


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


function p.getAttackEffects(attack)
function p.getAttackEffects(attack)
    local attackEffects = {}
local attackEffects = {}
    for effectName, effectDefn in pairs(p.effectDefinition) do
for effectName, effectDefn in pairs(p.effectDefinition) do
        if p.attackHasEffect(attack, effectDefn) then
if p.attackHasEffect(attack, effectDefn) then
            table.insert(attackEffects, effectName)
table.insert(attackEffects, effectName)
        end
end
    end
end
    return attackEffects
return attackEffects
end
end


-- Determines if attack applies the effect defined in effectDefinition
-- Determines if attack applies the effect defined in effectDefinition
function p.attackHasEffect(attack, effectDefn)
function p.attackHasEffect(attack, effectDefn)
    if type(attack) == 'table' and type(effectDefn) == 'table' then
if type(attack) == 'table' and type(effectDefn) == 'table' then
        -- Process pre-hit effects
-- Process pre-hit effects
        for i, effect in ipairs(attack.prehitEffects) do
for i, effect in ipairs(attack.prehitEffects) do
            if p.effectMatchesDefn(effect, effectDefn) then
if p.effectMatchesDefn(effect, effectDefn) then
                return true
return true
            end
end
        end
end
        -- Process on hit effects
-- Process on hit effects
        for i, effect in ipairs(attack.onhitEffects) do
for i, effect in ipairs(attack.onhitEffects) do
            if p.effectMatchesDefn(effect, effectDefn) then
if p.effectMatchesDefn(effect, effectDefn) then
                return true
return true
            end
end
        end
end
    end
end
    return false
return false
end
end


function p.effectMatchesDefn(effect, effectDefnIn)
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
local effectDefnList = nil
    if effectDefnIn[1] ~= nil and type(effectDefnIn[1]) == 'table' then
if type(effectDefnIn[1]) == 'table' then
        -- Definition is actually multiple definitions
-- Definition is actually multiple definitions
        effectDefnList = effectDefnIn
effectDefnList = effectDefnIn
    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 }
effectDefnList = { effectDefnIn }
    end
end


    for i, effectDefn in pairs(effectDefnList) do
for i, effectDefn in pairs(effectDefnList) do
        if p.effectMatchesDefnSingle(effect, effectDefn) then
if p.effectMatchesDefnSingle(effect, effectDefn) then
            return true
return true
        end
end
    end
end
    return false
return false
end
end


function p.effectMatchesDefnSingle(effect, effectDefn)
function p.effectMatchesDefnSingle(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
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))
          or (effectDefn.flavour ~= nil and (effect.flavour == nil or effect.flavour ~= effectDefn.flavour)) then
or (effectDefn.flavour ~= nil and (effect.flavour == nil or effect.flavour ~= effectDefn.flavour)) then
        -- Effect's subtype or flavour doesn't match that of the effect definition
-- Effect's subtype or flavour doesn't match that of the effect definition
        return false
return false
    elseif type(effectDefn.modifiers) == 'table' and (effectDefn.modifiers.include ~= nil or effectDefn.modifiers.exclude ~= nil) then
elseif type(effectDefn.modifiers) == 'table' and (effectDefn.modifiers.include ~= nil or effectDefn.modifiers.exclude ~= nil) then
        -- Definition contains modifiers which need to be checked
-- Definition contains modifiers which need to be checked
        local modsIncl, modsExcl = (effectDefn.modifiers.include or {}), (effectDefn.modifiers.exclude or {})
local modsIncl, modsExcl = (effectDefn.modifiers.include or {}), (effectDefn.modifiers.exclude or {})
        local modsInclFound = {}
local modsInclFound = {}
        if Shared.tableCount(modsIncl) > 0 and (type(effect.modifiers) ~= 'table' or Shared.tableCount(effect.modifiers) < Shared.tableCount(modsIncl)) then
if Shared.tableCount(modsIncl) > 0 and (type(effect.modifiers) ~= 'table' or Shared.tableCount(effect.modifiers) < Shared.tableCount(modsIncl)) then
            -- Definition has 1+ included modifiers but effect has fewer modifiers than the definition
-- Definition has 1+ included modifiers but effect has fewer modifiers than the definition
            return false
return false
        end
end


        for modName, modVal in pairs(effect.modifiers) do
for modName, modVal in pairs(effect.modifiers) do
            if Shared.contains(modsExcl, modName, false) then
if Shared.contains(modsExcl, modName, false) then
                -- Effect contains a modifier on the exclusion list
-- Effect contains a modifier on the exclusion list
                return false
return false
            elseif Shared.contains(modsIncl, modName, false) then
elseif Shared.contains(modsIncl, modName, false) then
                -- Flag included modifier as found
-- Flag included modifier as found
                modsInclFound[modName] = true
modsInclFound[modName] = true
            end
end
        end
end
        if Shared.tableCount(modsInclFound) < Shared.tableCount(modsIncl) then
if Shared.tableCount(modsInclFound) < Shared.tableCount(modsIncl) then
            -- Effect doesn't have all of the included modifiers
-- Effect doesn't have all of the included modifiers
            return false
return false
        end
end
    end
end
    return true
return true
end
end


return p
return p