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

city guard

kilirt

New Member
Joined
May 11, 2009
Messages
223
Reaction score
2
Excuse me but i've an idea and i dont know if is possible make a city guard, a npc or a monster who attack only player with skull(white,red skull,black skull ) and no yellow or green and only player with skull white,red,black can attack this npc/monster



sorry my english is bad
 
TFS 0.3.5pl1
It's NPC.

LUA:
local target = 0
local prevTarget = 0
local maxChaseDistance = 20
local origPos = 0
local lastAttack = 0
local followTimeout = 10

local function isSkulled(cid)
    if(getCreatureSkullType(cid) >= 3 and isPlayerPzLocked(cid) == TRUE) then
        return true
    end

    return false
end

local function goToOrigPos()
    target = 0
    lastAttack  = 0
    selfFollow(0)
    doTeleportThing(getNpcCid(), origPos)
end

local function updateTarget()
    if(isPlayer(target) == FALSE) then
        goToOrigPos()
    elseif(not isSkulled(target)) then
        selfSay("Now, behave in the future.")
        goToOrigPos()
    end

    if(target == 0) then
        local list = getSpectators(getNpcPos(), 9, 9, false)
        for i = 1, table.getn(list) do
            local _target = list[i]
            if(_target ~= 0) then
                if(isPlayer(_target) == TRUE and isSkulled(_target)) then
                    if(getTilePzInfo(getCreaturePosition(_target)) == FALSE) then
                        if(selfFollow(_target)) then
                            target = _target
                            if(target ~= prevTarget) then
                                selfSay("We do not tolerate people like you here!")
                            end

                            prevTarget = target
                            break
                        end
                    end
                end
            end
        end
    end
end

function onCreatureAppear(cid)
    if(cid == getNpcCid()) then
        origPos = getNpcPos()
    end
end

function onCreatureDisappear(cid)
    if(cid == target) then
        goToOrigPos()
    end
end

function onCreatureMove(creature, oldPos, newPos)
    --
end

function onThink()
    updateTarget()

    if(target == 0) then
        return
    end

    local playerPos = getCreaturePosition(target)
    local myPos = getNpcPos()

    if(myPos.z ~= playerPos.z) then
        goToOrigPos()
        return
    end

    if(math.abs(myPos.x - origPos.x) > maxChaseDistance or math.abs(myPos.y - origPos.y) > maxChaseDistance) then
        selfSay("I'll catch you next time.")
        goToOrigPos()
        return
    end

    if(lastAttack == 0) then
        lastAttack = os.clock()
    end

    if(os.clock() - lastAttack > followTimeout) then
        selfSay("You got me this time, but just wait.")
        goToOrigPos()
        return
    end

    if((math.abs(playerPos.x - myPos.x) <= 1) and (math.abs(playerPos.y - myPos.y) <= 1)) then
        doTargetCombatHealth(getNpcCid(), target, COMBAT_LIFEDRAIN, -200, -300, CONST_ME_BLOCKHIT)
        lastAttack = os.clock()
    end
end
 
Try the Mock, one.
I found it on BR forum.

Create in data/npc/scripts an file: guard lib.lua
LUA:
--[[
        ==========================
        |                        |
        |   Guard system 1.0     |
        |    Author: GS TEAM     |
        |   Create to OTNET      |
        |   Mock and kaotar     |
        ==========================

 1.0 Features:
        - Attack monsters and Pk players
]]

GUARD = 1
SELFGUARD = 2



Guard = {
        movingBack = false,
        move = {
            moving = false
        },
        config = {
            speed = 1000,
            changeFloor = false,
            moveType = GUARD,
            moveBack = true,
            playerExp = true,
            delay_attack = 0.5,
            exaustHeal=20,
            GPS=10,
            TIME=60,
        },
        focus={},
        combat = {
            min = 100,
            max = 200,
        },
        ignoreList = {
        }
}

function Guard:new()
        local tab = {}
        tab.combat = {}
        setmetatable(tab.combat, self.combat)
        tab.combat.__index = self.combat
        tab.ignoreList = {}
        setmetatable(tab.ignoreList, self.ignoreList)
        tab.ignoreList.__index = self.ignoreList
        tab.move = {}
        setmetatable(tab.move, self.move)
        tab.move.__index = self.move
        setmetatable (tab, self)
        self.__index = self
        return tab
end

