- Jun 2, 2017
- 30
- 21
[GUIDE] generic_actor (NPC) entity guide - generic_actor entity guide
----------Introduction----------
Heyo there! Did you ever wanted to make custom NPC's in your map? then this guide is for you!
With such a guide you can make stuff like this!
----------Basics----------
Let's start from basics - what generic_actor on it's own? It's a "puppet" npc entity.
It can do things like:
- Move(walk, run, stand)
- Move it's head towards player position
- lipsync
- Play animations at reaching certain destination
- Apply custom model of NPC
Not that much of functionality but working entity from HL2 is pretty much enough.
----------Working with Entity [KEYVALUES]----------
WARNING: You need HL2 fgd to make generic_actor entities appear in hammer. You can grab HL2 FGD there
https://cdn.discordapp.com/attachments/855906574232453192/921465285935005766/halflife2.fgd
To install FGD you should open up hammer, click Tools > Options > Find Game Data files tab and press Add. Select halflife2.fgd (the one you downloaded) After that restart hammer and we're good to go!
Let's start by placing generic_actor on our map
I'm gonna be short and just explain main keyvalues
Health - Health of generic_actor before it'll turn into ragdoll. Must be same or lower value than Max Health one Be sure to check BUG: observation.
Max Health - Same as Health. Clamps generic_actor's health
BUG: You should setup health and Max Health with big values like I did because killing generic_actor naturally (not kill input) will result in ragdoll that is client-side. It means that it cannot be killed
Weapon Held - Broken
Hull type - Used to specify collision box
Model - Model (that was obvious haha). You can take any model from HL2 that supports movement. Gman, Alyx, Headcrab, Zombie, Dog e.t.c.
You can also use custom model. Just decompile existing HL2 model (Sitizen recommended) and re-rig your model to those bones and then compile it back. DO NOT delete any bones. It'll result in crash.
BUG: If your model is human - then it's head is gonna break eventually due to some HL2 shaders. You can fix it but you'll need some modelling compiling/decompiling knowledge.
Dropping fixed Kleiner's model there
https://cdn.discordapp.com/attachments/855906574232453192/921469940773552128/kleiner_fix.rar
models/time_machine/kleiner.mdl
----------Working with Entity [FLAGS]----------
Ignore player push - generic_actor wouldn't run away from player when he touches generic_actor
Any other flag is not that important
----------Ragdoll [Optional]----------
Since we're setting up health up to infinite (immortal) state, we have to imitate process of making ragdoll.
Create prop_ragdoll entity and give it the same model name as you did for generic_actor. Then create point_template at the origin of ragdoll where pelvis is located
Open up point_template and change keyvalue's value of "Template 1" to your prop_ragdoll name.
Now, create env_entity_maker at the origin of generic_actor where pelvis is located.
Open up env_entity_maker and change keyvalue's values from/to
Parent - Name of your generic_actor
point_template to spawn - Point Template that you created earlier
PostSpawn Movement Speed - 15
PostSpawn Direction Variance - 0
After all of that we're mostly done. Create math_counter entity and set Maximum Legal Value to amount of hits that your generic_actor would receive to die. In outputs tab type:
OnHitMax name of your env_entity_maker ForceSpawn
OnHitMax name of your generic_actor Kill [DELAY 0.01]
The last thing we're left to-do is to open up generic_actor's Output tab and add
OnDamaged Name of your math_counter Add 1
If you want to add sounds - Do something like
OnDamaged mysound001 PlaySound. Be sure to check that sound has SourceEntityName set up to your generic_actor!
----------AI_RELATIONSHIP Entity----------
This entity is required to make generic_actor's head follow player while he's in specified radius
- Place ai_relationship on your level
Subject(s) - Name of your generic_actor
Target(s) - Target. Leave it as player
Disposition - The way the subject(s) should feel about the target(s)
Start Active - Yes/No
Reciprocal - Make the new disposition apply to the targets as well as the subjects.
----------LIPSYNCING----------
Most easiest thing is this tutorial is to make generic_actor lipsync. To-do so, create ambient_generic and find HL2 talking NPC sound. For kleiner, most of the sounds are located at vo/k_lab path. You can create your own lipsync files but I forgot how-to do that and as far as I remember program to-do so is really broken
The one thing you should change in ambient_generic is SourceEntityName keyvalue. Change it to your generic_actor name
----------Making generic_actor move----------
To make generic_actor finally moving you'll need 2 more entities:
- info_node
- scripted_sequence
info_node is used for HL2's navigation mesh. You have to place those in area where your generic_actor is supposed to walk. Bigger radius between each info_node reduces accuracy of moving. Smaller radius increases accuracy. Recommended gap between each node is 512 either 256 H/U
scripted_sequence is used to force generic_actor to actually move. It's just like path_track - you're specifying path one by one. Let's take closer look on all keyvalues
Target NPC - name of generic_actor
Entry Animation - Animation that goes before Action ( Mostly useless, just use Action Animation)
Action Animation - Animation that is gonna be played on generic_actor when passing this scripted_sequence. Leave blank for no animation. You can find animations by looking at your generic_actor's model
Loop Action Animation? - Used to loop Action Animation and not going to next scripted_sequence
Move to Position - Better to use Either Walk or Run. The way generic_actor would actually move
Next Script - Next scripted_sequence that'll follow generic_actor. Same as path_track
We've set up our first scripted_sequence! Yay! Now let's do other one just to make our generic_actor move in loop
Now let's run a map and test it out by firing BeginSequence to first scripted_sequence
Seems like it works! That's pretty neat. Now let's place THIRD scripted_sequence that'll play animation and change generic_actor's moving type to Run
Also let's cover output section! To make scripted_sequence fire outputs for events like opening door in sync with animation - we're gonna use OnBeginSequence
Now it's a little bit tricky. To make this all work you should fire to all of your scripted_sequence of that scientist CancelSequence with small delay (0.05) and then fire BeginSequence of the one with animation that we set up.
Let's check if it works!
That's basically it. If you find any part confusing - Feel free to ask here or in my DM about it!
About to left a prefab so you guys can look how it was done more precisely!
----------Introduction----------
Heyo there! Did you ever wanted to make custom NPC's in your map? then this guide is for you!
With such a guide you can make stuff like this!
Let's start from basics - what generic_actor on it's own? It's a "puppet" npc entity.
It can do things like:
- Move(walk, run, stand)
- Move it's head towards player position
- lipsync
- Play animations at reaching certain destination
- Apply custom model of NPC
Not that much of functionality but working entity from HL2 is pretty much enough.
----------Working with Entity [KEYVALUES]----------
WARNING: You need HL2 fgd to make generic_actor entities appear in hammer. You can grab HL2 FGD there
https://cdn.discordapp.com/attachments/855906574232453192/921465285935005766/halflife2.fgd
To install FGD you should open up hammer, click Tools > Options > Find Game Data files tab and press Add. Select halflife2.fgd (the one you downloaded) After that restart hammer and we're good to go!
Let's start by placing generic_actor on our map
I'm gonna be short and just explain main keyvalues
Health - Health of generic_actor before it'll turn into ragdoll. Must be same or lower value than Max Health one Be sure to check BUG: observation.
Max Health - Same as Health. Clamps generic_actor's health
BUG: You should setup health and Max Health with big values like I did because killing generic_actor naturally (not kill input) will result in ragdoll that is client-side. It means that it cannot be killed
Weapon Held - Broken
Hull type - Used to specify collision box
Model - Model (that was obvious haha). You can take any model from HL2 that supports movement. Gman, Alyx, Headcrab, Zombie, Dog e.t.c.
You can also use custom model. Just decompile existing HL2 model (Sitizen recommended) and re-rig your model to those bones and then compile it back. DO NOT delete any bones. It'll result in crash.
BUG: If your model is human - then it's head is gonna break eventually due to some HL2 shaders. You can fix it but you'll need some modelling compiling/decompiling knowledge.
Dropping fixed Kleiner's model there
https://cdn.discordapp.com/attachments/855906574232453192/921469940773552128/kleiner_fix.rar
models/time_machine/kleiner.mdl
----------Working with Entity [FLAGS]----------
Ignore player push - generic_actor wouldn't run away from player when he touches generic_actor
Any other flag is not that important
----------Ragdoll [Optional]----------
Since we're setting up health up to infinite (immortal) state, we have to imitate process of making ragdoll.
Create prop_ragdoll entity and give it the same model name as you did for generic_actor. Then create point_template at the origin of ragdoll where pelvis is located
Open up point_template and change keyvalue's value of "Template 1" to your prop_ragdoll name.
Now, create env_entity_maker at the origin of generic_actor where pelvis is located.
Open up env_entity_maker and change keyvalue's values from/to
Parent - Name of your generic_actor
point_template to spawn - Point Template that you created earlier
PostSpawn Movement Speed - 15
PostSpawn Direction Variance - 0
After all of that we're mostly done. Create math_counter entity and set Maximum Legal Value to amount of hits that your generic_actor would receive to die. In outputs tab type:
OnHitMax name of your env_entity_maker ForceSpawn
OnHitMax name of your generic_actor Kill [DELAY 0.01]
The last thing we're left to-do is to open up generic_actor's Output tab and add
OnDamaged Name of your math_counter Add 1
If you want to add sounds - Do something like
OnDamaged mysound001 PlaySound. Be sure to check that sound has SourceEntityName set up to your generic_actor!
----------AI_RELATIONSHIP Entity----------
This entity is required to make generic_actor's head follow player while he's in specified radius
- Place ai_relationship on your level
Subject(s) - Name of your generic_actor
Target(s) - Target. Leave it as player
Disposition - The way the subject(s) should feel about the target(s)
Start Active - Yes/No
Reciprocal - Make the new disposition apply to the targets as well as the subjects.
----------LIPSYNCING----------
Most easiest thing is this tutorial is to make generic_actor lipsync. To-do so, create ambient_generic and find HL2 talking NPC sound. For kleiner, most of the sounds are located at vo/k_lab path. You can create your own lipsync files but I forgot how-to do that and as far as I remember program to-do so is really broken
The one thing you should change in ambient_generic is SourceEntityName keyvalue. Change it to your generic_actor name
----------Making generic_actor move----------
To make generic_actor finally moving you'll need 2 more entities:
- info_node
- scripted_sequence
info_node is used for HL2's navigation mesh. You have to place those in area where your generic_actor is supposed to walk. Bigger radius between each info_node reduces accuracy of moving. Smaller radius increases accuracy. Recommended gap between each node is 512 either 256 H/U
scripted_sequence is used to force generic_actor to actually move. It's just like path_track - you're specifying path one by one. Let's take closer look on all keyvalues
Target NPC - name of generic_actor
Entry Animation - Animation that goes before Action ( Mostly useless, just use Action Animation)
Action Animation - Animation that is gonna be played on generic_actor when passing this scripted_sequence. Leave blank for no animation. You can find animations by looking at your generic_actor's model
Loop Action Animation? - Used to loop Action Animation and not going to next scripted_sequence
Move to Position - Better to use Either Walk or Run. The way generic_actor would actually move
Next Script - Next scripted_sequence that'll follow generic_actor. Same as path_track
We've set up our first scripted_sequence! Yay! Now let's do other one just to make our generic_actor move in loop
Now let's run a map and test it out by firing BeginSequence to first scripted_sequence
Seems like it works! That's pretty neat. Now let's place THIRD scripted_sequence that'll play animation and change generic_actor's moving type to Run
Also let's cover output section! To make scripted_sequence fire outputs for events like opening door in sync with animation - we're gonna use OnBeginSequence
Now it's a little bit tricky. To make this all work you should fire to all of your scripted_sequence of that scientist CancelSequence with small delay (0.05) and then fire BeginSequence of the one with animation that we set up.
Let's check if it works!
That's basically it. If you find any part confusing - Feel free to ask here or in my DM about it!
About to left a prefab so you guys can look how it was done more precisely!