• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

[TFS 1.1] Bot NPC?

  • Thread starter Thread starter tejdi
  • Start date Start date
T

tejdi

Guest
Can someone create NPC that will exp in specific area?

Without hp losses but with menu where can i change his dmg or spells.

Script need also to remove loot from monsters killed by this Bot NPC.

It will be great and famous script imo :D
 
Why not? I've seen npcs that follow you and help you in exp for money, so it's probably possible too. I belive in best scripters here.
 
It is very possible on the onthink function.
Not sure what npc think about monsters (are they enemies or friends), if none then get spectator should be used.
Other than that I really don't see any problems.
Npc+spells would take about 3hours to script.
There might be few people who has time to do it, I don't.
 
It is very possible on the onthink function.
Not sure what npc think about monsters (are they enemies or friends), if none then get spectator should be used.
Other than that I really don't see any problems.
Npc+spells would take about 3hours to script.
There might be few people who has time to do it, I don't.
Thanks for advice! Maybe it'll help someone who can do it :D
 
Can someone create NPC that will exp in specific area?

Without hp losses but with menu where can i change his dmg or spells.

Script need also to remove loot from monsters killed by this Bot NPC.

It will be great and famous script imo :D
Describe in first post what mean 'exp' for you.
It run around some area, search for monsters that are not summons and attack them with spells/melee [or fake attack (not 'target' monster), just deal dmg and show dmg animations like player] and if he does last hit he removes loot?
Or remove loot, if he attacked monster few times and someone else killed it?
Monsters should attack him (so he can be used as 'blocker' for players) or ignore him? It would require source edit.
 
Describe in first post what mean 'exp' for you.
It run around some area, search for monsters that are not summons and attack them with spells/melee [or fake attack (not 'target' monster), just deal dmg and show dmg animations like player] and if he does last hit he removes loot?
Or remove loot, if he attacked monster few times and someone else killed it?
Monsters should attack him (so he can be used as 'blocker' for players) or ignore him? It would require source edit.

Thanks for reply Gęsior!
I mean npc that search monsters that are not summons and killing them with spells & malee and if he did most dmg he removes loot.
Monsters should attack him, or just follow.
 
