• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

custom condition param values?

Paulix

Active Member
Joined
Sep 13, 2012
Messages
151
Solutions
8
Reaction score
36
here is an example of a soul fire rune
Code:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_TARGETCASTERORTOPMOST, true)
setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE)
setCombatParam(combat, COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE)
setCombatParam(combat, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE)

local condition = createConditionObject(CONDITION_FIRE)
setConditionParam(condition, CONDITION_PARAM_DELAYED, 1)
addDamageCondition(condition, 10, 2000, -10)
setCombatCondition(combat, condition)

function onCastSpell(cid, var)
   return doCombat(cid, combat, var)
end
the problem is, it only hits -10 damage...
you cant make -10 a custom value cause it still loading the script and you dont have access yet to who is "casting" this spell yet...
otherwise you cant just create a condition inside onCastSpell funcion, cause it says that it need to be loaded before function
the question is, is it possible to "add condition to a target" without set it first? cause i would like to poison damage based on player level, or even magic level, is this possible?
PS: im using tfs 0.4
 
Use a table, since the values of the spell needs to be loaded 1st you can create the objects and/or conditions and store them in a table for later use, in the future you can always reference these values from the table.

For instance
Code:
local possibleValuesBasedOnLevel = {
    [1] = -10, -- lvl 1 -- default value
    [20] = -20, -- lvl 20
    [100] = -30 -- lvl 100
}

local combat = {}
local condition = {}
for level, damage in pairs(possibleValuesBasedOnLevel) do

    combat[level] = createCombatObject()
    setCombatParam(combat[level], COMBAT_PARAM_TARGETCASTERORTOPMOST, true)
    setCombatParam(combat[level], COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE)
    setCombatParam(combat[level], COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE)
    setCombatParam(combat[level], COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE)


    condition[level] = createConditionObject(CONDITION_FIRE)
    setConditionParam(condition[level], CONDITION_PARAM_DELAYED, 1)
    addDamageCondition(condition[level], 10, 2000, damage)
    setCombatCondition(combat[level], condition[level])
end

function onCastSpell(cid, var)
   local level = getPlayerLevel(cid)
   return doCombat(cid, combat[level] and combat[level] or combat[1], var)
end

Edit:
Of course this is just a simple example and not very efficient, if you want to be more explicit you can use a range chance function i made to check for the a range of the player's level.

https://otland.net/threads/range-chance-function.240855/
 
Last edited:
Use a table, since the values of the spell needed to be loaded 1st you can create the objects and/or conditions and store them in a table for later use, in the future you can always reference these values from the table.

For instance
Code:
local possibleValuesBasedOnLevel = {
    [1] = -10, -- lvl 1 -- default value
    [20] = -20, -- lvl 20
    [100] = -30 -- lvl 100
}

local combat = {}
local condition = {}
for level, damage in pairs(possibleValuesBasedOnLevel) do

    combat[level] = createCombatObject()
    setCombatParam(combat[level], COMBAT_PARAM_TARGETCASTERORTOPMOST, true)
    setCombatParam(combat[level], COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE)
    setCombatParam(combat[level], COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE)
    setCombatParam(combat[level], COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE)


    condition[level] = createConditionObject(CONDITION_FIRE)
    setConditionParam(condition[level], CONDITION_PARAM_DELAYED, 1)
    addDamageCondition(condition[level], 10, 2000, damage)
    setCombatCondition(combat[level], condition[level])
end

function onCastSpell(cid, var)
   local level = getPlayerLevel(cid)
   return doCombat(cid, combat[level] and combat[level] or combat[1], var)
end

thats not what i really wanted, i want to make some sort of formula to calculate the damage.
can i declare a functions that calls a condition? this way i could call the function inside the script and add values by param to it
here is a example i had on my old 8.1 server
Code:
function doPoison(cid, var, rounds, delay, dmg)

   if var == 0 or dmg >= 0 then
     return 0
   end

   local function damage(x)
     doCreatureAddHealth(var, dmg)
     doSendAnimatedText(getCreaturePosition(var), ''..-dmg..'', TEXTCOLOR_GREEN)
     doSendMagicEffect(getCreaturePosition(var), CONST_ME_HITBYPOISON)
     return x
   end

   for i=1, rounds do
     addEvent(damage, (i * delay), 1)
   end

   return 1