function Guard:check(first)
    if (first) then
        if (self.config.moveType == 2 and self.player and isPlayer(self.player) == TRUE) then
            return false
                end
        end
        if not (self.cid) then
                return false
        end
        if not (self.firstPos) then
                self.firstPos = getThingPos(self.cid)
        end
        if (self:samePos(getThingPos(self.cid), self.firstPos)) then
                self.move.movingBack = false
        end
        if (self.config) then
                for i, v in pairs(Guard.config) do
                        if (tostring(self.config[i]) ~= "nil") then
                                if not (type(v) == type(self.config[i])) then
                                        print("Guard System - Config error:\n Variable ".. i .." is a not correct type.\n It's is setable a defaul value: "..   tostring(Guard.config[i]))
                                        self.config[i] = v
                                end
                        else
                                self.config[i] = v
                        end
                end
        end
        return true
end

function Guard:doMove()
        if (not self.move.moving and self.move.movingBack or self.target and isCreature(self.target) == TRUE and not self.move.moving) then
                if (self.config.changeFloor or self.move.movingBack or getThingPos(self.target).z == getThingPos(self.cid).z) then
                        if (not self.move.movingBack and getThingPos(self.target).z ~= getThingPos(self.cid).z) then
                                doTeleportThing(self.cid, getThingPos(self.config.moveType == 2 and self.player or self.target), TRUE)
                        end
                        if (self.move.movingBack or self.player == self.target and getDistanceBetween(getThingPos(self.cid), getThingPos(self.target)) > 2 or self.target ~= self.player and getDistanceBetween(getThingPos(self.cid), getThingPos(self.target)) > 1) then
                                if (self.move.movingBack and self.config.moveBack and getDistanceBetween(getThingPos(self.cid), self.firstPos) >= 50) then
                                        doTeleportThing(self.cid, self.firstPos)
                                        self.player = nil
                                        self.target = nil
                                        self.move.movingBack = nil
                                        self.move.moving = nil
                                        return false
                                end
                                local q = self:findDir(getThingPos(self.cid), self.move.movingBack == false and getThingPos(self.target) or self.firstPos)
                                local x = 0
                                while (not q and x <= 1) do
                                        q = self:findDir(getThingPos(self.cid), self.move.movingBack == false and getThingPos(self.target) or self.firstPos)
                                        if not (self.player == self.target) then
                                                break
                                        end
                                        x = x+1
                                end
                                if (q) then
                                        self:doMoving(true, q)
                                        for i = 1, #q do
                                                addEvent(eventMove, i*self.config.speed, self,  q[i])
                                        end
                                else
                                        if (self.player and self.player ~= self.target and not self.move.movingBack) then
                                                self.ignoreList[#self.ignoreList+1] = {self.target, os.clock()}
                                                self.target = self.player
                                        elseif (self.player == self.target and not self.move.movingBack) then
                                                doCreatureSay(self.cid, "I'm sorry, but I'm lost", 3)
                                                self.player = nil
                                                self.move.moving = true
                                                addEvent(function (var) var.target, self.move.moving = nil, false end, 3000, self)
                                        elseif (self.move.movingBack) then
                                                doTeleportThing(self.cid, self.firstPos)
                                        end
                                end
                        end
                else
                        doCreatureSay(self.cid, "I'm sorry, but I'm lost", 3)
                        self.player = nil
                        self.target = nil
                end
        elseif (self.target == nil or isCreature(self.target) == FALSE) then
                if (self.config.moveType == 2 and isPlayer(self.player) == TRUE) then
                        self.target = self.player
                elseif (self.config.moveType == 2 and isPlayer(self.player) == FALSE) then
                        self.player = nil
                        self.target = nil
                        if (self.config.changeFloor and self.config.moveBack) then
                                doTeleportThing(self.cid, self.firstPos)
                        elseif (not self.config.changeFloor and self.config.moveBack) then
                                self.move.movingBack = true
                        end
                elseif (self.config.moveType == 1 and self.config.changeFloor and self.config.moveBack) then
                        doTeleportThing(self.cid, self.firstPos)
                elseif (self.config.moveType == 1 and not self.config.changeFloor and self.config.moveBack) then
                        if (not self:samePos(getThingPos(self.cid), self.firstPos) and not self.moving) then
                                self.move.movingBack = true
                                self.target = nil
                        end
                else
                        self.player = nil
                        self.target = nil
                end
        elseif (self.move.moving and self.moveType == 2) then
                if (self:samePos(getThingPos(self.cid), self.move.lastPos or {x=0, y=0})) then
                        if (self.move.lastPos[2] and os.clock()-self.move.lastPos[2] >= 5) then
                                self.move.moving = false
                        else
                                return true
                        end
                else
                        self.move.lastPos = {getThingPos(self.cid), os.clock()}
                end
        end
end


function Guard:doMoving(bool, tab)
        if (bool and tab) then
                self.move.moveTable = tab
                self.move.moving = true
        else
                if (self.move.moveTable and #self.move.moveTable > 0) then
                        table.remove(self.move.moveTable, 1)
                        if (#self.move.moveTable == 0) then
                                self.move.moving = false
                                self.move.moveTable = nil
                                if (self.move.movingBack) then
                                        self.move.movingBack = false
                                end
                        end
                else
                        self.move.moving = false
                        self.move.moveTable = nil
                end
        end
end


function eventMove(var, dir)
        var:doMoving()
        if (isWalkable(getPosByDir(getCreaturePosition(var.cid), dir), true) == true) then
                doMoveCreature(var.cid, dir)
        end
end

function Guard:isNext()
        local dir
        if (self:samePos(getThingPos(self.target), getThingPos(self.cid))) then
                return true
        end
        for dir = 0, 7 do
                local pos = self:getPosByDir(getThingPos(self.cid), dir)
                if (self:samePos(getThingPos(self.target), pos)) then
                        return true
                end
        end
        return false
end

function Guard:doCheckAttack()
        local isIgnore = function(tableIgnore, uid)
                if not (#tableIgnore == 0) then
                        for i, v in pairs(tableIgnore) do
                                if (v[1] == uid) then
                                        return true
                                end
                        end
                end
                return false
        end
        if (self.ignoreList) then
                for i, v in pairs(self.ignoreList) do
                        if (type(v) == "table" and v[2] and os.clock()-v[2] >= 15) then
                                table.remove(self.ignoreList, i)
                        end
                end
        end
        if (self.config.moveType == 2 and isPlayer(self.player) == FALSE) then
                return false
        end
        battlelist = getSpectators(getThingPos(self.config.moveType == 2 and self.player or self.cid), 7, 8, false)
        if (type(battlelist) == "table" and #battlelist > 0) then
                if (self.config.moveType == 2 and isInArray(battlelist, self.player) == FALSE or isInArray(battlelist, self.cid) == FALSE) then
                        self.target = self.player
                        return false
                end
                for i = 1, #battlelist do
                        if (battlelist[i] ~= self.cid and battlelist[i] ~= self.player and not isIgnore(self.ignoreList, battlelist[i])) then
                                if (isMonster(battlelist[i]) == TRUE or isNpc(battlelist[i]) == FALSE and getCreatureSkullType(battlelist[i]) > 1 and isPlayerPzLocked(battlelist[i]) == TRUE) then
                                        if (self.target ~= self.player and isInArray(battlelist, self.target) == TRUE) then
                                                self:doAttack()
                                                break
                                        else
                                                self.target = battlelist[i]
                                                self:doAttack()
                                                break
                                        end
                                end
                        elseif (isIgnore(self.ignoreList, battlelist[i])) then
                                self:doMoving()
                        end
                end
        end
end

function Guard:doAttack()
        if (self:isNext() == true) then
                if not (self.combat.min or self.combat.max) then
                        error("GUARD SYSTEM: Can not found min or max value for attack")
                        return false
                end
                if (self.combat.min > self.combat.max) then
                        error("GUARD SYSTEM: Combat min value is greater of max")
                        return false
                end
                if (self.config.playerExp) then
                        doTargetCombatHealth(self.config.moveType == SELFGUARD and self.player or self.cid, self.target, COMBAT_PHYSICALDAMAGE, -self.combat.min, -self.combat.max, CONST_ME_DRAWBLOOD)
                else
                        doTargetCombatHealth(self.cid, self.target, COMBAT_PHYSICALDAMAGE, -self.combat.min, -self.combat.max, CONST_ME_DRAWBLOOD)
                end
        end
end

function  Guard:cash()
    if self.player then
        if isPlayer(self.player)   then
                        self.last_ =  self.last_ or os.time()
                        if  self.last_ <= os.time() then
                                if  getPlayerMoney(self.player) >= self.config.GPS then
                                        doPlayerRemoveMoney(self.player,self.config.GPS)
                                        doPlayerSendTextMessage(self.player,12,'You paid  '..self.config.GPS..'  now left '..getPlayerMoney(self.player)..',  you can hunt arond   '..((getPlayerMoney(self.player)/self.config.GPS)*self.config.TIME)..'   seconds yet.')
                else
                    selfSay('You  dont  have enghout money, bye!',self.player)
                                        self.player =  nil
                    self.target =  nil
                end
                                self.last_ =  os.time()+self.config.TIME
                        end
        else
                        self.player = nil
            self.target = nil
        end
    end
end
function Guard:runAttack()
    self.config.time = self.config.time or os.clock()
    if self.config.time <= os.clock() then
                self:doCheckAttack()
                self.config.time = os.clock()+self.config.delay_attack
    end
end

-- Mock Lib(Auto Walk)
function Guard:isPos(p1, q)
        for i, p2 in pairs(q) do
                if (p1.x == p2.x and p1.y == p2.y) then
                        return true
                end
        end
end

function Guard:getDir(start, finish, walked)
        local menor = getDistanceBetween(start, finish)+10
        local dir = nil
        for i=0,7 do
                ae = self:getPosByDir(start, i)
                if (isWalkable(ae, TRUE) == TRUE and self:isPos(ae, walked) == nil) then
                        if (getDistanceBetween(ae, finish) < menor) then
                                menor = getDistanceBetween(ae, finish)
                                dir = i
                        end
                end
        end
        return dir
end

function Guard:findDir(start, finish)
        local q = 0
    local walked = {}
        local go = {}
        local distance = getDistanceBetween(start, finish)
        local moves = self.move.movingBack and getDistanceBetween(start, finish) + 1 or getDistanceBetween(start, finish)
        while (moves > 1) do
                table.insert(walked, 1, start)
                local dir = self:getDir(start, finish, walked)
                if (not dir or q >= 25+distance) then
                        return false
                end
                start = self:getPosByDir(start, dir)
                if (self:samePos(start, finish) == true and not self.move.movingBack) then
                        break
                end
                table.insert(go, dir)
                q = q+1
                moves = getDistanceBetween(start, finish)
        end
        return go
end

function Guard:getPosByDir(position, direction, size)
        local n = size or 1
        local pos = position
        if(direction == NORTH) then
                return {x=pos.x, y=pos.y-1, z=pos.z}
        elseif(direction == SOUTH) then
                return {x=pos.x, y=pos.y+1, z=pos.z}
        elseif(direction == WEST) then
                return {x=pos.x-1, y=pos.y, z=pos.z}
        elseif(direction == EAST) then
                return {x=pos.x+1, y=pos.y, z=pos.z}
        elseif(direction == NORTHWEST) then
                return {x=pos.x-1, y=pos.y-1, z=pos.z}
        elseif(direction == SOUTHWEST) then
                return {x=pos.x-1, y=pos.y+1, z=pos.z}
        elseif(direction == NORTHEAST) then
                return {x=pos.x+1, y=pos.y-1, z=pos.z}
        elseif(direction == SOUTHEAST) then
                return {x=pos.x+1, y=pos.y+1, z=pos.z}
        end
end

function Guard:samePos(p1,p2)
        if (p1.x == p2.x and p1.y == p2.y) then
                return true
        end
end

function isWalkable(pos, creature, proj, pz)-- by Nord
        if hasSqm(pos) == false then return false end
        if isCreature(getThingFromPos({x=pos.x,y=pos.y,z=pos.z,stackpos=255}).uid) and creature then return false end
        if getTileThingByPos({x = pos.x, y = pos.y, z = pos.z, stackpos = 0}).itemid == 0 then return false end
        if getTileInfo(pos).protection and pz then return false, true end
        local n = not proj and 3 or 2
        for i = 0, 255 do
                pos.stackpos = i
                local tile = getTileThingByPos(pos)
                if tile.itemid == 459 then
                        return true
                end
                if tile.itemid ~= 0 and not isCreature(tile.uid) then
                        if hasProperty(tile.uid, n) or hasProperty(tile.uid, 7) then
                                return false
                        end
                end
        end
        return true
end

function hasSqm(pos)-- by Mock
    return getTileThingByPos({x=pos.x,y=pos.y,z=pos.z,stackpos=0}).itemid ~= 0
end

The NPC:
LUA:
dofile('data/npc/scripts/guard lib.lua')
local guarda = Guard:new()
guarda.config = {
        moveType=SELFGUARD,
        speed = 400,
        changeFloor = false,
        playerExp = false,
        delay_attack=1,
        exaustHeal=20,
        --- Payment
        GPS=100, --- Pagar 100 GPS a X de tempo
        TIME=60, --- Pagar a quantia acima a cada X segundos, no caso 60
}
guarda.focus={}

guarda.combat = {
    min = 10,
    max = 20
}


function onCreatureAppear(cid)
  guarda.cid = getNpcId()
end

function onCreatureDisappear(cid)
end

function onCreatureSay(cid, tsype, msg)
        msg = msg:lower()
        if msg == 'hi' and isInArray(guarda.focus,cid) == false and getDistanceBetween(getThingPos(cid), getThingPos(getNpcCid())) <= 5 then
            table.insert(guarda.focus,1,cid)
            selfSay("Hello!",cid)
        end
        if isInArray(guarda.focus,cid) and getDistanceBetween(getThingPos(cid), getThingPos(getNpcCid())) <= 5  then
            if msg:find('help') then
                if (guarda:check(true)) then
                    if (guarda.config.moveType == SELFGUARD) then
                            selfSay('It will cost '..guarda.config.GPS..' each '..guarda.config.TIME..' seconds.',cid)
                            selfSay('I will help you '..getCreatureName(cid)..'!',cid)
                            guarda.cid = getNpcId()
                            guarda.player = cid
                            guarda.target = cid
                    else
                        selfSay('Sorry but i cant help.',cid)
                    end
                else
                    if guarda.player == cid then
                        selfSay('I am helping you.',cid)
                    else
                        selfSay('Sorry i am busy.',cid)
                    end
                end
            elseif msg:find('heal') then
                local percent = (getCreatureHealth(cid)/getCreatureMaxHealth(cid))*100
                if percent <= 15 then
                    if getPlayerStorageValue(cid,15001) >= os.time() then
                        if not isPlayerPzLocked(cid) then
                            doCreatureAddHealth(cid,(getCreatureMaxHealth(cid)*(percent-15))/100)
                            setPlayerStorageValue(cid,15001,os.time()+ guarda['config']['exaustHeal'] )
                            selfSay('Oh my god! you are verry bad! i can heal you now.',cid)
                        else
                            selfSay('I cant heal you now.',cid)
                        end
                    else
                        selfSay('I am retired, i cant heal you now.',cid)
                    end
                else
                    selfSay('You aren\'t too bad.',cid)
                end
            elseif msg:find('leave') then
                if not (guarda:check(true)) then
                    if (guarda.config.moveType == SELFGUARD) then
                        if guarda.player == cid then
                            guarda.player = nil
                            guarda.target = nil
                            selfSay('Okay, i will stay here.',cid)
                        end
                    end
                end
            elseif msg:find('job') then
                selfSay('I am guard.',cid)
            elseif msg == 'bye' then
                for i,b in pairs(guarda.focus) do
                    if b == cid then
                        table.remove(guarda.focus,i)
                    end
                end
                if guarda.player and guarda.player == cid then
                    guarda.player = nil
                    guarda.target = nil
                end
                selfSay('Okay, bye',cid)
            end
        end
end

function onPlayerCloseChannel(cid)
end

function onPlayerEndTrade(cid)
end




function onThink()
    guarda:cash()
    if (guarda:check()) then
        guarda:runAttack()
        guarda:doMove() -- A ordem dos fatores altera o resultado
    end
    for i,b in pairs(guarda.focus) do
        if not isPlayer(b) then
            table.remove(guarda.focus,i)
        elseif getDistanceBetween(getThingPos(b), getThingPos(getNpcCid())) > 5 and guarda.player ~= b then
            table.remove(guarda.focus,i)
            selfSay('Then bye...',b)
        end
    end
end

XML part:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="guard" script="guard.lua" walkinterval="0" floorchange="0">
    <health now="150" max="150"/>
    <look type="129" head="114" body="119" legs="114" feet="114" corpse="2212"/>
</npc>

You can set if you want the Guard attack monsters or players, or monsters & players.
DONT GIVE ME REP, BECAUSE IM NOT AUTHOR OF THIS SCRIPT.
 
Back
Top