In this way, new encounters and vignettes can unlock based on things like:
* time of day - grave robbers stealing from the graveyard outside of town at night
* main quest line state - if you've advanced to a certain point in the story, new enemies or sidequests may appear.
Or even the kind of buildings at a location - a doctor can only offer you a quest to deliver some medicine if there's a doctor's office in town.
Each fragment also can specify an actual script function for more complex requirements than tags allow. It was a challenge getting designers to understand why they shouldn't just default to always putting conditions in this blueprint function, instead of special cases.
At a high level it's because the AI can't reason about (apply rules to) these fragments without that data. But even more importantly for the designers - it can't easily test them without that data.
If a fragment specifies its location tags (instead of chucking in random blueprint logic), the fragment testing interface can automatically populate a dropdown box with all the levels you could see this fragment in when testing it.
So in a few clicks you could jump to almost any fragment as closely matching real game conditions as possible (to reduce the chances of bugs appearing only via testing or only in a real game).
In any case, like other storylet systems, the player acts on the world, like they get new abilities/equipment, make friends/enemies, what they run into is built from their past experience. But the game also defines who and where can be incorporated into them.
Weird West uses some randomness/procedural generation in its world. The main story characters and locations are fixed or explicitly defined - however outside that, locations are somewhat randomized, as well as their population.
The random vs static ones aren't using different definitions or systems to be created - they both use the same underlying systems. The core principle for any procedural stuff like this on Weird West was always that it work seamlessly with bespoke content.
So at any given time, if you wanted to override the procedural behavior in some weird combination of events, it would be relatively easy.
This design philosophy came from LMNO, building a very systemic game that we knew at any point Spielberg might see and give feedback like "oh it would really cool if right there it did this".
For some backstory (sadly the original 1up story isn't around)
1UP examines Spielberg's LMNO, the game that 'tried to do too much' | Engadget
So we knew we would need to override multiple systems when they combined in certain ways/edge cases, to create the most Spielbergian* moments we could (*actual term we used).
In physics in games sometimes you "cheat" a little under the hood to make neat stuff happen - kick a guy near a ledge or window and he might happen to turn a little bit to have him fall spectacularly, or get pushed a little harder to make sure it happens.
Under the hood you're just giving an impulse to the physics sim, you don't have to go create a separate system, or use a custom animation. You just poke the sim in a way it understands being poked. The same can apply to other systems like story - "story physics" if you will.
We never quite got to that point on LMNO, but tldr I happened to spend the next 12 years thinking about the best ways to do it. This tech in Weird West is definitely a product of that.
To elaborate more on how that works, let me go thru with how characters and locations are created in the game. It doesn't matter if it's a randomly generated character or location, or a story specific one, they're created the same way - by specifying a series of tags.
Characters have classes (in tag form, "Class:Outlaw"), a creature type (the species like "CreatureType:Human"), gender, ethnicity, level, etc. Any tag not specified when creating a character means a random or default tag value gets assigned from a taxonomy.
A taxonomy is a categorization of how to apply random sets of tags to something. Each creature type has a general one - humans have a category in their taxonomy for Ethnicity, which randomly assigns values for the Ethnicity tag based on equal weighting of all the 5 values.
A specific character class might override that taxonomy with its own. The Oneirist class is only allowed to specify female for the gender, based on the fiction. The Outlaw class always assign the "Hat" tag to make sure they look distinct as potential enemies.
The character is then created from a database of meshes and materials for different body parts based on those tags (specified or randomly applied). Have the hat tag? Get a hat mesh. These assets are filtered like I described in the tagging thread linked earlier
So a crucial story character would have all their tags specified once when creating them/starting the game. Characters populating fully randomized location get all their tags randomized, according to those rules. But they go through the same pipeline at the end.
This allows the AI-selected story fragments to not just create new characters if it needs, it will first typically find an existing an existing character that matches a general set of tags it needs.
For that doctor has a side quest to deliver some medicine, you just care that the NPC has the right "Class: Doctor" tag, you don't care about the gender, ethnicity, etc.
So the procedurally populated fragments can totally use a specific bespoke story character to fulfill their needs for casting characters.
There's def more work under the hood to make that function that I'm glossing over here - For instance characters need to be able to have multiple conversation topics you can alternate between, if a character needs to perhaps tell you important things to advance multiple quests.
The system has to handle when a fragment can't find a character in a town that should have one - let's say the sheriff is needed b/c someone is gonna ask you to free a prisoner in jail, but you killed the sheriff last time you were there.
The system won't find a character and so needs to repopulate the sheriff - so it works with the population system to create a new one that acts as that town's sheriff, and not just some unaffiliated lawman passing through.
Locations are similar to characters, but more involved. There are layouts with different lot sizes, building types with multiple versions for variety, each having different lot sizes associated with them, and the system has to solve for valid random or specified combinations.
Now that the story AI can treat a random character or location exactly the same as a bespoke story one, it becomes a lot easier to apply rules to all the fragments, because the main difference between procedural fragments and bespoke is just how much they specify.
A lot of the rules are just making sure things don't happen too frequently or infrequently. But there's lots of fun to be had here - as long as you don't get too complicated. The effect of any single rule might be subtle yet pervasive, so you have to tread with care.
There are rules to boost random weights - if you have a straightforward fetch style side quest, action-heavy fragments can be boosted.
The system can prioritize some characters over others when casting random roles - you can get procedurally recurring side characters that way.
Some roles can be filled from anywhere in the surrounding area - if you're attacked by undead on the road, they can come from graveyards in any nearby location. So don't be surprised if you see someone you might know
Some fragments can take even deeper advantage of the history you have with other characters. You can form vendettas, make friends for life, and these characters will recur in special ways.
Sometimes people don't understand the power of managing this sequencing of story via AI. But even small bits of episodic writing can have powerful impacts on people experience something.
By episodic writing I mean story chunks where there's some starting state of the characters and world, and some resulting state when the episode completes - but other than that, they can be used anywhere or experienced in any order.
The example of this I always like to point to The Prisoner, 1967 British spy show where the main character is an ex-spy who is basically being fucked with because he knows too much to peacefully retire.
The Prisoner - Wikipedia
There are 17 episodes, each (except 1 iirc) has a different antagonist running the mind games. There's an order in which they were filmed, & a diff order that they were aired, but the subtle diffs in the shows have led to a 50 year long debate on the canonical order of the eps.
So yeah, episodic storytelling can have quite an impact.
All the systems in Weird West, all these layered randomized+"authored" systems and storytelling rules are just one way of defining "narrative legos".
And as perhaps understandable as that term may be to non-developers, compared to a more jargon-y term like storylets, it still doesn't capture the complexity of what you have to do to push forward on procedural narrative - perhaps it is too misleading.
Over the years, plenty of people have set out on to reach the goal of one narrative system that can be used to define all or a larger set of procedural stories - there's not, and never will be, any such thing of course.
All the principles I've gone through are absolutely applicable, like merging ways of authoring bespoke and randomized content, but the systems would not. A game with a smaller set of characters that you interact with even more, might have very different constraints.
It's not just a design problem, a programming problem, or a writing problem, it's a design+programming+writing problem, so in the end you often need designer-programmer-writers to craft the systems you need to "tell" your story.
You're not just using standard sets of bricks to build something, you have to decide on all the sizes of each brick type, each way they can link with every other type, and *then* use them to build something.
Well, hopefully I have in some small way for someone, somewhere, maybe dispelled maybe a little confusion about how complicated something like "narrative legos" can be. Thanks for reading!