• Hey, guest user. Hope you're enjoying NeoGAF! Have you considered registering for an account? Come join us and add your take to the daily discourse.

Kotaku: How A Designer Accidentally Opened Every Door In The Witcher 3

Crossing Eden

Hello, my name is Yves Guillemot, Vivendi S.A.'s Employee of the Month!
Source.
Video games like The Witcher 3 are enormous, complicated pieces of machinery with thousands upon thousands of moving parts. Make one mistake and you can break everything—or, as one developer discovered, you can accidentally unlock every door in the game.

Tost and the rest of the design team scoured the game’s world, trying to figure out how this had happened. Doors in The Witcher 3 weren’t automatically attached to buildings—instead, the designers had to place each one manually—so going through them all was a tedious process. Some doors were meant to be always open, while others were meant to be locked with specific keys that you could find in the world. Others, of course, were never supposed to open at all.

Eventually, the developers of The Witcher 3 identified the problem. During a quest in Blood and Wine involving the siege of a castle called Dun Tynne, CD Projekt Red’s quest design team had decided that they didn’t want the player to be able to enter any of the buildings. This was meant to be a linear, streamlined mission—Geralt shouldn’t be getting distracted. The Witcher 3 was supposed to lock all of the doors for the duration of the quest, and then, once the quest was over, unlock those doors once again.

Problem was, as Miles Tost recalled, the game had no way of knowing which doors had been open before the quest and which ones had been locked. So it would just open everything. “This would result in all the doors in the game being unlocked,” Tost said. “And I remember the solution for this was quite bitter—the quest designer had to actually go through every single door in the game and add this tag. ‘This is a door that was closed before, and it should be closed again after.’”

Thought this was pretty funny. Reminds me of how the BOTW devs said that a slight change in the wind systems for their engine caused every physical object in the world to perpetually fly all over the place.
 

KTallguy

Banned
Man, I feel their pain... it's hard to predict what sort of things you'll need in the future... thus you have situations like these. Doors that have memory and record their state to be referenced would be something useful... but you don't know you need it until you do :)
 
That seems like a strange solution, my memory of that mission is fuzzy but why couldn't they instead just barricade the player into the castle once they begin the assault (Doesn't have to use invisible walls, could just have carts and other battlefield debris blocking the exit) and disable fast travel so they can't leave, then only lock/unlock the doors in the castle rather than... Everywhere?
 

wetalo

Member
Sounds like a few lines of code could fix this.

I'm not a programmer

Basically, every door in the quest area has to be given an additional boolean value, we'll call it lockedBeforeQuest.

Before starting the quest, whenever Geralt unlocks a door, it'll flip that boolean from "true" to "false". When the quest is finished, and it's time to unlock all the doors, the game looks at the lockedBeforeQuest value and only unlocks the ones marked "false".

Depending on how their engine works, that can be a major pain to code. Also, what was probably harder to debug, was figuring out what piece of code unlocked the doors in the first place.
 

Randdalf

Member
Why would "opening all the doors" not just be a temporary state that doors could check?

i.e. if(doorManager.CloseAllDoors) return Closed; else return Door.State;

I guess this is what happens when you give designers the flexibility to do enough to get it working, but not check if they're doing it in the right way.

Also why were there dynamic doors on buildings that couldn't be entered? Seems like a total waste of resources, just have a static model, surely.

Also, why go through all the doors manually to fix it and not ask a programmer to rustle up a script which would do it for you?

I feel like this tells us more about how frequently the code and design teams speak to each other than anything else.
 

Alexlf

Member
If they didn't have a door object they could add a variable to track the state of each door I really don't know what they were doing. Copy and paste the door code for each instance?
 

Tyaren

Member
Then they forgot to close one door afterall! :) There is a house door in Beauclair, attached to the outer city wall, that you can open and there is nothing other than grass and the wall of rock that the house is attached to in it.
 

low-G

Member
Why would "opening all the doors" not just be a temporary state that doors could check?

i.e. if(doorManager.CloseAllDoors) return Closed; else return Door.State;

I guess this is what happens when you give designers the flexibility to do enough to get it working, but not check if they're doing it in the right way.

Also why were there dynamic doors on buildings that couldn't be entered? Seems like a total waste of resources, just have a static model, surely.

Also, why go through all the doors manually to fix it and not ask a programmer to rustle up a script which would do it for you?

I feel like this tells us more about how frequently the code and design teams speak to each other than anything else.

Because then you're slowing down the entire game to see if a single quest wants the door to be closed. You can't code games that way. You shouldn't code anything that way (loads and loads of branch statements for every possible occasion would make a calculator crawl). Then again, they're adding an extra state to every door in the game for this single quest, which isn't an ideal solution either...
 
This sounds likes hazing honestly. I'm pretty sure this was a joke on one of the penny arcade spin offs where they had some poor sap go through all the doors in a game, when a programmer could have made a script do it in a fraction of the time...
 

MattKeil

BIGTIME TV MOGUL #2
I think my solution would have just been "Hey, how about we go ahead and let Geralt go in doors during that quest and take out that one bit that's breaking the entire rest of the game?"
 

Randdalf

Member
Because then you're slowing down the entire game to see if a single quest wants the door to be closed. You can't code games that way. You shouldn't code anything that way (loads and loads of branch statements for every possible occasion would make a calculator crawl). Then again, they're adding an extra state to every door in the game for this single quest, which isn't an ideal solution either...

Sure you can code games that way - this isn't a check that has to be performed every frame, only when the door is instantiated (since this is an open world game after all, only a subset of doors will be active at any time). It's no more costly than adding the data-driven tag that they added as a solution here. Simpler as well.

