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

NPC Guard NPC v0.1 (1.0, should work for 0.3.X)

What kind of errors do you get?
Did you maybe changed different things than I posted?

The first 2 are just for the function with getThingPos, it's added 2x.
Code:
local position = getThingPos(nid)

opos = getThingPos(nid)
So just change those 2.
 
As I've said, Im using TFS 1.1, when I try to adapt the check_target function with nid:getPosition() or Creature(nid):getPosition(), in the first case it return me attempt to index a number value, and at the second attempt to index a nill value. Both erros are related with __index function.
 
It's added 2x, change the one in function onCreatureAppear aswell, if you don't change that one and only change the one in check_target, it will spam errors with attempt to index a number value.
Code:
function onCreatureAppear(cid)
    if isNpc(cid) then
        nid = cid
        opos = nid:getPosition() -- this line should be changed, it was with getThingPos before
    end
end
 
Code:
-- config
local npcname = "Townguard Steve" --Name of your guard NPC
local maxdmg = 500  -- maximum dmg dealt
local mindmg = 200 -- minimum dmg dealt
local speed = 200 -- NPC will follow target every 0.2 seconds (that's "ok" fast)
local atkspeed = 1 -- 1= 1 attack per second (!lowest value!) 2= 1 attack per 2 seconds, 3= 1 attack per 3 seconds,...
local maxchase = 12 -- 12 tiles chase length (depends on PZs, spawnpoint from NPC, surroundings,...
local area = 4 -- 4x4 area will be checked for monsters/players (6 is too much in my oppinion)

-- texts
local lost = {"I'll get you next time!","I'm to old for this..","Run, coward, RUN!"} -- text if NPC lost target
local ktext = {"One for me!","...unworthy!","Bad luck!"} -- text if NPC kills the target
local ctext = {"I'm here to help!","Let me handle this!","Die!"} -- text while NPC is in battle (talktype orange!)
local ttext = {"Come out ","You coward ","I'll be waiting for you "} -- taunt if player walks into PZ


-- Do not edit if you have no clue what you're doing!
local hit = 0
local target = 0
local opos = 0
local nid = 0
local spec = {}
local kill = 0
local pz = 0
local tpos = 0
local npos = 0


local function goback(nid, opos)
   if (kill == 0) and (pz == 0) then
     selfSay(lost[math.random(1,#lost)])
   end
doSendMagicEffect(getCreaturePosition(nid), 2)
doTeleportThing(nid, opos, false)
doSendMagicEffect(getCreaturePosition(nid), 101)
target = 0
spec = {}
pz = 0
kill = 0
end

local function closedis(nid, target, opos)
   if target ~= 0 then
     tpos = getCreaturePosition(target)
     npos = getCreaturePosition(nid)
     if isMonster(target) or isPlayer(target) then
       if getDistanceBetween(opos, tpos) <= maxchase then
         if getDistanceBetween(npos, tpos) <= area then
           if not getTilePzInfo(tpos) then
             if ((tpos.y - npos.y) >= 2) and ((tpos.y - npos.y)<= area) then
               if queryTileAddThing(nid, {x=npos.x,y=npos.y+1,z=npos.z}) == 1 then
                 doMoveCreature(nid, SOUTH)
               elseif queryTileAddThing(nid, {x=npos.x,y=npos.y+1,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if ((npos.y - tpos.y) >= 2) and ((npos.y - tpos.y) <= area) then
               if queryTileAddThing(nid, {x=npos.x,y=npos.y-1,z=npos.z}) == 1 then
                 doMoveCreature(nid, NORTH)
               elseif queryTileAddThing(nid, {x=npos.x,y=npos.y-1,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if((tpos.x - npos.x) >= 2) and ((tpos.x - npos.x) <= area) then
               if queryTileAddThing(nid, {x=npos.x+1,y=npos.y,z=npos.z}) == 1 then
                 doMoveCreature(nid, EAST)
               elseif queryTileAddThing(nid, {x=npos.x+1,y=npos.y,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if((npos.x - tpos.x) >= 2) and ((npos.x - tpos.x) <= area) then
               if queryTileAddThing(nid, {x=npos.x-1,y=npos.y,z=npos.z}) == 1 then
                 doMoveCreature(nid, WEST)
               elseif queryTileAddThing(nid, {x=npos.x-1,y=npos.y,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
           elseif pz == 0 then
             selfSay(ttext[math.random(1,#ttext)]..""..getCreatureName(target).."!")
             pz = 1
             target = 0
             goback(nid,opos)
           end
         end
       else
         target = 0
         goback(nid,opos)
       end
       addEvent(closedis, speed, Creature(nid).uid, target, opos)
     else
       goback(nid, opos)
     end
   end
end



local function check_target(nid, opos)
local position = Creature(nid):getPosition() --- Its returning a nil value as it's set // If it was nid:getPosition() error would show as  "attempt to index a number value"
spec = getSpectators(position, area, area,false,false)

   if spec then
     for i = 1, #spec do
       if isMonster(spec[i]) then
         target = spec[i]
         closedis(nid, target, opos)
         break
       elseif isPlayer(spec[i]) then
         if getPlayerSkullType(spec[i]) == (SKULL_WHITE or SKULL_RED) then
           target = spec[i]
           closedis(nid, target, opos)
           break
         end
       else
         target = 0
       end
     end
   end

end



function onCreatureAppear(cid)
   if isNpc(cid) then
     nid = cid
     opos = Creature(nid):getPosition() --- same as above
   end
end

function onThink(cid)

   if target == 0 then
     check_target(nid, opos)
   end
   if target == 0 and kill == 1 then
     goback(nid,opos)
   end
   if (os.clock() - hit) >= atkspeed then
     if target ~= 0 then
       if not getTilePzInfo(getCreaturePosition(target)) then
         if math.random(1,10) < 3 then
           doSendDistanceShoot(getCreaturePosition(nid), getCreaturePosition(target), 30)
           doTargetCombatHealth(nid, target, COMBAT_HOLYDAMAGE, -mindmg, -maxdmg, 39)
         else
           doTargetCombatHealth(nid, target, COMBAT_PHYSICALDAMAGE, -mindmg, -maxdmg, 0)
         end
         if getCreatureHealth(target) <= 0 then
           kill = 1
           selfSay(ktext[math.random(1,#ktext)])
           target = 0
         else
           kill = 0
         end
         hit = os.clock()
         if math.random(1,10) < 3 then
           doCreatureSay(nid, ctext[math.random(1,#ctext)],34)
         end
       end
     end
   end
end


Same errors Limos, here's the code as I'm using it.
 
I just tested it with the latest TFS 1.1 (already tested it with older TFS 1.1 version before and worked like that without errors) and can't reproduce this error.
Also tested the script you just posted and it works fine for me without any error (besides the debugs from 0 and 34 that you haven't changed yet).
 
I just tested it with the latest TFS 1.1 (already tested it with older TFS 1.1 version before and worked like that without errors) and can't reproduce this error.
Also tested the script you just posted and it works fine for me without any error (besides the debugs from 0 and 34 that you haven't changed yet).


o_o whaa how can this be? Maybe my NPC/lib files aren't up to date?

EDIT: NVM I just replaced the paste with the last TFS release and I have the same result :((

No clues now

EDIT2: OMG, I just tested the script with a brand new TFS 1.1 and it worked. Does anyone knows where I should look for those differences? Is it my datapack or my sources?

EDIT3: OK. I replaced the datapacks and I found out that the problem is within the sources. I just don't know where :p. Anyone knows?

EDIT4: I've fixed it, the problem as in both data and sources :X
 
Last edited:
Fixed the script for TFS 1.1. Now the script works without debug Tibia:
Code:
-- config
local maxdmg = 10  -- maximum dmg dealt
local mindmg = 1 -- minimum dmg dealt
local speed = 200 -- NPC will follow target every 0.2 seconds (that's "ok" fast)
local atkspeed = 1 -- 1= 1 attack per second (!lowest value!) 2= 1 attack per 2 seconds, 3= 1 attack per 3 seconds,...
local maxchase = 30 -- 12 tiles chase length (depends on PZs, spawnpoint from NPC, surroundings,...
local area = 4 -- 4x4 area will be checked for monsters/players (6 is too much in my oppinion)


-- Do not edit if you have no clue what you're doing!
local hit = 0
local target = 0
local opos = 0
local nid = 0
local spec = {}
local kill = 0
local pz = 0
local tpos = 0
local npos = 0


local function goback(nid, opos)
   if (kill == 0) and (pz == 0) then
   end
doTeleportThing(nid, opos, false)
target = 0
spec = {}
pz = 0
kill = 0
end

local function closedis(nid, target, opos)
   if target ~= 0 then
     tpos = getCreaturePosition(target)
     npos = getCreaturePosition(nid)
     if isMonster(target) or isPlayer(target) then
       if getDistanceBetween(opos, tpos) <= maxchase then
         if getDistanceBetween(npos, tpos) <= area then
           if not getTilePzInfo(tpos) then
             if ((tpos.y - npos.y) >= 2) and ((tpos.y - npos.y)<= area) then
               if queryTileAddThing(nid, {x=npos.x,y=npos.y+1,z=npos.z}) == 1 then
                 doMoveCreature(nid, SOUTH)
               elseif queryTileAddThing(nid, {x=npos.x,y=npos.y+1,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if ((npos.y - tpos.y) >= 2) and ((npos.y - tpos.y) <= area) then
               if queryTileAddThing(nid, {x=npos.x,y=npos.y-1,z=npos.z}) == 1 then
                 doMoveCreature(nid, NORTH)
               elseif queryTileAddThing(nid, {x=npos.x,y=npos.y-1,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if((tpos.x - npos.x) >= 2) and ((tpos.x - npos.x) <= area) then
               if queryTileAddThing(nid, {x=npos.x+1,y=npos.y,z=npos.z}) == 1 then
                 doMoveCreature(nid, EAST)
               elseif queryTileAddThing(nid, {x=npos.x+1,y=npos.y,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if((npos.x - tpos.x) >= 2) and ((npos.x - tpos.x) <= area) then
               if queryTileAddThing(nid, {x=npos.x-1,y=npos.y,z=npos.z}) == 1 then
                 doMoveCreature(nid, WEST)
               elseif queryTileAddThing(nid, {x=npos.x-1,y=npos.y,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
           elseif pz == 0 then
             pz = 1
             target = 0
             goback(nid,opos)
           end
         end
       else
         target = 0
         goback(nid,opos)
       end
       addEvent(closedis, speed, Creature(nid).uid, target, opos)
     else
       goback(nid, opos)
     end
   end
end



local function check_target(nid, opos)
local position = Creature(nid):getPosition() --- Its returning a nil value as it's set // If it was nid:getPosition() error would show as  "attempt to index a number value"
spec = getSpectators(position, area, area,false,false)

   if spec then
     for i = 1, #spec do
       if isMonster(spec[i]) then
         target = spec[i]
         closedis(nid, target, opos)
         break
       elseif isPlayer(spec[i]) then
         if getPlayerSkullType(spec[i]) == (SKULL_WHITE or SKULL_RED) then
           target = spec[i]
           closedis(nid, target, opos)
           break
         end
       else
         target = 0
       end
     end
   end

end



function onCreatureAppear(cid)
   if isNpc(cid) then
     nid = cid
     opos = Creature(nid):getPosition() --- same as above
   end
end

function onThink(cid)

   if target == 0 then
     check_target(nid, opos)
   end
   if target == 0 and kill == 1 then
     goback(nid,opos)
   end
   if (os.clock() - hit) >= atkspeed then
     if target ~= 0 then
       if not getTilePzInfo(getCreaturePosition(target)) then
        local abcRand = math.random(1, 3)
         if abcRand == 1 then
           doTargetCombatHealth(nid, target, COMBAT_HOLYDAMAGE, -mindmg, -maxdmg, CONST_ME_HOLYAREA)
         elseif abcRand == 2 then
           doTargetCombatHealth(nid, target, COMBAT_DEATHDAMAGE, -mindmg, -maxdmg, CONST_ME_MORTAREA)
         else
          doTargetCombatHealth(nid, target, COMBAT_PHYSICALDAMAGE, -mindmg, -maxdmg, CONST_ME_HITAREA)
         end
         if getCreatureHealth(target) <= 0 then
           kill = 1
           target = 0
         else
           kill = 0
         end
         hit = os.clock()
       end
     end
   end
end
 
really?
I keep getting a getDistance error haha.. mmm must be missing a function.. well good to know ;)

Try this (I'm using it):
Townguard Steve.xml
Code:
<?xml version="1.0" encoding="UTF-8"?><npc name="Townguard Steve" script="townsteve.lua" walkinterval="0" floorchange="0" speed="400">
<health now="1000" max="1000"/>
<look type="268" head="0" body="0" legs="79" feet="76" addons="3"/>
</npc>

npc/scripts/townsteve.lua

Code:
-- config
local maxdmg = 10  -- maximum dmg dealt
local mindmg = 1 -- minimum dmg dealt
local speed = 200 -- NPC will follow target every 0.2 seconds (that's "ok" fast)
local atkspeed = 2 -- 1= 1 attack per second (!lowest value!) 2= 1 attack per 2 seconds, 3= 1 attack per 3 seconds,...
local maxchase = 10 -- 12 tiles chase length (depends on PZs, spawnpoint from NPC, surroundings,...
local area = 4 -- 4x4 area will be checked for monsters/players (6 is too much in my oppinion)


-- Do not edit if you have no clue what you're doing!
local hit = 0
local target = 0
local opos = 0
local nid = 0
local spec = {}
local kill = 0
local pz = 0
local tpos = 0
local npos = 0


local function goback(nid, opos)
   if (kill == 0) and (pz == 0) then
   end
doTeleportThing(nid, opos, false)
target = 0
spec = {}
pz = 0
kill = 0
end

local function closedis(nid, target, opos)
   if target ~= 0 then
     tpos = getCreaturePosition(target)
     npos = getCreaturePosition(nid)
     if isMonster(target) or isPlayer(target) then
       if getDistanceBetween(opos, tpos) <= maxchase then
         if getDistanceBetween(npos, tpos) <= area then
           if not getTilePzInfo(tpos) then
             if ((tpos.y - npos.y) >= 2) and ((tpos.y - npos.y)<= area) then
               if queryTileAddThing(nid, {x=npos.x,y=npos.y+1,z=npos.z}) == 1 then
                 doMoveCreature(nid, SOUTH)
               elseif queryTileAddThing(nid, {x=npos.x,y=npos.y+1,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if ((npos.y - tpos.y) >= 2) and ((npos.y - tpos.y) <= area) then
               if queryTileAddThing(nid, {x=npos.x,y=npos.y-1,z=npos.z}) == 1 then
                 doMoveCreature(nid, NORTH)
               elseif queryTileAddThing(nid, {x=npos.x,y=npos.y-1,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if((tpos.x - npos.x) >= 2) and ((tpos.x - npos.x) <= area) then
               if queryTileAddThing(nid, {x=npos.x+1,y=npos.y,z=npos.z}) == 1 then
                 doMoveCreature(nid, EAST)
               elseif queryTileAddThing(nid, {x=npos.x+1,y=npos.y,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
             if((npos.x - tpos.x) >= 2) and ((npos.x - tpos.x) <= area) then
               if queryTileAddThing(nid, {x=npos.x-1,y=npos.y,z=npos.z}) == 1 then
                 doMoveCreature(nid, WEST)
               elseif queryTileAddThing(nid, {x=npos.x-1,y=npos.y,z=npos.z}) ~= 1 then
                 doTeleportThing(nid, tpos, true)
               else
                 target = 0
                 goback(nid,opos)
               end
             end
           elseif pz == 0 then
             pz = 1
             target = 0
             goback(nid,opos)
           end
         end
       else
         target = 0
         goback(nid,opos)
       end
       addEvent(closedis, speed, Creature(nid).uid, target, opos)
     else
       goback(nid, opos)
     end
   end
end



local function check_target(nid, opos)
local position = Creature(nid):getPosition() --- Its returning a nil value as it's set // If it was nid:getPosition() error would show as  "attempt to index a number value"
spec = getSpectators(position, area, area,false,false)

   if spec then
     for i = 1, #spec do
       if isMonster(spec[i]) then
         target = spec[i]
         closedis(nid, target, opos)
         break
       elseif isPlayer(spec[i]) then
         if getPlayerSkullType(spec[i]) == (SKULL_WHITE or SKULL_RED) then
           target = spec[i]
           closedis(nid, target, opos)
           break
         end
       else
         target = 0
       end
     end
   end

end



function onCreatureAppear(cid)
   if isNpc(cid) then
     nid = cid
     opos = Creature(nid):getPosition() --- same as above
   end
end

function onThink(cid)

   if target == 0 then
     check_target(nid, opos)
   end
   if target == 0 and kill == 1 then
     goback(nid,opos)
   end
   if (os.clock() - hit) >= atkspeed then
     if target ~= 0 then
       if not getTilePzInfo(getCreaturePosition(target)) then
        local abcRand = math.random(1, 3)
         if abcRand == 1 then
           doTargetCombatHealth(nid, target, COMBAT_HOLYDAMAGE, -mindmg, -maxdmg, CONST_ME_HOLYAREA)
         elseif abcRand == 2 then
           doTargetCombatHealth(nid, target, COMBAT_DEATHDAMAGE, -mindmg, -maxdmg, CONST_ME_MORTAREA)
         else
          doTargetCombatHealth(nid, target, COMBAT_PHYSICALDAMAGE, -mindmg, -maxdmg, CONST_ME_HITAREA)
         end
         if getCreatureHealth(target) <= 0 then
           kill = 1
           target = 0
         else
           kill = 0
         end
         hit = os.clock()
       end
     end
   end
end
 
Try this (I'm using it):

Error i get:
J6VT1Cq.png

Could you send me the function?

So i got the function i was missing from latest tfs but now the NPC just teleports to the monster, Hits it once and then crashes lol no error in console. I only get the error after i delete him.
 
Last edited:
Error i get:
J6VT1Cq.png

Could you send me the function?

So i got the function i was missing from latest tfs but now the NPC just teleports to the monster, Hits it once and then crashes lol no error in console. I only get the error after i delete him.

Check your "data/lib" functions. Maybe your folder ins't updated.
 
Can someone please post what functions are needed for this?
 
Back
Top