end

i could call this function anywhere, and just set parameters on it. the problem was that if creature dies, the addevent will return error in console...
my server weapons are heavily based on formulas I created by myself, i would like to conditions act the same as weapons
 
the same way this work with damage, without having to set it first

doTargetCombatHealth(cid, target, type, min, max, effect)

i have this function

doTargetCombatCondition(cid, target, condition, effect)

but i have no idea how it work... looks like condition must be set before btw
 
thats not what i really wanted, i want to make some sort of formula to calculate the damage.
can i declare a functions that calls a condition? this way i could call the function inside the script and add values by param to it
here is a example i had on my old 8.1 server
Code:
function doPoison(cid, var, rounds, delay, dmg)

   if var == 0 or dmg >= 0 then
     return 0
   end

   local function damage(x)
     doCreatureAddHealth(var, dmg)
     doSendAnimatedText(getCreaturePosition(var), ''..-dmg..'', TEXTCOLOR_GREEN)
     doSendMagicEffect(getCreaturePosition(var), CONST_ME_HITBYPOISON)
     return x
   end

   for i=1, rounds do
     addEvent(damage, (i * delay), 1)
   end

   return 1
end

i could call this function anywhere, and just set parameters on it. the problem was that if creature dies, the addevent will return error in console...
my server weapons are heavily based on formulas I created by myself, i would like to conditions act the same as weapons
Code:
-- cid is not being used for anything but i kept it there
function doPoison(cid, var, rounds, delay, dmg, iter)
    if var == 0 or dmg >= 0 then
        return 0
    end
    iter = iter and iter+1 or 1
    if isCreature(var) then
        doCreatureAddHealth(var, dmg)
        doSendAnimatedText(getCreaturePosition(var), ''..-dmg..'', TEXTCOLOR_GREEN)
        doSendMagicEffect(getCreaturePosition(var), CONST_ME_HITBYPOISON)
        if iter < rounds then
            addEvent(doPoison, delay, cid, var, rounds, delay, dmg, iter)
        end
    end
    return 1
end

To do it using conditions you would need to edit the source to add parameter for formula.
 
Last edited:
Code:
-- cid is not being used for anything but i kept it there
function doPoison(cid, var, rounds, delay, dmg, iter)
    if var == 0 or dmg >= 0 then
        return 0
    end
    iter = iter and iter+1 or 1
    if isCreature(var) then
        doCreatureAddHealth(var, dmg)
        doSendAnimatedText(getCreaturePosition(var), ''..-dmg..'', TEXTCOLOR_GREEN)
        doSendMagicEffect(getCreaturePosition(var), CONST_ME_HITBYPOISON)
        if iter < rounds then
            addEvent(doPoison, delay, cid, var, rounds, delay, dmg, iter)
        end
    end
    return 1
end

To do it using conditions you would need to edit the source to add parameter for formula.

using your function, if player dies does it return error on console?
 
problem solved after a couple hours working on it...
now it dispells on exana pox, and you can make your own formula for damage ^^
add this funcion to your function.lua or global.lua
Code:
function doPoison(var, rounds, delay, dmg, iter)
  if var == 0 or dmg >= 0 then
  return 0
  end
  iter = iter and iter+1 or 1
  if isCreature(var) and getCreatureCondition(var, CONDITION_POISON) then
     doTargetCombatHealth(0, var, COMBAT_POISONDAMAGE, dmg, dmg, CONST_ME_NONE)
  if iter < rounds then
  addEvent(doPoison, delay, var, rounds, delay, dmg, iter)
  end
  end
  return 1
end

and your weapon/skill now need to be like this
Code:
local poison = {
delay = 1 * 1000,
rounds = 12
}

local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_POISONDAMAGE)
setCombatParam(combat, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_POISON)

