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

Lua Limit spell range when targeting

Misterion

New Member
Joined
Jan 24, 2014
Messages
52
Reaction score
4
EDIT: I forgot, im using TFS 0.3.6

I know it sounds like a simple question but it's for a custom spell, where the caster becomes invisible and sneaks up on the enemy when he clicks to attack. I wonder if there is any function to activate this only if the enemy is melee.

Explaining the spell: Conjuring it works like a utana vid for a short period, in case you attack someone you move behind the target and cause damage. I wish I had a way to limit this distance so it would not become a spell where the user could cross walls.

Here is the script

Code:
local condition = createConditionObject(CONDITION_INVISIBLE)
setConditionParam(condition, CONDITION_PARAM_TICKS, 5000)
local function isWalkable(cid, pos)
    pos.stackpos = 253
    if doTileQueryAdd(cid, pos) == 1 then -- checks if we can add cid to a position of choice
        return true
    end
    return false
end
local function jumpBehindTarget(cid, target)
    local tPos = getCreaturePosition(target)
    local tPositions = {
        north = {x = tPos.x, y = tPos.y - 1, z = tPos.z},
        east = {x = tPos.x + 1, y = tPos.y, z = tPos.z},
        west = {x = tPos.x - 1, y = tPos.y, z = tPos.z},
        south = {x = tPos.x, y = tPos.y + 1, z = tPos.z}
    }
    local tDir = getPlayerLookDir(target)
    if tDir == NORTH then
        dir = tPositions.south
    elseif tDir == EAST then
        dir = tPositions.west
    elseif tDir == WEST then
        dir = tPositions.east
    elseif tDir == SOUTH then
        dir = tPositions.north
    end
    return dir
end
local function checkHasTarget(cid, count, oldPos)
    local target = getCreatureTarget(cid)
    if target ~= 0 then
        local behindTarget = jumpBehindTarget(cid, target)
        if isWalkable(cid, behindTarget) then
            doTeleportThing(cid, behindTarget)
            --addEvent(doTeleportThing, 100, cid, oldPos)
        else
            doTeleportThing(cid, getCreaturePosition(target))
            --addEvent(doTeleportThing, 100, cid, oldPos)
        end
        doCreatureSetLookDir(cid, getPlayerLookDir(target))
        doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -20, -100, CONST_ME_FIREATTACK)
        doRemoveCondition(cid, CONDITION_INVISIBLE)
        return true
    end
    addEvent(checkHasTarget, 100, cid, count - 1, getCreaturePosition(cid))
end
function onCastSpell(cid, var)
    local pPos = getCreaturePosition(cid)
    doSendMagicEffect(pPos, CONST_ME_POFF)
    doAddCondition(cid, condition)
    addEvent(checkHasTarget, 50, cid, 50, pPos)
    return true
end

Thanks for listening
 
Last edited:
Solution
Im getting a loop error when logout after cast the spell and before hit the enemy.

Code:
[28/12/2017 09:52:02] [Error - Spell Interface]
[28/12/2017 09:52:02] In a timer event called from:
[28/12/2017 09:52:02] data/spells/scripts/attack/sneakattack.lua:onCastSpell
[28/12/2017 09:52:02] Description:
[28/12/2017 09:52:02] (luaGetCreatureStorage) Creature not found
Lua:
local function checkHasTarget(cid, count, oldPos)
    local target = getCreatureTarget(cid)
Lua:
local function checkHasTarget(cid, count, oldPos)
    if not isPlayer(cid) then
        return true
    ned
    local target = getCreatureTarget(cid)
not in this case, its works like a buff. Just after u target the enemy teleport to behind the target;
tried using area formula?
--
just ignore didn't read the thread

i think there's a spell like this around

imo you're not working with range since the spell trigger when the target is targeted
 
Last edited by a moderator:
Is this what your looking for?
Lua:
function getDistanceBetween(firstPosition, secondPosition)
    local xDif = math.abs(firstPosition.x - secondPosition.x)
    local yDif = math.abs(firstPosition.y - secondPosition.y)
    local posDif = math.max(xDif, yDif)
    if(firstPosition.z ~= secondPosition.z) then
        posDif = posDif + 9 + 6
    end
    return posDif
end
 
