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

TFS 1.X+ Prevent magic wall spam on same tile with macro

henkas

Well-Known Member
Joined
Jul 8, 2015
Messages
1,067
Solutions
5
Reaction score
63
TFS 1.2. How can i prevent magic wall macro abuse where people place new magic wall on the same position without any delay and can basically trap someone permanently, so its like when they put magic wall the see the timer and with scripts when the timer ends they put new magic wall on same position with zero delay. In spells.xml casting delay is 1 second, overall magic wall stays for 10 seconds, dont wantto make magic wall casting delay for 11 seconds that would be terrible solution
LUA:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, 18)
combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_MAGICWALL)

function onCastSpell(creature, var, isHotkey)
    local targetPosition = variantToPosition(var)
    local targetTile = Tile(targetPosition)
    local targetZoneId = targetTile and targetTile:getZoneId()

    local blockedZoneId = 6438

    if targetZoneId == blockedZoneId then
        creature:sendCancelMessage("You can't cast magic wall here.")
        return false
    end

    return combat:execute(creature, var)
end
 
Solution
addEvent(function() ground:setActionId() end, 20050)
It's rare and unexpected scenario, but ground item can be removed from map. Script should expect this and not use Item object in addEvent.
It should pass position (Lua table with x,y,z attributes) and restore Tile->Item from it.
Replace this:
LUA:
    addEvent(function()
        ground:setActionId()
    end, 20050)
with:
LUA:
    addEvent(function(position)
        local eventTile = Tile(position)
        if not eventTile then return end
        local eventGround = eventTile:getGround()
        if not eventGround then return end
        eventGround:removeAttribute(ITEM_ATTRIBUTE_ACTIONID)
    end, 20050, variant:getPosition())

Also ground:setActionId()...
What I would do is if there was a magic wall befor you can not use magic wall on that position again for like 50-100MS like 0.1 seconds so people can run out?
 
What I would do is if there was a magic wall befor you can not use magic wall on that position again for like 50-100MS like 0.1 seconds so people can run out?
Yea i though the same i tried adding action id to that magicwall and apply cooldown on that tile, but all i managed to create is crash :D
 
Try this:

LUA:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, 18)
combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_MAGICWALL)
function onCastSpell(creature, variant, isHotkey)
    local targetPosition = variant:getPosition()
    local targetTile = Tile(targetPosition)
    local targetZoneId = targetTile and targetTile:getZoneId()
    local blockedZoneId = 6438
    if targetZoneId == blockedZoneId then
        creature:sendCancelMessage("You can't cast magic wall here.")
        return false
    end
    local tile = variant:getPosition():getTile()
    local ground = tile:getGround()
    if not tile and not ground then
        return true
    end
    if ground:getActionId() == 2000 then
        creature:sendTextMessage(MESSAGE_INFO_DESCR, 'You can not MW there right now.')
        return true
    end
    ground:setActionId(2000)
    addEvent(function()
        ground:setActionId()
    end, 20050)
    return combat:execute(creature, variant)
end

You can change the 20050 to something like 21000 so its like 21 second which means player has 1 second to run out of the magic wall

1752248642930.webp
 
addEvent(function() ground:setActionId() end, 20050)
It's rare and unexpected scenario, but ground item can be removed from map. Script should expect this and not use Item object in addEvent.
It should pass position (Lua table with x,y,z attributes) and restore Tile->Item from it.
Replace this:
LUA:
    addEvent(function()
        ground:setActionId()
    end, 20050)
with:
LUA:
    addEvent(function(position)
        local eventTile = Tile(position)
        if not eventTile then return end
        local eventGround = eventTile:getGround()
        if not eventGround then return end
        eventGround:removeAttribute(ITEM_ATTRIBUTE_ACTIONID)
    end, 20050, variant:getPosition())

Also ground:setActionId() may not work. Calling setActionId without parameter will show some error or set actionID to 100. To remove actionID you should use item:removeAttribute(ITEM_ATTRIBUTE_ACTIONID).

Anyway, using action ID for this system is a bad idea, because some tiles ground item may already have actionID set for some quest/script and we should not modify it.

It would be better to store blocked positions in some table and remove them after time passed ex.:
LUA:
local mwBlockedPositions = {}

