• 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 Check if specified monster is in specified position

mark87

New Member
Joined
May 29, 2023
Messages
1
Reaction score
0
I'm making a simple waypoints system and I need to check if a specified monster is on specified position(to move creature to the next waypoint).

I think I need to pass a monster cid to function and then check if this monster current position exists in waypoints array, but I can't find a way to do this.

Maybe I need to use onStepIn() but I'm not sure if it works the way as I think.

Any ideas would be appreciated.
 
Entirely depends on how you want to trigger it..

But if the monster is supposed to be autonomous, make an onThink event for the monster.

I'm not sure what you're trying to do, so here's some generic code to get you moving.

Lua:
local waypoints = {
    Position(1000, 1000, 7),
    Position(1000, 1000, 7),
    Position(1000, 1000, 7)
}

local function checkNode(creatureId, currentNode, minimumNodeDistance, repeatNodes)
    local creature = Creature(creatureId)
    if not creature then
        return
    end
    
    local distanceToNode = creature:getPosition:getDistance(waypoints[currentNode])
    if distanceToNode <= minimumNodeDistance then
        -- reached node, move on to next
        currentNode = currentNode + 1
        if currentNode > #waypoints then
            -- reached end of nodes
            if not repeatNodes then
                -- exit
                return
            end
            -- restart from beginning of node list / loop
            currentNode = 1
        end
    end
    
    return
end
Lua:
-- pseudo code
function onThink(creature)
    local currentNode = creature:getStorage?
    local minimumNodeDistance = 1
    local repeatNodes = true
    checkNode(creature:getId(), currentNode, minimumNodeDistance, repeatNodes)
    return true
end
 
I'm making a simple waypoints system and I need to check if a specified monster is on specified position(to move creature to the next waypoint).

I think I need to pass a monster cid to function and then check if this monster current position exists in waypoints array, but I can't find a way to do this.

Maybe I need to use onStepIn() but I'm not sure if it works the way as I think.

Any ideas would be appreciated.
Please remember to mention which version you are using, otherwise you may not get an accurate answer. No one is a mind-reader 🔮
 
I'm using 1.4.2 and I have some questions about onThink() event

1. Does it run when monster is not in combat? Does it need to not have targetList empty to work?
pic rel:
1686483900376.png


2. Does this event run for every monster based on interval set somewhere inside source files? Or do I have to implement it for every monster type?

3. From what I see, there's no examples of implementation of this event in tfs script files. Can you tell me if my implementation is correct?

a) Inside tfs\data\creaturescripts\creaturescripts.xml add
XML:
<event type="think" name="WaypointsSystem" script="waypointssystem.lua" />

b) Inside tfs\data\creaturescripts\scripts\waypointssystem.lua
Lua:
function onThink(creature)
    if creature:isMonster() then
       -- check monster:getTargetCount() == 0(?), other custom checks to select correct waypoints list, monster:moveTo(waypoint) code here
      print("test")
    end
end

Of course I couldn't even make it to print anything so there's something I don't understand.
 
Last edited:
(Second post because previous got blocked by filter)

I'm using 1.4.2 and I have some questions about onThink() event

1. Does it run when monster is not in combat? Does it need to not have targetList empty to work?
pic rel:
View attachment 76086


2. Does this event run for every monster based on interval set somewhere inside source files? Or do I have to implement it for every monster type?

3. From what I see, there's no examples of implementation of this event in tfs script files. Can you tell me if my implementation is correct?

a) Inside tfs\data\creaturescripts\creaturescripts.xml add
XML:
<event type="think" name="WaypointsSystem" script="waypointssystem.lua" />

b) Inside tfs\data\creaturescripts\scripts\waypointssystem.lua
Lua:
function onThink(creature)
    if creature:isMonster() then
       -- check monster:getTargetCount() == 0(?), other custom checks to select correct waypoints list, monster:moveTo(waypoint) code here
      print("test")
    end
end

Of course I couldn't even make it to print anything so there's something I don't understand.
 
(Second post because previous got blocked by filter)

I'm using 1.4.2 and I have some questions about onThink() event

1. Does it run when monster is not in combat? Does it need to not have targetList empty to work?
pic rel:
View attachment 76086


2. Does this event run for every monster based on interval set somewhere inside source files? Or do I have to implement it for every monster type?

3. From what I see, there's no examples of implementation of this event in tfs script files. Can you tell me if my implementation is correct?

