• How to make an SNPC follow you?
    6 replies, posted
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.