• 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!

Hit whole stack [TFS 1.2]

zippy

Member
Joined
Feb 1, 2011
Messages
233
Reaction score
8
Hi,

I wonder how can i make that for example SD damage a whole stack. Which means if 10 players are on eachother it should damage everyone expect the caster.

I use tfs 1.2

Thanks
 
I don't use tfs 1.2, so I can't really show you how, but you'd want to use get spectators, then loop through all creatures.. or use a lua function that exists for damaging the tile.
 
Hello, im looking for this too!! Someone wirh knowledge here in otland help me to implement this on tfs 1.2? All agressive spells runes damage all stacked players
 
In the master repository (TFS 1.3), you could do this (if you're not using master, just create these files in their respective path):

But you will have to use
Lua:
doTargetCombatHealth(cid, target, type, min, max, effect[, origin = ORIGIN_SPELL])
in all spells to apply damage to all creatures in a single tile.

Example for "Sudden Death Rune" spell:
Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SUDDENDEATH)

function onCastSpell(creature, variant, isHotkey)
    local min = (creature:getLevel() / 5) + (creature:getMagicLevel() * 4.3) + 32
    local max = (creature:getLevel() / 5) + (creature:getMagicLevel() * 7.4) + 48
    local positions = combat:getPositions()
    for _, position in ipairs(positions)) do
        local tile = Tile(position)
        if tile then
            for _, creature in ipairs(tile:getCreatures()) do
                doTargetCombatHealth(0, creature, COMBAT_DEATHDAMAGE, -min, -max)
            end
        end
    end
    return true
end

An example using
Lua:
combat:getTargets()
 
I will test, but in this case for example if i down a stair and have a player on stack there and i use sudden death rune on me in stack, i will need close the hand yes? Also the hit will show of one player or all stacked players? For exemple my damage sd is 100 if i use on 2 stacked player will appear 200 or not?
 
If said spell is aggressive, yes, you will still have to close your hands to be able to cast the spell. The spell will target every single player currently in that tile - but it will not hit you. If the resulted damage is 100, casting the spell will apply 100 damage to each player stacked in that tile (although, due to the nature of the client and server itself, visually it may appear "200" (I may be wrong) damage on your screen, but the damage will still be 100 to each target.)
 
spells.cpp

bool CombatSpell::castSpell(Creature* creature, Creature* target)


get creatures(players) on that target position. If > 1 = stack. Send the combat damage for everyone.
 
spells.cpp

bool CombatSpell::castSpell(Creature* creature, Creature* target)


get creatures(players) on that target position. If > 1 = stack. Send the combat damage for everyone.

In this function
bool CombatSpell::castSpell(Creature* creature, Creature* target)
what i put there?
 
up? im really interested in apply this function to can hit whole targets in the stack.. currently im using a tfs 1.2 Nostalrius and i'm fixing some stuffs to give a better experience in pve/pvp

sorry for reup this old thread.

i tried few things but got just errors, so i came to ask some heelp :D

-----
this is my spells.cpp in the function of CombatSpell::castSpell :

C++:
bool CombatSpell::castSpell(Creature* creature, Creature* target)
{
    if (scripted) {
        LuaVariant var;

        if (combat->hasArea()) {
            var.type = VARIANT_POSITION;

            if (needTarget) {
                var.pos = target->getPosition();
            } else if (needDirection) {
                var.pos = Spells::getCasterPosition(creature, creature->getDirection());
            } else {
                var.pos = creature->getPosition();
            }
        } else {
            var.type = VARIANT_NUMBER;
            var.number = target->getID();
        }
        return executeCastSpell(creature, var);
    }

    if (combat->hasArea()) {
        if (needTarget) {
            combat->doCombat(creature, target->getPosition());
        } else {
            return castSpell(creature);
        }
    } else {
        combat->doCombat(creature, target);
    }
    return true;
}

ty duds
 
Last edited:
For TFS 1.3+

data/scripts/sd_edited.lua
Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH)

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 1.2) + 7
    local max = (level / 5) + (magicLevel * 2.85) + 16
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

local rune = Spell(SPELL_RUNE)
function rune.onCastSpell(player, variant, isHotkey)
    local tile = Tile(variant:getPosition())
    if tile then
        local topVisibleCreature = tile:getTopVisibleCreature(player)
        if topVisibleCreature then
            if topVisibleCreature:getId() ~= player:getId() and (not topVisibleCreature:isPlayer() or not topVisibleCreature:getGroup():getAccess()) then
                return combat:execute(player, variant)
            end
        end

        local bottomVisibleCreature = tile:getBottomVisibleCreature(player)
        if bottomVisibleCreature then
            if bottomVisibleCreature:getId() ~= player:getId() and (not bottomVisibleCreature:isPlayer() or not bottomVisibleCreature:getGroup():getAccess()) then
                return combat:execute(player, variant)
            end
        end
    end

    player:getPosition():sendMagicEffect(CONST_ME_POFF)
    player:sendCancelMessage(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES)
    return false
end

