Handling a trap room in a zelda-like game

Started by
15 comments, last by Exorph 12 years, 8 months ago
This is a very specific question, so maybe I can't provide you with enough information to help me solve the problem.

It's an issue of triggers and events.

I have triggers that have a condition and events to fire off.
I have a Trigger Handler that sends events to active triggers.
The triggers check the event against their condition and if the condition is met, it fires off its events.

My world consists of a bunch of rooms. Each room can have triggers in it that are moved into the TriggerHandler when the player enters.

I have trap rooms that have an area trigger that closes all exits. These rooms also have kill count triggers that opens the doors when all enemies are killed.

It all works splendidly.

The problem reveals itself when the player dies or saves the game in a closed trap room. Now the doors are closed when the player returns, and so they can't enter.
I figure I could maybe solve the death issue by having a PlayerDiedTrigger that opens all doors in the room and resets the triggers.

Saving feels more difficult. There are other doors that need their states saved, so I have to save whether they are closed or not. Not only that, but I have to save the state of the triggers too (I don't want the player to have to redo the trap rooms they've cleared), so even if I manage to reset the doors with some ugly myShouldResetWhenLoaded flag, the trigger that closes the doors has already been triggered.

I can probably figure something out, but it feels as if any solution I come up with is ugly as hell. I don't expect anyone to know an exact solution, but maybe someone could point me in the right direction?
Advertisement
I'm not sure what the problem actually is. What's wrong with saving the state of triggers and doors?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Ah, maybe the missing piece of information is that upon loading a saved game or dying, the player is returned to the entrance of the dungeon.

So if the player saves the game in a room where the exits have been sealed, there's no longer any way in there and the dungeon is unsolvable. And if I write code to force the doors to open somehow, the area trigger that seals the exits is no longer active, so the player would have bypassed the trap room without having to fight.

I'm starting to consider just putting a isTrapRoom-flag in the room and solve it that way, but I have a feeling that'll lead me on a path where rooms have a bazillion update and activation functions depending on their combination of isTrapRoom, isShop, isInside, isUpsideDown, isDirty, isDangerousToGoats and smellsOfElderberries flags...
I still don't see what the problem is. What's wrong with saving the states of both the triggers and the doors?


[edit] Never mind, I see. Answer pending.


[edit 2] What I would do is simply not save the states of doors or door lock triggers at all. This way, when the player re-enters the dungeon, either via death or save/load, the dungeon returns to its original state with regard to trap doors. Monsters and items can still be saved off, though, so it's possible for the player to partially complete a dungeon and then revisit it entirely, but not abuse the system by just respawning a lot and gobbling up dupe items/monster XP.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

And if you kind of cheat in this.... if the player saves in the locked doors room, when he loads he returns a little before entering the room, behaving like a checkpoint

It's something a lot of games do and is actually easier than saving inside....

[Edit]

Oh sorry, didn't pay attention to the "return to the entrance" part...

ApochPiQ way of doing it is good. You stay kind of "saved" in the instance until you finish it

Edit 2:

Thinking of it by a moment.... if you are using a database, you could have 2-3 columns:

enteredDoorLock
passedDoorLock

This way you can check if the player already entered in the locked room, and if he passed it. Thus restoring the dungeon "should be a brezze"
"It doesn't matter how slow you go - as long as you don't stop"

"Declare variables, not war"

"There are only 10 types of people: those who understand binary and those who don't"

What I would do is simply not save the states of doors or door lock triggers at all. This way, when the player re-enters the dungeon, either via death or save/load, the dungeon returns to its original state with regard to trap doors. Monsters and items can still be saved off, though, so it's possible for the player to partially complete a dungeon and then revisit it entirely, but not abuse the system by just respawning a lot and gobbling up dupe items/monster XP.


That would probably work for the trap rooms specifically, but there are also doors which are opened by keys that the player picks up. The dungeons can grow quite large, and forcing the players to find the keys for all the doors every time they die seems rather... brutal. So the state of some doors must be saved.

