Hey, I'm just some kid who makes games for fun :)

RSS My Blogs

How I made my simple NPC (HL2)

kill3rtomato Blog

SHello, and welcome back. I'm here again for another little (or rather large) blog entry. This one, like the last one, is also related to Half-Life 2 modding, specifically NPCs.

Now, before I go on I'd like to say something. I realize it has been months since I've posted anything here (I wonder if anybody reads this?). I haven't been modding the entire time. In fact, I basically just got back into it again (now that I understand C++ more thoroughly).

This time around I went ahead and followed the basic entity tutorials on the Valve Developer Community (Very good resource for all Half-Life 2 modding) again, to get myself back into gear with Half-Life's coding ways.

After I figured those out (didn't take long at all this time c:), I went ahead and started on another little "project": Make an NPC that follows the player around. Sounds simple right? Well, it actually is pretty simple, once you get the hang of how NPCs work in Half-Life 2 (In HL2 NPCs include zombies, combine, headcrabs, citizens, etc..).

First up was to figure out how exactly do NPCs work in HL2. I would say this was the biggest hurdle of all. I was pretty intimidated when I looked at how VALVe made the zombie, combine and other NPCs. So mcuh code! I didn't even know where to start at all! So what did I do? Went back to ye good ol' VDC!And sure enough, they bascially had a full tutorial on how to code your very own NPC (You can find it here).

Although at the time, when I read through that, I basically understoon nothing. I was still pretty confused on how exactly I would make an NPC work. So I started experimenting and looking around the files that came with the SDK, and I found a file called "monster_dummy.cpp" (For those who don't know, cpp files are C++ files). VALVe was nice enough to provide some explination at the top on what exactly that file was.


Turns out that was an NPC template! How convinient. All I needed to do was flesh it out.

The first thing I did was make my own cpp file for my new npc (I called it npc_box), copy and pasted the monster_dummy code into the new CPP file, changed all the class names to my own class name, etc etc...

Saved, compiled, started the mod, loaded up a map, spawned one of the new NPCs, and lo' and behold, it worked! Granted all it did was turn to look at you as soon as you walked up to it (and turned back a second later). But it still worked, and that's what matters right? .. Of course.. *sigh*

Anyways, now it was time to try and understand how NPCs worked. Well, needless to say I was pretty overwhelmed with all the NPC gibberish (schedules, tasks, conditions?? What is all this?!), I decided that something so simple as an entity that would follow the player couldn't be THAT hard right? Why would I need a complicated NPC?

So I ditched the NPC idea and went back to the model entity (which I created using this tutorial), and started tinkering with how it moved, behaved etc..

Well it basically got me nowhere at all. So I headed over to the Steam forums, more specifically the Source Coding forum, and made my topic asking for help (You can read through that topic right here), and asked for help. Long story short, they basically told me "you'll need NPCs to do that". So I was k', I guess I really am going to have to learn how NPCs worked.

Now, I told them how I thought an NPC worked. Here's what I said:

kill3rtomato wrote: Well, I guess I'll have to work with NPCs.. although I'm pretty confused by how they work. What I gathered from the tut on the VDC, was that the NPC first finds out what's happening around him, then it picks a state, then it selects a schedule.

The appropriate schedule, which is a list of tasks, is executed. It will continue to execute until it's either interrupted (by a defined interruption) or until it ends.. then it picks something else to do..

So.. am I right?


And this guy told me:

Winston wrote: Sounds right to me


Alrighty! So I at least had SOME idea as to how this all worked. Now, I'll say right now that I was basically summarizing what the VDC told me (the wiki.. remember?). This basically just told me "I'm right, stop doubting myself". (:

Anyways, so then it was time to really figure out how it all worked, code-wise. I followed this tutorial, read it all twice (or maybe three.. twelve times c:) until I had a pretty solid idea of how to code my NPC.

Another long-story short, I figured out how to get the NPC to work with all of it's schedules, tasks, conditions, etc.. Surprisingly, it really isn't that hard at all! It just seemed very confusing at first, but once I got the grasp of it, I was basically an exper- Ok, I'm still pretty noobish when it comes to this, but hey, give me some credit! ;)

Anyways! The fact that you are reading this makes me happy. Why don't you comment, and TELL me that you're reading this? ;)

Ok, ok, back on topic. So now that I knew how the NPC worked (sort-of), I then needed to give the NPC a schedule that said "follow the player". Well, technically the schedule says "turn to face the player, then find a path to the player, then follow that path", but that's for another time.

Now, at this point the NPC would basically just sit there and do absolutley nothing. This pretty much bothered me, since I specifially said in the schedule he should find a path to the player, then follow it.

Now, an odd quirk. Whenever I spawned an NPC, he would just sit there, but there would also be sparks coming from the top of his head. I had absolutley NO idea what that meant, and since there were no console messages I was REALLY stumped.. back to the Source Coding on the Steam forums for me!

Sormii was kind enough to post one of his own problems (and the solution) in my topic, so went and read through the topic. Now that I look back at it, it really didn't help me THAT much, it basically just told me that I KNOW that the problem is somewhere within the schedule, not making the NPC know that that's the schedule it should follow.

Basically the problem was somewhere within all the tasks within the schedule. The NPC knew that it should follow the schedule, but it didn't know HOW! Ok, two steps forward, one step back. Great.

Ok, so I said "screw this" and I went to bed. Next morning, I wake up, check the topic and voila! Sormii has come to my aid once more, with this very simple piece of code:

cpp code:
CapabilitiesAdd( bits_CAP_MOVE_GROUND );

It's funny, really. If you ever did read my other blog post (the one talking about the swimming engines), you'll know that I spent at least 3 hours (or an hour?) looking for one line of code. Granted, I wasn't looking for one line of code to fix my problem, I was looking for a solution in general.

But it seemed that this ONE piece of code solved all my problems! So, SUPER SPECIAL THANKS TO SORMII! (Along with Winston, and everybody else who helped me in my topic c:)

Ok, so now the NPC was "jumpy". Here's what happened. The NPC would turn to face you (like it should), then it would start towards you in a "lumpy" fasion. Think Zombie on crack. It would step forward, then stop for half a millisecond and begin again. It looked like it was limping. However, it did eventually make it to me, so I at least knew that it was finding a path to me and moving towards me. At least I had something going for me ;p

Well that was a pretty simple fix really. My schedule said this:
Task 1: Face player
Task 2: Find path to player
Task 3: Walk path

The problem? It wouldn't wait until it was at the end of the path to repeat the tasks. It had to continually stop, face player, find the path again, walk the path. This is not only not efficient, it gave me odd results.

Of course, there was a simple fix, add another task.
Task 4: Wait until all movement is complete to continue tasks

Well, that fixed that, didn't it? Now my NPC worked just as it should!

Although this is kind of off topic, I did some more experimenting with the NPC. I used some conditions to check wheter or not the NPC was within 128 units of the player. If it was farther, go through the process of getting to the player. Otherwise stand there. I won't bore you with that (plus it was relativly simple ;p).

And that basically concludes my adventures on finding out how to make a simple NPC, and how to get it to follow the player on Half-Life 2.

Who knows, one day I may write a tutorial on this! Actually, that isn't such a bad idea.. and it would include all code and stuff.. I know this blog post is not for those who are not very familiar with HL2 coding ;p

Until next time,
~Wurmy/Kill3rTomato

Swimming with Engines

kill3rtomato Blog

[SCROLL TO BOTTOM FOR PICTURES]

WARNING: Swimming with live engines could be hazardous to your health! Specially when they explode!

Heh, lately I have been modding Half Life 2: Ep2. It's really fun, and I'm definitely getting somewhere. So, after creating my first entity (Logical entity, one you can't see), I obviously moved on to the second tutorial, the model entity (One you can see). Well, as you can see from the pictures provided below that went well. Before I began the tutorial I though I was just going to finish this one up, then move along to the next one and see what would happen next. But, as I was about to find out, there was a bit of text in the model tutorial:

Authoring wrote: Our entity won't begin moving until prompted by InputToggle(). Changing this behaviour so that it starts active (which isn't just as simple as changing m_bActive in the code above!) would be a good project once you finish the tutorial proper.


Ok, so after I finished the tutorial, went back and challenged myself to do just that. Instead of maknig it activate by a button, I made the model start all on it's own (You can still toggle it on/off, it will just start automatically).

While I was messing with this, I began to look at the engine model. And it sparked my imagination. I just though "Wow that looks like a little ship.. that's moving around backwards". Well, usually ships don't move around on all 3 axes (meaning the model would fly, as in take off and move up). So I decided to mess with it some more.

So to get the moving to work on two axes I needed to change a line (or two). Really what I did is not important. What IS important however is this:
To make a vector you need 3 variables. X, Y, and Z. Valve has decided to use their own float types called vec_t. Well, for some stupid reason it took me 1-2 hours to find out that I was not typing vec_t but I was actually typing (and reading) vect_t. Notice the extra T. Yes, 2 hours. I looked at the VDC, studyied Vectors on wikipedia (which made little to no sense) and searched through the given HL2 code. Then I looked at my code again and found out that I had an extra T. Compiled, tested everything worked. The problem was my reading ability. Go me :)

