Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: Snarky on Sun 06/11/2011 23:46:48

Title: Coding story progression
Post by: Snarky on Sun 06/11/2011 23:46:48
I have a game where the main character revisits the same rooms many time over the course of the story, and different things happen depending on how far along it is. What is the best way to write code to keep track of that, to make sure it does the right things at the right times?  I also want to be able to jump to various points in the game for debug/testing purposes.

I started with a global "GameChapter" variable that I defined as an enum. But I'm having some trouble deciding which developments should qualify as new chapters, and how to integrate this with other parameters (like carrying/not carrying an inventory object, or having talked to a certain character before or not) and with parallelism in the game design. And I feel like whenever I add logic for another stage of the game, I have to change a lot of the earlier code, too.

The other big problem is that I'm having trouble with debugging, since by jumping to different rooms and so on, I bypass a lot of the logic for setting the Game Chapter, and end up in strange states.

I probably haven't been as disciplined as I should about keeping all the code consistent, sometimes using the "on first entry" event to separate what happens, sometimes switching depending on the chapter (depending on how the room will appear in the game).

Is there a better way?
Title: Re: Coding story progression
Post by: NickyNyce on Mon 07/11/2011 00:11:32
I really can't wait to hear some of the ingenious ideas that will sprite from this thread. I ran into some problems myself when testing my own game. I ended up placing code around my scripts while testing and then deleting them afterwards. Add inventory, this or that variable to true, start here etc....

I would do this sometimes one room at a time to make sure things work right. I'm pretty sure thats not the greatest way of doing it, but I never really did much with the debug mode buttons. I Probably should have.

I do remember reading a thread around here that talks about this...but this should be interesting
Title: Re: Coding story progression
Post by: selmiak on Mon 07/11/2011 12:13:00
why not make a new room with same background and give it the differences it needs...
The only downside is a bigger gamesize but a lot more understandable code ;)
Title: Re: Coding story progression
Post by: Rocco on Mon 07/11/2011 17:48:47
i do that with one variable and an enum for easier readability:


// globalscript.ash
import int gameprogress;

enum eGameprogress
{
 eProlog     = 0,
 eMiddle     = 1,
 eFinal       = 2,
};


// globalscript.asc

int gameprogress;
export gameprogress;

function game_start()
{  

 gameprogress = eMiddle;
}



// Roomsript
function room_Load()
{


 if(gameprogress == eProlog)
 {

     StartCutscene(eSkipESCOrRightButton);
     cKlaus.ChangeRoom(10, 423, 119);
     cMichael.EnterRoom(10,460, 139, eDirLeft);
     .
     .
     
   }
   else if(gameprogress == eMiddle)
   {
     //StartCutscene(eSkipESCOrRightButton);
     cKlaus.ChangeRoom(10, 423, 119);
     player.Walk(325, 127, eBlock, eWalkableAreas);
     .

 
   }
   
}


and so on.
And for debugging, set the gameprogress variable at gamestart and you can play the room at any state of the game.
(eventuelly need to give the player some inventory items manually, which he should have at this point)

Title: Re: Coding story progression
Post by: Calin Leafshade on Mon 07/11/2011 20:53:01
one way might be to have a big global array of flags that denote game progression. Then you can use enums or DEFINEs to make it more readable.


bool Flags[1000];

#define EATENAPPLE 0
#define KILLEDMONKEY 1
#define DANCEDAJIG 2


//wrapped in functions in case we need to do any checking later on or something.

void SetFlag(int index, bool val)
{
  Flags[index] = val;

}

bool Flag(index)
{
return Flags[index];
}



Now you can set the game at any point just by setting all the appropriate flags



void SetToStart()
{
  SetFlag(0,false); //use the number or the define
  SetFlag(EATENAPPLE,false);
  SetFlag(2,false);

}

void SetToMiddle()
{
  SetFlag(0,true);
}



Its not particularly good practice to have global state variables but the advantage here is that you can set the state of the game from any script in the game. If you use local flags inside rooms it becomes impossible to set their state from somewhere else in the game.

Also you dont have to group things into chapters, you can set *any* game state at any point.

If you wanted to get really complicated (and awesome) you could define a linked-list type tree structure where every event requires all the previous events to happen first so you can set the most recent event and the system will automatically set all the flags prior to it in the list like this:


                     /   - EVENT 4 - EVENT 5
EVENT 1 - EVENT 2 |
                     \     - EVENT 3 - EVENT 6


if you set the flag associated with event 5 to true then the system would work backwards through the list setting Events 4, 2 and 1 to true but not affecting events 3 and 6. This allows for non-linear story progression too.

Title: Re: Coding story progression
Post by: Snarky on Wed 09/11/2011 16:31:14
Rocco, that's essentially my approach, except I don't have the method at the beginning to switch to the different chapters. That would probably do a lot to help. Individual flags like Calin proposes would be a good way to handle non-linear progression within chapters, but seems too involved as a way to handle the complete game logic.

I have defined about six acts in my game (essentially parts where you have access to different rooms, and room state is usually different for each), but one problem is that my plans for the structure are evolving, so I want to be able to add, split and merge the acts, which is a lot of work with this approach. (Also since I've named them like eAct01_Intro, so that they'll sort correctly in the autocomplete, it requires me to rename all of them if the ordering changes.)

Quote from: selmiak on Mon 07/11/2011 12:13:00
why not make a new room with same background and give it the differences it needs...
The only downside is a bigger gamesize but a lot more understandable code ;)

Because then I have to replicate every aspect of the room (walkable areas, walkbehinds, hotspots, regions, objects, exits and events, just to take the most obvious) in every copy, and keep them all up to date if I make any changes. And write special logic to go to the right version from any adjoining room. In short, it's a terrible idea in most cases. (I am in fact doing exactly that in some exceptional cases where I need special versions of the room for cut scenes and so on, though.)
Title: Re: Coding story progression
Post by: selmiak on Wed 09/11/2011 16:37:29
yeah, you're right, somehow I forgot about this stuff *whistles*
Title: Re: Coding story progression
Post by: Wyz on Thu 10/11/2011 00:47:37
I use a very similar approach to yours but with a slight twist :D.
First I have about the same enumeration you use but I will not set it manually. Instead each Act has a function that needs to be called to change to it.


// module header:
void GotoAct0(); // Introduction
void GotoAct1(); // First act
void GotoAct2(); // etc
//...


Secondly I make a distinction between acts and chapters, well its not really important how you call them but they also differ in effect. While the act functions will set the complete game state to the beginning of that act, the chapter functions will only set things that have changed subsequently from the last character. That way say you want to switch to the 3th chapter of the second act you'd call:

GotoAct2();
Chapter1();
Chapter2();
Chapter3();


Still the difficulty is in keeping track of everything that can change, yes you need to have a spider-sense for that. Dividing the game up in smaller parts may help keep the amount of things that may have changed to a conveniently small. Though, here is a general check list from the top of my head: