Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: bx83 on Tue 27/04/2021 14:31:28

Title: How do I get savegame sccreenshots to work?
Post by: bx83 on Tue 27/04/2021 14:31:28
I *have* gotten them working, but problems remain.
The two main ones are:

1. Savegame screenshots are slow by one; when you save the first screenshot it's blank; the second, it has the first one's screenshot; and so on.

2. I can't figure out how to close the gSaveLoad dialog when a save is restored. Despite the fact that the diaog is never visible when the game's doing it's saving, the dialog refuses to disappear when the game is restored.

code:

globalscript.asc:
DynamicSprite *buttonSavePic1;
DynamicSprite *buttonSavePic2;
DynamicSprite *buttonSavePic3;
DynamicSprite *buttonSavePic4;


function ShowSaveGUI() {
 
  buttonSavePic1 = DynamicSprite.CreateFromSaveGame(1, 171, 96);
  if (buttonSavePic1 != null) {
    buttonLoad1.Visible=true;
    //LabelLoad1.Visible=true;
    LabelDescr1.Text=Game.GetSaveSlotDescription(1);
    buttonSaveSlot1.NormalGraphic = buttonSavePic1.Graphic;
    buttonSaveSlot1.Visible=true;
  } 
  buttonSavePic2 = DynamicSprite.CreateFromSaveGame(2, 171, 96);
  if (buttonSavePic2 != null) {
    buttonLoad2.Visible=true;
    //LabelLoad2.Visible=true;
    LabelDescr2.Text=Game.GetSaveSlotDescription(2);
    buttonSaveSlot2.NormalGraphic = buttonSavePic2.Graphic;
    buttonSaveSlot2.Visible=true;
  } 
  buttonSavePic3 = DynamicSprite.CreateFromSaveGame(3, 171, 96);
  if (buttonSavePic3 != null) {
    buttonLoad3.Visible=true;
    //LabelLoad3.Visible=true;
    LabelDescr3.Text=Game.GetSaveSlotDescription(3);
    buttonSaveSlot3.NormalGraphic = buttonSavePic3.Graphic;
    buttonSaveSlot3.Visible=true;
  } 
  buttonSavePic4 = DynamicSprite.CreateFromSaveGame(4, 171, 96);
  if (buttonSavePic4 != null) {
    buttonLoad4.Visible=true;
    //LabelLoad4.Visible=true;
    LabelDescr4.Text=Game.GetSaveSlotDescription(4);
    buttonSaveSlot4.NormalGraphic = buttonSavePic4.Graphic;
    buttonSaveSlot4.Visible=true;
  }
 
  gSaveLoad.Visible = true;
}


// SAVE gSaveLoad save button functions

function buttonSave1_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("SLOT #1 @%02d:%02d:%02d %02d:%02d:%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveGameSlot(1, SaveDesc);
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  buttonSavePic1 = DynamicSprite.CreateFromSaveGame(1, 171, 96);
  Wait(GetGameSpeed()*1);
 
  if (buttonSavePic1 != null) {
    buttonSaveSlot1.NormalGraphic = buttonSavePic1.Graphic;
    buttonSaveSlot1.Visible=true;
    buttonLoad1.Visible=true;
    //LabelLoad1.Visible=true;
    LabelDescr1.Text=Game.GetSaveSlotDescription(1);
  }
 
  gSaveLoad.Visible=true;
}
function buttonSave2_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("SLOT #2 @%02d:%02d:%02d %02d:%02d:%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveGameSlot(2, SaveDesc);
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  buttonSavePic2 = DynamicSprite.CreateFromSaveGame(2, 171, 96);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;
 
  if (buttonSavePic2 != null) {
    buttonSaveSlot2.NormalGraphic = buttonSavePic2.Graphic;
    buttonSaveSlot2.Visible=true;
    buttonLoad2.Visible=true;
    //LabelLoad2.Visible=true;
    LabelDescr2.Text=Game.GetSaveSlotDescription(2);
  }
}
function buttonSave3_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("SLOT #3 @%02d:%02d:%02d %02d:%02d:%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveGameSlot(3, SaveDesc);
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  buttonSavePic3 = DynamicSprite.CreateFromSaveGame(3, 171, 96);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;
 
  if (buttonSavePic3 != null) {
    buttonSaveSlot3.NormalGraphic = buttonSavePic3.Graphic;
    buttonSaveSlot3.Visible=true;
    buttonLoad3.Visible=true;
    //LabelLoad3.Visible=true;
    LabelDescr3.Text=Game.GetSaveSlotDescription(3);
  }

}
function buttonSave4_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("SLOT #4 @%02d:%02d:%02d %02d:%02d:%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveGameSlot(4, SaveDesc);
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  buttonSavePic4 = DynamicSprite.CreateFromSaveGame(4, 171, 96);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;
 
  if (buttonSavePic4 != null) {
    buttonSaveSlot4.NormalGraphic = buttonSavePic4.Graphic;
    buttonSaveSlot4.Visible=true;
    buttonLoad4.Visible=true;
    //LabelLoad4.Visible=true;
    LabelDescr4.Text=Game.GetSaveSlotDescription(4);
  }

}