After that dilemma, instead of being able to move anyway it wants, it can only move on two axes, x and y (Meaning it can't move up or down). Then because of the earlier "ship" looking decision, I also decided to put smoke on it. Well, like the pictures go, there is no smoke (Maybe I'll add it now!) but I did steal the grenade's sprite trail effect (the red glowing line that follows the grenade) and slapped it on my thing. I also modified it so it lasts longer.

Ok, so then in hammer I stuck a whole bunch of these together because I wanted to see what they would all look like. Now, keep in mind that I did test this all behind a glass wall that was toggled off when I stepped on two platforms (Thanks to my first logical entity). So, I put in a bunch of little flying thingies, then it struck me again. They look like fish!

Ok, now that really doesn't have much to do with anything but since they look like fish swimming around I decided to put water in the background. Made no difference, but that's how that got there.

Next comes explosions and gibs. And the fact that they can explode. Ok, generally when you shoot an airboat engine [in the movies] it blows up, So I then decided lets make them die (Buhaha). Started looking around, and found npc_combinecamera. That's the little camera that gets out of it's little cage, and looks at you. And when you shoot it, it creates an explosion and goes back up never to come back down again (lol).

So after many a minute searching and looking through it's code, I retyped my own code copy and pasted the code, modified it to my own will, and voila! It did nothing. That's right, it did nothing at all. It just kinda sat there and went back to floating aimlessly when I shot at it.

