• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 0.X Is it possible to change things on receive damage in LUA?

runsicky

Member
Joined
Apr 19, 2018
Messages
80
Reaction score
12
It is possible to change attack formula in weapons, like i did on this example:

Code:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_BLOCKARMOR, 1)
setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE)

function onGetFormulaValues(cid, level, skill, attack, factor)
    -- get attack mode
    local damagebase_min = wbdmg_melee_min
    local damagebase_max = wbdmg_melee_min
    min = ((damagebase_min) * (attack * 12) * (skill * 3)) * -0.10
    max = ((damagebase_max) * (attack * 12) * (skill * 3)) * -1.00
    return min, max
end
setCombatCallback(combat, CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")

function onUseWeapon(cid, var)
    return doCombat(cid, combat, var)
end

But what about defense?
Is it possible to change things on receive damage in LUA?


I mean, something like:
reduce death/fire/ice/energy/holy damage depending if player got a storage X
also reflect some dmg % if player got a storage Y
dont recive any dmg if player got a storage Z
paralyze who attacks the player if player got the storage C
 
I'm on the right way?

Code:
function onStatsChange(cid, attacker, enps, combatee, value)

-- how to get fire dmg?
if getPlayerStorageValue(cid, 1000) > 0 then
    doSendAnimatedText(getThingPos(cid), "FIRE PROTECT!", TEXTCOLOR_WHITE)
    local elementaldmg = ?
    value = value - elementaldmg
end
-- how to get death dmg?
if getPlayerStorageValue(cid, 1001) > 0 then
    doSendAnimatedText(getThingPos(cid), "DEATH PROTECT!", TEXTCOLOR_WHITE)
    local elementaldmg = ?
    value = value - elementaldmg
end
-- how to get ice dmg?
if getPlayerStorageValue(cid, 1002) > 0 then
    doSendAnimatedText(getThingPos(cid), "ICE PROTECT!", TEXTCOLOR_WHITE)
    local elementaldmg = ?
    value = value - elementaldmg
end
-- how to get energy dmg?
if getPlayerStorageValue(cid, 1003) > 0 then
    doSendAnimatedText(getThingPos(cid), "ENERGY PROTECT!", TEXTCOLOR_WHITE)
    local elementaldmg = ?
    value = value - elementaldmg
end
-- how to get holy dmg?
if getPlayerStorageValue(cid, 1004) > 0 then
    doSendAnimatedText(getThingPos(cid), "HOLY PROTECT!", TEXTCOLOR_WHITE)
    local elementaldmg = ?
    value = value - elementaldmg
end
-- reflect
if getPlayerStorageValue(cid, 1005) > 0 then
    if attacker == nil then return TRUE end
    doSendAnimatedText(getThingPos(cid), "REFLECT PROTECT!", TEXTCOLOR_WHITE)
    set attacker health -= value ?
end
-- dodge
if getPlayerStorageValue(cid, 1006) > 0 then
    doSendAnimatedText(getThingPos(cid), "DODGE PROTECT!", TEXTCOLOR_WHITE)
    value = 0
end
-- paralyze who attacks
if getPlayerStorageValue(cid, 1007) > 0 then
    if attacker == nil then return TRUE end
    doSendAnimatedText(getThingPos(cid), "PARALYZE PROTECT!", TEXTCOLOR_WHITE)
    if not getCreatureCondition(attacker, CONDITION_PARALYZE) then
        local condition = createConditionObject(CONDITION_PARALYZE)
        setConditionParam(condition, CONDITION_PARAM_TICKS, 1000)
        setConditionFormula(condition, -0.5, 0, -0.5, 0)
        doAddCondition(attacker, condition)
    end
end


return TRUE
end

Could you help me to
detect the elementals dmgs?
local elementaldmg = ?

and

set attacker health -= value ?
 
I believe you use

Code:
combat.type

ex.
if combat.type == COMBAT_FIREDAMAGE then
    do stuff
end

Code:
[21:39:17.300] [Error - CreatureScript Interface] 
[21:39:17.300] data/creaturescripts/scripts/charm_bestiary.lua:onStatsChange
[21:39:17.300] Description: 
[21:39:17.300] data/creaturescripts/scripts/charm_bestiary.lua:33: attempt to index global 'combat' (a nil value)
[21:39:17.300] stack traceback:
[21:39:17.300]     data/creaturescripts/scripts/charm_bestiary.lua:33: in function <data/creaturescripts/scripts/charm_bestiary.lua:1>


Code:
[21:39:17.300] [Error - CreatureScript Interface] 

[21:39:17.300] data/creaturescripts/scripts/test.lua:onStatsChange

[21:39:17.300] Description: 

[21:39:17.300] data/creaturescripts/scripts/test.lua:33: attempt to index global 'combat' (a nil value)

[21:39:17.300] stack traceback:

[21:39:17.300]     data/creaturescripts/scripts/test.lua:33: in function <data/creaturescripts/scripts/test.lua:1>

Code:
function onStatsChange(cid, attacker, enps, combatee, value)
    if getPlayerStorageValue(cid, 1000) > 0 then
        if combat.type == COMBAT_FIREDAMAGE then
            doSendAnimatedText(getThingPos(cid), "FIRE PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1001) > 0 then
        if combat.type == COMBAT_DEATHDAMAGE then
            doSendAnimatedText(getThingPos(cid), "DEATH PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1002) > 0 then
        if combat.type == COMBAT_ICEDAMAGE then
            doSendAnimatedText(getThingPos(cid), "ICE PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1003) > 0 then
        if combat.type == COMBAT_ENERGYDAMAGE then
            doSendAnimatedText(getThingPos(cid), "ENERGY PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1004) > 0 then
        if combat.type == COMBAT_HOLYDAMAGE then
            doSendAnimatedText(getThingPos(cid), "HOLY PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1005) > 0 then
        if combat.type == COMBAT_EARTHDAMAGE then
            doSendAnimatedText(getThingPos(cid), "EARTH PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    -- reflect
    if getPlayerStorageValue(cid, 1006) > 0 then
        if attacker == nil then return TRUE end
        doSendAnimatedText(getThingPos(cid), "REFLECT PROTECT!", TEXTCOLOR_WHITE)
        doCreatureAddHealth(cid, -(value))
    end
    -- dodge
    if getPlayerStorageValue(cid, 1007) > 0 then
        if combat.type == COMBAT_PHYSICALDAMAGE then
            doSendAnimatedText(getThingPos(cid), "DODGE PROTECT!", TEXTCOLOR_WHITE)
            value = 0
        end
    end
    -- paralyze who attacks
    if getPlayerStorageValue(cid, 1008) > 0 then
        if attacker == nil then return TRUE end
        doSendAnimatedText(getThingPos(cid), "PARALYZE PROTECT!", TEXTCOLOR_WHITE)
        if not getCreatureCondition(attacker, CONDITION_PARALYZE) then
            local condition = createConditionObject(CONDITION_PARALYZE)
            setConditionParam(condition, CONDITION_PARAM_TICKS, 1000)
            setConditionFormula(condition, -0.5, 0, -0.5, 0)
            doAddCondition(attacker, condition)
        end
    end

    return TRUE
end
 
It's just combat, nothing more, but you have the param named combatee for some reason.

i was think that was the normal, i got from a exemple on internet...

i change to combat,

Code:
function onStatsChange(cid, attacker, enps, combat, value)
    if getPlayerStorageValue(cid, 1000) > 0 then
        if combat.type == COMBAT_FIREDAMAGE then
            doSendAnimatedText(getThingPos(cid), "FIRE PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1001) > 0 then
        if combat.type == COMBAT_DEATHDAMAGE then
            doSendAnimatedText(getThingPos(cid), "DEATH PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1002) > 0 then
        if combat.type == COMBAT_ICEDAMAGE then
            doSendAnimatedText(getThingPos(cid), "ICE PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1003) > 0 then
        if combat.type == COMBAT_ENERGYDAMAGE then
            doSendAnimatedText(getThingPos(cid), "ENERGY PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1004) > 0 then
        if combat.type == COMBAT_HOLYDAMAGE then
            doSendAnimatedText(getThingPos(cid), "HOLY PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    if getPlayerStorageValue(cid, 1005) > 0 then
        if combat.type == COMBAT_EARTHDAMAGE then
            doSendAnimatedText(getThingPos(cid), "EARTH PROTECT!", TEXTCOLOR_WHITE)
            value = value / 2
        end
    end
    -- reflect
    if getPlayerStorageValue(cid, 1006) > 0 then
        if attacker == nil then return TRUE end
        doSendAnimatedText(getThingPos(cid), "REFLECT PROTECT!", TEXTCOLOR_WHITE)
        doCreatureAddHealth(cid, -(value))
    end
    -- dodge
    if getPlayerStorageValue(cid, 1007) > 0 then
        if combat.type == COMBAT_PHYSICALDAMAGE then
            doSendAnimatedText(getThingPos(cid), "DODGE PROTECT!", TEXTCOLOR_WHITE)
            value = 0
        end
    end
    -- paralyze who attacks
    if getPlayerStorageValue(cid, 1008) > 0 then
        if attacker == nil then return TRUE end
        doSendAnimatedText(getThingPos(cid), "PARALYZE PROTECT!", TEXTCOLOR_WHITE)
        if not getCreatureCondition(attacker, CONDITION_PARALYZE) then
            local condition = createConditionObject(CONDITION_PARALYZE)
            setConditionParam(condition, CONDITION_PARAM_TICKS, 1000)
            setConditionFormula(condition, -0.5, 0, -0.5, 0)
            doAddCondition(attacker, condition)
        end
    end

    return TRUE
end


Code:
[21:45:51.855] [Error - CreatureScript Interface] 
[21:45:51.856] data/creaturescripts/scripts/test.lua:onStatsChange
[21:45:51.856] Description: 
[21:45:51.856] data/creaturescripts/scripts/test.lua:33: attempt to index local 'combat' (a number value)
[21:45:51.856] stack traceback:
[21:45:51.856]     data/creaturescripts/scripts/test.lua:33: in function <data/creaturescripts/scripts/test.lua:1>
 
As I said, it's only combat, not combat.type, and you need to return false and add a storage to check for to avoid stack overflow. Here's an example:
Lua:
local avoidOverflowStorage = 77362

function onStatsChange(cid, attacker, type, combat, value)
    if getCreatureStorageValue(cid, avoidOverflowStorage) == 1 then
        doCreatureSetStorageValue(cid, avoidOverflowStorage, -1)
        return true
    end
    if combat == COMBAT_FIREDAMAGE then
        doCreatureSetStorageValue(cid, avoidOverflowStorage, 1)
        doCreatureAddHealth(cid, -value)
        return false
    end
    return true
end
 
Code:
local combatTypes = {
    [1] = {storage = 1000, type = COMBAT_FIREDAMAGE, text = "Fire Protect"},
    [2] = {storage = 1001, type = COMBAT_DEATHDAMAGE, text = "Death Protect"},
    [3] = {storage = 1002, type = COMBAT_ICEDAMAGE, text = "Ice Protect"},
    [4] = {storage = 1003, type = COMBAT_ENERGYDAMAGE, text = "Energy Protect"},
    [5] = {storage = 1004, type = COMBAT_HOLYDAMAGE, text = "Holy Protect"},
    [6] = {storage = 1005, type = COMBAT_EARTHDAMAGE, text = "Earth Protect"}

}

function onStatsChange(cid, attacker, type, combat, value)
    if isPlayer(cid) then
        -- Handle all of the protections at once in a loop for efficientcy. --
        for i = 1, #combatTypes do
            if combat == combatTypes[i].type then
                if getPlayerStorageValue(cid, combatTypes[i].storage) > 0 then
                    doSendAnimatedText(getThingPos(cid), combatTypes[i].text, TEXTCOLOR_WHITE)
                    value = value / 2
                    break
                end
            end
        end
        
    if attacker ~= nil then
        if getPlayerStorageValue(cid, 1006) > 0 then
            if math.random(1, 10) == 1 then -- If you don't add a random it will reflect everytime.
                doSendAnimatedText(getThingPos(cid), "REFLECT!", TEXTCOLOR_WHITE)
                -- Changed this so the reflected damage will be the same damage as recieved and also will count as the player hitting him and not the server hitting him. --
                doTargetCombatHealth(cid, attacker, combat, -value, -value, CONST_ME_NONE)
            else -- You have to base dodge off of reflect's math.random so they both don't happen.
            if getPlayerStorageValue(cid, 1007) > 0 then
                if math.random(1, 10) == 1 then
                    doSendAnimatedText(getThingPos(cid), "DODGE!", TEXTCOLOR_WHITE)
                    value = 0
                else -- You have to base paralize off of dodge do they both don't happen. --
                if getPlayerStorageValue(cid, 1008) > 0 then
                    doSendAnimatedText(getThingPos(cid), "PARALYZE!", TEXTCOLOR_WHITE)
                    if not getCreatureCondition(attacker, CONDITION_PARALYZE) then
                        local condition = createConditionObject(CONDITION_PARALYZE)
                        setConditionParam(condition, CONDITION_PARAM_TICKS, 1000)
                        setConditionFormula(condition, -0.5, 0, -0.5, 0)
                        doAddCondition(attacker, condition)
                    end
                end
                end
            end
            end
        end
    end
    end
return true
end
 
Code:
local combatTypes = {
    [1] = {storage = 1000, type = COMBAT_FIREDAMAGE, text = "Fire Protect"},
    [2] = {storage = 1001, type = COMBAT_DEATHDAMAGE, text = "Death Protect"},
    [3] = {storage = 1002, type = COMBAT_ICEDAMAGE, text = "Ice Protect"},
    [4] = {storage = 1003, type = COMBAT_ENERGYDAMAGE, text = "Energy Protect"},
    [5] = {storage = 1004, type = COMBAT_HOLYDAMAGE, text = "Holy Protect"},
    [6] = {storage = 1005, type = COMBAT_EARTHDAMAGE, text = "Earth Protect"}

}

function onStatsChange(cid, attacker, type, combat, value)
    if isPlayer(cid) then
        -- Handle all of the protections at once in a loop for efficientcy. --
        for i = 1, #combatTypes do
            if combat == combatTypes[i].type then
                if getPlayerStorageValue(cid, combatTypes[i].storage) > 0 then
                    doSendAnimatedText(getThingPos(cid), combatTypes[i].text, TEXTCOLOR_WHITE)
                    value = value / 2
                    break
                end
            end
        end
       
    if attacker ~= nil then
        if getPlayerStorageValue(cid, 1006) > 0 then
            if math.random(1, 10) == 1 then -- If you don't add a random it will reflect everytime.
                doSendAnimatedText(getThingPos(cid), "REFLECT!", TEXTCOLOR_WHITE)
                -- Changed this so the reflected damage will be the same damage as recieved and also will count as the player hitting him and not the server hitting him. --
                doTargetCombatHealth(cid, attacker, combat, -value, -value, CONST_ME_NONE)
            else -- You have to base dodge off of reflect's math.random so they both don't happen.
            if getPlayerStorageValue(cid, 1007) > 0 then
                if math.random(1, 10) == 1 then
                    doSendAnimatedText(getThingPos(cid), "DODGE!", TEXTCOLOR_WHITE)
                    value = 0
                else -- You have to base paralize off of dodge do they both don't happen. --
                if getPlayerStorageValue(cid, 1008) > 0 then
                    doSendAnimatedText(getThingPos(cid), "PARALYZE!", TEXTCOLOR_WHITE)
                    if not getCreatureCondition(attacker, CONDITION_PARALYZE) then
                        local condition = createConditionObject(CONDITION_PARALYZE)
                        setConditionParam(condition, CONDITION_PARAM_TICKS, 1000)
                        setConditionFormula(condition, -0.5, 0, -0.5, 0)
                        doAddCondition(attacker, condition)
                    end
                end
                end
            end
            end
        end
    end
    end
return true
end
you need to return false and add a storage to check for to avoid stack overflow
 
How would checking for a storage that is set during code execution then deleted immediately when the code starts stop a stack overflow?
 
How would checking for a storage that is set during code execution then deleted immediately when the code starts stop a stack overflow?
Because you trigger onStatsChange infinitely by having a condition that sends a new attack to the player again, which causes the code to execute again, mitigates it, resends the attack with new value, and keeps going.
That's the point of return false, you stop the initial damage, send the new damage and let the script know to return true and not mitigate that incoming damage.
 
So this would be correct then I believe?

Code:
local combatTypes = {
    [1] = {storage = 1000, type = COMBAT_FIREDAMAGE, text = "Fire Protect"},
    [2] = {storage = 1001, type = COMBAT_DEATHDAMAGE, text = "Death Protect"},
    [3] = {storage = 1002, type = COMBAT_ICEDAMAGE, text = "Ice Protect"},
    [4] = {storage = 1003, type = COMBAT_ENERGYDAMAGE, text = "Energy Protect"},
    [5] = {storage = 1004, type = COMBAT_HOLYDAMAGE, text = "Holy Protect"},
    [6] = {storage = 1005, type = COMBAT_EARTHDAMAGE, text = "Earth Protect"}

}

local stackOverflow = 65111

function onStatsChange(cid, attacker, type, combat, value)
    if isPlayer(cid) then
   
        if getPlayerStorageValue(cid, stackOverflow) == 1 then
            setPlayerStorageValue(cid, stackOverflow, -1)
            return true
        end
   
        -- Handle all of the protections at once in a loop for efficientcy. --
        for i = 1, #combatTypes do
            if combat == combatTypes[i].type then
                if getPlayerStorageValue(cid, combatTypes[i].storage) > 0 then
                    doSendAnimatedText(getThingPos(cid), combatTypes[i].text, TEXTCOLOR_WHITE)
                    value = value / 2
                    break
                end
            end
        end
       
    if attacker ~= nil then
        if getPlayerStorageValue(cid, 1006) > 0 then
            if math.random(1, 10) == 1 then -- If you don't add a random it will reflect everytime.
                doSendAnimatedText(getThingPos(cid), "REFLECT!", TEXTCOLOR_WHITE)
                -- Changed this so the reflected damage will be the same damage as recieved and also will count as the player hitting him and not the server hitting him. --
                setPlayerStorageValue(cid, stackOverflow, 1)
                doTargetCombatHealth(cid, attacker, combat, -value, -value, CONST_ME_NONE)
                return false
            else -- You have to base dodge off of reflect's math.random so they both don't happen.
            if getPlayerStorageValue(cid, 1007) > 0 then
                if math.random(1, 10) == 1 then
                    doSendAnimatedText(getThingPos(cid), "DODGE!", TEXTCOLOR_WHITE)
                    value = 0
                else -- You have to base paralize off of dodge do they both don't happen. --
                if getPlayerStorageValue(cid, 1008) > 0 then
                    doSendAnimatedText(getThingPos(cid), "PARALYZE!", TEXTCOLOR_WHITE)
                    if not getCreatureCondition(attacker, CONDITION_PARALYZE) then
                        local condition = createConditionObject(CONDITION_PARALYZE)
                        setConditionParam(condition, CONDITION_PARAM_TICKS, 1000)
                        setConditionFormula(condition, -0.5, 0, -0.5, 0)
                        doAddCondition(attacker, condition)
                    end
                end
                end
            end
            end
        end
    end
    end
return true
end
 
Last edited:
So this would be correct then I believe?

Code:
local combatTypes = {
    [1] = {storage = 1000, type = COMBAT_FIREDAMAGE, text = "Fire Protect"},
    [2] = {storage = 1001, type = COMBAT_DEATHDAMAGE, text = "Death Protect"},
    [3] = {storage = 1002, type = COMBAT_ICEDAMAGE, text = "Ice Protect"},
    [4] = {storage = 1003, type = COMBAT_ENERGYDAMAGE, text = "Energy Protect"},
    [5] = {storage = 1004, type = COMBAT_HOLYDAMAGE, text = "Holy Protect"},
    [6] = {storage = 1005, type = COMBAT_EARTHDAMAGE, text = "Earth Protect"}

}

local stackOverflow = 65111

function onStatsChange(cid, attacker, type, combat, value)
    if isPlayer(cid) then
  
        if getPlayerStorageValue(cid, stackOverflow) == 1 then
            setPlayerStorageValue(cid, stackOverflow, -1)
            return true
        end
  
        -- Handle all of the protections at once in a loop for efficientcy. --
        for i = 1, #combatTypes do
            if combat == combatTypes[i].type then
                if getPlayerStorageValue(cid, combatTypes[i].storage) > 0 then
                    doSendAnimatedText(getThingPos(cid), combatTypes[i].text, TEXTCOLOR_WHITE)
                    value = value / 2
                    break
                end
            end
        end
      
    if attacker ~= nil then
        if getPlayerStorageValue(cid, 1006) > 0 then
            if math.random(1, 10) == 1 then -- If you don't add a random it will reflect everytime.
                doSendAnimatedText(getThingPos(cid), "REFLECT!", TEXTCOLOR_WHITE)
                -- Changed this so the reflected damage will be the same damage as recieved and also will count as the player hitting him and not the server hitting him. --
                setPlayerStorageValue(cid, stackOverflow, 1)
                doTargetCombatHealth(cid, attacker, combat, -value, -value, CONST_ME_NONE)
                return false
            else -- You have to base dodge off of reflect's math.random so they both don't happen.
            if getPlayerStorageValue(cid, 1007) > 0 then
                if math.random(1, 10) == 1 then
                    doSendAnimatedText(getThingPos(cid), "DODGE!", TEXTCOLOR_WHITE)
                    value = 0
                else -- You have to base paralize off of dodge do they both don't happen. --
                if getPlayerStorageValue(cid, 1008) > 0 then
                    doSendAnimatedText(getThingPos(cid), "PARALYZE!", TEXTCOLOR_WHITE)
                    if not getCreatureCondition(attacker, CONDITION_PARALYZE) then
                        local condition = createConditionObject(CONDITION_PARALYZE)
                        setConditionParam(condition, CONDITION_PARAM_TICKS, 1000)
                        setConditionFormula(condition, -0.5, 0, -0.5, 0)
                        doAddCondition(attacker, condition)
                    end
                end
                end
            end
            end
        end
    end
    end
return true
end

It's showing the message "Earth Protection" but it's not reducing any damage...
 
Probably because he's negating the damage when it's already negative, change all cases of -value to value.

the -damage is on reflect
Code:
doTargetCombatHealth(cid, attacker, combat, -value, -value, CONST_ME_NONE)

i was testing the earth protection its have only the value = value / 2
Code:
        for i = 1, #combatTypes do
            if combat == combatTypes[i].type then
                if getPlayerStorageValue(cid, combatTypes[i].storage) > 0 then
                    doSendAnimatedText(getThingPos(cid), combatTypes[i].text, TEXTCOLOR_WHITE)
                    value = value / 2
                    break
                end
            end
        end

it's printing the message but not reducing anything
 
I tried even to set to 0

Code:
                    doSendAnimatedText(getThingPos(cid), combatTypes[i].text, TEXTCOLOR_WHITE)
                    value = 0

it's sending the doSendAnimatedText(getThingPos(cid), combatTypes.text, TEXTCOLOR_WHITE)
but the damage is not changing...

Code:
local combatTypes = {
    [1] = {storage = 1000, type = COMBAT_FIREDAMAGE, text = "Fire Protect"},
    [2] = {storage = 1001, type = COMBAT_DEATHDAMAGE, text = "Death Protect"},
    [3] = {storage = 1002, type = COMBAT_ICEDAMAGE, text = "Ice Protect"},
    [4] = {storage = 1003, type = COMBAT_ENERGYDAMAGE, text = "Energy Protect"},
    [5] = {storage = 1004, type = COMBAT_HOLYDAMAGE, text = "Holy Protect"},
    [6] = {storage = 1005, type = COMBAT_EARTHDAMAGE, text = "Earth Protect"}

}

local stackOverflow = 65111

function onStatsChange(cid, attacker, type, combat, value)
    if isPlayer(cid) then
   
        if getPlayerStorageValue(cid, stackOverflow) == 1 then
            setPlayerStorageValue(cid, stackOverflow, -1)
            return true
        end
   
        -- Handle all of the protections at once in a loop for efficientcy. --
        for i = 1, #combatTypes do
            if combat == combatTypes[i].type then
                if getPlayerStorageValue(cid, combatTypes[i].storage) > 0 then
                    doSendAnimatedText(getThingPos(cid), combatTypes[i].text, TEXTCOLOR_WHITE)
                    value = 0
                    break
                end
            end
        end
       
    if attacker ~= nil then
        if getPlayerStorageValue(cid, 1006) > 0 then
            if math.random(1, 10) == 1 then -- If you don't add a random it will reflect everytime.
                doSendAnimatedText(getThingPos(cid), "REFLECT!", TEXTCOLOR_WHITE)
                -- Changed this so the reflected damage will be the same damage as recieved and also will count as the player hitting him and not the server hitting him. --
                setPlayerStorageValue(cid, stackOverflow, 1)
                doTargetCombatHealth(cid, attacker, combat, -value, -value, CONST_ME_NONE)
                return false
            else -- You have to base dodge off of reflect's math.random so they both don't happen.
            if getPlayerStorageValue(cid, 1007) > 0 then
                if math.random(1, 10) == 1 then
                    doSendAnimatedText(getThingPos(cid), "DODGE!", TEXTCOLOR_WHITE)
                    value = 0
                else -- You have to base paralize off of dodge do they both don't happen. --
                if getPlayerStorageValue(cid, 1008) > 0 then
                    doSendAnimatedText(getThingPos(cid), "PARALYZE!", TEXTCOLOR_WHITE)
                    if not getCreatureCondition(attacker, CONDITION_PARALYZE) then
                        local condition = createConditionObject(CONDITION_PARALYZE)
                        setConditionParam(condition, CONDITION_PARAM_TICKS, 1000)
                        setConditionFormula(condition, -0.5, 0, -0.5, 0)
                        doAddCondition(attacker, condition)
                    end
                end
                end
            end
            end
        end
    end
    end
return true
end
 
Back
Top