How to create a Save/load system
by Edwin Gomez · in Game Design and Creative Issues · 05/16/2007 (8:44 am) · 16 replies
I'm working over the starter.fps and i don't have any idea how to use or create a save and load system. Any help will be appreciated
About the author
#2
05/16/2007 (5:36 pm)
Thanks for the answer but, do you have any *.cs example to understand clearly and thanks for your support.
#3
If an employee says different, then yes I will show what I did. Otherwise, sorry but thats all I can give.
05/16/2007 (7:50 pm)
Hmm the problem with that Edwin is that your profile says you are not a Torque Engine owner. Sharing such things in a public area is prohibited last I heard, especially with those who haven't bought the product.If an employee says different, then yes I will show what I did. Otherwise, sorry but thats all I can give.
#4
Gotta help the new guys get their feet wet, so they know what they are getting into and feel like they can get help from our community.
05/17/2007 (6:17 am)
Sharing C++ and engine information is prohibited. Sharing Torque Script information and help is allowed, which is why the Torque Game Engine Public area exists =).Gotta help the new guys get their feet wet, so they know what they are getting into and feel like they can get help from our community.
#5
05/17/2007 (6:31 am)
What exactly are you trying to save? I've written a few save systems that go from saving what mission you're on to saving a large, dynamic world.
#6
It's script driven, so it should suit your needs. Right now, it only covers writing the character name, mission name, and a checkpoint. It can easily be expanded to cover ammo, weapons, and stats, as well as other critical variables you need saved out.
05/17/2007 (6:36 am)
This resource is a great starting point: Save/Load SystemIt's script driven, so it should suit your needs. Right now, it only covers writing the character name, mission name, and a checkpoint. It can easily be expanded to cover ammo, weapons, and stats, as well as other critical variables you need saved out.
#7
05/17/2007 (7:56 am)
It would be nice if someone could write a good tutorial on the Save/Load system. I never good get to work right.
#8
However, the code I used is in a public forum area, so this is not my fault.
www.garagegames.com/mg/forums/result.thread.php?qt=7555
I added Daniel Eden's code not script and then made my own.
I'll show what I did for an example to work from. Modify it as you see fit. Keep in mind as well I use bitmap buttons in my gui so you may need to change things if you are copying.
First, I needed a new set of saveable variables that didn't have anything to do with config.cs or pref.cs so I created two new .cs files and added their execution in the main.cs file you would find in starter.fps or racing
Also, in the same file in the function onExit()
Since these will compile into DSO files they should be fine. However that last step can be skipped if you would like, I just needed it for the purposes of my game since the varaibles are needed in my game at startup.
My variables in clientProfileDefaults.cs look like this:
Now the file clientProfileDefaults.cs is kept in the start.fps/client/ directory.
Gonna break this up into separate posts.
05/17/2007 (10:15 am)
OK well my solution is not entirely script-based. I wanted mine to work in a way to prevent would-be game hackers from modifying their profile stats or even viewing them. However, the code I used is in a public forum area, so this is not my fault.
www.garagegames.com/mg/forums/result.thread.php?qt=7555
I added Daniel Eden's code not script and then made my own.
I'll show what I did for an example to work from. Modify it as you see fit. Keep in mind as well I use bitmap buttons in my gui so you may need to change things if you are copying.
First, I needed a new set of saveable variables that didn't have anything to do with config.cs or pref.cs so I created two new .cs files and added their execution in the main.cs file you would find in starter.fps or racing
// Defaults console values
exec("./client/defaults.cs");
exec("./server/defaults.cs");
exec("./client/clientProfileDefaults.cs");
// Preferences (overide defaults)
exec("./client/prefs.cs");
exec("./client/clientProfilePrefs.cs");
exec("./server/prefs.cs");Also, in the same file in the function onExit()
echo("Exporting client prefs");
export("$pref::*", "./client/prefs.cs", False);
export("$clProfPref::*", "~/client/clientProfilePrefs.cs", False);Since these will compile into DSO files they should be fine. However that last step can be skipped if you would like, I just needed it for the purposes of my game since the varaibles are needed in my game at startup.
My variables in clientProfileDefaults.cs look like this:
$clProfPref::chassisDB = "Buggy"; $clProfPref::vehicleTrans = "true"; $clProfPref::vehicleFWheel = "BuggyFWheel3"; $clProfPref::vehicleRWheel = "BuggyRWheel3"; $clProfPref::vehicleSprings = "buggySpring1"; $clProfPref::wheelsPowered = 4; $clProfPref::vehicleEngine = "buggyEngine1";
Now the file clientProfileDefaults.cs is kept in the start.fps/client/ directory.
Gonna break this up into separate posts.
#9
Just add it around the others .cs executions in the file.
Now for the profileGui.cs:
05/17/2007 (10:23 am)
Next, I have my functions in another .cs file called profileGui.cs (held in starter.fps/client/scripts) which you will have to add its execution to the init.cs like so:exec("./scripts/profileGui.cs");Just add it around the others .cs executions in the file.
Now for the profileGui.cs:
$saveVPName = "";
$vProfileDir = "main/client/profiles/*.dso";
$fileNameLd = "";
$fileNameDel = "";
function profileGui::onWake(%this)
{
mainMenuGui.hideButtons();
}
function exportVProfile()
{
echo("Export vehicle profile function called");
if($saveVPName $= "")
{
echo("If Check successful");
return;
}
export("$clProfPref::*", "main/client/profiles/" @ $saveVPName @ ".cs", False);
eval(%pfFile = "main/client/profiles/" @ $saveVPName @ ".cs");
exec(%pfFile);
deleteFile(%pfFile);
$saveVPName = "";
Canvas.popDialog(saveVProfile);
}
//----------------------------------------
function loadVProfileGui::onWake()
{
vehicleProfileList.displayByType();
}
//----------------------------------------
function vehicleProfileList::displayByType()
{
vehicleProfileList.clear();
%i = 0;
for(%file = findFirstFile($vProfileDir); %file !$= ""; %file = findNextFile($vProfileDir))
{
%filetmp = Strreplace(%file, "main/client/profiles/", "");
%file = Strreplace(%filetmp, ".cs.dso", "");
vehicleProfileList.addRow(%i++, %file);
}
vehicleProfileList.sort(0);
vehicleProfileList.scrollVisible(0);
}
//----------------------------------------
function vehicleProfileList::onSelect(%this, %row, %text)
{
$fileNameLd = "main/client/profiles/" @ %text @ ".cs";
$fileNameDel = "main/client/profiles/" @ %text @ ".cs.dso";
}
function deleteVProfile()
{
deleteFile($fileNameDEL);
vehicleProfileList.displayByType();
}
function loadVProfile()
{
exec($fileNameLd);
Canvas.popDialog(loadVProfileGui);
updateVehicle($mmThis);
}
function updateVehicle(%this)
{
// Combination create player and drop him somewhere
$mmPlayer.delete();
$mmVehicle.delete();
%spawnPoint = pickSpawnPoint();
%this.createMMPlayer(%spawnPoint);
%spawnPoint = pickVehicleSpawnPoint();
%this.createMMVehicle(%spawnPoint);
mmRotate();
}
#10
05/17/2007 (10:25 am)
Finally the guis. profileGui.gui is first. Remeber to add these to the init.cs file as well. Look at the existing gui executions as an example.//--- OBJECT WRITE BEGIN ---
new GuiControl(profileGui) {
canSaveDynamicFields = "1";
Profile = "GuiModelessDialogProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "0 0";
Extent = "640 480";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
hovertime = "1000";
new GuiBitmapButtonTextCtrl(close) {
canSaveDynamicFields = "0";
Profile = "DTButtonProfile";
HorizSizing = "relative";
VertSizing = "relative";
position = "528 444";
Extent = "108 28";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "Canvas.popDialog(profileGui); mainMenuGui.showButtons();";
hovertime = "1000";
text = "CLOSE";
groupNum = "-1";
buttonType = "PushButton";
bitmap = "./blackblank";
};
new GuiTextEditCtrl() {
canSaveDynamicFields = "0";
Profile = "GuiTextEditProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "394 450";
Extent = "119 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Variable = "$clProfPref::chassisDB";
hovertime = "1000";
maxLength = "1024";
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
password = "0";
passwordMask = "*";
};
new GuiBitmapButtonTextCtrl(saveVEProfile) {
canSaveDynamicFields = "0";
Profile = "DTButtonProfile";
HorizSizing = "relative";
VertSizing = "relative";
position = "528 412";
Extent = "108 28";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "Canvas.pushDialog(saveVProfile);";
hovertime = "1000";
text = "SAVE";
groupNum = "-1";
buttonType = "PushButton";
bitmap = "./blackblank";
};
new GuiBitmapButtonTextCtrl(close) {
canSaveDynamicFields = "0";
Profile = "DTButtonProfile";
HorizSizing = "relative";
VertSizing = "relative";
position = "528 348";
Extent = "108 28";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "updateVehicle($mmThis);";
hovertime = "1000";
text = "APPLY";
groupNum = "-1";
buttonType = "PushButton";
bitmap = "./blackblank";
};
new GuiBitmapButtonTextCtrl(loadVEProfile) {
canSaveDynamicFields = "0";
Profile = "DTButtonProfile";
HorizSizing = "relative";
VertSizing = "relative";
position = "528 380";
Extent = "108 28";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Command = "Canvas.pushDialog(loadVProfileGui);";
hovertime = "1000";
text = "LOAD";
groupNum = "-1";
buttonType = "PushButton";
bitmap = "./blackblank";
};
};
//--- OBJECT WRITE END ---
#11
05/17/2007 (10:26 am)
Then the saveVPProfile.gui://--- OBJECT WRITE BEGIN ---
new GuiControl(saveVProfile) {
canSaveDynamicFields = "0";
Profile = "GuiDefaultProfile";
HorizSizing = "width";
VertSizing = "height";
position = "0 0";
Extent = "640 480";
MinExtent = "8 8";
canSave = "1";
Visible = "1";
hovertime = "1000";
new GuiWindowCtrl(profileManager) {
canSaveDynamicFields = "0";
Profile = "GuiWindowProfile";
HorizSizing = "center";
VertSizing = "center";
position = "145 202";
Extent = "349 75";
MinExtent = "48 0";
canSave = "1";
Visible = "1";
hovertime = "1000";
text = "SAVE PROFILE";
maxLength = "255";
resizeWidth = "0";
resizeHeight = "0";
canMove = "0";
canClose = "0";
canMinimize = "0";
canMaximize = "0";
minSize = "50 50";
new GuiTextCtrl() {
canSaveDynamicFields = "0";
Profile = "GuiTextProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "9 38";
Extent = "63 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
hovertime = "1000";
text = "Profile Name:";
maxLength = "255";
};
new GuiTextEditCtrl() {
canSaveDynamicFields = "1";
Profile = "GuiTextEditProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "76 40";
Extent = "119 18";
MinExtent = "8 2";
canSave = "1";
Visible = "1";
Variable = "$saveVPName";
hovertime = "1000";
maxLength = "255";
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
password = "0";
passwordMask = "*";
};
new GuiBitmapButtonTextCtrl() {
canSaveDynamicFields = "0";
Profile = "DTNmTextButtonProfile";
HorizSizing = "right";
VertSizing = "top";
position = "199 38";
Extent = "70 23";
MinExtent = "8 8";
canSave = "1";
Visible = "1";
Command = "exportVProfile();";
hovertime = "1000";
text = "SAVE";
groupNum = "-1";
buttonType = "PushButton";
bitmap = "./blackblank";
};
new GuiBitmapButtonTextCtrl() {
canSaveDynamicFields = "0";
Profile = "DTNmTextButtonProfile";
HorizSizing = "right";
VertSizing = "top";
position = "272 38";
Extent = "70 23";
MinExtent = "8 8";
canSave = "1";
Visible = "1";
Command = "Canvas.popDialog(saveVProfile);";
hovertime = "1000";
text = "CANCEL";
groupNum = "-1";
buttonType = "PushButton";
bitmap = "./blackblank";
};
};
};
//--- OBJECT WRITE END ---
#12
Canvas.pushDialog(profileGui);
Now keep in mind this will not work exactly the way you want for your game needs, it is designed for my own and the fact that I use the mission in the main menu resource instead of the objectview gui for a much better effect. Laso my directory struction is much different than the exmples so if you see references to main/client directories, change it to suit your needs.
However, the script I have show here should give you a few examples of what to try.
05/17/2007 (10:29 am)
Finally just add a button somewhere you want with the command assigned to it like:Canvas.pushDialog(profileGui);
Now keep in mind this will not work exactly the way you want for your game needs, it is designed for my own and the fact that I use the mission in the main menu resource instead of the objectview gui for a much better effect. Laso my directory struction is much different than the exmples so if you see references to main/client directories, change it to suit your needs.
However, the script I have show here should give you a few examples of what to try.
#13
05/25/2007 (7:38 am)
Well thank you very much for all your help
#14
05/25/2007 (9:13 am)
Thanks for information.
#15
07/26/2007 (5:47 pm)
Thanks a ton
#16
07/26/2007 (8:46 pm)
NP, Its nice to be able to give advice for a change rather than asking for it all of the time.
Torque Owner Ronald J Nelson
Code Hammer Games
To load I just have a function for an list gui that sets up an array of *.cs files in that folder. I got a bit fancy and had it remove parts of the file name and add them on when needed for display purposes. If you want to prevent hackers in the manner I did you will have to add the delete file functionality found on some resource or forum here, I must admit I forget where I found it. Then I have it execute the file so it compiles to a DSO then immediately deletes the orginal *.cs file.