It's been ages since I've tried making my own save/load GUI, and I didn't really get it back then either. I've searched the forums alot today, looking for different solutions. I never managed to even get to the whole "testing" part, since it was always some error I did in the global script. I also found the link to Greek AGS Community's old save/load toturial, but it seems to be out of order.
I'm using AGS v. 2.62.509.0, by the way. Before the whole "code change" deal. I could really use a simple step-by-step toturial right now, or an importable gui I could snatch the code from. I really don't want anything fancy, I just want to change the graphics.
I feel bad about posting this, since I don't got anything to show for myself, but I don't know where else to turn. If anyone could help me out on a simple 3-5 slot save/load system, I'd be very grateful.
Maybe you could use SSHs savegame with screenshots module: http://www.adventuregamestudio.co.uk/yabb/index.php?topic=23320.0
Not sure if it suits your purposes since I've never tried it.
GG, script modules are only supported since AGS v2.70.
Oops, sorry didn't notice that. Would upgrading the game to 2.72 be a problem if you just unchecked the enforce oo-scripting and new strings boxes?
Otherwise, here's the code from the Greek AGS Community site. I can't get the link to work either, but I had it saved on my HD:
GUI 0 (Restore interface) :
Object 0 : List Box
Object 1 : Button (cancel)
GUI 1 (Save interface) :
Object 0 : Textbox
Object 1 : Label (Save game name)
Object 2 : Button (cancel)
Object 3 : ListBox
GLOBAL SCRIPT :
string text;
int index;
function on_key_press(int keycode) {
if (keycode==363) {
// Press F5
SetTextBoxText(1,0,"");
// Clear Text box
ListBoxSaveGameList(1,3);
// Fill List Box with saved games
index=ListBoxGetNumItems(1,3);
// Count how many saved games there are
if (index>19){
// If saved games 20 (maximum)
Display("You must overwrite a previous saved game");
// Display warning
}
InterfaceOn(1);
// Bring Save interface on
}
if (keycode==365) {
// Press F7
ListBoxSaveGameList(0,0);
// Fill List box with saved games
InterfaceOn(0);
// Bring restore Interface on
}
function interface_click(int interface, int button) {
if (interface==0) {
// if Restore interface
if (button==1) {
// if cancel is pressed
InterfaceOff(0);
// Close interface
else { index=ListBoxGetSelected(0,0);
// else get the selected game
RestoreGameSlot(savegameindex[index]);}
// restore the game
}
}
if (interface==1) {
// if save interface
if (button==0) {
// if enter is pressed
index=ListBoxGetNumItems(1,3);
// Count saved games
if (index<20) {
// if less than 20
GetTextBoxText(1,0,text);
// Get the typed text
InterfaceOff(1);
// Close interface
SaveGameSlot(index+1,text); }
// Save game (text as description)
else {
// if saved games are 20
index=ListBoxGetSelected(1,3);
// Get the selected save game
GetTextBoxText(1,0,text);
// Get the typed text
InterfaceOff(1);
// Close the interface
SaveGameSlot(savegameindex[index],text); }
// Overwrite the selected game
}
if (button==2) InterfaceOff(1);
// if cancel is pressed close interface
Thanks, GG. I managed to code it in without much of a problem.
However, I still got three issues I need help with:
1. I can't overwrite save games. I've fiddled around, but I can't figure it out. I'm guessing I need another button? Here's the code(GUI 6 is LOAD, while GUI 7 is SAVE):
#sectionend repeatedly_execute // DO NOT EDIT OR REMOVE THIS LINE
string text;
int index;
function show_inventory_window () {
// This demonstrates both types of inventory window - the first part is how to
// show the built-in inventory window, the second part uses the custom one.
// Un-comment one section or the other below.
// ** DEFAULT INVENTORY WINDOW
InventoryScreen();
/*
// ** CUSTOM INVENTORY WINDOW
GUIOn (INVENTORY);
// switch to the Use cursor (to select items with)
SetCursorMode (MODE_USE);
// But, override the appearance to look like the arrow
SetMouseCursor (6);
*/
}
#sectionstart on_key_press // DO NOT EDIT OR REMOVE THIS LINE
function on_key_press(int keycode) {
// called when a key is pressed. keycode holds the key's ASCII code
if (IsGamePaused() == 1) keycode=0; // game paused, so don't react to keypresses
if (keycode==17) QuitGame(1); // Ctrl-Q
if (keycode==367) RestartGame(); // F9
if (keycode==434) SaveScreenShot("scrnshot.bmp"); // F12
if (keycode==9) show_inventory_window(); // Tab, show inventory
if (keycode==19) Debug(0,0); // Ctrl-S, give all inventory
if (keycode==22) Debug(1,0); // Ctrl-V, version
if (keycode==1) Debug(2,0); // Ctrl-A, show walkable areas
if (keycode==24) Debug(3,0); // Ctrl-X, teleport to room
if (keycode==363) {
// Press F5
SetMouseCursor (6);
// Sets cursormode 6
PauseGame();
//Pauses the game
SetTextBoxText(7,0,"");
// Clear Text box
ListBoxSaveGameList(7,3);
// Fill List Box with saved games
index=ListBoxGetNumItems(7,3);
// Count how many saved games there are
if (index>19){
// If saved games 20 (maximum)
Display("You must overwrite a previous saved game");
// Display warning
}
InterfaceOn(7);
// Bring Save interface on
}
if (keycode==365) {
// Press F7
SetMouseCursor (6);
// Sets cursormode 6
PauseGame();
//Pauses the game
ListBoxSaveGameList(6,0);
// Fill List box with saved games
InterfaceOn(6);
// Bring restore Interface on
}
}
#sectionend on_key_press // DO NOT EDIT OR REMOVE THIS LINE
#sectionstart on_mouse_click // DO NOT EDIT OR REMOVE THIS LINE
function on_mouse_click(int button) {
// called when a mouse button is clicked. button is either LEFT or RIGHT
if (IsGamePaused() == 1) {
// Game is paused, so do nothing (ie. don't allow mouse click)
}
else if (button==LEFT) {
ProcessClick(mouse.x, mouse.y, GetCursorMode() );
}
else { // right-click, so cycle cursor
SetNextCursorMode();
}
}
#sectionend on_mouse_click // DO NOT EDIT OR REMOVE THIS LINE
#sectionstart interface_click // DO NOT EDIT OR REMOVE THIS LINE
function interface_click(int interface, int button) {
if (interface==6) {
// if Restore interface
if (button==1) {
// if cancel is pressed
UnPauseGame();
//Pauses the game
InterfaceOff(6);
// Close interface
}
else { index=ListBoxGetSelected(6,0);
// else get the selected game
RestoreGameSlot(savegameindex[index]);}
// restore the game
}
if (interface==7) {
// if save interface
if (button==0) {
// if enter is pressed
UnPauseGame();
//Pauses the game
index=ListBoxGetNumItems(7,3);
// Count saved games
if (index<20) {
// if less than 20
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close interface
SaveGameSlot(index+1,text); }
// Save game (text as description)
else {
// if saved games are 20
index=ListBoxGetSelected(7,3);
// Get the selected save game
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close the interface
SaveGameSlot(savegameindex[index],text); }
// Overwrite the selected game
UnPauseGame();
//Pauses the game
}
}
if (button==2) InterfaceOff(7);
// if cancel is pressed close interface
UnPauseGame();
//Pauses the game
2. I want the cursor to change to cursor 6 when SAVE/LOAD opens. I've managed to get it to change right after the window opens, but if you move the mouse over and away from e.g. the typing field, it changes back to walk-mode, look-mode or whatever it was before SAVE/LOAD was opened.
3. When I open save/load from the iconbar, the "quit" GUI opens behind it. I've tried playing with brackets and else's and if's, but I'm just not logical that way. This is just one of those annoying obvious bugs I couldn't solve to save my grandma. This is the code that follows right after the above one:
if (interface == ICONBAR) {
if (button == 4) { // show inventory
show_inventory_window();
}
else if (button == 5) { // use selected inventory
if (character[ GetPlayerCharacter() ].activeinv >= 0)
SetCursorMode(4);
}
else if (button == 0) // save game
GUIOn(7);
else if (button == 1) // load game
GUIOn(6);
else if (button == 2) // quit
SetCursorMode(6);
PauseGame ();
GUIOn(5);
} // end if interface ICONBAR
if (interface == INVENTORY) {
// They clicked a button on the Inventory GUI
if (button == 1) {
// They pressed SELECT, so switch to the Get cursor
SetCursorMode (MODE_USE);
// But, override the appearance to look like the arrow
SetMouseCursor (6);
}
if (button == 2) {
// They pressed LOOK, so switch to that mode
SetActiveInventory(-1);
SetCursorMode(MODE_LOOK);
}
if (button == 3) {
// They pressed the OK button, close the GUI
GUIOff (INVENTORY);
SetDefaultCursor();
}
if ((button == 4) && (game.top_inv_item < game.num_inv_items - game.num_inv_displayed)) {
// scroll down
game.top_inv_item = game.top_inv_item + game.items_per_line;
}
if ((button == 5) && (game.top_inv_item > 0)){
// scroll up
game.top_inv_item = game.top_inv_item - game.items_per_line;
}
}
if (interface == 4) {
if (button == 0) { // show inventory
SetCursorMode (MODE_USE);
SetMouseCursor (6);
GUIOn(2);
}
}
if (interface == EXIT) {
if (button == 1) { // Close Window
SetCursorMode(0);
UnPauseGame();
GUIOff (EXIT);
}
else if (button == 0) // quit game
QuitGame(0);
}
}
This post was alot longer and pathetic than I hoped for. It'll be fun to see what problems I encounter when I change to AGS v2.7.
1.
Yes, adding another button is the easiest way. You can use the 'more than 20 save games' code from the normal save condition.
index=ListBoxGetSelected(7,3);
// Get the selected save game
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close the interface
SaveGameSlot(savegameindex[index],text); }
// Overwrite the selected game
UnPauseGame();
//Pauses the game
Although you'll probably need to add a check (to the overwrite button, if not both) that there IS something selected first, e.g.:
index=ListBoxGetSelected(7,3);
// Get the selected save game
if (index == -1) Display("Please select a slot to overwrite"); // No selection
else { // Overwrite the selected game
GetTextBoxText(7,0,text); // Get the typed text
InterfaceOff(7); // Close the interface
SaveGameSlot(savegameindex[index],text);
}
You could also make a condition for the list box, so that double clicking a game will overwrite it.
2. I don't know, sorry. It might be something in repeatedly_execute[/i, except that you call PauseGame().
3.
Looks like there's a problem with the conditions:
else if (button == 2) // quit
SetCursorMode(6);
PauseGame ();
GUIOn(5);
SetCursorMode(6) will only be run if button 2 is pressed, the other lines (including the one which turns on GUI6, which I guess is the Quit GUI) will run for ANY button on ICONBAR. Try:
else if (button == 2) { // quit
SetCursorMode(6);
PauseGame ();
GUIOn(5);
} // end quit
Or (depending on what commands you actually want to run when)
else if (button == 2) // quit
GUIOn(5); // Only runs on quit
SetCursorMode(6); // Runs for all (Might solve question 2)
PauseGame (); // Runs for all
On a general note: change all the InterfaceOn/Offs to GUIOn/Off, as I'm fairly sure InterfaceOn/Off was already obsolete by 2.62 - it still works, but it makes sense to keep them all the same.
Also, since you originally asked for a 3-5 slot system, you might want to change all the references to if(index>19), to decrease the possible number of save games.
Quote from: Ashen on Fri 19/05/2006 13:26:03Yes, adding another button is the easiest way. You can use the 'more than 20 save games' code from the normal save condition.
Thanks for the quick answer! Here's what I've come up with this far:
#sectionstart interface_click // DO NOT EDIT OR REMOVE THIS LINE
function interface_click(int interface, int button) {
if (interface==6) {
// if Restore interface
if (button==1) {
// if cancel is pressed
UnPauseGame();
//Pauses the game
InterfaceOff(6);
// Close interface
}
else { index=ListBoxGetSelected(6,0);
// else get the selected game
RestoreGameSlot(savegameindex[index]);}
// restore the game
}
if (interface==7) {
// if save interface
if (button==0) {
// if enter is pressed
UnPauseGame();
//Pauses the game
index=ListBoxGetNumItems(7,3);
// Count saved games
if (index<20) {
// if less than 20
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close interface
SaveGameSlot(index+1,text); }
// Save game (text as description)
else {
// if saved games are 20
index=ListBoxGetSelected(7,3);
// Get the selected save game
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close the interface
SaveGameSlot(savegameindex[index],text); }
// Overwrite the selected game
UnPauseGame();
//Pauses the game
}
}
if (button==4) {
// if "save" is pressed
UnPauseGame();
//unPauses the game
index=ListBoxGetNumItems(7,3);
// Count saved games
if (index<20) {
// if less than 20
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close interface
SaveGameSlot(index+1,text); }
// Save game (text as description)
else {
// if saved games are 20
index=ListBoxGetSelected(7,3);
// Get the selected save game
if (index == -1) Display("Please select a slot to overwrite"); // No selection
else { // Overwrite the selected game
GetTextBoxText(7,0,text); // Get the typed text
InterfaceOff(7); // Close the interface
SaveGameSlot(savegameindex[index],text);
}
}
}
if (button==2) InterfaceOff(7);
// if cancel is pressed close interface
UnPauseGame();
//Pauses the game
Button 4 is the new button. Here's the result I've got from this:
When I open the save GUI, I type in a name in the text field and press enter. The GUI closes, but don't save the game. Same result with pressing the new button. I've obviously done something wrong here.
Also, you mentioned something about making a condition for the list box, and making it overwrite a game by double clicking? Do you think you could give me a little step by step on how to do that? Or would it be easier to just fix the system I'm trying now?
Your solution for the quit code, pluss a little bracket, worked perfect. Thanks alot.
I think there's a problem with your braces in there - the condition for GUI 7 ends right after the button 0 condition (the second '}' just before
if (button == 4), meaning the following conditons will work on any GUI. However, that shouldn't be causing the problem since they should still be run. (I think, I'm a little rusty in 2.62 code, but that makes logical sense.)
Check the Compiled folder - are you sure it's not actually saving? I notice that when you turn the save/load GUIs on from the ICONBAR GUI, you
only turn the GUIs on, and don't run the
ListBoxSaveGameList(7,3); needed to display existing save games. Other than that, the code looks fine to me I can't see why it wouldn't save, especially if you've just copied the code GG posted. (Although, like I said - rusty in 2.62.)
Quoteyou mentioned something about making a condition for the list box, and making it overwrite a game by double clicking? Do you think you could give me a little step by step on how to do that?
In the
if (interface == 7) condition:
if (button == 3) { // I THINK control 3 is your listbox? Check to be sure
if (index != ListBoxGetSelected(7,3)) index != ListBoxGetSelected(7,3);
// First click. If clicked item hasn't been selected before, remember it for next time.
else { // Second click. (i.e. clicked item has already been selected.)
GetTextBoxText(7,0,text); // Get the typed text
GUIOff(7); // Close the interface
SaveGameSlot(savegameindex[index],text);
}
}
That
should do it. However, it probably would make more sense to get normal saving working first, before getting into anything else.
Hey,
Sorry for not responding. I've been trying to work out a solution myself, among other things.
The saving works now, but not the overwriting. It's basically doomed to save in a new slot for every save. When I turn the GUI on, the top game is always marked. I guess it shouldn't, and only be marked when it's supposed to be saved over? Is this possible without re-organizing too much of the code?
if (interface==7) {
// if save interface
if (button==0) {
// if enter is pressed
UnPauseGame();
//Pauses the game
index=ListBoxGetNumItems(7,3);
// Count saved games
if (index<6) {
// if less than 20
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close interface
SaveGameSlot(index+1,text); }
// Save game (text as description)
else {
// if saved games are 20
index=ListBoxGetSelected(7,3);
// Get the selected save game
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close the interface
SaveGameSlot(savegameindex[index],text); }
// Overwrite the selected game
UnPauseGame();
//Pauses the game
}
}
if (button==4) {
// if "save" is pressed
UnPauseGame();
//unPauses the game
index=ListBoxGetNumItems(7,3);
// Count saved games
if (index<6) {
// if less than 20
GetTextBoxText(7,0,text);
// Get the typed text
InterfaceOff(7);
// Close interface
SaveGameSlot(index+1,text); }
// Save game (text as description)
else {
// if saved games are 20
index=ListBoxGetSelected(7,3);
// Get the selected save game
if (index == -1) Display("Please select a slot to overwrite"); // No selection
else { // Overwrite the selected game
GetTextBoxText(7,0,text); // Get the typed text
InterfaceOff(7); // Close the interface
SaveGameSlot(savegameindex[index],text);
}
}
}
if (button==2) InterfaceOff(7);
// if cancel is pressed close interface
UnPauseGame();
//Pauses the game
I take it button 4 is your Overwrite button?
You've still got the code set to check if there's less than 6 save games already, before it checks for a highlighted slot to save over. Try changing the code to:
if (button==4) { // if "save" is pressed
UnPauseGame(); //unPauses the game
index=ListBoxGetSelected(7,3); // Get the selected save game
if (index == -1) Display("Please select a slot to overwrite"); // No selection
else { // Overwrite the selected game
GetTextBoxText(7,0,text); // Get the typed text
InterfaceOff(7); // Close the interface
SaveGameSlot(savegameindex[index],text);
}
}
This'll overwrite the slot that's selected when button 4 is pressed, however many existing games there are.
You'll need to add a line wherever you turn the GUI on to clear the selected item (ListBoxSetSelected, but I'm not sure of the useage).
If you mean it's creating new savegames over 6, then I can't see the problem, sorry.