Game Development Community

Yet another save system help request:

by NA · in Torque Game Engine · 04/21/2005 (8:30 am) · 13 replies

I've spent the last 14 hours reading as many resorces, threads, etc on implementing a save system.
I browsed all the way back in the forums until 2003, and am still kind of in the dark here.

What I'm looking to do is a simple save system, all that needs to be saved is:
Player Health
Player Inventory
Location
World Status (primarily enemies there or not)

Is it possible someone could point me to the best resource for this? Or point me in the right direction? I'll admit straight up that I'm not much of a C++ coder, so the less techincal the description, the better. :)


On a related note - 3d Game Programming All in One, purchasing that today, does the book have any information that might help with this save system creation?

And a last note: If it comes down to it, if someone is interested in coding this for me, I will pay and dont mind the code being released in full to the community.

Thanks for any help though.

#1
04/21/2005 (8:46 am)
I posted in your plan
#2
04/21/2005 (8:47 am)
Thank you. :)
Will check that out now.
#3
04/21/2005 (8:55 am)
This would really depend more or less on if you are talking single or multiplayer.

In single player you could just create $Pref::Player::Vars
With vars being the variable you want to save and it will automagically be written out when you close the game.

This wouldn't work in a multiplayer envrionment though.

In a multiplayer environment, you would probably want to use a SQLite DB for this stuff, pretty simple to implement, here is a short example.

%query = "CREATE TABLE Inventory (Name VARCHAR(20),Item VARCHAR(20),Amount INT(11))";
%result = $SqLite.query(%query,0);
$SqLite.clearResult(%result);

function UpdateClientInventory(%client,%Item,%Amount){
   //Update Client Inventory
   //Opens DB
   //Creates Inventory Table if it doesn't exist
   //Looks for Items in inventory
   //If they do exist it increments inventory amount
   //If they don't exist it creates them
   echo("Item passed! " @ %Item);
   

   //Decide whether to create the item in inventory or merely increment	
   %query = "SELECT * FROM Inventory WHERE Item = \'"@%Item@"\' AND Name = \'"@%client.name@"\'";
   echo(%query);
   %result = $SqLite.query(%query,0);
   echo(%result);
   
   if($SqLite.numrows(%result) >=1){
        //The person already posseses one or more of the Item
	%OldAmount = $SqLite.getColumn(%result, "Amount");
	echo("It looks like "@%client.name@" already owns "@%OldAmount@" of "@%Item);
	
	echo("Client now owns "@%Amount@" of the item called "@%Item);
	%query ="UPDATE Inventory SET Amount = \'"@%Amount@"\' WHERE Name = \'"@%client.name@"\' AND Item = \'"@%Item@"\'";
	echo(%query);
	%result = $SqLite.query(%query,0);
	echo("Result from Update was "@%result);
	$SqLite.clearResult(%result);
   }else{
	//The Name owns none of the item, but we are giving him some
	echo("Client now owns "@%Amount@" of the item called "@%Item);
	%query = "INSERT INTO Inventory (Name,Item,Amount) VALUES (\'"@%client.name@"\',\'"@%Item@"\',\'"@%Amount@"\')";
	echo(%query);
	$SqLite.query(%query,0);
	$SqLite.clearResult(%result);
   }
   $SqLite.clearResult(%result);
}

Note that the above is the result of me merging a SQLite based Inventory with the script based inventory system, so the code for updating the DB could be alot cleaner since there is really no longer a need to see what quantity of items a player has, during that function.

function ShapeBase::setInventory(%this,%data,%value)
{
   // Set the inventory amount for this datablock and invoke
   // inventory callbacks.  All changes to inventory go through this
   // single method.

   // Impose inventory limits
   if (%value < 0)
      %value = 0;
   else {
      %max = %this.maxInventory(%data);
      if (%value > %max)
         %value = %max;
   }

   // Set the value and invoke object callbacks
   %name = %data.getName();
   echo("Adding "@%name@" to client inventory");
   if (%this.inv[%name] != %value) 
   {
      %this.inv[%name] = %value;
      %data.onInventory(%this,%value);
      %this.getDataBlock().onInventory(%data,%value);
       UpdateClientInventory(%this.client,%name,%value);
   }
   return %value;
}