local combat = Combat()
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, 18)
combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_MAGICWALL)
function onCastSpell(creature, variant, isHotkey)
    local targetPosition = variant:getPosition()
    local targetTile = Tile(targetPosition)
    local targetZoneId = targetTile and targetTile:getZoneId()
    local blockedZoneId = 6438
    if targetZoneId == blockedZoneId then
        creature:sendCancelMessage("You can't cast magic wall here.")
        return false
    end

    local position = variant:getPosition()
    local positionAsString = position.x .. ',' .. position.y .. ',' .. position.z
    if mwBlockedPositions[positionAsString] then
        creature:sendCancelMessage("You can't cast magic wall on that position now.")
        return false
    end

    mwBlockedPositions[positionAsString] = true
    addEvent(function()
        mwBlockedPositions[positionAsString] = nil
    end, 20050)

    return combat:execute(creature, variant)
end
 
Last edited:
Solution
It's rare and unexpected scenario, but ground item can be removed from map. Script should expect this and not use Item object in addEvent.
It should pass position (Lua table with x,y,z attributes) and restore Tile->Item from it.
Replace this:
LUA:
    addEvent(function()
        ground:setActionId()
    end, 20050)
with:
LUA:
    addEvent(function(position)
        local eventTile = Tile(position)
        if not eventTile then return end
        local eventGround = eventTile:getGround()
        if not eventGround then return end
        eventGround:removeAttribute(ITEM_ATTRIBUTE_ACTIONID)
    end, 20050, variant:getPosition())

Also ground:setActionId() may not work. Calling setActionId without parameter will show some error or set actionID to 100. To remove actionID you should use item:removeAttribute(ITEM_ATTRIBUTE_ACTIONID).

Anyway, using action ID for this system is a bad idea, because some tiles ground item may already have actionID set for some quest/script and we should not modify it.

It would be better to store blocked positions in some table and remove them after time passed ex.:
LUA:
local mwBlockedPositions = {}

local combat = Combat()
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, 18)
combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_MAGICWALL)
function onCastSpell(creature, variant, isHotkey)
    local targetPosition = variant:getPosition()
    local targetTile = Tile(targetPosition)
    local targetZoneId = targetTile and targetTile:getZoneId()
    local blockedZoneId = 6438
    if targetZoneId == blockedZoneId then
        creature:sendCancelMessage("You can't cast magic wall here.")
        return false
    end

    local position = variant:getPosition()
    local positionAsString = position.x .. ',' .. position.y .. ',' .. position.z
    if mwBlockedPositions[positionAsString] then
        creature:sendCancelMessage("You can't cast magic wall on that position now.")
        return false
    end

    mwBlockedPositions[positionAsString] = true
    addEvent(function()
        mwBlockedPositions[positionAsStringEvent] = nil
    end, 20050)

    return combat:execute(creature, variant)
end

Didnt think that far tbh
Thanks you
 
It's rare and unexpected scenario, but ground item can be removed from map. Script should expect this and not use Item object in addEvent.
It should pass position (Lua table with x,y,z attributes) and restore Tile->Item from it.
Replace this:
LUA:
    addEvent(function()
        ground:setActionId()
    end, 20050)
with:
LUA:
    addEvent(function(position)
        local eventTile = Tile(position)
        if not eventTile then return end
        local eventGround = eventTile:getGround()
        if not eventGround then return end
        eventGround:removeAttribute(ITEM_ATTRIBUTE_ACTIONID)
    end, 20050, variant:getPosition())

Also ground:setActionId() may not work. Calling setActionId without parameter will show some error or set actionID to 100. To remove actionID you should use item:removeAttribute(ITEM_ATTRIBUTE_ACTIONID).

Anyway, using action ID for this system is a bad idea, because some tiles ground item may already have actionID set for some quest/script and we should not modify it.

It would be better to store blocked positions in some table and remove them after time passed ex.:
LUA:
local mwBlockedPositions = {}

local combat = Combat()
combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, 18)
combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_MAGICWALL)
function onCastSpell(creature, variant, isHotkey)
    local targetPosition = variant:getPosition()
    local targetTile = Tile(targetPosition)
    local targetZoneId = targetTile and targetTile:getZoneId()
    local blockedZoneId = 6438
    if targetZoneId == blockedZoneId then
        creature:sendCancelMessage("You can't cast magic wall here.")
        return false
    end

    local position = variant:getPosition()
    local positionAsString = position.x .. ',' .. position.y .. ',' .. position.z
    if mwBlockedPositions[positionAsString] then
        creature:sendCancelMessage("You can't cast magic wall on that position now.")
        return false
    end

    mwBlockedPositions[positionAsString] = true
    addEvent(function()
        mwBlockedPositions[positionAsStringEvent] = nil
    end, 20050)

    return combat:execute(creature, variant)
end
Slight typo on the variable name on line 25 Gesior 👍
 
Back
Top