local condition = createConditionObject(CONDITION_POISON)
addDamageCondition(condition, poison.rounds, poison.delay, 0)

function onGetFormulaValues(cid, level, maglevel)

   local min = -(((level/2)+maglevel) * 1.0)
   local max = -(((level/2)+maglevel) * 1.1)
   
   return min, max
end

setCombatCallback(combat, CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onUseWeapon(cid, var)
local dmg = getPlayerLevel(cid)
   doCombat(cid, combat, var)
   if not getCreatureCondition(var.number, CONDITION_POISON) then
     doAddCondition(var.number, condition)
     doPoison(var.number, poison.rounds, poison.delay, -dmg)
   end
   return 1
end

remember that this is the way I solved my problem, im just sharing
warning when making your weapon, cause the doPoison function can be stacked multiple times, so if you dont filter it you'll end up with a lot of poison damage stacked on same player, and that could be a problem
this topic is SOLVED, an admin can close it, thank you very much for who helped me
PS: not native english speaker
 
Last edited:
problem solved after a couple hours working on it...
now it dispells on exana pox, and you can make your own formula for damage ^^
add this funcion to your function.lua or global.lua
Code:
function doPoison(var, rounds, delay, dmg, iter)
  if var == 0 or dmg >= 0 then
  return 0
  end
  iter = iter and iter+1 or 1
  if isCreature(var) and getCreatureCondition(var, CONDITION_POISON) then
     doTargetCombatHealth(0, var, COMBAT_POISONDAMAGE, dmg, dmg, CONST_ME_NONE)
  if iter < rounds then
  addEvent(doPoison, delay, var, rounds, delay, dmg, iter)
  end
  end
  return 1
end

and your weapon/skill now need to be like this
Code:
local poison = {
delay = 1 * 1000,
rounds = 12
}

local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_POISONDAMAGE)
setCombatParam(combat, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_POISON)

local condition = createConditionObject(CONDITION_POISON)
addDamageCondition(condition, poison.rounds, poison.delay, 0)

function onGetFormulaValues(cid, level, maglevel)

   local min = -(((level/2)+maglevel) * 1.0)
   local max = -(((level/2)+maglevel) * 1.1)
  
   return min, max
end