Is this what your looking for?
Lua:
function getDistanceBetween(firstPosition, secondPosition)
    local xDif = math.abs(firstPosition.x - secondPosition.x)
    local yDif = math.abs(firstPosition.y - secondPosition.y)
    local posDif = math.max(xDif, yDif)
    if(firstPosition.z ~= secondPosition.z) then
        posDif = posDif + 9 + 6
    end
    return posDif
end

Yep, but how can i use this as condition, heare is how o did try:

Code:
local condition = createConditionObject(CONDITION_INVISIBLE)
setConditionParam(condition, CONDITION_PARAM_TICKS, 5000)
local function isWalkable(cid, pos)
    pos.stackpos = 253
    if doTileQueryAdd(cid, pos) == 1 then -- checks if we can add cid to a position of choice
        return true
    end
    return false
end
local function jumpBehindTarget(cid, target)
    local tPos = getCreaturePosition(target)
    local tPositions = {
        north = {x = tPos.x, y = tPos.y - 1, z = tPos.z},
        east = {x = tPos.x + 1, y = tPos.y, z = tPos.z},
        west = {x = tPos.x - 1, y = tPos.y, z = tPos.z},
        south = {x = tPos.x, y = tPos.y + 1, z = tPos.z}
    }
    local tDir = getPlayerLookDir(target)
    if tDir == NORTH then
        dir = tPositions.south
    elseif tDir == EAST then
        dir = tPositions.west
    elseif tDir == WEST then
        dir = tPositions.east
    elseif tDir == SOUTH then
        dir = tPositions.north
    end
    return dir
end

function getDistanceBetween(firstPosition, secondPosition)
    local xDif = math.abs(firstPosition.x - secondPosition.x)
    local yDif = math.abs(firstPosition.y - secondPosition.y)
    local posDif = math.max(xDif, yDif)
    if(firstPosition.z ~= secondPosition.z) then
        posDif = posDif + 9 + 6
    end
    return posDif
end
local function checkHasTarget(cid, count, oldPos)
    local target = getCreatureTarget(cid)
    if target ~= 0 and getPlayerStorageValue(cid, 4451) == 0 and posDif == 1 then
        local behindTarget = jumpBehindTarget(cid, target)
        if isWalkable(cid, behindTarget) then
            doTeleportThing(cid, behindTarget)
            --addEvent(doTeleportThing, 100, cid, oldPos)
        else
            doTeleportThing(cid, getCreaturePosition(target))
            --addEvent(doTeleportThing, 100, cid, oldPos)
        end
        doCreatureSetLookDir(cid, getPlayerLookDir(target))
        doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -20, -100, CONST_ME_FIREATTACK)
        doRemoveCondition(cid, CONDITION_INVISIBLE)
        return true
    end
    addEvent(checkHasTarget, 100, cid, count - 1, getCreaturePosition(cid))
end
function onCastSpell(cid, var)
    local pPos = getCreaturePosition(cid)
    setPlayerStorageValue(cid, 4451, 0)
    addEvent(setPlayerStorageValue, 6*1000, cid, 4451, -1)
    doSendMagicEffect(pPos, CONST_ME_POFF)
    doAddCondition(cid, condition)
    addEvent(checkHasTarget, 50, cid, 50, pPos)
    return true
end

String 42.
 
Yep, but how can i use this as condition, heare is how o did try:

Code:
local condition = createConditionObject(CONDITION_INVISIBLE)
setConditionParam(condition, CONDITION_PARAM_TICKS, 5000)
local function isWalkable(cid, pos)
    pos.stackpos = 253
    if doTileQueryAdd(cid, pos) == 1 then -- checks if we can add cid to a position of choice
        return true
    end
    return false
end
local function jumpBehindTarget(cid, target)
    local tPos = getCreaturePosition(target)
    local tPositions = {
        north = {x = tPos.x, y = tPos.y - 1, z = tPos.z},
        east = {x = tPos.x + 1, y = tPos.y, z = tPos.z},
        west = {x = tPos.x - 1, y = tPos.y, z = tPos.z},
        south = {x = tPos.x, y = tPos.y + 1, z = tPos.z}
    }
    local tDir = getPlayerLookDir(target)
    if tDir == NORTH then
        dir = tPositions.south
    elseif tDir == EAST then
        dir = tPositions.west
    elseif tDir == WEST then
        dir = tPositions.east
    elseif tDir == SOUTH then
        dir = tPositions.north
    end
    return dir