Thanks for reply Gęsior!
I mean npc that search monsters that are not summons and killing them with spells & malee and if he did most dmg he removes loot.
Monsters should attack him, or just follow.
I think it's possible. There are many things to test, but it should work. I don't know, if monsters will attack NPC, whwn you set NPC flag 'attackable' to '1' ( https://github.com/otland/forgottenserver/blob/master/src/npc.cpp#L157 ). It may require source edits, rest should be easy.

There are functions:

creature:getPathTo(pos[, minTargetDist = 0[, maxTargetDist = 1[, fullPathSearch = true[, clearSight = true[, maxSearchDist = 0]]]]]) - test if NPC can go to some position

NPC selfMoveTo(x,y,z) - make NPC walk to this position

There can be some problems with stupid 'moveTo' implementation. I reported it here, maybe they will fix in next TFS release:

https://github.com/otland/forgottenserver/issues/1565

--------------------
I read some TFS code and it looks like monsters will attack NPCs when you set flag attackable="1" in NPC .xml file.
 
I think it's possible. There are many things to test, but it should work. I don't know, if monsters will attack NPC, whwn you set NPC flag 'attackable' to '1' ( https://github.com/otland/forgottenserver/blob/master/src/npc.cpp#L157 ). It may require source edits, rest should be easy.

There are functions:

creature:getPathTo(pos[, minTargetDist = 0[, maxTargetDist = 1[, fullPathSearch = true[, clearSight = true[, maxSearchDist = 0]]]]]) - test if NPC can go to some position

NPC selfMoveTo(x,y,z) - make NPC walk to this position

There can be some problems with stupid 'moveTo' implementation. I reported it here, maybe they will fix in next TFS release:

https://github.com/otland/forgottenserver/issues/1565

--------------------
I read some TFS code and it looks like monsters will attack NPCs when you set flag attackable="1" in NPC .xml file.

It seems like attackable="1" only allows players to attack NPCs. "Wild" monsters will not attack NPCs.
Red
 
It seems like attackable="1" only allows players to attack NPCs. "Wild" monsters will not attack NPCs.
Red
Can you post line in which is code that make monsters not attack NPCs?
I haven't found any code that block it (except check for 'isAttackable()'), but monsters AI code is very long and maybe I missed it.
If you got idea which part of it may block attacks of monster, it would be much easier to make that 'bot npc'.
 
Can you post line in which is code that make monsters not attack NPCs?
I haven't found any code that block it (except check for 'isAttackable()'), but monsters AI code is very long and maybe I missed it.
If you got idea which part of it may block attacks of monster, it would be much easier to make that 'bot npc'.

I'm not entirely such which part of the code makes it so "wild" monsters (monsters placed using /m, for example) don't target NPCs if they have the attackable="1" flag.
I only tested it on my local server.

Red
 
Can u please explain detailed what you want?
I've just finished my "League of Legends" event, where we have Minion waves that walk to the same direction and the attack enemy/enemy towers/enemy inhibitors. <-- M0nsters are actually NPC's.
 
Can u please explain detailed what you want?
I've just finished my "League of Legends" event, where we have Minion waves that walk to the same direction and the attack enemy/enemy towers/enemy inhibitors. <-- M0nsters are actually NPC's.

I mean npc that search monsters that are not summons (on specific area) and killing them with spells & malee and if he did most dmg he removes loot.
Monsters should attack NPC, or just follow him.
 
Just made the npc fast, used a old script. (Handle monster targetting the same, so the will target npc in the area (You just need to attach the lua in the .xml of the monster, and add npc check & npc name check* then it will target npc. )
*if monster:isNpc() and monster:getName() == "NPC NAME" then

Code:
<npc name="Red Turret" script="events/redturret.lua" walkinterval="0" attackable="1" floorchange="0" access="0" level="21" maglevel="1">
    <health now="10000" max="10000"/>
    <look typeex="18132"/>
    <defenses armor="0" defense="0"/>
    <flags>
      <flag pushable="0"/>
     <flag hostile="1" />
     <flag attackable="1" />
    </flags>
</npc>



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

local level = 10  ----- change this to make the npc hit more/less---------------------|damage_min = (level * 2 + maglevel * 3) * min_multiplier |
local maglevel = 30  ----- change this to make the npc hit more/less -----------------|damage_max = (level * 2 + maglevel * 3) * max_multiplier |
local min_multiplier = 1.0  ----- change this to make the npc hit more/less ----------|damage_formula = math.random(damage_min,damage_max)      |
local max_multiplier = 2.1  ----- change this to make the npc hit more/less ---------------------------------------------------------------------
local check_interval = 0  ----- change this to the time between checks for a creature (the less time the more it will probably lag :S) 
local radiusx = 4  ----- change this to the amount of squares left/right the NPC checks (default 7 so he checks 7 squares left of him and 7 squares right (the hole screen) 
local radiusy = 4  ----- change this to the amount of squares left/right the NPC checks (default 5 so he checks 5 squares up of him and 5 squares down (the hole screen) 
local Attack_monsters = TRUE  ----- set to TRUE for the npc to attack monsters in his area or FALSE if he doesnt 
local Attack_swearers = false  ----- set to TRUE for the npc to attack players that swear near him or FALSE if he doesnt 
local Attack_pkers = TRUE  ----- set to TRUE for the npc to attack players with white and red skulls or FALSE if he doesnt 
local health_left = 0  ----- set to the amount of health the npc will leave a player with if they swear at him (ie at 10 he will hit the player to 10 health left) 
local hit_effect = CONST_ME_MORTAREA  ----- set this to the magic effect the creature will be hit with, see global.lua for more effects
local shoot_effect = CONST_ANI_SUDDENDEATH  ----- set this to the magic effect that will be shot at the creature, see global.lua for more effects
local damage_colour = TEXTCOLOR_RED  ----- set this to the colour of the text that shows the damage when the creature gets hit
------------------end of config------------------ 
local check_clock = os.clock()  ----- leave this 
local focus = 0  ----- leave this 
  function getMonstersfromAreaRedTurret(pos, radiusx, radiusy, stack) 
local monsters = { } 
local starting = {x = x, y = y, z = z, stackpos = 253}   --------Top left of killing area
local ending = {x = x, y = y, z = z, stackpos = 253}     --------Bottom right of killing area
    repeat 
        creature = creature:getPosition() 
            if creature.itemid > 0 then 
                if isCreature(creature.uid) == TRUE then 
                    if isPlayer(creature.uid) == FALSE then
                        if Attack_monsters == TRUE then 
                        local monster = Creature(creature.uid)                       
                      if monster:getMaster() == nil then     ----Target all Monsters in speficik area EXECPT for summons.          
                            table.insert (monsters, creature.uid) 
                            check_clock = os.clock()                         
                        end
                        end
                    elseif isPlayer(creature.uid) == TRUE then             ----Target all players in speficik area.

                                table.insert (monsters, creature.uid) 
                                check_clock = os.clock()       
                    end 
                end 
            end 
        if checking.x == pos.x-1 and checking.y == pos.y then 
            checking.x = checking.x+2 
        else   
            checking.x = checking.x+1 
        end 
        if checking.x > ending.x then 
            checking.x = starting.x 
            checking.y = checking.y+1 
        end 
    until checking.y > ending.y 
        return monsters 
end 


    function onThink()   
local cid = Npc(getNpcCid(  )) 
if isFightOn() and (Attack_monsters == TRUE and Attack_pkers == TRUE) or (Attack_monsters == TRUE and Attack_pkers == FALSE) or (Attack_monsters == FALSE and Attack_pkers == TRUE) then 
    if (os.clock() - check_clock) > check_interval then     
        monster_table = getMonstersfromAreaRedTurret(cid:getPosition(), radiusx, radiusy, 253) 
            if #monster_table >= 1 then 
                    target = math.random(1,#monster_table)
                        doNpcSetCreatureFocus(monster_table[target]) 
                        local damage_min = (level * 2 + maglevel * 3) * min_multiplier 
                        local damage_max = (level * 2 + maglevel * 3) * max_multiplier 
                        local damage_formula = math.random(damage_min,damage_max)
                        doSendDistanceShoot(cid:getPosition(), getThingPos(monster_table[target]), shoot_effect)
                        doSendMagicEffect(monster_table[target],hit_effect) 
                        --doSendAnimatedText(monster_table[i],damage_formula,damage_colour) 
                        doCreatureAddHealth(monster_table[target],-damage_formula) 
                        check_clock = os.clock() 
                        focus = 0 
                    end 
            elseif #monster_table < 1 then
                focus = 0 
                check_clock = os.clock()           
    end 
end 
    focus = 0 
end



npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
@Mokerhamer

hz73gp.jpg


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

local level = 21  ----- change this to make the npc hit more/less---------------------|damage_min = (level * 2 + maglevel * 3) * min_multiplier |
local maglevel = 4  ----- change this to make the npc hit more/less -----------------|damage_max = (level * 2 + maglevel * 3) * max_multiplier |
local min_multiplier = 1.0  ----- change this to make the npc hit more/less ----------|damage_formula = math.random(damage_min,damage_max)      |
local max_multiplier = 2.1  ----- change this to make the npc hit more/less ---------------------------------------------------------------------
local check_interval = 0  ----- change this to the time between checks for a creature (the less time the more it will probably lag :S)
local radiusx = 6  ----- change this to the amount of squares left/right the NPC checks (default 7 so he checks 7 squares left of him and 7 squares right (the hole screen)
local radiusy = 6  ----- change this to the amount of squares left/right the NPC checks (default 5 so he checks 5 squares up of him and 5 squares down (the hole screen)
local Attack_monsters = true  ----- set to TRUE for the npc to attack monsters in his area or FALSE if he doesnt
local Attack_swearers = false  ----- set to TRUE for the npc to attack players that swear near him or FALSE if he doesnt
local Attack_pkers = false  ----- set to TRUE for the npc to attack players with white and red skulls or FALSE if he doesnt
local health_left = 0  ----- set to the amount of health the npc will leave a player with if they swear at him (ie at 10 he will hit the player to 10 health left)
local hit_effect = CONST_ME_MORTAREA  ----- set this to the magic effect the creature will be hit with, see global.lua for more effects
local shoot_effect = CONST_ANI_SUDDENDEATH  ----- set this to the magic effect that will be shot at the creature, see global.lua for more effects
local damage_colour = TEXTCOLOR_RED  ----- set this to the colour of the text that shows the damage when the creature gets hit
------------------end of config------------------
local check_clock = os.clock()  ----- leave this
local focus = 0  ----- leave this
  function getMonstersfromAreaRedTurret(pos, radiusx, radiusy, stack)
local monsters = { }
local starting = {x = x, y = y, z = z, stackpos = 253}   --------Top left of killing area
local ending = {x = x, y = y, z = z, stackpos = 253}     --------Bottom right of killing area
    repeat
        creature = creature:getPosition()
            if creature.itemid > 0 then
                if isCreature(creature.uid) == TRUE then
                    if isPlayer(creature.uid) == FALSE then
                        if Attack_monsters == TRUE then
                        local monster = Creature(creature.uid)                      
                      if monster:getMaster() == nil then     ----Target all Monsters in speficik area EXECPT for summons.         
                            table.insert (monsters, creature.uid)
                            check_clock = os.clock()                        
                        end
                        end
                    elseif isPlayer(creature.uid) == TRUE then             ----Target all players in speficik area.

                                table.insert (monsters, creature.uid)
                                check_clock = os.clock()      
                    end
                end
            end
        if checking.x == pos.x-1 and checking.y == pos.y then
            checking.x = checking.x+2
        else  
            checking.x = checking.x+1
        end
        if checking.x > ending.x then
            checking.x = starting.x
            checking.y = checking.y+1
        end
    until checking.y > ending.y
        return monsters
end


    function onThink()  
local cid = Npc(getNpcCid(  ))
if isFightOn() and (Attack_monsters == TRUE and Attack_pkers == TRUE) or (Attack_monsters == TRUE and Attack_pkers == FALSE) or (Attack_monsters == FALSE and Attack_pkers == TRUE) then
    if (os.clock() - check_clock) > check_interval then    
        monster_table = getMonstersfromAreaRedTurret(cid:getPosition(), radiusx, radiusy, 253)
            if #monster_table >= 1 then
                    target = math.random(1,#monster_table)
                        doNpcSetCreatureFocus(monster_table[target])
                        local damage_min = (level * 2 + maglevel * 3) * min_multiplier
                        local damage_max = (level * 2 + maglevel * 3) * max_multiplier
                        local damage_formula = math.random(damage_min,damage_max)
                        doSendDistanceShoot(cid:getPosition(), getThingPos(monster_table[target]), shoot_effect)
                        doSendMagicEffect(monster_table[target],hit_effect)
                        --doSendAnimatedText(monster_table[i],damage_formula,damage_colour)
                        doCreatureAddHealth(monster_table[target],-damage_formula)
                        check_clock = os.clock()
                        focus = 0
                    end
            elseif #monster_table < 1 then
                focus = 0
                check_clock = os.clock()          
    end
end
    focus = 0
end



npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Change
creature = creature:getPosition()
to
creature = getThingfromPos(pos)
@Mokerhamer

hz73gp.jpg


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

local level = 21  ----- change this to make the npc hit more/less---------------------|damage_min = (level * 2 + maglevel * 3) * min_multiplier |
local maglevel = 4  ----- change this to make the npc hit more/less -----------------|damage_max = (level * 2 + maglevel * 3) * max_multiplier |
local min_multiplier = 1.0  ----- change this to make the npc hit more/less ----------|damage_formula = math.random(damage_min,damage_max)      |
local max_multiplier = 2.1  ----- change this to make the npc hit more/less ---------------------------------------------------------------------
local check_interval = 0  ----- change this to the time between checks for a creature (the less time the more it will probably lag :S)
local radiusx = 6  ----- change this to the amount of squares left/right the NPC checks (default 7 so he checks 7 squares left of him and 7 squares right (the hole screen)
local radiusy = 6  ----- change this to the amount of squares left/right the NPC checks (default 5 so he checks 5 squares up of him and 5 squares down (the hole screen)
local Attack_monsters = true  ----- set to TRUE for the npc to attack monsters in his area or FALSE if he doesnt
local Attack_swearers = false  ----- set to TRUE for the npc to attack players that swear near him or FALSE if he doesnt
local Attack_pkers = false  ----- set to TRUE for the npc to attack players with white and red skulls or FALSE if he doesnt
local health_left = 0  ----- set to the amount of health the npc will leave a player with if they swear at him (ie at 10 he will hit the player to 10 health left)
local hit_effect = CONST_ME_MORTAREA  ----- set this to the magic effect the creature will be hit with, see global.lua for more effects
local shoot_effect = CONST_ANI_SUDDENDEATH  ----- set this to the magic effect that will be shot at the creature, see global.lua for more effects
local damage_colour = TEXTCOLOR_RED  ----- set this to the colour of the text that shows the damage when the creature gets hit
------------------end of config------------------
local check_clock = os.clock()  ----- leave this
local focus = 0  ----- leave this
  function getMonstersfromAreaRedTurret(pos, radiusx, radiusy, stack)
local monsters = { }
local starting = {x = x, y = y, z = z, stackpos = 253}   --------Top left of killing area
local ending = {x = x, y = y, z = z, stackpos = 253}     --------Bottom right of killing area
    repeat
        creature = creature:getPosition()
            if creature.itemid > 0 then
                if isCreature(creature.uid) == TRUE then
                    if isPlayer(creature.uid) == FALSE then
                        if Attack_monsters == TRUE then
                        local monster = Creature(creature.uid)                    
                      if monster:getMaster() == nil then     ----Target all Monsters in speficik area EXECPT for summons.       
                            table.insert (monsters, creature.uid)
                            check_clock = os.clock()                      
                        end
                        end
                    elseif isPlayer(creature.uid) == TRUE then             ----Target all players in speficik area.

                                table.insert (monsters, creature.uid)
                                check_clock = os.clock()    
                    end
                end
            end
        if checking.x == pos.x-1 and checking.y == pos.y then
            checking.x = checking.x+2
        else
            checking.x = checking.x+1
        end
        if checking.x > ending.x then
            checking.x = starting.x
            checking.y = checking.y+1
        end
    until checking.y > ending.y
        return monsters
end


    function onThink()
local cid = Npc(getNpcCid(  ))
if isFightOn() and (Attack_monsters == TRUE and Attack_pkers == TRUE) or (Attack_monsters == TRUE and Attack_pkers == FALSE) or (Attack_monsters == FALSE and Attack_pkers == TRUE) then
    if (os.clock() - check_clock) > check_interval then  
        monster_table = getMonstersfromAreaRedTurret(cid:getPosition(), radiusx, radiusy, 253)
            if #monster_table >= 1 then
                    target = math.random(1,#monster_table)
                        doNpcSetCreatureFocus(monster_table[target])
                        local damage_min = (level * 2 + maglevel * 3) * min_multiplier
                        local damage_max = (level * 2 + maglevel * 3) * max_multiplier
                        local damage_formula = math.random(damage_min,damage_max)
                        doSendDistanceShoot(cid:getPosition(), getThingPos(monster_table[target]), shoot_effect)
                        doSendMagicEffect(monster_table[target],hit_effect)
                        --doSendAnimatedText(monster_table[i],damage_formula,damage_colour)
                        doCreatureAddHealth(monster_table[target],-damage_formula)
                        check_clock = os.clock()
                        focus = 0
                    end
            elseif #monster_table < 1 then
                focus = 0
                check_clock = os.clock()        
    end
end
    focus = 0
end



npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Back
Top