rune:name("SD Edited")
rune:group("attack")
rune:vocation("sorcerer", "master sorcerer;true", "druid", "elder druid;true")
rune:runeId(2294)
--rune:runeSpellName("exevo sd edited")
rune:charges(1)
rune:id(24)
rune:cooldown(1000)
rune:groupCooldown(1000)
rune:level(60)
rune:magicLevel(14)
rune:mana(1100)
rune:allowFarUse(true)
rune:isPremium(true)
rune:isBlocking(true, false)
rune:register()

For TFS 1.2+
data/spells/scripts/attacks/sd_edited.lua
Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH)

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 1.2) + 7
    local max = (level / 5) + (magicLevel * 2.85) + 16
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(player, variant, isHotkey)
    local tile = Tile(variant:getPosition())
    if tile then
        local topVisibleCreature = tile:getTopVisibleCreature(player)
        if topVisibleCreature then
            if topVisibleCreature:getId() ~= player:getId() and (not topVisibleCreature:isPlayer() or not topVisibleCreature:getGroup():getAccess()) then
                return combat:execute(player, variant)
            end
        end

        local bottomVisibleCreature = tile:getBottomVisibleCreature(player)
        if bottomVisibleCreature then
            if bottomVisibleCreature:getId() ~= player:getId() and (not bottomVisibleCreature:isPlayer() or not bottomVisibleCreature:getGroup():getAccess()) then
                return combat:execute(player, variant)
            end
        end
    end

    player:getPosition():sendMagicEffect(CONST_ME_POFF)
    player:sendCancelMessage(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES)
    return false
end
and data/spells/spells.xml
XML:
<rune group="attack" spellid="21" name="SD Edited" id="2294" allowfaruse="1" mana="1100" charges="1" level="60" magiclevel="14" cooldown="1000" groupcooldown="1000" blocktype="solid" script="attack/sd_edited.lua" />

GIF 05-05-2022 10-58-33 p. m..gif
 
Last edited:
as i can see testing here how far i understood what u did was just let disabled the [ needtarget="1" ] in your xml, considering this i will need to create runes again with this script and probably this rune what u showing in the gif can be used in "void" space cuz the needtarget was get be disabled.

and i got it about the function in the lua for the "tile" but.. just with this new function in the lua the runes dont hit the others (monsters and players)

-----
if i didnt be clear:
(shooting rune in the roof(void) )

gif1-sd-explanation.gif

anyway i glad for ur answer and thanks to try help! <3
 
Last edited:
For TFS 1.3+

data/scripts/sd_edited.lua
Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH)

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 1.2) + 7
    local max = (level / 5) + (magicLevel * 2.85) + 16
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

local rune = Spell(SPELL_RUNE)
function rune.onCastSpell(player, variant, isHotkey)
    local tile = Tile(variant:getPosition())
    if tile and tile:getCreatureCount() == 0 then
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        player:sendCancelMessage(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES)
        return false
    end
    return combat:execute(player, variant)
end

rune:name("SD Edited")
rune:group("attack")
rune:vocation("sorcerer", "master sorcerer;true", "druid", "elder druid;true")
rune:runeId(2294)
--rune:runeSpellName("exevo sd edited")
rune:charges(1)
rune:id(24)
rune:cooldown(1000)
rune:groupCooldown(1000)
rune:level(60)
rune:magicLevel(14)
rune:mana(1100)
rune:allowFarUse(true)
rune:isPremium(true)
rune:isBlocking(true, false)
rune:register()

For TFS 1.2+
data/spells/scripts/attacks/sd_edited.lua
Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH)

function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 1.2) + 7
    local max = (level / 5) + (magicLevel * 2.85) + 16
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(player, variant, isHotkey)
    local tile = Tile(variant:getPosition())
    if tile and tile:getCreatureCount() == 0 then
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        player:sendCancelMessage(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES)
        return false
    end
    return combat:execute(player, variant)
end
and data/spells/spells.xml
XML:
<rune group="attack" spellid="21" name="SD Edited" id="2294" allowfaruse="1" mana="1100" charges="1" level="60" magiclevel="14" cooldown="1000" groupcooldown="1000" blocktype="solid" script="attack/sd_edited.lua" />

View attachment 67583
thank you! this wil save me and others time, editing source code.
 
Last edited:
thank you! this wil save me and others time, editing source code.
did u told that need a edition in source code? that was what i thinking about... thats the point just with the modifications that Sarah told i dont think it will work correctly...

what we need add in src code?

ps: i want be wrong about it
 
did u told that need a edition in source code? that was what i thinking about... thats the point just with the modifications that Sarah told i dont think it will work correctly...

ps: i want be wrong about it
check again the code and try to test it again
 
inserted exactly like u told

thats the result:

ps: i cant shoot more runes in the "void"


gif2-sd-explanation.gif

but the players stacked there dont get damage, nobody
 
did u told that need a edition in source code? that was what i thinking about... thats the point just with the modifications that Sarah told i dont think it will work correctly...

ps: i want be wrong about it