end

function getDistanceBetween(firstPosition, secondPosition)
    local xDif = math.abs(firstPosition.x - secondPosition.x)
    local yDif = math.abs(firstPosition.y - secondPosition.y)
    local posDif = math.max(xDif, yDif)
    if(firstPosition.z ~= secondPosition.z) then
        posDif = posDif + 9 + 6
    end
    return posDif
end
local function checkHasTarget(cid, count, oldPos)
    local target = getCreatureTarget(cid)
    if target ~= 0 and getPlayerStorageValue(cid, 4451) == 0 and posDif == 1 then
        local behindTarget = jumpBehindTarget(cid, target)
        if isWalkable(cid, behindTarget) then
            doTeleportThing(cid, behindTarget)
            --addEvent(doTeleportThing, 100, cid, oldPos)
        else
            doTeleportThing(cid, getCreaturePosition(target))
            --addEvent(doTeleportThing, 100, cid, oldPos)
        end
        doCreatureSetLookDir(cid, getPlayerLookDir(target))
        doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -20, -100, CONST_ME_FIREATTACK)
        doRemoveCondition(cid, CONDITION_INVISIBLE)
        return true
    end
    addEvent(checkHasTarget, 100, cid, count - 1, getCreaturePosition(cid))
end
function onCastSpell(cid, var)
    local pPos = getCreaturePosition(cid)
    setPlayerStorageValue(cid, 4451, 0)
    addEvent(setPlayerStorageValue, 6*1000, cid, 4451, -1)
    doSendMagicEffect(pPos, CONST_ME_POFF)
    doAddCondition(cid, condition)
    addEvent(checkHasTarget, 50, cid, 50, pPos)
    return true
end

String 42.
try
Lua:
if target ~= 0 and getPlayerStorageValue(cid, 4451) == 0 and getDistanceBetween(getThingPosition(cid), getThingPosition(target)) == 1 then
 
try
Lua:
if target ~= 0 and getPlayerStorageValue(cid, 4451) == 0 and getDistanceBetween(getThingPosition(cid), getThingPosition(target)) == 1 then

Thank alot heare is the full script for those who want to solve something like this

Lua:
local condition = createConditionObject(CONDITION_INVISIBLE)
setConditionParam(condition, CONDITION_PARAM_TICKS, 5000)
local function isWalkable(cid, pos)
    pos.stackpos = 253
    if doTileQueryAdd(cid, pos) == 1 then -- checks if we can add cid to a position of choice
        return true
    end
    return false
end
local function jumpBehindTarget(cid, target)
    local tPos = getCreaturePosition(target)
    local tPositions = {
        north = {x = tPos.x, y = tPos.y - 1, z = tPos.z},
        east = {x = tPos.x + 1, y = tPos.y, z = tPos.z},
        west = {x = tPos.x - 1, y = tPos.y, z = tPos.z},
        south = {x = tPos.x, y = tPos.y + 1, z = tPos.z}
    }
    local tDir = getPlayerLookDir(target)
    if tDir == NORTH then
        dir = tPositions.south
    elseif tDir == EAST then
        dir = tPositions.west
    elseif tDir == WEST then
        dir = tPositions.east
    elseif tDir == SOUTH then
        dir = tPositions.north
    end
    return dir
end

function getDistanceBetween(firstPosition, secondPosition)
    local xDif = math.abs(firstPosition.x - secondPosition.x)
    local yDif = math.abs(firstPosition.y - secondPosition.y)
    local posDif = math.max(xDif, yDif)
    if(firstPosition.z ~= secondPosition.z) then
        posDif = posDif + 9 + 6
    end
    return posDif
end
local function checkHasTarget(cid, count, oldPos)
    local target = getCreatureTarget(cid)
        if target ~= 0 and getPlayerStorageValue(cid, 4451) == 0 and getDistanceBetween(getThingPosition(cid), getThingPosition(target)) == 1 then
        local behindTarget = jumpBehindTarget(cid, target)
        if isWalkable(cid, behindTarget) then
            doTeleportThing(cid, behindTarget)
            --addEvent(doTeleportThing, 100, cid, oldPos)
        else
            doTeleportThing(cid, getCreaturePosition(target))
            --addEvent(doTeleportThing, 100, cid, oldPos)
        end
        doCreatureSetLookDir(cid, getPlayerLookDir(target))
        doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -20, -100, CONST_ME_FIREATTACK)
        doRemoveCondition(cid, CONDITION_INVISIBLE)
        return true
    end
    addEvent(checkHasTarget, 100, cid, count - 1, getCreaturePosition(cid))
