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

Zyntax

*WannaBe Scripter*
Joined
Jan 27, 2010
Messages
533
Reaction score
40
Location
Lua & XML Section
This is a new Guard NPC for TFS1.0 (10.31).

Description:
  • attacks Monsters
  • attacks Players with Skull (Red or White)
  • chases the Target (until maxchase is reached)
  • uses either melee attack or distance (random)
I tried to bugfix it as good as possible, but I need you guys to test it out properly to make it as bugfree as possible.

If you want to spawn this NPC make sure that you have atleast 15 tiles (or "maxchase" in the .lua file) distance to a PZ or else the NPC will spam like a beast as soon as a player runs into a PZ!

Implementaion:
create a new npc.xml file and insert this:
PHP:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Townguard Steve" script="townsteve.lua" walkinterval="0" floorchange="0" speed="400">
   <health now="100" max="100"/>
   <look type="268" head="0" body="0" legs="79" feet="76" addons="3"/>
</npc>

now at npc/scripts create townsteve.lua and insert this:
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, nid, target, opos)
     else
       goback(nid, opos)
     end
   end
end



local function check_target(nid, opos)
local position = getThingPos(nid)
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 = getThingPos(nid)
   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


Bugfixing:
I will update this post and the script with bugfixes (and maybe features players requesting)

Please be so kind and test it thoroughly and report all bugs you find right in this post!
I'll do my best to keep it updated.

*If you want to add some features yourself, feel free to post a modified script here and I'll update it!


Kind regards and happy slaying!
 
Last edited:
Thank You for making it Patrick ;)
Lets check for bugs and improve it.

Kind Regards,
Eldin.
 
Zyntax,

Thank your for contribution.
 
Quick questions, what are the functions that you are using that make it TFS 1.0?
Is this possible to use on TFS 0.3?
 
Lol I love this guy..

Is it possible that you can make him Paralyze?

Sure Thing, ill add a Chance to make the Monster/Player be paralyzed.

@Znote I found an issue, it killed a character's summon.

Uhm, I'm Zyntax, but never mind that, I'll make a check for summons and let the guard dont touch them :)

Thanks for your Input ! Keep it coming!
 
Sure Thing, ill add a Chance to make the Monster/Player be paralyzed.



Uhm, I'm Zyntax, but never mind that, I'll make a check for summons and let the guard dont touch them :)

Thanks for your Input ! Keep it coming!

My apologies XD And thank you! :D
 
Huh. Never seen an NPC attack, funny. How come it just teleports back to its spawn location and not walk back?
 
o6P8UOz.png
 
I think that maybe the function getThingPos is equal to getPosition or getThingfromPos in Tfs 1.1. But in both it still return errors. If you could make a version to 1.1x I would be very happy =]
 
For the getThingPos error.
Code:
local position = nid:getPosition()

opos = nid:getPosition()

For the unsafe warning.
Code:
addEvent(closedis, speed, Creature(nid).uid, target, opos)

For the debugs from this.
doTargetCombatHealth(nid, target, COMBAT_PHYSICALDAMAGE, -mindmg, -maxdmg, 0)
doCreatureSay(nid, ctext[math.random(1,#ctext)], 34)
You can change it to this.
Code:
doTargetCombatHealth(nid, target, COMBAT_PHYSICALDAMAGE, -mindmg, -maxdmg, CONST_ME_DRAWBLOOD)
doCreatureSay(nid, ctext[math.random(1,#ctext)], TALKTYPE_MONSTER_SAY)
 
Back
Top