// LOAD  gSaveLoaad load button functions

function buttonLoad1_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
  RestoreGameSlot(1);
  GameJustRestored=1;
}
function buttonLoad2_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
  RestoreGameSlot(2);
  GameJustRestored=2;
}
function buttonLoad3_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
  RestoreGameSlot(3);
  GameJustRestored=3;
}
function buttonLoad4_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
  RestoreGameSlot(4);
  GameJustRestored=4;
}



// click save icon in giconbar
function btnIconSave_OnClick(GUIControl *control, MouseButton button)
{
  gPanel.Visible = false;
  gIconbar.Visible = false;
  mouse.UseModeGraphic(eModePointer);
  ShowSaveGUI();
}
// click load icon in gIconbar
function btnIconLoad_Click(GUIControl* control, MouseButton button)
{
  gPanel.Visible=false;
  gIconbar.Visible=false;
  gSaveLoad.Visible=true;
  mouse.UseModeGraphic(eModePointer);
}


Title: Re: How do I get savegame sccreenshots to work?
Post by: bx83 on Wed 28/04/2021 15:17:19
Alright - worked on the code. The only problem which remains is the dreaded dialogue not disappearing when I restore a game.

globlscript.asc

DynamicSprite *buttonSavePic1;
DynamicSprite *buttonSavePic2;
DynamicSprite *buttonSavePic3;
DynamicSprite *buttonSavePic4;

function PrepareSaveGUI(int slot) {
  if (InStartupMenu) {
    buttonSave1.Visible=false;
    buttonSave2.Visible=false;
    buttonSave3.Visible=false;
    buttonSave4.Visible=false;
  } else {
    buttonSave1.Visible=true;
    buttonSave2.Visible=true;
    buttonSave3.Visible=true;
    buttonSave4.Visible=true;
  }
 
  buttonSavePic1 = DynamicSprite.CreateFromSaveGame(1, 171, 96);
  if (buttonSavePic1 != null) {
    buttonLoad1.Visible=true;
    LabelDescr1.Text=Game.GetSaveSlotDescription(1);
    buttonSaveSlot1.NormalGraphic = buttonSavePic1.Graphic;
    buttonSaveSlot1.Visible=true;
    RefreshGameSlots=0;
  } else {
    if (File.Exists("$SAVEGAMEDIR$/agssave001.lociv")) {
      buttonLoad1.Visible=false;
      RefreshGameSlots=1;
      return;
    }   
  }
 
  buttonSavePic2 = DynamicSprite.CreateFromSaveGame(2, 171, 96);
  if (buttonSavePic2 != null) {
    buttonLoad2.Visible=true;
    LabelDescr2.Text=Game.GetSaveSlotDescription(2);
    buttonSaveSlot2.NormalGraphic = buttonSavePic2.Graphic;
    buttonSaveSlot2.Visible=true;
    RefreshGameSlots=0;
  } else {
    if (File.Exists("$SAVEGAMEDIR$/agssave002.lociv")) {
      buttonLoad2.Visible=false;
      RefreshGameSlots=2;
      return;
    }
  }
 
  buttonSavePic3 = DynamicSprite.CreateFromSaveGame(3, 171, 96);
  if (buttonSavePic3 != null) {
    buttonLoad3.Visible=true;
    LabelDescr3.Text=Game.GetSaveSlotDescription(3);
    buttonSaveSlot3.NormalGraphic = buttonSavePic3.Graphic;
    buttonSaveSlot3.Visible=true;
    RefreshGameSlots=0;
  } else {
    if (File.Exists("$SAVEGAMEDIR$/agssave003.lociv")) {
      buttonLoad3.Visible=false;
      RefreshGameSlots=3;
      return;
    }
  }
 
  buttonSavePic4 = DynamicSprite.CreateFromSaveGame(4, 171, 96);
  if (buttonSavePic4 != null) {
    buttonLoad4.Visible=true;
    LabelDescr4.Text=Game.GetSaveSlotDescription(4);
    buttonSaveSlot4.NormalGraphic = buttonSavePic4.Graphic;
    buttonSaveSlot4.Visible=true;
    RefreshGameSlots=0;
  } else {
    if (File.Exists("$SAVEGAMEDIR$/agssave004.lociv")) {
      buttonLoad4.Visible=false;
      RefreshGameSlots=4;
      return;
    }
  } 
}