end
function onCastSpell(cid, var)
    local pPos = getCreaturePosition(cid)
    setPlayerStorageValue(cid, 4451, 0)
    addEvent(setPlayerStorageValue, 6*1000, cid, 4451, -1)
    doSendMagicEffect(pPos, CONST_ME_POFF)
    doAddCondition(cid, condition)
    addEvent(checkHasTarget, 50, cid, 50, pPos)
    return true
end

try
Lua:
if target ~= 0 and getPlayerStorageValue(cid, 4451) == 0 and getDistanceBetween(getThingPosition(cid), getThingPosition(target)) == 1 then

Im getting a loop error when logout after cast the spell and before hit the enemy.

Code:
[28/12/2017 09:52:02] [Error - Spell Interface]
[28/12/2017 09:52:02] In a timer event called from:
[28/12/2017 09:52:02] data/spells/scripts/attack/sneakattack.lua:onCastSpell
[28/12/2017 09:52:02] Description:
[28/12/2017 09:52:02] (luaGetCreatureStorage) Creature not found
 
Last edited by a moderator:
Im getting a loop error when logout after cast the spell and before hit the enemy.

Code:
[28/12/2017 09:52:02] [Error - Spell Interface]
[28/12/2017 09:52:02] In a timer event called from:
[28/12/2017 09:52:02] data/spells/scripts/attack/sneakattack.lua:onCastSpell
[28/12/2017 09:52:02] Description:
[28/12/2017 09:52:02] (luaGetCreatureStorage) Creature not found
Lua:
local function checkHasTarget(cid, count, oldPos)
    local target = getCreatureTarget(cid)
Lua:
local function checkHasTarget(cid, count, oldPos)
    if not isPlayer(cid) then
        return true
    ned
    local target = getCreatureTarget(cid)
 
Solution
Seems to be perfect ! Thanks alot. Heare's the final code:

Lua:
local condition = createConditionObject(CONDITION_INVISIBLE)
setConditionParam(condition, CONDITION_PARAM_TICKS, 5000)
local function isWalkable(cid, pos)
    pos.stackpos = 253
    if doTileQueryAdd(cid, pos) == 1 then -- checks if we can add cid to a position of choice
        return true
    end
    return false
end
local function jumpBehindTarget(cid, target)
    local tPos = getCreaturePosition(target)
    local tPositions = {
        north = {x = tPos.x, y = tPos.y - 1, z = tPos.z},
        east = {x = tPos.x + 1, y = tPos.y, z = tPos.z},
        west = {x = tPos.x - 1, y = tPos.y, z = tPos.z},
        south = {x = tPos.x, y = tPos.y + 1, z = tPos.z}
    }
    local tDir = getPlayerLookDir(target)
    if tDir == NORTH then
        dir = tPositions.south
    elseif tDir == EAST then
        dir = tPositions.west
    elseif tDir == WEST then
        dir = tPositions.east
    elseif tDir == SOUTH then
        dir = tPositions.north
    end
    return dir
end

function getDistanceBetween(firstPosition, secondPosition)
    local xDif = math.abs(firstPosition.x - secondPosition.x)
    local yDif = math.abs(firstPosition.y - secondPosition.y)
    local posDif = math.max(xDif, yDif)
    if(firstPosition.z ~= secondPosition.z) then
        posDif = posDif + 9 + 6
    end
    return posDif
end
local function checkHasTarget(cid, count, oldPos)
    if not isPlayer(cid) then
        return true
    end
    local target = getCreatureTarget(cid)
    if target ~= 0 and getPlayerStorageValue(cid, 4451) == 0 and getDistanceBetween(getThingPosition(cid), getThingPosition(target)) == 1 then
        local behindTarget = jumpBehindTarget(cid, target)
        if isWalkable(cid, behindTarget) then
            doTeleportThing(cid, behindTarget)
            --addEvent(doTeleportThing, 100, cid, oldPos)
        else
            doTeleportThing(cid, getCreaturePosition(target))
            --addEvent(doTeleportThing, 100, cid, oldPos)
        end
        doCreatureSetLookDir(cid, getPlayerLookDir(target))
        doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -20, -100, CONST_ME_FIREATTACK)
        doRemoveCondition(cid, CONDITION_INVISIBLE)
        return true
    end
    addEvent(checkHasTarget, 100, cid, count - 1, getCreaturePosition(cid))
