• 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 1.X+ Summons teleporting faster (onThink too slow)

Mjmackan

Mapper ~ Writer
Premium User
Joined
Jul 18, 2009
Messages
1,424
Solutions
15
Reaction score
176
Location
Sweden
What would be the best way to create a faster way for summons to follow a player?
Is it possible to add something in movements somehow?

Right now I have it in creaturescripts:eek:nThink and it works but since the onThink is slow it takes years before responding. Reducing the onThink in sources creates bugs with monsters not moving at all.

Script im using:
Lua:
function onStepIn(creature)
    local master = creature:getMaster()
    if not master then return true end

    local pos = creature:getPosition()
    local master_pos = master:getPosition()
    local master_teleport = {x=(master_pos.x+(math.random(-1,1))),y=(master_pos.y),z=(master_pos.z)}
    if getDistanceBetween(pos, master_pos) > 1 or master_pos.z ~= pos.z then
        if creature:teleportTo(master_teleport, true) then
        end
    end
    return true
end
 
Last edited:
Solution
Here is a example how you can achive it. If you dont want to make any source edits.
Replace: otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/data/lib/core/creature.lua#L97)

Lua:
function teleportSummon(summonId, masterId)
    local summon = Monster(summonId)
    if not summon then
        return
    end

    local master = Creature(masterId)
    if not master then
        return
    end

    local maxDistance = 7
    local position = summon:getPosition()
    local masterPosition = master:getPosition()

    if position.z ~= masterPosition.z or position:getDistance(masterPosition) >= maxDistance then
        local tile = Tile(masterPosition)
        if tile and not tile:hasFlag(TILESTATE_PROTECTIONZONE)...
Here is a example how you can achive it. If you dont want to make any source edits.
Replace: otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/data/lib/core/creature.lua#L97)

Lua:
function teleportSummon(summonId, masterId)
    local summon = Monster(summonId)
    if not summon then
        return
    end

    local master = Creature(masterId)
    if not master then
        return
    end

    local maxDistance = 7
    local position = summon:getPosition()
    local masterPosition = master:getPosition()

    if position.z ~= masterPosition.z or position:getDistance(masterPosition) >= maxDistance then
        local tile = Tile(masterPosition)
        if tile and not tile:hasFlag(TILESTATE_PROTECTIONZONE) then
            position:sendMagicEffect(CONST_ME_TELEPORT)
            summon:teleportTo(masterPosition)
            summon:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
        end
    end
end

function Creature:addSummon(monster)
    local summon = Monster(monster)
    if not summon then
        return false
    end

    summon:setTarget(nil)
    summon:setFollowCreature(nil)
    summon:setDropLoot(false)
    summon:setSkillLoss(false)
    summon:setMaster(self)
    summon:getPosition():notifySummonAppear(summon)
    addEvent(teleportSummon, 100, summon.uid, self.uid)
    return true
end
 
Last edited:
Solution
Here is a example how you can achive it. If you dont want to make any source edits.
Replace: otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/data/lib/core/creature.lua#L97)

Lua:
function teleportSummon(summonId, masterId)
    local summon = Summon(summonId)
    if not summon then
        return
    end

    local master = Creature(masterId)
    if not master then
        return
    end

    local maxDistance = 7
    local position = summon:getPosition()
    local masterPosition = master:getPosition()

    if position.z ~= masterPosition.z or position:getDistance(masterPosition) >= maxDistance then
        position:sendMagicEffect(CONST_ME_TELEPORT)
        summon:teleportTo(masterPosition)
        summon:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
    end
end

function Creature:addSummon(monster)
    local summon = Monster(monster)
    if not summon then
        return false
    end

    summon:setTarget(nil)
    summon:setFollowCreature(nil)
    summon:setDropLoot(false)
    summon:setSkillLoss(false)
    summon:setMaster(self)
    summon:getPosition():notifySummonAppear(summon)
    addEvent(teleportSummon, 100, summon.uid, self.uid)
    return true
end

Thanks, thats great, I have no issue with source edits, but I do think it will get a bit complex since I dont want to use same system for all summons.

What Im seeking is actually just a summon that will follow the player everywhere, teleporting might look dumb if it isnt executed fast enough, not sure, but will have to try what you posted. Im welcoming all other ideas such as source edits aswell.

