In the first part I told you how I created the open-world of Ashworld. In this part I’ll explain how I link all the buildings, entities and missions into one big adventure.
Keeping track of things
When you play Ashworld, you’ll frequently swap between surviving the over-world, and running into buildings with it’s own set of challenges. I wasn’t really sure how I would keep all this working correctly, so I decided for the most basic and obvious solution. The buildings are their own world, with their own set of entities. The only thing that exists in both the overworld and the building itself is the “Door-entity” you used to enter the building.
To keep track of what happens in buildings and in the over-world, I decided to use a simple array of settings that each door has. This could be just a single setting like “levelDark” meaning that the building is dark and requires your torch or matches (or flamethrower if you are one of those persons). But the settings can be a full list of specifics that decide how the level is generated.
When you step through the door, the game switches to the 2D-sideview and then starts generating a building. For most buildings this will be a random building, but there are some specific buildings like Shops, Garage’s, your Home, Communications, and a few more.
The world-generator then picks a random pre-designed level template, and randomly decides if it wants to flip the template horizontally or not. It will also pick the textures to use (background and wall images) to give the building a unique look.
(early version of the buildings)
The fun thing is that once we enter a building, walk around, and exit it again. It would be pretty strange to re-enter the building and get a whole new look because the random-generation decided different situations.
Luckily I had already figured out how to avoid things like this when working on Heroes of Loot 2:
The trick, once again, is very simple. Every entity in the game get’s it’s own random-generator-seed. It also has it’s own “getMyRandomValue()” function which uses this seed to generate a random value and then increase the seed to the next random value.
So when I enter a door, the randomvalue is reset to the door’s original random-seed, and all random values that are generated at that point will be the same since the function to calculate the next random value will always do the same trick with the same base value.
Besides the random seed, all entities also have a “respawnCount” value which is linked to the game-time. So if you pick up all the weapons in the weaponry building, the building won’t magically respawn all the weapons the minute you re-enter the building. It will take up to a full day (in game time) to have those items placed again, limiting the loot-cheating a bit.
The trick is to still randomly generate those items, just not place them. If you wouldn’t generate them, or in other words call the getMyRandomValue() function, the whole random-number-order would be different and the building might look different. So do get the random values, just optionally don’t use them!
Some of the settings that a door can have are things like: levelDark, levelToxic, levelSkellynest. These indicate that the building has darkness, is full of toxic radiation, or has a Skelly-nest inside.
These are also sub-missions in the game, so finding these buildings and remedying the problem will get your XP and completes missions. Once you light a building-torch, the levelDark setting will be removed from the building and replaced with a “levelWasDark”. This still generates a darker building than normal, but it does light the torches on entry as if you already lit all of them before.
The levelToxic flag is removed once you bring a battery to the generator powering the big fans in a building. At which point the building will always generate a building without that flag, and with a turned on generator.
It’s a pretty sweet system, and really easy to expand on. I can just create new level flags, and test for those during world-generation to modify specific settings in a building. The recent addition was levelInfected, which will generate big mutations in a building blocking your path. Once I had the setting added, I randomly give it to doors on world-generation, and we suddenly have a bunch of buildings with a new mission!
One final thing which is linked to buildings, are some of the story-missions. The earliest of these is Gaz’ Garage (your first mission). In this case the door has gotten a myQuestID value that corresponds to a specific quest. So upon generating the building, this myQuestID is checked and based on that a specific building is generated.
For Gaz’ garage it generates the same garage building as always, but the avatar inside is generated with specific text and also receives the myQuestID so that it knows what it’s looking for.
Once you talk to the avatar, the quest is triggered, and this then spawns ragers outside the garage all linked with the same myQuestID. Taking out all the ragers will decrease the quest target, until all ragers are dead and the quest-target is zero. At that point the game will trigger a “wrapUpMission” event which spawns Gaz outside the building, running toward you with the “quest wrap-up text”. The door is freed of his myQuestID (set to -1) and from that point on the garage will be just a normal garage again.
This is how most quests trigger, and how everything is linked again from indoors to outdoor area’s.
(and as simple as it sounds now, it took a long time and many rewrites before I got this stuff working smoothly for all cases)