ID:264273
 
Code:
Player/var/Team/team 
Player
proc/saveCharacter()
....
Write(F)
proc/loadCharacter()
....
Read(F)
Player
Write(savefile/F)
..()
[Deals with saving coordinates]
Read(savefile/F)
..()
[Deals with loading coordinates]

Team/var/Monster/monster1


Problem description:
Essentially I have three datum based things to save, the mob based Player Datum, which has a Team datum, containing mob based Monster Datums.

Now, I'm working under the assumption that when the Player saves, the team will save, and the monsters, etc. And for the most part it's worked.
But, I'm noticing problems. Specifically, the monsters aren't saving correctly. I don't believe any of the actual vars of the monsters are saving, such as name, gender, or stats.

I think that the problem may be with my New procs. I pass arguments into my Monster/New(), for example, to deal with original stats and such for new monsters. Are these procs getting in the way of the load, possibly?

Yikes! Let's get started... Just keep in mind that we cannot diagnose the exact problem without seeing your code, but we can certainly make some valid guesses.

You don't need to call Read() and Write() manually. They are called every single time an atom is written directly to a savefile. I think it is always better to just write the variables directly to the savefile, skipping those that aren't necessary to save (see: icon in the reference). It really does help avoid some unnecessary problems you may come across.

Now when saving atoms, anything that isn't /tmp, /const, /global, or equal to its initial() value is saved. This is all handled by Read() and Write() functions of the atom. New() technically does nothing at all unless otherwise defined, so that is not the source of your problem. Of course, the exception there is that you may be overwriting the saved stats. Keep in mind that New() is only called after the object has been created and has had all of its variables initialized.

So I'm going to blame your problem on the possible overwritten Read() and Write() functions of your code. Make sure you look not only for the derivative /Monster type functions, but also for the parent_type of /Monster's functions and anything else that may follow, for example:

mob/npcs
Monster
parent_type = /mob/npcs

// You want to look at /mob, /mob/npcs, and /Monster here


It is also possible that you have some other problems with stuff like cross-referencing between savefiles. Take a look at the following article, it may be a great help:
The Pitfalls of Savefiles

Good luck with HAH!
In response to CaptFalcon33035 (#1)
CaptFalcon33035 wrote:
You don't need to call Read() and Write() manually.

It's one method of object saving. You can either call Read() and Write() manually, or use the >> and << operators (though not mixing them, or using both). The result is a different saving type (for example, the << operator saves the type unlike Write(), because >> needs to create a new object to call Read() on, whereas Read() on its own runs on an existing object of course).
In response to Kaioken (#2)
Yeah, I was basing my work on saving on that Pitfalls of saving and the DM guide. The DM guide also mentioned the differences between using << and Write().

I've been sort of torn about how to handle saving. I can't decide whether I'm going to manually save vars or do it all automatically.


As for derivatives, Monster derives directly from mob, and I haven't really defined anything for mob at all. (This code is essentially entirely based on datums so far) I believe mob/Move() is the only proc I've got so far.

Anyways, I guess I'll just copy my entire saving file. (Minus stuff that I've commented out)
Coords //Used to save a players location.
var/x
var/y
var/z
New(_x,_y,_z)
x = _x
y = _y
z = _z
proc/Place(Player/P)
ASSERT(P && istype(P))
P.Place(locate(x,y,z))
atom/proc/toCoords()
var/Coords/c = new(src.x,src.y,src.z)
return c

Player
Logout()
saveCharacter()
del(src)
proc/saveCharacter()
var/Player/P = src
ASSERT(P && istype(P))
if(fexists(PLAYER_SAVE)) fdel(PLAYER_SAVE)
var/savefile/F = new(PLAYER_SAVE)
Write(F)
proc/loadCharacter()
if(!fexists(PLAYER_SAVE)) return
var/savefile/F = new(PLAYER_SAVE)
Read(F)


Player
Write(savefile/F)
..()
var/Coords/place
if(!loc)
if(team && team.return_spot)
place = team.return_spot:toCoords()
else
var/atom/a = DEFAULT_LOC
place= a.toCoords()
else
place = loc.toCoords()
F["coords"] << place
Read(savefile/F)
..()
var/Coords/place
F["coords"] >> place
if(team)
team.owner = src
spawn() place.Place(src)
Monster
Write(savefile/F)
..()
F["icon"] << null
F["overlays"] << null
F["underlays"] << null
Read(savefile/F)
..()
owner = findPlayer(owner_ckey)

Let's see... what else.
Team is derived from /atom (to make use of Stat())...
The Coords thing is really just a way of encompassing 3 vars into one. It might be overkill, but I guess if it ends up being wasteful I'll cut it later. (The return_spot thing is if a player is in the middle of the battle when they logout)

Edit: The other thing that might help is my login code, I attached this to client/New()
client
New()
var/Player/M = new/Player()
if(fexists(PLAYER_SAVE))
switch(alert(...))
if("Load Game")
M.key = key
M.loadCharacter()
return M
if("New Game")
fdel(PLAYER_SAVE)
M.client = src
M.gender = gender
M.name = key
spawn() M.newGame()
return M
In response to Chessmaster_19 (#3)
Honestly, I don't see the point in making a datum for Coordinates...just use x, y, and z that are already built in for you :). Plus if you're using datums, it's probably a better idea to save them manually.
In response to Axerob (#4)
Well, x,y, and z don't save automatically. No matter what you do, you've got to account for location saving. I figured that handling one object might be less cumbersome than handling 3 separate variables.
Like I said, in the end, if it's not useful I can just scrap it. I might find more ways to use it before I'm done.
I'm thinking of trying to use them as a substitute for using areas to manage locations like start locations and perhaps map edges (moving from one area of a map to another).


Anyways, I found the source of my problem. It was just a few stray lines of code in a different file that was causing Monsters to save wrong. Thanks for the help. I'll need to be more careful in the future.
In response to Axerob (#4)
Axerob wrote:
Honestly, I don't see the point in making a datum for Coordinates...just use x, y, and z that are already built in for you :). Plus if you're using datums, it's probably a better idea to save them manually.

I rather like his object-oriented approach to saving location. It keeps things uniform and organized.