There's always the option of special-casing the doors, I guess, and not saving the state of the trap doors, but then I instead run the risk of having a billion different door types in the end, instead of a billion different room types.

It feels like there must be a more general way of doing this without changing the game design around.


Thinking of it by a moment.... if you are using a database, you could have 2-3 columns:

enteredDoorLock
passedDoorLock

This way you can check if the player already entered in the locked room, and if he passed it. Thus restoring the dungeon "should be a brezze"


If I understand correctly (I'm not using a database and have no experience with doing so), that means I must tag the room as locked instead of relying on a more general system of triggers and events. I'm leaning towards your solution, but I'm not very happy with it, as it'll mean that if I want to create other types of rooms later, that means a bunch of special cases for each one, instead of just adding other triggers.
Then again, I could luck out and realize that the trap rooms are the only special cases, in which case I'm wasting my time thinking about this too much. :rolleyes:
what happens if the guy never finish the dungeon?

I mean, he started, picked like 10 keys, died and didn't play this dungeon again.

These keys disappear after using them?
The player keep them forever?

It's two different situations with different approaches

[Edit]

Is it a single player game?
"It doesn't matter how slow you go - as long as you don't stop"

"Declare variables, not war"

"There are only 10 types of people: those who understand binary and those who don't"
But isn't a door-unlocked-by-key a different concept than door-locked-by-trap?

I see no reason why they should behave the same from a code or design standpoint; instead, I'd say that you classify door behavior based precisely on how gameplay rules say it should work. If the door is key-activated, store its state. If a door is trap-activated, don't.

More generally, you really only have two "types" of doors here: those that retain their locked state, and those that reset. Those binary choices cover all possibilities of how door-lock-state-serialization should work, so in the specific case where your code needs to decide whether or not to save a door's lock state, you only have to worry about two categories. Then, as you add different types of door to the mix, they always fall into one of these two buckets, so as far as lock-state-saving goes, nothing ever gets more complicated.

Obviously if you favor a lot of inheritance this doesn't work nicely, because you have IDoorSavesLockState and IDoorCanBeDamaged and IDoorWhatever and ten million other things. This is where composition and tagging become far superior approaches to describing the behavior of game objects.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


But isn't a door-unlocked-by-key a different concept than door-locked-by-trap?

I see no reason why they should behave the same from a code or design standpoint; instead, I'd say that you classify door behavior based precisely on how gameplay rules say it should work. If the door is key-activated, store its state. If a door is trap-activated, don't.

More generally, you really only have two "types" of doors here: those that retain their locked state, and those that reset. Those binary choices cover all possibilities of how door-lock-state-serialization should work, so in the specific case where your code needs to decide whether or not to save a door's lock state, you only have to worry about two categories. Then, as you add different types of door to the mix, they always fall into one of these two buckets, so as far as lock-state-saving goes, nothing ever gets more complicated.

Obviously if you favor a lot of inheritance this doesn't work nicely, because you have IDoorSavesLockState and IDoorCanBeDamaged and IDoorWhatever and ten million other things. This is where composition and tagging become far superior approaches to describing the behavior of game objects.


Sure. And in the code side you can have some generic events and triggers for these categories. But will inheritance don't work if one door inherits only one type of door? I don't see much problems.. but i might be wrong
"It doesn't matter how slow you go - as long as you don't stop"

"Declare variables, not war"

"There are only 10 types of people: those who understand binary and those who don't"
Suppose my game design calls for a door which:

  • Can be opened with a key
  • Can be destroyed by weapons
  • Can be opened via a specific magic spell
  • Can lock itself again based on triggering a trap
  • Changes color occasionally


Then I need another door that has all of those, except it is immune to magic.

Then there's a third door in the game which can only be opened with magic or keys, but not destroyed by weapons.

And maybe I also want a door for the final boss chamber that doesn't open until I reach a certain point in the story.


As soon as you describe your objects and their capabilities in terms of inheritance, you create a maintenance hell. Extending the class hierarchy to support all those different combinations of behavior is going to suck.

Hence: use composition or tagging (aka data-driven modeling).

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This topic is closed to new replies.

Advertisement