Devlog 12/07/2021.
After almost a week of designing, redesigning, asking for advice and thoughts and rethinking everything I've ever done, I've finally completed the design of the NPC system.
Behold, what was, not going to lie, a few very stressful days, where this was the only thing I could think about.
First to get the terminology out of the way. An NPC is a Non-Player Character - a character that the player cannot control. Since we only control Erik in this game, all other characters - including Christine, Raoul and everyone else - are NPCs.
An NPC System is an algorythm - a set of instructions - that manages all NPCs in the game, allowing them to walk around, to interact with the world and with the player, and react to things.
In my case, the NPC System includes:
An NPC Manager
A number of NPC scripts, describing general NPC behavior
A number of specific NPC scripts, describing specific, unique NPC behavior.
NPC Manager.
The NPC Manager is a large script that manages everything NPC-related. It is what loads and unloads NPCs in the game and saves all data about them.
NPC General scripts.
The NPC General script is an even larger script that describes general NPC behavior. It describes things that ALL NPCs have and can do:
Name, Appearance
Personality, Type
State (idle, unconscious, working, dead, etc)
Routine
Reacting to the player, as well as murder, bodies and theft
Dying and becoming a body
Having a mini-menu popup on mouse hovering over them.
Having a conversation with the player
Having a conversation with another NPC.
Then the NPC General script is inherited by a number of other NPC General scripts - one general script for each type (Worker, Artist, Administration, Visitor, Police), because the way they function differs so much between types.
Each of these scripts defines behavior specific for these types. Stuff like all possible "work" that this type might do. And also, subtypes specific for this type. For instance, Workers are divided into stud grooms, gas men, scene-shifters, maids, box-keepers, etc.
So now we have an NPC General script, an NPC Worker script, Artist script, Administration script, Visitor script and Police script. Wow. Quite a few scripts already.
There are gonna be a lot more.
NPC Specific scripts.
These are unique to ONE character. That is, if we have Christine - she's an Artist, Singer subtype - there will be a separate script just for her that describes how she interacts with Erik, all possible conversations (that'll be a long one) and all other behavior specific just to her. Yeah, I'm not dealing with these for now. These will most likely grow by themselves as I build up the plot.
Routines.
Now that we have all the general and specific behavior laid out... how about we actually put it into the game?
Here's the catch: my game is built in a way that requires only ONE location at a time to be loaded. Thus, I have no need - and no way - to calculate and predict what every single NPC does in every single location. So I need to deal with just one location at a time.
But before we decide how we do that... how do we deal with the actions themselves?
Answer: Routine.
Every character follows some sort of routine. That is, go there, do that, then go there and do that. Return tomorrow, repeat. A pattern begins to emerge. A Routine is a chronological list of Activities. An Activity must contain a starting time, a location and an action. That alone would be easy to implement. But how to deal with characters moving about BETWEEN locations?
In a game where the entire map is loaded, it would have been easy: use a pathfinder to guide the character into another room. But in my game, only one room is loaded at a time, and thus, once a character leaves a room that the player is in, they just go poof into oblivion.
This prompted me to think of another system: a system where the NPC Manager checks through all NPC routines once in a while, and if it finds an Activity with a starting time equal to that of the check, and with a location equal to that which is loaded, the NPC is loaded into the game, in a required position, doing a Thing.
This system, however, is very much imperfect. For instance, how would a character know when to leave the location they're in to arrive at the location of another Activity in time? Due to there being only one location loaded, we have no way of knowing how much time exactly all the walking is going to take. Additionally to that, the character's routine can be interrupted by the player, or another NPC - how do we account for that?
This prompted me to establish time periods in routine, instead of just mentioning the starting times. There is a time period, during which the character can arrive in a certain location, a time period during which they complete the action, and a time period during which they can leave. This allows for more flexibility and leniency. Additionally, with this system, the player will be able to follow the character from location to location.
But what if the player holds up the character (for example, with a conversation) so much that the time limit of the current period will pass? The character can leave the location immediately after the interruption is finished, but it will be impossible for the player to follow the character after that - since the character's routine will already be in another time period, and they won't be loaded into the current location scripted.
This question bugged me a lot, and then I was proposed the following: make such interactions extremely limited. Which would be realistic, since who is going to stand in a middle of corridor for hours on end, missing all their daily activities, just because a ghostly voice called for them and then didn't answer?
All interactions between Erik and NPCs who are going about their daily routine are going to have a timer attached, and are going to be designed to be very short. Once the timer is up, the character says that they're busy and leaves. Of course, this does not apply to those NPCs who go out of their way specifically to talk to Erik - that is, who break their routine. And no, stopping time isn't an option - since when do all people around stop walking when you're having a conversation with someone?
--‐----------------
Devlog 13/07/2021.
Few things happened.
First, I devised a way that won't allow NPCs to be early. The NPC Manager will read the appropriate time period from their routine, calculate what fraction of that time period has passed, and place the NPC in the middle of their path accordingly.
For instance, if Erik enters the location at 0:13, and the NPC is programmed to pass through this location from 0:10 to 0:15, then that NPC will be placed as if they had already passed 3/5 of their path from one door to another.
Secondly, I have realized that I can reuse what is currently tied to locations in NPCs instead: the "plot progression" variable.
The plot progression variable has a method that goes with it, and that method reads the plot progression variable from the save file, and then does things accordingly.
In each NPC Specific script (like with Christine) there will be a plot progression tree that will determine where the player currently stands. Since various events and conversations can happen across multiple locations, it'll make much more sense to program all conversations into NPCs, when I move into the opera house.
Does that mean that the location-tied plot progression variable will become obsolete? Eh, not necessarily. Sometimes I'll need to tie events to places. Maybe I'll find a way to intertwine the usage of location-tied and npc-tied plot progression. Like, if this location has this plot progression, and this npc loads into it that has this plot progression, then something happens. I might be able to "prepare" different locations for different events like that - and "launch" them through npcs.
----------------------------
And that leaves us in the present. I realize that this system is still imperfect, that I will most likely find fallacies in it going forward, but this gives me a solid foundation, a solid idea of what I am going to do. Starting tomorrow, I'll be slowly programming this into the game - and of course, I'll be sharing my progress with you.
I hope you're having a wonderful Monday, and I'll see you later. 💖💖💖