...

function repeatedly_execute()
{
...
  if (RestoreCheck) {
    if (gSaveLoad.Visible) {
      gSaveLoad.Visible=false;
    } else {
      RestoreGameSlot(RestoreSlotNm);
      RestoreSlotNm=0;
      RestoreCheck=false;
    }
  }
...
}

...


function SaveTheGame(int slot, String desc)
{
  SaveGameSlot(slot, desc);
}

function LoadTheGame(int slot)
{
  RestoreCheck=true;
  RestoreSlotNm=slot;
}

// SAVE gSaveLoad save button functions

function buttonSave1_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("slot #1 @%02d:%02d:%02d_%02d/%02d/%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveTheGame(1, SaveDesc);
 
  if (buttonSavePic1!=null) buttonSavePic1.Delete();
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  buttonSavePic1 = DynamicSprite.CreateFromSaveGame(1, 171, 96);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;
 
  if (buttonSavePic1 != null) {
    buttonSaveSlot1.NormalGraphic = buttonSavePic1.Graphic;
    buttonSaveSlot1.Visible=true;
    buttonLoad1.Visible=true;
    LabelDescr1.Text=Game.GetSaveSlotDescription(1);
  }
 
  RefreshGameSlots=1;
}
function buttonSave2_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("slot #2 @%02d:%02d:%02d_%02d/%02d/%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveGameSlot(2, SaveDesc);
 
  if (buttonSavePic2!=null) buttonSavePic2.Delete();
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  buttonSavePic2 = DynamicSprite.CreateFromSaveGame(2, 171, 96);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;
 
  if (buttonSavePic2 != null) {
    buttonSaveSlot2.NormalGraphic = buttonSavePic2.Graphic;
    buttonSaveSlot2.Visible=true;
    buttonLoad2.Visible=true;
    LabelDescr2.Text=Game.GetSaveSlotDescription(2);
  }
 
  RefreshGameSlots=2;
}
function buttonSave3_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("slot #3 @%02d:%02d:%02d_%02d/%02d/%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveGameSlot(3, SaveDesc);
 
  if (buttonSavePic3!=null) buttonSavePic3.Delete();
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  buttonSavePic3 = DynamicSprite.CreateFromSaveGame(3, 171, 96);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;
 
  if (buttonSavePic3 != null) {
    buttonSaveSlot3.NormalGraphic = buttonSavePic3.Graphic;
    buttonSaveSlot3.Visible=true;
    buttonLoad3.Visible=true;
    LabelDescr3.Text=Game.GetSaveSlotDescription(3);
  }
 
  RefreshGameSlots=3;
}
function buttonSave4_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("slot #4 @%02d:%02d:%02d_%02d/%02d/%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveGameSlot(4, SaveDesc);
 
  if (buttonSavePic4!=null) buttonSavePic4.Delete();
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  buttonSavePic4 = DynamicSprite.CreateFromSaveGame(4, 171, 96);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;
 
  if (buttonSavePic4 != null) {
    buttonSaveSlot4.NormalGraphic = buttonSavePic4.Graphic;
    buttonSaveSlot4.Visible=true;
    buttonLoad4.Visible=true;
    LabelDescr4.Text=Game.GetSaveSlotDescription(4);
  }
 
  RefreshGameSlots=4;
}


// LOAD  gSaveLoaad load button functions

