• 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!
  • New resources must be posted under Resources tab. A discussion thread will be created automatically, you can't open threads manually anymore.

NPC Advance Guard [Attacking Pk's and Monsters with options] [TFS 1.x]

Printer

if Printer then print("LUA") end
Senator
Premium User
Joined
Dec 27, 2009
Messages
5,781
Solutions
31
Reaction score
2,290
Location
Sweden?
Hello,

Here is a guard npc, that will protect the city from intruders!

Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Guard" script="guard.lua" walkinterval="0" floorchange="0">
    <health now="100" max="100" />
    <look type="139" head="20" body="39" legs="45" feet="7" addons="0" />
</npc>

Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureDisappear(cid)           npcHandler:onCreatureDisappear(cid)         end
function onCreatureSay(cid, type, msg)      npcHandler:onCreatureSay(cid, type, msg)    end

local config = {
    attackRadius = {x = 7, y = 5, targetDistance = 2, walkDistance = 7},
    attackPK = {value = true, skulls = {SKULL_WHITE, SKULL_RED}},
    attackMonster = {value = true, ignore = {"Rat", "Cave Rat"}, ignoreSummon = true},
    damageValue = {min = 10, max = 20}
}

-- Do not touch
local targetId = 0
local masterPosition

function Creature.isAttackable(self)
    if not self:isNpc() then
        if self:isPlayer() and not self:getGroup():getAccess() then
            if config.attackPK.value and isInArray(config.attackPK.skulls, self:getSkull()) then
                return true
            end
        end

        if self:isMonster() and config.attackMonster.value then
            local master = self:getMaster()
            if (config.attackMonster.ignoreSummon and master and not master:isPlayer()) or not isInArray(config.attackMonster.ignore, self:getName()) then
                return true
            end
        end

    end

    return false
end

function Npc.searchTarget(self)
    local attackRadius = config.attackRadius
    for _, spectator in ipairs(Game.getSpectators(self:getPosition(), false, false, attackRadius.x, attackRadius.x, attackRadius.y, attackRadius.y)) do
        if spectator:isAttackable() then
            targetId = spectator:getId()
        end
    end
end

function onThink()
    local npc = Npc()
    local target = Creature(targetId)

    -- If we have not a target, then we shall search for one
    if not target then
        npc:searchTarget()
        return
    end
 
    -- Let's get target offset position
    local npcPosition = npc:getPosition()
    local targetPosition = target:getPosition()
    local offsetX = npcPosition.x - targetPosition.x
    local offsetY = npcPosition.y - targetPosition.y

    -- Target is out of reach, search for new one
    local radius = config.attackRadius
    if math.abs(offsetX) > radius.x or math.abs(offsetY) > radius.y then
        npc:searchTarget()
        return
    end

    -- Back to spawn position
    if npcPosition:getDistance(masterPosition) >= radius.walkDistance then
        npcPosition:sendMagicEffect(CONST_ME_TELEPORT)
        npc:teleportTo(masterPosition)
        return
    end

    -- If target is found
    local npcId = npc:getId()
    doTargetCombatHealth(npcId, targetId, COMBAT_FIREDAMAGE, -config.damageValue.min, -config.damageValue.max, CONST_ME_HITBYFIRE)
    npcPosition:sendDistanceEffect(targetPosition, CONST_ANI_FIRE)
    doNpcSetCreatureFocus(targetId)
 
    -- Follow Target
    local distance = radius.targetDistance
    local path = npc:getPathTo(targetPosition, 0, distance, true, true)
    if path and npcPosition:getDistance(targetPosition) > distance then
        doMoveCreature(npcId, path[1])
    end

    npcHandler:onThink()                    
end

function onCreatureAppear(self)
    if self == Npc() and not masterPosition then
        masterPosition = self:getPosition()
    end
       
    npcHandler:onCreatureAppear(self)         
end
 
Last edited:
I will for sure test this out soon.
Thank You Printer.

Kind Regards,
Eldin.
 
good work is work on 1.2?

can you edit npc atak witch sword or ice
 
Last edited by a moderator:
Ideas for Updates:
-The NPC will follow it's target to walk back/teleport back if out of reach.
(Maybe even set keep away x sqm from target like a monster so you can make range or melee guards)
-Option (true/false) to attack and be able to kill the NPC (and get a skull like attacking a player)
-Maybe let the Guard NPC be able to ignore summons instead of killing them?
-An example/easy way to add existing spells for the NPC and and rate when used to make him more advanced.

Kind Regards,
Eldin.
 
I found it very interesting NPC .
I tried to make him follow the target, the more I could not.
 
Another note: @Printer
If the Guard attack a target he will "freeze" once the attack is over, if you speak to him and go away/say bye the Guard will go back to normal and walk around again.

Kind Regards,
Eldin.
 
Added so he follows the target, also get teleported back to it's spawn position after reaching a certain distance and does not attack player summons.

Make sure recopy the xml file aswell.
 
Added so he follows the target, also get teleported back to it's spawn position after reaching a certain distance and does not attack player summons.

Make sure recopy the xml file aswell.

Awesome! But there is something wrong with ignore. The guard attack ignore monsters and ignore the unignore monsters. :)
 
@Printer
Up already noted it.

Amazing work Printer.

Wanted features:
-Option (true/false) to attack and be able to kill the NPC (and get a skull like attacking a player)
-An example/easy way to add existing spells for the NPC and and rate when used to make him more advanced. Add spell like on a monster or so.

Kind Regards,
Eldin.
 
@Printer
Up already noted it.

Amazing work Printer.

Wanted features:
-Option (true/false) to attack and be able to kill the NPC (and get a skull like attacking a player)
-An example/easy way to add existing spells for the NPC and and rate when used to make him more advanced. Add spell like on a monster or so.

Kind Regards,
Eldin.
I am still waiting on Eldin's World! :(
 
Begins to attack players without the skull.
Awesome! But there is something wrong with ignore. The guard attack ignore monsters and ignore the unignore monsters. :)
Fixed.

@Printer
Up already noted it.

Amazing work Printer.

Wanted features:
-Option (true/false) to attack and be able to kill the NPC (and get a skull like attacking a player)
-An example/easy way to add existing spells for the NPC and and rate when used to make him more advanced. Add spell like on a monster or so.

Kind Regards,
Eldin.
First, need to check if it's possible to kill a npc, asfar i know. It's not.
Second, there is no easy way to do that, without any source edit.
 
I'm so glad you upgraded this Printer, it's basicly perfect now, thank you for that.

Kind Regards,
Eldin.
 
Last edited:
Help please, i'm using this, the script load correctly, but the guard wont attack any player or monster....
it seems that he can't find any target... !
 
Ok, I find out now,, the problem happen only when there is more than 1 guard on the map
when I added 10 guard by city, it bugs
 
Back
Top