check again the code and try to test it again
it ask for mana to shoot the rune and is not dealing damage players only receive sd effect and blockhiteffect

my bad it does work very good but if i edit the formulas it does not work
example this
Lua:
local base = 150
    local variation = 20

    local min = math.max((base - variation), ((3 * maglevel + 2 * level) * (base - variation) / 100))
    local max = math.max((base + variation), ((3 * maglevel + 2 * level) * (base + variation) / 100))

    return -min, -max
end
Code:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH)

function onGetFormulaValues(player, level, magicLevel)
local base = 150
    local variation = 20

    local min = math.max((base - variation), ((3 * maglevel + 2 * level) * (base - variation) / 100))
    local max = math.max((base + variation), ((3 * maglevel + 2 * level) * (base + variation) / 100))

    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

local rune = Spell(SPELL_RUNE)
function rune.onCastSpell(player, variant, isHotkey)
    local tile = Tile(variant:getPosition())
    if tile then
        local topVisibleCreature = tile:getTopVisibleCreature(player)
        if topVisibleCreature then
            if topVisibleCreature:getId() ~= player:getId() and (not topVisibleCreature:isPlayer() or not topVisibleCreature:getGroup():getAccess()) then
                return combat:execute(player, variant)
            end
        end

        local bottomVisibleCreature = tile:getBottomVisibleCreature(player)
        if bottomVisibleCreature then
            if bottomVisibleCreature:getId() ~= player:getId() and (not bottomVisibleCreature:isPlayer() or not bottomVisibleCreature:getGroup():getAccess()) then
                return combat:execute(player, variant)
            end
        end
    end

    player:getPosition():sendMagicEffect(CONST_ME_POFF)
    player:sendCancelMessage(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES)
    return false
end

rune:name("SD Edited")
rune:group("attack")
rune:vocation("sorcerer", "master sorcerer;true", "druid", "elder druid;true")
rune:runeId(2268)
--rune:runeSpellName("exevo sd edited")
rune:charges(1)
rune:id(24)
rune:cooldown(1000)
rune:groupCooldown(1000)
--rune:level(60c)
rune:magicLevel(18)
rune:mana(0)
rune:allowFarUse(true)
rune:isPremium(false)
rune:isBlocking(true, false)
rune:register()
it says that can't perform aritmetic ... conversion something like that but i use the same values in spells.xml
 
Last edited:
nobody knows any edition thats possible to do in source code maybe in that part that i referred few posts up? probably is the best way to solve it but the things that i tried didnt work also i tried few stuffs in the part of .lua/.xml but without success too...

note: if u guys want a partial solution for Nostalrius tfs 1.2 you can just disable this parameter in the /data/spells/spells.xml needtarget="1" on the runes but the problem is the runes will be able to shoot the "void" and considering old protocol that are without hotkeys and battle target you gonna spent a lot of runes in nobody. but doing that if u test u gonna see the runes hitting whole stack but also u can spent them in nobody like the area runes.

thanks to everyone!


editing the post and explaining whats happened, the problem was solved!!!

first of all i want to thanks @Sarah Wesker!! "you gave me the knife so its was just i slice" :D

if u are using the tfs 1.2 like im, u dont need add a new one line of code in spells and create another file for the runes, u can do that:

first of all change the needtarget="1" to needtarget="0" in the respective lines of target runes what u want to hit whole stack.
example:

Lua:
<rune name="Sudden Death" id="3155" allowfaruse="1" charges="1" needtarget="0" maglv="15" blocktype="solid" script="runes/sudden death.lua" />

after that you go to the /data/spells/scripts/runes/rune.lua in this case for me sudden death.lua and there you can keep your formulas, just adding in the final the function onCastSpell and the .lua will stay like that:

Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH)

function onGetFormulaValues(player, level, maglevel)
    local base = 150
    local variation = 20
 
    local formula = 3 * maglevel + (2 * level)
 
    local min = (formula * (base - variation)) / 100
    local max = (formula * (base + variation)) / 100
    return -min, -max
end

combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

function onCastSpell(player, variant, isHotkey)
    local tile = Tile(variant:getPosition())
    if tile then
        local topVisibleCreature = tile:getTopVisibleCreature(player)
        if topVisibleCreature then
            if topVisibleCreature:getId() ~= player:getId() and (not topVisibleCreature:isPlayer() or not topVisibleCreature:getGroup():getAccess()) then
                return combat:execute(player, variant)
            end
        end

        local bottomVisibleCreature = tile:getBottomVisibleCreature(player)
        if bottomVisibleCreature then
            if bottomVisibleCreature:getId() ~= player:getId() and (not bottomVisibleCreature:isPlayer() or not bottomVisibleCreature:getGroup():getAccess()) then
                return combat:execute(player, variant)
            end
        end
    end

    player:getPosition():sendMagicEffect(CONST_ME_POFF)
    player:sendCancelMessage(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES)
    return false
end

note: pay attention on the variables, they must be equal the other runes


gif-hitting-whole-stack.gif
sorry for the laggy gif my computer is a #@$&@#&
 
Last edited:
Back
Top