function buttonLoad1_OnClick(GUIControl *control, MouseButton button)
{
  LoadTheGame(1);
}
function buttonLoad2_OnClick(GUIControl *control, MouseButton button)
{
  LoadTheGame(2);
}
function buttonLoad3_OnClick(GUIControl *control, MouseButton button)
{
  LoadTheGame(3);
}
function buttonLoad4_OnClick(GUIControl *control, MouseButton button)
{
  LoadTheGame(4);
}



// click save icon in giconbar
function btnIconSave_OnClick(GUIControl *control, MouseButton button)
{
  gPanel.Visible = false;
  gIconbar.Visible = false;
  mouse.UseModeGraphic(eModePointer);
  PrepareSaveGUI(0);
  gSaveLoad.Visible = true;
}


function SaveLoadExit_OnClick(GUIControl *control, MouseButton button)
{
  gSaveLoad.Visible=false;
  if (!InStartupMenu) {
    gIconbar.Visible=true;
  } else {
    FadeInControls_startup();
   
    for (int x=100;x>=0;x-=2) {
      object[0].Transparency=x;
      object[1].Transparency=x;
      object[2].Transparency=x;
      object[3].Transparency=x;
    }
  }
}


I know this may give you an odd desire for Italian food (caus it's spaghetti? :P) - but can anyone suggest what might be:
a) Causing the gSaveLoad dialogue to come up visible when a game is restored (ie. despite the fact it was specifically visible=false when the game was saved); and
b) How do I actually know when a process like RestoreGameSlot() has finished? How can I do something *after* it's executed? I've used repeatedly_execute() and some flags, but it still won't separate from the final final operation being 'okay, now restore the game (and bring up the dialog as part of this)'

I have a theory it has the amount of time it pauses when saving that it still brings up the gSaveLoad as visible with a restore -- but no idea.
Title: Re: How do I get savegame sccreenshots to work?
Post by: Khris on Wed 28/04/2021 15:49:47
1. saving a game is queued until the current function has finished, so the dialog is probably turned visible again before the game is saved

2. you're looking for the global  on_event(EventType event, int data)  function and its  eEventRestoreGame.

