Well… this is a data structure.
You could use something like a relational, or even a multidimensional, data structure for this.
So relationally you’d have (think like sql, where a table is a single spreadsheet):
A table of all NPCs
A table of all gamestates
A table of all spawn points/dialogues
The first 2 tables are as long as there are NPCs and gamestates.
Then in the spawn point table you’d have 4 columns:
npc id
gamestate id
spawnpoint
dialogue
Now you just go through and row by row you work with each npc/gamestate. I personally would go npc by npc, so something like this (note I’m using english names for ids, but you can use ints to speed it up):
NPC ID | GSTATE | POINT | DIALOGUE
Eric |1 |... |Hello, I am Eric.
Eric |4 |... |Thank you sooooo much!
Sally |1 |... |How's it going?
Sally |2 |... |Oh no, the evil emperor kidnapped Eric!
Sally |3 |... |Stop dilly-dallying, go save Eric!
Sally |4 |... |Thanks again for saving Eric.
Joe |1 |... |Ooga booga
Joe |2 |... |Spare a nickel for some beer?
Joe |3 |... |Evil emperor? I care not for the evil emperor. Got some beer?
Joe |4 |... |You bastard! You destroyed all the beer kegs in your stupid fight with the evil emperor!
Note how Eric doesn’t exist in game states 2 and 3 because he was kidnapped by the evil emperor. So he just doesn’t have entries for that.
If you need to know who Eric is, you look up Eric in the NPCs table. So if you want to know which model to use, or which house is his, or what other data you store on the NPCs table, you look it up by matching (hence the ‘relational’ bit in the name of this structure). Heck you can even store a ‘default spawn point’ on the NPC table, and that way you just put something like ‘default’ in the point column saying to just spawn him in his preferred location… saving you from having to type the same coordinates over and over.
Heck, you could even create a ‘spawn point’ table of actual positions, and the point column of the point/dialogue table you just reference the spawn point again. Foregoing the ‘default’ position, and instead you create a spawn point called ‘erics default’, or ‘by the well’, or ‘at front gate’. And then you just swap out who goes where by putting in the id of the location in the point column.
Note…
you can rearrange the order in that table I drew out.
For instance sort it by gamestate. Such a work flow might make more sense in a timeline sort of way.
NPC ID | GSTATE | POINT | DIALOGUE
Eric |1 |ericdef|Hello, I am Eric.
Sally |1 |salldef|How's it going?
Joe |1 |joedef |Ooga booga
Sally |2 |well |Oh no, the evil emperor kidnapped Eric!
Joe |2 |alley |Spare a nickel for some beer?
Sally |3 |well |Stop dilly-dallying, go save Eric!
Joe |3 |alley |Evil emperor? I care not for the evil emperor. Got some beer?
Eric |4 |gate |Thank you sooooo much!
Sally |4 |salldef|Thanks again for saving Eric.
Joe |4 |well |You bastard! You destroyed all the beer kegs in your stupid fight with the evil emperor!
…
I don’t know, just tossing around some ideas.