Continue game [How to save while a GUI is open, but have it close on load]

Started by Lewis, Sat 17/08/2013 11:43:31

Previous topic - Next topic

Lewis

Part 1 solved. Read on for part 2...

PART 1 [SOLVED]

Hello! So, I've been trying to wrap my head around this all morning but can't seem to manage.

Let's say your game saves automatically on quit.

The first time you launch the game, you have two menu options: NEW GAME or QUIT.

You select NEW GAME. You play for a while, then you QUIT.

When you re-launch the game the next day, you now have three menu options: CONTINUE, NEW GAME or QUIT. In other words, the game knows you've played before, and saved-and-quit, so pops up the option to continue from where you left off.

That's fine. I've sorted the GUIs and made the game save on quit and tied it all up, and it's lovely. The question to which I can't fathom the answer is this:

How can you check on game_start whether the game has been played before?

I'd set it up with a simple variable before but, of course, that's silly - until the game loads in the save file, the variable will be in its original state, so the game will behave as if it's being launched for the first time.

So hey, I thought, why not just load the save file automatically on start, then have the game immediately check which (if any) GUI to pop up? But no, that doesn't work either, because you can't restore save files from game_start. You just get a crash and an error.

I've looked all over the forums and the manual and tried everything I can think of. It seems like something that would be possible to do: it's a common feature in many games. It seems like the sensible option would be to simply check whether there's a file in the relevant save slot. But I just can't fathom it. Any help greatly appreciated.

UPDATE: Ah! I thought I was on to something just now with the following in game_start:

Code: AGS
  if (Game.GetSaveSlotDescription(2) == "current save") {
    gMenu2.Visible=true;
  }
  else {
    gMenu1.Visible=true;
  }


...but the game crashes on launch if there's nothing in that save slot yet.

UPDATE 2: Got it! This works.

Code: AGS
File *output = File.Open("$SAVEGAMEDIR$/agssave.025",eFileRead);
if (output == null) {
  gMenu1.Visible=true;
}
else {
  gMenu2.Visible=true;
  output.Close();
}


PART 2

Just one tiny two-pronged problem now.

1) SaveGameSlot(); only occurs at the end of the script. So if it's on quit, the game quits before the game has chance to save itself.

2) The easy way to get around this is to just have the game save every time you pull up the menu - the player would never notice any difference. However, this means that when you load the game by pressing CONTINUE, the main menu is always left there on-screen until you get rid of it. Because the game saved when the menu was up.

And now I'm really stumped as to how to get around this issue - because I need the menu to automatically load on launch, the game to save while it's visible, but for the menu to immediately shut after loading, even if the save state includes the menu.

Any ideas at all? :/
Returning to AGS after a hiatus. Co-director of Richard & Alice and The Charnel House Trilogy.

Andail

Have you tried using something like
if (File.Exists("autosavefilename"))
?

Edit:
Oh you managed.

Lewis

Hey. Cheers. That might work. Arrived at a solution though (see above) - it's another problem I'm faced with now... :(
Returning to AGS after a hiatus. Co-director of Richard & Alice and The Charnel House Trilogy.

Khris

Re the second issue:
Use on_event / eEventRestoreGame to turn off the GUI.

monkey0506

If you're still trying to figure out how to do an autosave just before quitting, you could do this:

Code: ags
bool wantQuit = false;

function btnQuit_Click(GUIControl *control, MouseButton button) // or whatever your 'Quit' button's event handler is named
{
  gMenu1.Visible = false; // whatever menus need to be turned off by clicking the quit button
  gMenu2.Visible = false; // turn them off here
  wantQuit = true; // we're waiting to quit
  SaveGameSlot(25, "Auto-save"); // make sure this is the right save slot, put whatever description here
  // DO NOT call QuitGame from here!
  // SaveGameSlot will be called at the end of this game loop, we'll call QuitGame the next
}

function repeatedly_execute_always() // this is only run at the BEGINNING of a game loop (e.g., the NEXT loop after we saved)
{
  if (wantQuit) QuitGame(0); // if we've reached this point the game is saved, it's safe to quit!
}

function on_event(EventType event, int data)
{
  if (event == eEventRestoreGame)
  {
    gMenu1.Visible = false; // turn these off in case they were on
    gMenu2.Visible = false; // e.g., if you're saving the game elsewhere than just when quitting
    wantQuit = false; // make sure that this flag is reset when the game is loaded
  }
}


Edit: As per Andail's comment below, I forgot that the wantQuit variable would still be set to true when the game is restored. However, when it is restored, on_event is executed before the next time that rep_ex_always runs. The code above is updated, and tested. ;)

Andail

Curious, Monkey_05_06, if I didn't know you had suggested that code, I'd say the save-game would keep the bool wantQuit in the true state, thus immediately quitting the game once loaded.

Either way, isn't Khris's example much simpler? It simply removes the menu before fading in. I would have suggested always closing down the gui in question at
on_event / eEventEnterRoomBeforeFadein
myself, but using the restore game event is even more elegant.

monkey0506

Urgh, you're right about keeping the bool in that state. This is the great benefit of me never testing my code.

But Khris never addressed autosaving when the player quits, which is something that was asked about. I'll edit my code above.

Edit: Reading back over it I realize that Khris was suggesting to go for the always autosave when the menu is opened route, which I will concede is simpler in terms of code, but it's also (arguably) less efficient. My code was based only around autosaving at the time the game is being quit. In any case, there's usually options when scripting something like this. :P

Andail

Would it work if the
on_event / eEventRestoreGame
included a
wantQuit = false;
?

Wouldn't that load the game and prevent it from quitting?

Edit:
Haha, didn't see you had updated your code, with that precise solution :)

monkey0506

Yup! I even tested it to verify! ;)

RestoreGameSlot doesn't run until the call stack is empty (presumably at or near the end of the game loop, depending which function queued it), but after it does run, it always calls on_event(eEventRestoreGame, slot) before the next game loop runs and repeatedly_execute_always is run again. I had also inadvertently left a line in there referencing a different variable name (and usage), but it's been removed.

The code in my post is (now) functional, if that's the route you choose to take. :)

SMF spam blocked by CleanTalk