I need some way of making an SNPC toggle between Following the player who invokes ENT:Use(), or randomly wandering. I have tried self.Entity:NavSetGoalTarget(ply, Vector(0,0,0)) but that does not seem to work by itself.
Any help with this one?
Try
[lua]
self.Entity:SetTarget(ply)
self.Enitty:SetSchedule(SCHED_TARGET_CHASE)
[/lua]
That should make it run to the player. Will need to be called every time the schedule finishes for it to be following.
Yeah, Ive thought about that, but doesn't that cause the NPC to target the actual player as the "enemy"? Im trying to mimic the HL2 Rebels how they join your squad. They need to still be able target enemies, fire at them, etc.
[editline]8th March 2011[/editline]
Ok. So I figured out why this is not working. ENT:Use() apparently does not work on SNPCs?
I put a debug message as the first line of the Use function and I am not seeing it.
[lua]
function ENT:Use(activator, caller)
Msg("Use was called")
//0 - never found
//1 - following
//2 - holding position
if (self.State == 0) then
self.State = 1
self.Entity:SetTarget(activator)
//self.Entity:SetSchedule( sched )
//self.Entity:SetCurrentSchedule( sched )
Msg("Following!!!")
elseif (self.state == 1) then
self.State = 2
else
self.State = 1
end
end
[/lua]
NOTE: I am setting the schedule elsewhere.
Did you set the use type on the npc in Initialize? Because i've made a shop npc before and use worked
[b][url=http://wiki.garrysmod.com/?title=Entity.SetUseType]Entity.SetUseType [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]
As far as them being enemies, no it's just a target, [b][url=http://wiki.garrysmod.com/?title=NPC.SetEnemy]NPC.SetEnemy [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] would set the player as the enemy target. If the relationship is Neutral or Like, it shouldn't be an enemy anyway.
Here's the set target page also [b][url=http://wiki.garrysmod.com/?title=NPC.SetTarget]NPC.SetTarget [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b]
Yep, Ive had that in from the beginning. And I know what you mean because I've done similar things before.
Here's my entire init.lua for the NPC. Theres not much else in cl_init or shared other than the few required things like "Draw"
[lua]
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include('shared.lua')
ENT.RemoveTime = 0
ENT.RemovePos = Vector(0,0,0)
function ENT:Initialize()
self.Entity:InitializeCharacter()
self.Entity:SetHullSizeNormal()
self.Entity:SetHullType( HULL_HUMAN )
self.Entity:SetSolid( SOLID_BBOX )
self.Entity:SetMoveType( MOVETYPE_STEP )
self.Entity:SetMaxYawSpeed( 5000 )
self.Entity:SetHealth( 100 )
self.Entity:CapabilitiesAdd( CAP_MOVE_GROUND | CAP_TURN_HEAD | CAP_USE_WEAPONS | CAP_AIM_GUN | CAP_WEAPON_RANGE_ATTACK1 | CAP_MOVE_SHOOT )
self.Entity:DropToFloor()
self.Entity:Give( "weapon_glock" )
self.Entity:SetUseType(SIMPLE_USE)
end
function ENT:InitializeCharacter()
self.Entity:SetModel( "models/Humans/Group03/Male_0" .. math.random( 1, 9 ) .. ".mdl" )
//0 - never found
//1 - following
//2 - holding position
self.State = 0
self.Items = {}
end
function ENT:Think()
if self.Entity:GetCurrentSchedule() == SCHED_RANGE_ATTACK1 then
local wep = self.Entity:GetActiveWeapon()
if ValidEntity( wep ) then
wep:PrimaryAttack()
end
end
end
function ENT:SpawnRagdoll( att, model )
local ang = self.Entity:GetAngles()
local shooter = ents.Create("env_shooter")
shooter:SetPos( self.Entity:GetPos() )
shooter:SetKeyValue( "m_iGibs", "1" )
shooter:SetKeyValue( "shootsounds", "3" )
shooter:SetKeyValue( "gibangles", ang.p.." "..ang.y.." "..ang.r )
shooter:SetKeyValue( "angles", ang.p.." "..ang.y.." "..ang.r )
shooter:SetKeyValue( "shootmodel", ( model or self.Entity:GetModel() ) )
shooter:SetKeyValue( "simulation", "2" )
shooter:SetKeyValue( "gibanglevelocity", math.random(-50,50).." "..math.random(-250,250).." "..math.random(-250,250) )
if ValidEntity( att ) then
shooter:SetKeyValue( "m_flVelocity", tostring( math.Rand( -40, 0 ) ) )
shooter:SetKeyValue( "m_flVariance", tostring( math.Rand( -2, 0 ) ) )
end
shooter:Spawn()
shooter:Fire( "shoot", 0, 0 )
shooter:Fire( "kill", 0.1, 0.1 )
if not att:IsPlayer() then return end
//local ent = ents.Create( "sent_lootbag" )
//for k,v in pairs( self.Items ) do
// ent:AddItem( v )
//end
//ent:SetPos( self.Entity:GetPos() + Vector(0,0,25) )
//ent:SetRemoval( 60 * 3 )
//ent:Spawn()
end
function ENT:DoDeath( dmginfo )
if self.Dying then return end
self.Dying = true
self.Entity:SpawnRagdoll( dmginfo:GetAttacker() )
self.Entity:SetSchedule( SCHED_FALL_TO_GROUND )
self.Entity:Remove()
end
function ENT:VoiceSound( tbl )
if ( self.VoiceTime or 0 ) > CurTime() then return end
self.VoiceTime = CurTime() + 2
self.Entity:EmitSound( Sound( table.Random( tbl ) ) )
end
function ENT:OnTakeDamage( dmginfo )
self.Entity:SetHealth( math.Clamp( self.Entity:Health() - dmginfo:GetDamage(), 0, 1000 ) )
if self.Entity:Health() < 1 then
self.Entity:DoDeath( dmginfo )
end
end
function ENT:GetRelationship( entity )
if string.find( entity:GetClass(), "npc_headcrab" ) or string.find( entity:GetClass(), "zombie" ) then
return D_HT
end
return D_LI
end
function ENT:UpdateEnemy( enemy )
if ValidEntity( enemy ) and ( string.find( enemy:GetClass(), "npc_headcrab" ) or string.find( enemy:GetClass(), "zombie" ) ) then
self.Entity:SetEnemy( enemy, true )
self.Entity:UpdateEnemyMemory( enemy, enemy:GetPos() )
else
self.Entity:SetEnemy( NULL )
end
end
function ENT:FindEnemy()
local tbl = ents.FindByClass( "npc_zombie*" )
tbl = table.Add( tbl, ents.FindByClass( "npc_headcrab*" ) )
if #tbl < 1 then
return NULL
else
local enemy = NULL
local dist = 99999
for k,v in pairs( tbl ) do
local compare = v:GetPos():Distance( self.Entity:GetPos() )
if (compare < dist and string.find( v:GetClass(), "npc" ) ) then
enemy = v
dist = compare
end
end
return enemy
end
end
function ENT:SelectSchedule()
local enemy = self.Entity:GetEnemy()
local sched = SCHED_IDLE_WANDER
if (self.State == 1) then
Msg("We choose to follow")
sched = SCHED_TARGET_CHASE
if self.Entity:HasCondition( 21 ) then // COND_CAN_RANGE_ATTACK1
sched = SCHED_RANGE_ATTACK1
end
elseif (self.State == 2) then
sched = SCHED_ALERT_STAND
elseif ValidEntity( enemy ) and enemy:GetPos():Distance( self.Entity:GetPos() ) < 2000 then
if self.Entity:HasCondition( 21 ) then // COND_CAN_RANGE_ATTACK1
sched = SCHED_RANGE_ATTACK1
else
sched = SCHED_CHASE_ENEMY
end
else
self.Entity:UpdateEnemy( self.Entity:FindEnemy() )
end
self.Entity:SetSchedule( sched )
self.Entity:SetCurrentSchedule( sched )
end
function ENT:SetCurrentSchedule( sched )
self.CurrSched = sched
end
function ENT:GetCurrentSchedule()
return self.CurrSched or SCHED_IDLE_WANDER
end
function ENT:Use(activator, caller)
Msg("Use was called")
//0 - never found
//1 - following
//2 - holding position
if (self.State == 0) then
self.State = 1
self.Entity:SetTarget(activator)
//self.Entity:SetSchedule( sched )
//self.Entity:SetCurrentSchedule( sched )
Msg("Following!!!")
elseif (self.state == 1) then
self.State = 2
else
self.State = 1
end
end
//NavSetGoalTarget
[/lua]
Just looked up my old code, i'm not using ENT:Use() i'm using
[lua]
function ENT:AcceptInput( Name, Activator, Caller)
if( Name == "Use") and CurTime() >= (Activator.LastUse or 0) + 3 then
Activator.LastUse = CurTime()
-- Insert Shop or whatever code here
end
end
[/lua]
[QUOTE=Fantym420;28499261]Just looked up my old code, i'm not using ENT:Use() i'm using
function ENT:AcceptInput( Name, Activator, Caller)
if( Name == "Use") and CurTime() >= (Activator.LastUse or 0) + 3 then
Activator.LastUse = CurTime()
-- Insert Shop or whatever code here
end
end
[/QUOTE]
Works great. Thanks mate!
Sorry, you need to Log In to post a reply to this thread.