TL;DR

I’ve made a lot of progress towards an NPC which patrols around and shoots players, but there’s nothing worth showing in a video.

This Week

My goal this week has been to get an NPC which patrols around the map and then shoots people that he encounters who are not on the same team. If you think about it this is actually a pretty complex goal with lots of sub goals:

  • AI steerable characters
  • Patrol routes
  • Path finding
  • Path following
  • AIs using tools (i.e. guns)
  • Teams
  • Detection
  • Planning

I’ve had a few of these in place for quite a long time, specifically steerable characters, path finding and path following have all been solidly implemented for quite a long time, this narrows my work down to teams, AIs using tools and planning. Planning has also been implemented for a long time (in fact I demonstrated it a while back in Changelog #16) but I’ve not used it for a long time and so my first task was to remind myself how the system worked.

I spent a couple of days neatening up a few sharp corners of the planning system - mostly integrating it better into the plugin API to make it much easier to implement goals and actions. I wasn’t really happy with what I ended up with though, it felt like defining an AI had a lot of annoying “ceremonial” code associated with it. For example, here’s a random like example AI:

//setup graphics.... nothing to do with AI
AddBehaviour<IGraphicsCylinder>();

//setup physics... nothing to do with AI
AddBehaviour<IPhysicsCylinder>();
AddBehaviour<IPhysicsBody>();
AddBehaviour<IHumanoid>();

//Setup sound... nothing to do with AI
AddBehaviour<IAudioEmitter3D>();

//Oh hey looks some AI stuff
AddBehaviour<IPlanningAgent>();
AddBehaviour<AiAction1>();
AddBehaviour<AiAction2>();
AddBehaviour<AiAction3>();
AddBehaviour<AiAction4>();

All this stuff is really important (there’s usually a load of configuration in here, rather than just some behaviours and nothing else but I left that out). The problem is composability: this example AI doesn’t have an animated body it’s just a cylinder which moves around, if I want an animated AI I can use exactly the same AI behaviours (yay, reuse) but I have to repeat everything here except repace IGraphicsCylinder with something else (boo, repetition).

I came with with a system for “Mix-ins” of behaviours. So for example I define a mix-in with the behaviours for AI, physics, audio and graphics and now my definition looks like this:

MixIn<AiStuff>();
MixIn<PhysicsStuff>();
MixIn<GraphicsStuff>();
MixIn<AudioStuff>();

This is great, because I can define a load of default mixins and save everyone from a load of make-work setting up the the same old entities everywhere… but if you do need to setup exactly what’s what you just stop using the mixin and define it yourself! Of course if I want to swap GraphicsStuff from a solid cylinder to a fully animated character well that’s easy, I just mixin a different set of graphical behaviours!

With this done, I spent some time overhauling the entity creation API a little more - again just fixing a few annoying bits of the API and removing unused parts of the system. It required me to go over all of my mods and modify my entity definitions but now they’re all shorter and easier to write which is a massive win for such an important part of the plugin system!

Finally, I spent some time building sensors for the AI to detect things (like other players). I started work on the suspicion and audio detection framework before, but this time I was working on visual detection. The NPC probes the physics engine every frame to find who is in sight and then does some raycasting to determine if they are hidden (behind a wall or in cover or something).

What’s Next?

I’ll continue working on this patrol and shoot AI. This touches most of the parts of the AI system so once this is done I should be able to build much more complex NPCs (for example a cooperating squad of NPCs who work together to encircle and flank players - that would be super cool).