Getting an NPC to attack properly

For some reason the NPC’s never actually attack the ‘core’ entity. Even though you can tell that the ‘core’ is closest. They only attack players, and when there are no players alive, they just stay where they are and stare at the ‘core’.

Their relationship with the core is D_HT with a value of 999.

[lua]
// npc_control.lua

function _R.Vector:DistanceSqr( vec )
return (self - vec):LengthSqr()
end

function NPCThink( )

local npcs = ents.FindByClass( "npc_*" )
local AllCores = ents.FindByClass( "info_game_core" )
local core = AllCores[1]
local plyTbl = player.GetAll()

for _,npc in pairs( npcs ) do

    table.sort( plyTbl, function( a, b )
                        return npc:GetPos():DistanceSqr( a:GetPos() ) < npc:GetPos():DistanceSqr( b:GetPos() )
                        end )
        
    if npc:GetPos():Distance( plyTbl[1]:GetPos() ) < npc:GetPos():Distance( core:GetPos() ) then
        npc:SetEnemy( plyTbl[1], true )
        npc:SetTarget( plyTbl[1] )
        npc:UpdateEnemyMemory( plyTbl[1], plyTbl[1]:GetPos() )
        npc:NavSetGoal( plyTbl[1]:GetPos() )
    else
        npc:SetEnemy( core, true )
        npc:SetTarget( core )
        npc:UpdateEnemyMemory( core, core:GetPos() )
        npc:NavSetGoal( core:GetPos() )
    end
end

end

timer.Create( “npc_think”, 10, 0, NPCThink )
[/lua]

Does anyone know of a solution?

You want them to attack the core?

To find NPC’s use ents.GetAll(), then use is Ent.IsNPC(), way more compatible with different types of npcs. An enemy has to have “ai” as an ENT.Type for the NPC to consider it worthy of its time.

Okay, I changed the shared.lua of the core to:

[lua]
ENT.Type = “ai”
ENT.PrintName = “info”
ENT.Author = “TalkingGoose”
ENT.Spawnable = false
ENT.AdminSpawnable = false
ENT.AutomaticFrameAdvance = true
[/lua]

And the npc_control.lua to:

[lua]
// npc_control.lua

function _R.Vector:DistanceSqr( vec )
return (self - vec):LengthSqr()
end

function NPCThink( )

local all_ents = ents.GetAll()
local AllCores = ents.FindByClass( "info_game_core" )
local core = AllCores[1]
local plyTbl = player.GetAll()

for _,npc in pairs( all_ents ) do
    if npc:IsNPC() then
        table.sort( plyTbl, function( a, b )
                            return npc:GetPos():DistanceSqr( a:GetPos() ) < npc:GetPos():DistanceSqr( b:GetPos() )
                            end )
            
        if npc:GetPos():Distance( plyTbl[1]:GetPos() ) < npc:GetPos():Distance( core:GetPos() ) then
            npc:ClearEnemyMemory()
            npc:SetEnemy( plyTbl[1], true )
            npc:SetTarget( plyTbl[1] )
            npc:UpdateEnemyMemory( plyTbl[1], plyTbl[1]:GetPos() )
            npc:NavSetGoal( plyTbl[1]:GetPos() )
        else
            npc:ClearEnemyMemory()
            npc:SetEnemy( core, true )
            npc:SetTarget( core )
            npc:UpdateEnemyMemory( core, core:GetPos() )
            npc:NavSetGoal( core:GetPos() )
        end
    end
end

end

timer.Create( “npc_think”, 10, 0, NPCThink )

[/lua]

The NPC’s now walk up to it, but only when there are no players alive, and they don’t attack very often…

Any ideas?

[editline]6th February 2011[/editline]

Yes. :3

[editline]6th February 2011[/editline]

Solved my problem.

All I did was:

[lua]
if npc:GetPos():Distance( plyTbl[1]:GetPos() ) < npc:GetPos():Distance( core:GetPos() ) or !core:IsValid() then
npc:ClearEnemyMemory()
npc:SetEnemy( plyTbl[1], true )
npc:SetTarget( plyTbl[1] )
npc:UpdateEnemyMemory( plyTbl[1], plyTbl[1]:GetPos() )
npc:NavSetGoal( plyTbl[1]:GetPos() )
npc:AddRelationship(“player D_HT 99”)
else
npc:ClearEnemyMemory()
npc:SetEnemy( core, true )
npc:SetTarget( core )
npc:UpdateEnemyMemory( core, core:GetPos() )
npc:NavSetGoal( core:GetPos() )
npc:AddRelationship(“player D_NU 99”)
end
[/lua]

…and just took damage away when the NPC was close enough to the core to hit it every damage tick.

Looks weird visually but works the way it should. :slight_smile:

Thanks for the help guys.