Bear in mind also that this isn't a solution which needs to be specifically for this quest - a global override for the state of doors could be useful in other quests too.
 

madjoki

Member
Why just not store list of door locked to 'quest state' when you actually lock each door? Then reverse those when quest is finished.

Or let quests override/hook global scripts (like checking if door is closed or open). this of course would require it to be designed in such way.
 

AColdDay

Member
My solution: Replace all doors with walls with painted on pictures of doors and then change Geralt's model to Wile E Coyote.
 

Lister

Banned
Hmmm... I'd store the state of all doors, then retrieve and restore it when the quest was done. Even if there are ten thousand doors { doorId: $, state: $} shouldn't be too much memory overhead, right?
 

Regiruler

Member
It's awful when you don't plan for that sort of thing beforehand. Although couldn't there be a universal check to see whether you were in that quest or not, instead of changing the unlocked status of the door itself?
 

FyreWulff

Member
Hmmm... I'd store the state of all doors, then retrieve and restore it when the quest was done. Even if there are ten thousand doors { doorId: $, state: $} shouldn't be too much memory overhead, right?

it would still be a perf hit because every single little script would have to make a detour through the giant door array on every loop when it's checking conditionals. You also have to store it on disk.

This and similar stuff about open world games is one of those things people take for granted. I always thought Bethesda's solution for storing the game world state was pretty clever to try and keep file size down. What they do is they basically store a diff between the original designed state and what changes you've made to objects/etc. So the more you change the world the larger your save file gets.


And this happens a lot more than people think. One idea, or quest, or weapon gets introduced during development that everyone loves.. and then it turns out it specifically touches the code/engine in such a way that you need to rewrite or add on significant parts of the engine to get it into the game.
 

Lister

Banned
It's awful when you don't plan for that sort of thing beforehand. Although couldn't there be a universal check to see whether you were in that quest or not, instead of changing the unlocked status of the door itself?

You'd have to be careful. You don't want to trigger a bunch of state checks every time you try to open a door, but yeah that would probably be best so long as the list of checks doesn't get out fo control. Anytime a door is about to be opened, check if this quest is active, then prevent opening.
 

Lister

Banned
it would still be a perf hit because every single little script would have to make a detour through the giant door array on every loop when it's checking conditionals. You also have to store it on disk.

I think the solution below mine is better. But my idea was to do this on quest start, and then on quest end only. Nothing else would need to traverse the array and no need for extra checks or tags on the doors.
 

ElFly

Member
on quest start they should have compiled a list of which doors were open and which not (or at least which doors were not in their default state) and save it until quest completion

or...just not have the requirement that Gerard would not be able to go inside a building during that quest

it would still be a perf hit because every single little script would have to make a detour through the giant door array on every loop when it's checking conditionals. You also have to store it on disk.

This and similar stuff about open world games is one of those things people take for granted. I always thought Bethesda's solution for storing the game world state was pretty clever to try and keep file size down. What they do is they basically store a diff between the original designed state and what changes you've made to objects/etc. So the more you change the world the larger your save file gets.


And this happens a lot more than people think. One idea, or quest, or weapon gets introduced during development that everyone loves.. and then it turns out it specifically touches the code/engine in such a way that you need to rewrite or add on significant parts of the engine to get it into the game.

the game _has_ to keep a list of which doors are open, closed or locked, or at least which doors are unlocked or in a different state to the default

probably the main problem is getting the info of the default state, which maybe is stored on each section of the map, and thus across the whole game map...but maybe it'd work with the doors currently in memory?

maybe during the siege a script could be constantly closing doors as Gerald walked around; before unloading that script, you just reset the last set of doors the script closed, and let the regular game loading take over

the solution described strikes me as less flexible and more bug prone, but maybe the article glossed over the details. then again, more dynamic solutions may need a lot of memory that the game won't have, at least on consoles

then again, maybe the quest designers are working in a script language that doesn't have full access to the engine
 

Htown

STOP SHITTING ON MY MOTHER'S HEADSTONE
soo.... could they not just temporarily disable the player's ability to open doors? Why change the state of the doors themselves at all?
 

Ahasverus

Member
Damn, poor programmer.
soo.... could they not just temporarily disable the player's ability to open doors? Why change the state of the doors themselves at all?
Must probably be psychics based or flag based. Would probably break any interactivity on the quest.
 
I mean, it's not like making it so Geralt can't go inside during that one mission is such a big deal to warrant that, but I'm not a game designer, so whatever.
 

Lister

Banned
soo.... could they not just temporarily disable the player's ability to open doors? Why change the state of the doors themselves at all?

A .canOpenDoors property on Geralt? :)

This boils down to a different take on what Regiruler proposed.
 

madjoki

Member
Hmmm... I'd store the state of all doors, then retrieve and restore it when the quest was done. Even if there are ten thousand doors { doorId: $, state: $} shouldn't be too much memory overhead, right?

Well stored as an array:

10000 doors = 1 bit per door = ~1.25kilobytes + few bytes for number of doors

This would be like 0.000000003% of memory available on consoles.
That's basically nothing. and it could be instantly removed from state as quest is over.

(such: doors[doorid] would correspond to state.)

This would be more effecient for large number of changes (such as this)

otherwise storing id + state would be more efficient. (like 5% of doors opened, assuming 16 bits for door id + state).
 

meerak

Member
It would be good for game education for Kotaku to post stories like this daily.

There is an unlimited amount of shit like this.
 

Jimrpg

Member
I haven't played the mission but why does it matter so much that he shouldn't be distracted, is it that big of a deal? Sounds like perfectionalism gone mad.

Or just draw a new door over every doorway and be done with it.
 
Top Bottom