end
function onCastSpell(cid, var)
    local pPos = getCreaturePosition(cid)
    setPlayerStorageValue(cid, 4451, 0)
    addEvent(setPlayerStorageValue, 6*1000, cid, 4451, -1)
    doSendMagicEffect(pPos, CONST_ME_POFF)
    doAddCondition(cid, condition)
    addEvent(checkHasTarget, 50, cid, 50, pPos)
    return true
end

May i ask you why the

Lua:
  posDif = posDif + 9 + 6

Those 9 and 6 what is their purpose?
 
Seems to be perfect ! Thanks alot. Heare's the final code:

Lua:
local condition = createConditionObject(CONDITION_INVISIBLE)
setConditionParam(condition, CONDITION_PARAM_TICKS, 5000)
local function isWalkable(cid, pos)
    pos.stackpos = 253
    if doTileQueryAdd(cid, pos) == 1 then -- checks if we can add cid to a position of choice
        return true
    end
    return false
end
local function jumpBehindTarget(cid, target)
    local tPos = getCreaturePosition(target)
    local tPositions = {
        north = {x = tPos.x, y = tPos.y - 1, z = tPos.z},
        east = {x = tPos.x + 1, y = tPos.y, z = tPos.z},
        west = {x = tPos.x - 1, y = tPos.y, z = tPos.z},
        south = {x = tPos.x, y = tPos.y + 1, z = tPos.z}
    }
    local tDir = getPlayerLookDir(target)
    if tDir == NORTH then
        dir = tPositions.south
    elseif tDir == EAST then
        dir = tPositions.west
    elseif tDir == WEST then
        dir = tPositions.east
    elseif tDir == SOUTH then
        dir = tPositions.north
    end
    return dir
end

function getDistanceBetween(firstPosition, secondPosition)
    local xDif = math.abs(firstPosition.x - secondPosition.x)
    local yDif = math.abs(firstPosition.y - secondPosition.y)
    local posDif = math.max(xDif, yDif)
    if(firstPosition.z ~= secondPosition.z) then
        posDif = posDif + 9 + 6
    end
    return posDif
end
local function checkHasTarget(cid, count, oldPos)
    if not isPlayer(cid) then
        return true
    end
    local target = getCreatureTarget(cid)
    if target ~= 0 and getPlayerStorageValue(cid, 4451) == 0 and getDistanceBetween(getThingPosition(cid), getThingPosition(target)) == 1 then
        local behindTarget = jumpBehindTarget(cid, target)
        if isWalkable(cid, behindTarget) then
            doTeleportThing(cid, behindTarget)
            --addEvent(doTeleportThing, 100, cid, oldPos)
        else
            doTeleportThing(cid, getCreaturePosition(target))
            --addEvent(doTeleportThing, 100, cid, oldPos)
        end
        doCreatureSetLookDir(cid, getPlayerLookDir(target))
        doTargetCombatHealth(cid, target, COMBAT_PHYSICALDAMAGE, -20, -100, CONST_ME_FIREATTACK)
        doRemoveCondition(cid, CONDITION_INVISIBLE)
        return true
    end
    addEvent(checkHasTarget, 100, cid, count - 1, getCreaturePosition(cid))
end
function onCastSpell(cid, var)
    local pPos = getCreaturePosition(cid)
    setPlayerStorageValue(cid, 4451, 0)
    addEvent(setPlayerStorageValue, 6*1000, cid, 4451, -1)
    doSendMagicEffect(pPos, CONST_ME_POFF)
    doAddCondition(cid, condition)
    addEvent(checkHasTarget, 50, cid, 50, pPos)
    return true
end

May i ask you why the

Lua:
  posDif = posDif + 9 + 6

Those 9 and 6 what is their purpose?
Not sure tbh.
I found the code here on OtLand quite awhile ago.
It's always worked flawlessly though, so I just assume some really smart person knows what they were doing. xP
 
Looks like it adds approx. one additional size of a game screen to the posDif outcome, in case when positions are on different floors.
 
Back
Top