setCombatCallback(combat, CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onUseWeapon(cid, var)
local dmg = getPlayerLevel(cid)
   doCombat(cid, combat, var)
   if not getCreatureCondition(var.number, CONDITION_POISON) then
     doAddCondition(var.number, condition)
     doPoison(var.number, poison.rounds, poison.delay, -dmg)
   end
   return 1
end

remember that this is the way I solved my problem, im just sharing
warning when making your weapon, cause the doPoison function can be stacked multiple times, so if you dont filter it you'll end up with a lot of poison damage stacked on same player, and that could be a problem
this topic is SOLVED, an admin can close it, thank you very much for who helped me
PS: not native english speaker
It can still be stacked with your solution if the player exana pox and get hit before the addevent fires again
 
How about a storage value?
Just throwing it out there.. while waiting for @MatheusMkalo to shoot it down :p
i would have to change storage values on exana pox spell and antidote rune to make it viable, also i think i'll have some problem if player dies
cause the storage will not be back to normal
 
no idea what it is :p
Code:
PLAYER_CONDITIONS = {}
ConditionDamage = {}

setmetatable(ConditionDamage, {__call = function(t, combat)
    local condition = {rounds=math.huge, delay=1000, combat = combat}
    return setmetatable(condition, {__index = ConditionDamage})
end}
)

function ConditionDamage:addDamage(dmg, delay, rounds)
    self.dmg = dmg
    self.delay = delay or self.delay
    self.rounds = rounds or self.rounds
end

function removePlayerCondition(player, combat)
    local conditions = PLAYER_CONDITIONS[player]
    if conditions then
        for i = #conditions, 1, -1 do
            if conditions[i].combat == combat then
                table.remove(conditions, i)
            end
        end
    end
end

function ConditionDamage:doDamage(player, iter)
    iter = iter and iter+1 or 1
    PLAYER_CONDITIONS[player] = PLAYER_CONDITIONS[player] or {}
    if isPlayer(player) and self.dmg and self.combat then
        doTargetCombatHealth(0, player, self.combat, self.dmg, self.dmg, CONST_ME_NONE)
        if iter < self.rounds then
            if iter == 1 then
                removePlayerCondition(player, self.combat)
                table.insert(PLAYER_CONDITIONS[player], self)
            elseif not isInArray(PLAYER_CONDITIONS[player], self) then
                return false
            end
            addEvent(ConditionDamage.doDamage, self.delay, self, player, iter)
        else
            removePlayerCondition(player, self.combat)
        end
    end
end
Add this to some lib file or w/e you want

Use it like this:

local a = ConditionDamage(COMBAT_POISONDAMAGE)
a:addDamage(dmg, [delay, [rounds]])
a:doDamage(cid)
Delay default is 1000 and rounds default is infinit.

That will reset the damage condition every hit, to remove the poison with exana pox you have to add this in the exana pox spell:
removePlayerCondition(cid, COMBAT_POISONDAMAGE)

Also you have to put PLAYER_CONDITIONS[cid] = nil in logout.lua.

In your weapon script:
Change this "doPoison(var.number, poison.rounds, poison.delay, -dmg)"

To this:

Code:
local cond = ConditionDamage(COMBAT_POISONDAMAGE)
cond:addDamage(-dmg, poison.delay, poison.rounds)
cond:doDamage(var.number)
 
Last edited:
Code:
PLAYER_CONDITIONS = {}
ConditionDamage = {}

setmetatable(ConditionDamage, {__call = function(t, combat)
    local condition = {rounds=math.huge, delay=1000, combat = combat}
    return setmetatable(condition, {__index = ConditionDamage})
end}
)

function ConditionDamage:addDamage(dmg, delay, rounds)
    self.dmg = dmg
    self.delay = delay or self.delay
    self.rounds = rounds or self.rounds
end

function removePlayerCondition(player, combat)
    local conditions = PLAYER_CONDITIONS[player]
    if conditions then
        for i = #conditions, 1, -1 do
            if conditions[i].combat == combat then
                table.remove(conditions, i)
            end
        end
    end
end

function ConditionDamage:doDamage(player, iter)
    iter = iter and iter+1 or 1
    PLAYER_CONDITIONS[player] = PLAYER_CONDITIONS[player] or {}
    if isPlayer(player) and self.dmg and self.combat then
        doTargetCombatHealth(0, player, self.combat, self.dmg, self.dmg, CONST_ME_NONE)
        if iter < self.rounds then
            if iter == 1 then
                removePlayerCondition(player, self.combat)
                table.insert(PLAYER_CONDITIONS[player], self)
            elseif not isInArray(PLAYER_CONDITIONS[player], self) then
                return false
            end
            addEvent(ConditionDamage.doDamage, self.delay, self, player, iter)
        else
            removePlayerCondition(player, self.combat)
        end
    end
end
Add this to some lib file or w/e you want

Use it like this:

local a = ConditionDamage(COMBAT_POISONDAMAGE)
a:addDamage(dmg, [delay, [rounds]])
a:doDamage(cid)
Delay default is 1000 and rounds default is infinit.

That will reset the damage condition every hit, to remove the poison with exana pox you have to add this in the exana pox spell:
removePlayerCondition(cid, COMBAT_POISONDAMAGE)

Also you have to put PLAYER_CONDITIONS[cid] = nil in logout.lua.

In your weapon script:
Change this "doPoison(var.number, poison.rounds, poison.delay, -dmg)"

To this:

Code:
local cond = ConditionDamage(COMBAT_POISONDAMAGE)
cond:addDamage(-dmg, poison.delay, poison.rounds)
cond:doDamage(var.number)
omg hahaha
i'll give a try at this, but im not sure if i'll use it cause its kinda hard to use what you cant understand
thank you anyway
 
Back
Top