Since (1) is the case, you can probably solve this by setting a one or two frame timer to save the game.
Title: Re: How do I get savegame sccreenshots to work?
Post by: Crimson Wizard on Wed 28/04/2021 16:45:01
I just wanted to mention (also in connection with this thread (https://www.adventuregamestudio.co.uk/forums/index.php?topic=59070.0)) that you may significantly reduce amount of code there, and so also reduce amount of possible problems with that code, by writing functions that accept Button as a pointer, and then calling these functions with different buttons.


For example, let's take this piece of code:

  buttonSavePic1 = DynamicSprite.CreateFromSaveGame(1, 171, 96);
  if (buttonSavePic1 != null) {
    buttonLoad1.Visible=true;
    LabelDescr1.Text=Game.GetSaveSlotDescription(1);
    buttonSaveSlot1.NormalGraphic = buttonSavePic1.Graphic;
    buttonSaveSlot1.Visible=true;
    RefreshGameSlots=0;
  } else {
    if (File.Exists("$SAVEGAMEDIR$/agssave001.lociv")) {
      buttonLoad1.Visible=false;
      RefreshGameSlots=1;
      return;
    }   
  }

  buttonSavePic2 = DynamicSprite.CreateFromSaveGame(2, 171, 96);
  if (buttonSavePic2 != null) {
    buttonLoad2.Visible=true;
    LabelDescr2.Text=Game.GetSaveSlotDescription(2);
    buttonSaveSlot2.NormalGraphic = buttonSavePic2.Graphic;
    buttonSaveSlot2.Visible=true;
    RefreshGameSlots=0;
  } else {
    if (File.Exists("$SAVEGAMEDIR$/agssave002.lociv")) {
      buttonLoad2.Visible=false;
      RefreshGameSlots=2;
      return;
    }
  }


Here you do very similar things to buttonSaveSlot1 and buttonLoad1 first, then to buttonSaveSlot2 and buttonLoad2. The only difference are: variable names and index of save. These "differences" become "parameters" of this code.

So, you could write a function:
Code (ags) Select

void SetSavePicToButton(Button *butSave, Button *butLoad, Label *label, DynamicSprite *pic, int save_id) {
   if (pic != null) {
    butLoad.Visible=true;
    label.Text=Game.GetSaveSlotDescription(save_id);
    butSave.NormalGraphic = pic.Graphic;
    butSave.Visible=true;
    RefreshGameSlots=0;
  } else {
    String filename = String.Format("$SAVEGAMEDIR$/agssave%03d.lociv", save_id);
    if (File.Exists(filename)) {
      butLoad.Visible=false;
      RefreshGameSlots=1;
    }   
  }
}


And then your long code becomes something like:
Code (ags) Select

buttonSavePic1 = DynamicSprite.CreateFromSaveGame(1, 171, 96);
SetSavePicToButton(buttonSaveSlot1, buttonLoad1, LabelDescr1, buttonSavePic1, 1);

buttonSavePic2 = DynamicSprite.CreateFromSaveGame(2, 171, 96);
SetSavePicToButton(buttonSaveSlot2, buttonLoad2, LabelDescr2, buttonSavePic2, 2);

buttonSavePic3 = DynamicSprite.CreateFromSaveGame(3, 171, 96);
SetSavePicToButton(buttonSaveSlot3, buttonLoad3, LabelDescr3, buttonSavePic3, 3);

buttonSavePic4 = DynamicSprite.CreateFromSaveGame(4, 171, 96);
SetSavePicToButton(buttonSaveSlot4, buttonLoad4, LabelDescr4, buttonSavePic4, 4);




Similarily, your 4 big button_OnClick functions may be replaced with one function:

Code (ags) Select

void OnSaveButtonClick(Button *butSave, Button *butLoad, Label *label, DynamicSprite *pic, int save_id) {
  gSaveLoad.Visible=false;

  DateTime *dt = DateTime.Now;
  String SaveDesc=String.Format("slot #1 @%02d:%02d:%02d_%02d/%02d/%04d",dt.Hour, dt.Minute, dt.Second, dt.DayOfMonth, dt.Month, dt.Year);
  SaveTheGame(save_id, SaveDesc);

  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;

  if (pic!= null) {
    butSave.NormalGraphic = pic.Graphic;
    butSave.Visible=true;
    butLoad.Visible=true;
    label.Text=Game.GetSaveSlotDescription(save_id);
  }

  RefreshGameSlots=1;
}


And then you just call this function from button_OnClicks:
Code (ags) Select

function buttonSave1_OnClick(GUIControl *control, MouseButton button) {
  if (buttonSavePic1!=null) buttonSavePic1.Delete();
  buttonSavePic1= DynamicSprite.CreateFromSaveGame(1, 171, 96);
  OnSaveButtonClick(buttonSaveSlot1, buttonLoad1, LabelDescr1, buttonSavePic1, 1);
}
function buttonSave2_OnClick(GUIControl *control, MouseButton button) {
  if (buttonSavePic2!=null) buttonSavePic2.Delete();
  buttonSavePic2= DynamicSprite.CreateFromSaveGame(2, 171, 96);
  OnSaveButtonClick(buttonSaveSlot2, buttonLoad2, LabelDescr2, buttonSavePic2, 2);
}
function buttonSave3_OnClick(GUIControl *control, MouseButton button) {
  if (buttonSavePic3!=null) buttonSavePic3.Delete();
  buttonSavePic3= DynamicSprite.CreateFromSaveGame(3, 171, 96);
  OnSaveButtonClick(buttonSaveSlot3, buttonLoad3, LabelDescr3, buttonSavePic3, 3);
}
function buttonSave4_OnClick(GUIControl *control, MouseButton button) {
  if (buttonSavePic4!=null) buttonSavePic4.Delete();
  buttonSavePic4= DynamicSprite.CreateFromSaveGame(4, 171, 96);
  OnSaveButtonClick(buttonSaveSlot4, buttonLoad4, LabelDescr4, buttonSavePic4, 4);
}



This may be reduced further maybe, for example using array to store dynamic sprites and button/label pointers, then you will only have to pass one index into functions.
Title: Re: How do I get savegame sccreenshots to work?
Post by: bx83 on Wed 28/04/2021 22:53:31
Thank you oh thank you :D

Khris - solved my problems :)  I'm reading up on on_event types.
Crimson Wizard - thank you for this code, I'm saving it ad using it (in the coming weeks) to make mine more efficient :)
Title: Re: How do I get savegame sccreenshots to work?
Post by: bx83 on Thu 27/05/2021 08:40:52
Here is a working, scrollable save-game system if anyone is interested. There are 25 save-slots prepared.

(https://bluekeystudios.com/img/savegamedialogueonload.png)

code:

GlobalScript.asc
/////////////////////////////////////////
// save/load game with screenshot code //
/////////////////////////////////////////

DynamicSprite *buttonSavePic1;
DynamicSprite *buttonSavePic2;
...
DynamicSprite *buttonSavePic24;
DynamicSprite *buttonSavePic25;

void SetSavePicToButton(Button *butSave, Button *butLoad, Label *label, DynamicSprite *pic, int save_id) {
  if (pic != null) {
    label.Text=Game.GetSaveSlotDescription(save_id);
    butSave.NormalGraphic = pic.Graphic;
    butSave.Visible=true;
    RefreshGameSlots=0;
  } else {
    String filename = String.Format("$SAVEGAMEDIR$/agssave.%03d.lociv", save_id);
    if (File.Exists(filename)) {
      RefreshGameSlots=save_id;
    }   
  }
}

function PrepareSaveGUI_Display(Button *saveSlotFrame, Button *butLoad, DynamicSprite *pic, int save_id)
{
  if (pic != null) {
    saveSlotFrame.NormalGraphic = pic.Graphic;
    saveSlotFrame.Visible=true;
  } 
  if (File.Exists(String.Format("$SAVEGAMEDIR$/agssave.%03d.lociv",save_id))) {
    butLoad.Clickable=true;      //clickable
    butLoad.NormalGraphic=2644;  //bright blue
    butLoad.TextColor=51199;     //normal light
    RefreshGameSlots=0;
  } else {
    butLoad.Clickable=false;     //not clickable
    butLoad.NormalGraphic=9780;  //greyed out
    butLoad.TextColor=33808;     //dark
  }
}

function PrepareSaveGUI(int slot)
{
  if (InStartupMenu) {   
    buttonSave1.Clickable=false;    //not clickable
    buttonSave2.Clickable=false;
    ...
    buttonSave24.Clickable=false;
    buttonSave25.Clickable=false;

    buttonSave1.NormalGraphic=9780; //greyed out
    buttonSave2.NormalGraphic=9780;
    ...
    buttonSave24.NormalGraphic=9780;
    buttonSave25.NormalGraphic=9780;
   
    buttonSave1.TextColor=33808;  //dark
    buttonSave2.TextColor=33808;
    ...
    buttonSave24.TextColor=33808; 
    buttonSave25.TextColor=33808;

  } else {
    buttonSave1.Clickable=true;    //clickable
    buttonSave2.Clickable=true;
    ...
    buttonSave24.Clickable=true;
    buttonSave25.Clickable=true;
   
    buttonSave1.NormalGraphic=2644; //bright blue
    buttonSave2.NormalGraphic=2644;
    ...
    buttonSave24.TextColor=51199;
    buttonSave25.TextColor=51199;
  } 
 
  buttonSavePic1 = DynamicSprite.CreateFromSaveGame(1, 171, 96);
  buttonSavePic2 = DynamicSprite.CreateFromSaveGame(2, 171, 96);
  ...
  buttonSavePic24 = DynamicSprite.CreateFromSaveGame(24, 171, 96);
  buttonSavePic25 = DynamicSprite.CreateFromSaveGame(25, 171, 96);
 
  SetSavePicToButton(buttonSaveSlot1, buttonLoad1, LabelDescr1, buttonSavePic1, 1);
  SetSavePicToButton(buttonSaveSlot2, buttonLoad2, LabelDescr2, buttonSavePic2, 2);
  ...
  SetSavePicToButton(buttonSaveSlot24, buttonLoad24, LabelDescr24, buttonSavePic24, 24);
  SetSavePicToButton(buttonSaveSlot25, buttonLoad25, LabelDescr25, buttonSavePic25, 25);
 
  PrepareSaveGUI_Display(buttonSaveSlot1, buttonLoad1, buttonSavePic1, 1);
  PrepareSaveGUI_Display(buttonSaveSlot2, buttonLoad2, buttonSavePic2, 2);
  ...
  PrepareSaveGUI_Display(buttonSaveSlot24, buttonLoad24, buttonSavePic24, 24);
  PrepareSaveGUI_Display(buttonSaveSlot25, buttonLoad25, buttonSavePic25, 25);
}

function SaveTheGame(int slot, String desc)
{
  SaveGameSlot(slot, desc);
}

function LoadTheGame(int slot)
{
  RestoreCheck=true;
  RestoreSlotNm=slot;
}

void OnSaveButtonClick(Button *butSave, Button *butLoad, Label *label, DynamicSprite *pic, int save_id) {
  gSaveLoad.Visible=false;
 
  DateTime *dt = DateTime.Now;
  String month=String.Format("%02d",dt.Month);
  switch(month) {
    case "01": month="JAN"; break;
    case "02": month="FEB"; break;
    case "03": month="MAR"; break;
    case "04": month="APR"; break;
    case "05": month="MAY"; break;
    case "06": month="JUN"; break;
    case "07": month="JUL"; break;
    case "08": month="AUG"; break;
    case "09": month="SEP"; break;
    case "10": month="OCT"; break;
    case "11": month="NOV"; break;
    case "12": month="DEC"; break;
  }
 
  String SaveDesc=String.Format("#%d %02d:%02d %02d-%03s-%02d", save_id, dt.Hour, dt.Minute, dt.DayOfMonth, month, dt.Year);
  SaveGameSlot(save_id, SaveDesc);
 
  aCameraSnap.Play(eAudioPriorityNormal, eOnce);
  pic = DynamicSprite.CreateFromSaveGame(save_id, 171, 96);
  Wait(GetGameSpeed()*1);
  gSaveLoad.Visible=true;
 
  if (pic!= null) {
    butSave.NormalGraphic = pic.Graphic;
    butSave.Visible=true;
    butLoad.Visible=true;
    label.Text=Game.GetSaveSlotDescription(save_id);
  }

  RefreshGameSlots=save_id;
}

//all the different buttonSave_OnClicks:
function buttonSave1_OnClick(GUIControl *control, MouseButton button)
{
  if (buttonSavePic1!=null) buttonSavePic1.Delete();
  buttonSavePic1= DynamicSprite.CreateFromSaveGame(1, 171, 96);
  OnSaveButtonClick(buttonSaveSlot1, buttonLoad1, LabelDescr1, buttonSavePic1, 1);
}

function buttonSave2_OnClick(GUIControl *control, MouseButton button)
{
  if (buttonSavePic2!=null) buttonSavePic2.Delete();
  buttonSavePic2= DynamicSprite.CreateFromSaveGame(2, 171, 96);
  OnSaveButtonClick(buttonSaveSlot2, buttonLoad2, LabelDescr2, buttonSavePic2, 2);
}

...

function buttonSave24_OnClick(GUIControl *control, MouseButton button)
{
  if (buttonSavePic24!=null) buttonSavePic24.Delete();
  buttonSavePic24= DynamicSprite.CreateFromSaveGame(24, 171, 96);
  OnSaveButtonClick(buttonSaveSlot24, buttonLoad24, LabelDescr24, buttonSavePic24, 24);
}

function buttonSave25_OnClick(GUIControl *control, MouseButton button)
{
  if (buttonSavePic25!=null) buttonSavePic25.Delete();
  buttonSavePic25= DynamicSprite.CreateFromSaveGame(25, 171, 96);
  OnSaveButtonClick(buttonSaveSlot25, buttonLoad25, LabelDescr25, buttonSavePic25, 25);
}

// LOAD  gSaveLoaad load button functions
function buttonLoad1_OnClick(GUIControl *control, MouseButton button)
{
  LoadTheGame(1);
}
function buttonLoad2_OnClick(GUIControl *control, MouseButton button)
{
  LoadTheGame(2);
}
...
function buttonLoad24_OnClick(GUIControl *control, MouseButton button)
{
  LoadTheGame(24);
}
function buttonLoad25_OnClick(GUIControl *control, MouseButton button)
{
  LoadTheGame(25);
}

...

function repeatedly_execute()
{
...
  if (RefreshGameSlots!=0) {
    PrepareSaveGUI(RefreshGameSlots);
  }

  if (RestoreCheck) {
    if (gSaveLoad.Visible) {
      gSaveLoad.Visible=false;
    } else {
      RestoreGameSlot(RestoreSlotNm);
      RestoreSlotNm=0;
      RestoreCheck=false;
    }
  }
...
}


Anyone questons, code reducing or anything else welcome :)