And finally...
function getPlayerInventory(%player){
	%query = "SELECT * from Inventory WHERE Name = \'"@%player.ShapeName@"\'";
	%result = $SQLite.query(%query,0);
	while(!$SqLite.endOfResult(%result)){
		%ItemName = $SqLite.getColumn(%result,"Item");
		%Amount  = $SqLite.getColumn(%result,"Amount");
		%player.setInventory(%ItemName,%Amount); 
		$SqLite.nextRow(%result);
	}
	$SqLite.clearResult(%result);
}

Now for this to actually work properly, you need create a new SQLiteObject as a server side global, I named mine $Sqlite

Hope that helps!
#4
04/21/2005 (8:56 am)
Yeah, as I posted in my plan - I just cant seem to take these resources and quite wrap my head around how to implement them exactly.

I understand the process of writing to the file, and loading it - but not writing the specifics of the mission, and player data, etc.


I think I just need to do a lot more reading personally, but I'd be greatful of any additional insight on this.

edit: didnt see the new post either, reading that now. But yes, this is singleplayer only.
#5
04/21/2005 (8:57 am)
Note on a single player game you will probably want some sort of encryption when you save out, so the player doesn't just open up that file and change there values :)
#6
04/21/2005 (8:58 am)
Okay, hold on a minute:

"In single player you could just create $Pref::Player::Vars
With vars being the variable you want to save and it will automagically be written out when you close the game."

Thats excellent to know - and I know this is a stupid question, but where does this line go?
And would that work for mission data such as enemies? I do not see how, but again, I'm probably just being thick here in one way or another.


Edit: Any I'm not too worried about the player having fun changing their saves - its no worse than them using cheats, and its a bit more work on their part :P
#7
04/21/2005 (8:59 am)
Well you could easily take my example above, and modify it for things other than inventory. I am using essentially the same system for all my players skills and stats in Dream.

*Update NM, I think we are posting out of sequence here.*
Give me a few minutes and I will track down what you may want to edit for single player.
#8
04/21/2005 (9:06 am)
In the set inventory function modify it to this...
function ShapeBase::setInventory(%this,%data,%value)
{
   // Set the inventory amount for this datablock and invoke
   // inventory callbacks.  All changes to inventory go through this
   // single method.

   // Impose inventory limits
   if (%value < 0)
      %value = 0;
   else {
      %max = %this.maxInventory(%data);
      if (%value > %max)
         %value = %max;
   }

   // Set the value and invoke object callbacks
   %name = %data.getName();
   echo("Adding "@%name@" to client inventory");
   if (%this.inv[%name] != %value) 
   {
      %this.inv[%name] = %value;
      $Pref::Player::Inv[%name] = %value;
      %data.onInventory(%this,%value);
      %this.getDataBlock().onInventory(%data,%value);

   }
   return %value;
}

Take note, I moved my Inventory system up out of the datablock, to make persistance work, so you may have to adjust either that function to work with the as-is inventory, or adjust the related functions to accomodate for the change. IIRC, the changes took all of about 3 minutes. And they were all contained in the inventory.cs file.

Oh yeah almost forgot... What happens here is the $Pref::Player::Blah will be written to a file called prefs.cs, this file is automatically written at close and read from at launch. So the only thing you would have to do is Initialize these vars in the first place, which you should be doing with a player creation screen, or whatnot.
#9
04/21/2005 (9:10 am)
Thanks, this all shold get me started - this save system is my weekend project unless someone wants to do it for me for a bit of money. :p

I'm still worried its over my head though - pride out the window, I'm a horrible coder; I'm a mapper at heart.
#10
04/21/2005 (9:12 am)
Mapper eh? You any good with Interior Objects? I need some new interiors and would gladly whip this out for ya in exchange for some shiney new buildings :)

By shiney I mean rough, and by new I mean RPG, and ramshackle looking :)

Got PayPal?
If you're not any good with interiors, I'll still help ya and you can pay me whatever it's worth to you, hows that sound?
#11
04/21/2005 (9:18 am)
Dreamer: I'd be MORE than happy to do some sort of swap with you :)

Setash@gmail.com and we'll see what we can work out, I'd much rather map this weekend than code :P
#12
04/21/2005 (9:25 am)
Dreamer: I'm heading out for the day, but I'll gladly do your interiors in exchange for a save system. :)

And, if theyre not up to spec, I'll pay you as long as I can use the interiors instead. :P

Shoot me an email or AIM me (WalkedYarplane)

And thank everyone much for the help - I'm AMAZED at the quality of the community here.
#13
04/21/2005 (9:26 am)
Email is already sent, just read it before heading out, since there are a couple more things I need from you before I can start.