On a sidenote: Where can i check when players walks out of PZ to spawn x summon since I believe inside PZ wouldn't work. Or do we need addevent loops for that aswell? It seems like it would slow down the server a bit if 100x players have their individual loop?



Edit: bug on above code.(couldnt use code tags, not sure why) error occurs while summoning a monster.
Lua Script Error: [Main Interface]
in a timer event called from:
(Unknown scriptfile)
data/lib/core/creature.lua:98: attempt to call global 'Summon' (a nil value)
stack traceback:
[C]: in function 'Summon'
data/lib/core/creature.lua:98: in function <data/lib/core/creature.lua:97>
 
Last edited:
Thanks, thats great, I have no issue with source edits, but I do think it will get a bit complex since I dont want to use same system for all summons.

What Im seeking is actually just a summon that will follow the player everywhere, teleporting might look dumb if it isnt executed fast enough, not sure, but will have to try what you posted. Im welcoming all other ideas such as source edits aswell.

On a sidenote: Where can i check when players walks out of PZ to spawn x summon since I believe inside PZ wouldn't work. Or do we need addevent loops for that aswell? It seems like it would slow down the server a bit if 100x players have their individual loop?



Edit: bug on above code.(couldnt use code tags, not sure why)
Lua Script Error: [Main Interface]
in a timer event called from:
(Unknown scriptfile)
data/lib/core/creature.lua:98: attempt to call global 'Summon' (a nil value)
stack traceback:
[C]: in function 'Summon'
data/lib/core/creature.lua:98: in function <data/lib/core/creature.lua:97>
Updated post
 
I tested the @Printer script and it works fine, I tried it like this:

Lua:
function followTeleportMaster(cid)
    local creature = Creature(cid)
    if creature then
        local master = creature:getMaster()
        if master then
            local masterPos, creaturePos = master:getPosition(), creature:getPosition()
            if masterPos.z ~= creaturePos.z or masterPos:getDistance(creaturePos) >= 7 then
                local tile = Tile(masterPos)
                if tile and not tile:hasFlag(TILESTATE_PROTECTIONZONE) then
                    creaturePos:sendMagicEffect(CONST_ME_POFF)
                    creature:teleportTo(masterPos)
                    masterPos:sendMagicEffect(CONST_ME_TELEPORT)
                end
            end
            addEvent(followTeleportMaster, 500, cid)
        end
    end
end

local talkTest = TalkAction("/tt")

function talkTest.onSay(player, words, param, type)
    local monster = Game.createMonster("rat", player:getPosition())
    if monster then
        player:addSummon(monster)
        followTeleportMaster(monster:getId())
    end
    return false
end

I recommend that you do not change this function:
function Creature:addSummon(monster)
as it is not necessary for your purpose to just add this tracking to a single particular monster
 
I tested the @Printer script and it works fine, I tried it like this:

Lua:
function followTeleportMaster(cid)
    local creature = Creature(cid)
    if creature then
        local master = creature:getMaster()
        if master then
            local masterPos, creaturePos = master:getPosition(), creature:getPosition()
            if masterPos.z ~= creaturePos.z or masterPos:getDistance(creaturePos) >= 7 then
                local tile = Tile(masterPos)
                if tile and not tile:hasFlag(TILESTATE_PROTECTIONZONE) then
                    creaturePos:sendMagicEffect(CONST_ME_POFF)
                    creature:teleportTo(masterPos)
                    masterPos:sendMagicEffect(CONST_ME_TELEPORT)
                end
            end
            addEvent(followTeleportMaster, 500, cid)
        end
    end
end

local talkTest = TalkAction("/tt")

function talkTest.onSay(player, words, param, type)
    local monster = Game.createMonster("rat", player:getPosition())
    if monster then
        player:addSummon(monster)
        followTeleportMaster(monster:getId())
    end
    return false
end

I recommend that you do not change this function:
function Creature:addSummon(monster)
as it is not necessary for your purpose to just add this tracking to a single particular monster
It works like a charm, did exactly as you wrote. BUT! The original idea i had was to make the summon "move" towards the player faster, is it possible to instead of teleport. Trying to pathfind to the character or something? This script is doing whats intended.
But its not what Im looking for, I want the summons to actually follow the player, the onThink is way to slow for that, makes the monster stand still in 2 minutes then trying to follow the master. Is it possible to add an pathfinding into this addEvent aswell making the summon react faster?
 
Back
Top