a) Inside tfs\data\creaturescripts\creaturescripts.xml add
XML:
<event type="think" name="WaypointsSystem" script="waypointssystem.lua" />

b) Inside tfs\data\creaturescripts\scripts\waypointssystem.lua
Lua:
function onThink(creature)
    if creature:isMonster() then
       -- check monster:getTargetCount() == 0(?), other custom checks to select correct waypoints list, monster:moveTo(waypoint) code here
      print("test")
    end
end

Of course I couldn't even make it to print anything so there's something I don't understand.
the onThink event in creatures is executed approximately 1 time per second, and if this interval is defined in the sources.

if the monster is inactive, this event will not be executed.
 
if the monster is inactive, this event will not be executed.
But what does inactive mean? That monster target list is empty? I'm still confused why it's getting recommended for handling monster walk when going by that logic it won't even be executed? Or maybe Xikini is right and I'm missing something?

I'm also thinking about making the monsters permanently active because my use case doesn't need to worry about performance much(small number of monsters on server). I looked inside source files and onThink() function but on first look I couldn't find any simple solution.
 
But what does inactive mean? That monster target list is empty? I'm still confused why it's getting recommended for handling monster walk when going by that logic it won't even be executed? Or maybe Xikini is right and I'm missing something?

I'm also thinking about making the monsters permanently active because my use case doesn't need to worry about performance much(small number of monsters on server). I looked inside source files and onThink() function but on first look I couldn't find any simple solution.
It's not printing, because you didn't register it in the monster, I think.

you can use onSpawn to register it to the monsters globally..
Or if attaching to a specific creature.. via lua, both would use this line
Lua:
creature:registerEvent("name_of_creatureEvent")
single monsters you can put it into the monsters.xml file like this..
XML:
<script>
    <event name="name_of_creatureEvent" />
</script>

About onThink itself.. yeah it's only when the monster is classified as active.
I haven't attempted to read the source code, but what happens in-game, is that it only triggers when a player is nearby, and the creature 'wakes up', doing normal auto walking stuff.

I'd say like.. 30 tiles away, +- a floor. (unless it's floor 7 or 6) then it's just -1/+1 floor, cuz of that interaction.
And probably would also not trigger on a god?

So unless you can read and alter source code..
My work-around to this, if you need it to always be active.. or least always be able to trigger..
Would be to make a looping addEvent.

Lua:
addEvent(loopingFunction, 1000, creature:getId())
Lua:
local function loopingFunction(creatureId)
    local creature = Creature(creatureId)
    if not creature then
        return
    end
    print("Working.")
    addEvent(loopingFunction, 1000, creatureId)
end
And then you would 'attach' this to any creature you want, and would replace your onThink event entirely.

The only caveat to the above solution, is that even tho we are setting the timer to trigger every 1000 milliseconds, is that it's 1000ms + time to execute the functions up to that point. (1001 milliseconds.. and over 1000 seconds, it would trigger 1 less time then expected)

So generally it'll be slightly slower then once per second.. where onThink is triggered via source, every 1 second, based on the runtime of the application.

But that minor time discrepancy won't really be an issue because we're waiting for the monster to walk around anyway.
 
Last edited:
But what does inactive mean? That monster target list is empty? I'm still confused why it's getting recommended for handling monster walk when going by that logic it won't even be executed? Or maybe Xikini is right and I'm missing something?

I'm also thinking about making the monsters permanently active because my use case doesn't need to worry about performance much(small number of monsters on server). I looked inside source files and onThink() function but on first look I couldn't find any simple solution.
If there are no spectators, what's the point of the monster being active doing some things? It's not just about performance, but rather about logic.

In theory, if you use the function setIdle(false) you can keep the monster active.

You also have another option, which is to add an aggressive condition with infinite time. It doesn't necessarily have to be a condition that causes damage, just a condition that does nothing.

or using addEvent how Xikini mentioned.
 
If there are no spectators, what's the point of the monster being active doing some things? It's not just about performance, but rather about logic.
For classic tibia it doesn't have many uses, but It could be used for some custom features like arenas.

I used the addEvent way because it seemed the fastest to implement. It may not be the most optimal, but it works for prototyping purposes and with some additional code like checking monster target list and using moveTo() the monster can be made "pseudo autonomous".

Mods can mark the thread as solved.
 
Back
Top