Ok, that didn't go to well. So being who I am I persisted until it finally worked. So at this point I had a flying engine that just stopped when I shot it enough. It just stopped. Didn't do anything. Ok, MORE searching! Now to find a function that removes/kills the entity! (Basically a function that just gets rid of the entity I'm working with. When I say remove/kill I mean just play vanish never to be seen again. No fancy effects).

Then after much searching the VDC, and knowing I couldn't find anything I went back to searching through the original source code only to find nothing. Ok, being a smartass that I am I know a little bit about coding. So I did this:

Ok, so you might not be a coder. Basically I went through every single function and looked for one that had anything to do with killing, getting rid of etc.. the entity. As you can see from the little bar this took a while (Damn that's a lot of methods/functions!)

So I finally found it. Do you want to know what it's called? Here I'll show you!

code:
Remove();

Ok so I spent at least 2 hours looking for something so obvious. Go me again :)

Well at that point, when you shot and "killed" one of the things, it just dissapeared. Now, that's what I wanted mind you! I hadn't added any special effects yet!

Now onto the more visual aspect of the killing of innocent airboat engines. Looked again at npc_combinecamera and found out how the explosions were made. Turns out it's one line of code (for pre-made Valve explosions). I'm not going to bother you with it though :)

Then came the gibs (which you may be able to see in the last picture). Again, I looked at Valve's code. This time at npc_scanner. You know, those scanners that go around and take pictures of you? Yeah those. They have gibs and that's what I want. And if you don't know, look at wikipedia to find out what gibs are. Although wikipedia says they're organic, they don't have to be.

So after much toil, and 3 days worth of messing around I present to you the "final" fishes that leave random red trails behind for no reason. And explode when shot at (enough).

Here, have some pictures!
Swimming EnginesSwimming EnginesSwimming Engines

And I guess that's all! If anybody reads this, may you suggest anything else I can do to these little rascals?

So, until next time
~Wurmy AKA Kill3rTomato