ID:1898575
 
Code:
//save+load code
mob
proc
Savenow()
if(src.cansave && src.issaveing == 0)
var/savefile/F = new("[src.ckey].sav")
Write(F)
F["i"] << src.image
F["X"] << src.x
F["Y"] << src.y
F["Z"] << src.z

spawn(10) src << "<font color=green><b>Your game has been saved!"
spawn(10)for(var/mob/m in world)
if(m.admin >= 1)m << output("<font color = red>[src] has saved.","info")
usr.issaveing = 1
spawn(500)usr.issaveing = 0

mob
verb
LoadPlayer()
set hidden = 1
if(src.canload == 0)return
if(fexists("[src.ckey].sav"))

var/savefile/F = new("[src.ckey].sav")
Read(F)
var/image/i = new/image(F["i"],src)
src.image = i
src << i
world<<output("<font size=1><font color=green><B>Info: <font color=white>[src]([src.key]) has loaded a character...","info")
src.loc = locate(F["X"],F["Y"],F["Z"])
if(src.ko == 1)
src.ko = 0
spawn()src.KO(,src)
if(src.isSleeping == 1)src.sleep_cycle()

issonared = 0
whosonared = null
src.canmove = 1
src.isfly = 0
src.grabbing = 0
src.grabbed = 0
src.whoGrabbed = null
src.whoGrabbing = null
src.canload = 1
src.UpdateCansee()
src.age()
loggedyet = 1
online += "<font color=[src.player_clr]>([src.key])[src.name]"
winshow(src, "outputs", "show=0")
winshow(src, "window1")
else alert(src,"You have no save")

//Obj that seems to be causing the issue

obj/Captain
droppable = 0
caninv = 0
var/repPoints = 0
var/influence = 0
var/squadMembers = 1
var/demeanour = "Unknown"
var/squadNumber
var/mob/user
var/squadTheme
verb
////////////***//////////////captain verbs!///////////***//////////


Apoint_Trainee()//As a side note, the code that decides when to appoint a shinigami as fully fledged is in the spirit gain part of the statgain proc
set category = "Squad"
var/tmp/mob/m = input("Who do you wish to apoint as a trainee Shinigami?")as mob in view()
if(m.race != "Spirit")
usr << "They can't be made a Shinigami Trainee, either they aren't dead or they are already a different race."
return
m.Become_Shini()
m << output("<br><br><Font color = green>As you were made a trainee directly by a Captain, you learn a bit about shakkahou, the basic Shinigami Kidou! You also gain a hell butterfly.","OOC")
var/obj/h = new/obj/Hell_Butterfly
h.loc = m.contents
for(var/obj/skill/projectile/Shakkahou/s in m.contents)
s.MasterIncrease(25,m,1)

// ** // ** // ** // ** // ** //

Invite_To_Squad()
set category = "Squad"
var/tmp/mob/m = input("Who do you wish to invite into your squad?") as mob in view()|"None"
if(m == "None"||m.race != "Shinigami")
return
else
switch(input("Are you sure? This will cost you 15 rep points if they accept.")in list("Yes","No"))
if("No")
return
if("Yes")
for(var/tmp/obj/Captain/c in usr.contents)
if(c.repPoints < 15)
usr << output("Not enough rep points.")
return
if(m.squad != null)
usr << "They are already in a squad."
return
switch(alert(m,"[usr] is inviting you into their squad. Do you wish to accept?","Squad invite","Yes","No"))
if("Yes")
view() << "<font color = green>[m] courteously accepts [usr]'s invite into their squad!"
var/tmp/obj/Squad/s = new/obj/Squad
m.contents += s
s.squadNumber = usr.squad //s = the object containing the squads details that the new squad member receives.
s.user = m
m.rank = "Rank and File"
s.captain = usr
src.influence += 1+(m.basesp/1000)
for(var/tmp/obj/Captain/C in usr.contents)
C.repPoints -= 15

if("No")
view() << "<font color = red>[m] rejected [usr]'s offer to join their squad...ouch."


// ** // ** /// ** /// ** // ** // ** // ** // ** // ** // ** //

Spend_Reputation_Points()
set category = "Squad"
var/tmp/reppoints
for(var/tmp/obj/Captain/c in usr.contents)
reppoints = c.repPoints
var/tmp/t = input("What do you wish to spend your reputation points on? You have [reppoints] to spend.","Choose something.")in list("Change Squad Theme: 50 points","Temporary Gains Increase: 40 points")

if(t == "Temporary Gains Increase: 40 points" && reppoints >= 40)
squadgainup(usr,0.5)
for(var/tmp/obj/Captain/C in usr.contents)
C.repPoints -= 40

if(t == "Change Squad Theme: 50 points" && reppoints >= 50)
switch(alert("Change your squad's theme?",,"Yes","No"))
if("Yes")
var/tmp/i = input("What do you wish to change it to?")in list("Politics","Technology","Healing and Protection","Reiatsu Speciality","Warrior Speciality","Bloodlust","Shadow Operations","Honour Bound","Kidou Specialisation","Businessman-ship","Lone Wolf","Teamwork","None")
if(i == "None")
return
if(usr.squad == 1)
squad_1_theme = i

if(usr.squad == 2)
squad_2_theme = i

if(usr.squad == 3)
squad_3_theme = i

if(usr.squad == 4)
squad_4_theme = i

if(usr.squad == 5)
squad_5_theme = i

if(usr.squad == 6)
squad_6_theme = i

if(usr.squad == 7)
squad_7_theme = i

if(usr.squad == 8)
squad_8_theme = i

if(usr.squad == 9)
squad_9_theme = i

if(usr.squad == 10)
squad_10_theme = i

if(usr.squad == 11)
squad_11_theme = i

if(usr.squad == 12)
squad_12_theme = i

if(usr.squad == 13)
squad_13_theme = i
for(var/tmp/mob/m in world)
if(m.squad == usr.squad)
usr << output("Your Captain [usr] has set your squad's theme to [i].","OOC")

if("No")
return

else usr << "<font color = red>Not enough Reputation Points. You currently possess [reppoints]."


Problem description:
For the longest time I've not understood fully saving/loading. I thought I'd finally cracked it, but for some reason, when a player is made a "Captain", and they are given the above Captain obj, an error occures when loading the savefil containing said obj.
Searching.dmb...connected
runtime error: cannot append to list
proc name: LoadPlayer (/mob/verb/LoadPlayer)
source file: Saveing.dm,36
usr: Jin150 (/mob/Player/admin/Jin150)
src: Jin150 (/mob/Player/admin/Jin150)
call stack:
Jin150 (/mob/Player/admin/Jin150): LoadPlayer()

Line 36 is the part of the load code that says "Read(F)". This error only seems to occur when a player has been made a "Captain". Any thoughts guys?
Bumping thread.
Does anyone at least have any idea what "Cannot append to list" means??
heres a save code example and please dont copy and paste it makes things much more complicated
client
Del() //whenever a player logs out
if(src.mob) src.mob.Save() //we want to automaticaly save their character
return ..() //returns to the parent proc (letting any other client Del()s run)

//i manualy save each variable on my save files
//sure it may be a tedious process
//but ive found it to be much more effective then using the built in Read/Write procs
mob/proc
Save()
if(src.z==2) return //we dont want to save them at the title screens!
var/savefile/F = new("Players/[src.key].sav") //creates a new savefile or overwrites an old one
F["LastX"]<<src.x //this saves a variable to the savefile, the << point at where youre sending the data
F["LastY"]<<src.y
F["LastZ"]<<src.z
F["dir"]<<src.dir
F["name"]<<src.name
F["icon_state"]<<src.icon_state
F["Level"]<<src.level
F["Str"]<<src.str
F["Def"]<<src.def
F["MaxHP"]<<src.Maxhp
F["Exp"]<<src.exp
F["Level"]<<src.level
F["Money"]<<src.money
F["contents"]<<src.contents
F["GuildMembers"] << src.Guildmembers//Saves the Guildnmembers list
F["Clan"] << src.guild//Saves what guild the player is in
F["Verbs"] << src.verbs//saves the players verbs
src<<"Game Saved"

Load()
if(fexists("Players/[src.key].sav")) //check if they have a file
//placing a \n in a popup will cause the text to jump to the next line
var/savefile/F = new("Players/[src.key].sav") //load up the players file
var/LastX //these 3 variables are here since you cant directly save a players location
var/LastY
var/LastZ
F["LastX"]>>LastX //this loads a variable from the savefile
F["LastY"]>>LastY
F["LastZ"]>>LastZ
F["dir"]>>src.dir
F["name"]>>src.name
F["icon_state"]>>src.icon_state
F["Level"]>>src.level
F["Str"]>>src.str
F["Def"]>>src.def
F["MaxHP"]>>src.Maxhp
F["Exp"]>>src.exp
F["Level"]<<src.level
F["Money"]>>src.money
F["contents"]>>src.contents
var/verbsave
F["GuildMembers"] >> src.Guildmembers//Loads the Guildmembers list
F["Clan"] >> src.guild//Loads what guild the player is in
F["Verbs"] >> verbsave//Loads the players verbs
src.verbs += verbsave//Adds the loaded verbs to the playe
src.hp=src.Maxhp //refresh em when they log back in
src.loc=locate(LastX,LastY,LastZ)
src<<"Game Loaded"
return 1 //return 1 if the file was loaded
else return 0 //return 0 if there was no file
making it to a verb is also easy
mob/verb
SaveVerb()
usr.Save() //runs the save proc, found in SaveSystem.dm
mob/verb
LoadVerb()
usr.Load() //runs the save proc, found in SaveSystem.dm
I have an issue where my map doesn even show... all I'm getting is a black screen. How would I fix that?
What did I do wrong?

mob/verb/SAVE()
usr<<"YOU SAVED YOUR GAME"
SAVEcharacter()
mob/proc
SAVEcharacter()
var/savefile/F = new("Players/[src.ckey].sav")
F["icname"] << src.icname
F["LastX"] << src.x
F["LastY"] << src.y
F["LastZ"] << src.z
F["mob"] << client.mob
mob/verb/LOAD()
usr<<"YOU SAVED YOUR GAME"
LOADcharacter()
mob/proc
LOADcharacter()
if(fexists("Players/[src.ckey].sav"))
var/savefile/F = new("Players/[client.ckey].sav")
var/LastX
var/LastY
var/LastZ
F["icname"] << src.icname
F["LastX"] >> LastX
F["LastY"] >> LastY
F["LastZ"] >> LastZ
F["mob"] >> client.mob
world<<"YOU LOADED"
winshow(usr,"mainwindow",1)


I dislocated my statpan and when i'm in the game I can see my x,y,z but when I load all the other vars appear but my coord
You're never setting your location back to the variables you're loading to.

src.loc = locate(LastX,LastY,LastZ)


(You should be using 'src' in that winshow() by the way.)
see i will take you through the tour of code mistake you did
Your Code
mob
proc
Savenow()
if(src.cansave && src.issaveing == 0)
var/savefile/F = new("[src.ckey].sav")
Write(F)
F["i"] << src.image
F["X"] << src.x
F["Y"] << src.y
F["Z"] << src.z

Its correct but you have to define the X,Y,Z thing
atom/var
X
Y
Z


Your Load Proc
mob
verb
LoadPlayer()
set hidden = 1
if(src.canload == 0)return
if(fexists("[src.ckey].sav"))

var/savefile/F = new("[src.ckey].sav")
Read(F)
var/image/i = new/image(F["i"],src)
src.image = i
src << i
world<<output("<font size=1><font color=green><B>Info: <font color=white>[src]([src.key]) has loaded a character...","info")
src.loc = locate(F["X"],F["Y"],F["Z"])

How the thing should be
mob
verb
LoadPlayer()
set hidden = 1
if(src.canload == 0)return
if(fexists("[src.ckey].sav"))

var/savefile/F = new("[src.ckey].sav")
Read(F)
var/image/i = new/image(F["i"],src)
src.image = i
src << i
//the biggest mistake is you are not loading his last x,y,z place where he should spawn is this
F["X"]>>src.X
F["Y"]>>src.Y
F["Z"]>>src.Z
world<<output("<font size=1><font color=green><B>Info: <font color=white>[src]([src.key]) has loaded a character...","info")
src.loc = locate(F["x"],F["y"],F["z"])
//or you can even do this
//src.loc=locate(X,Y,Z)

Jesus christ, is this awful advice day?
I tried that above and it didn't work
In response to Alex Ovide
Alex Ovide wrote:
I tried that above and it didn't work

I'll help out when i get home. I normally wouldn't say this in public, but i've gotten on tarun for the quality of his advice in the past and he straight up doesn't care. Best to not listen to him. There's a lot wrong with his example and he's violating basic standards that are explicitly mentioned in the reference. Notably that read and write should never be called manually.
this is what my code looks like now

mob/verb/SAVE()
alert("SAVE VERB")
SAVEcharacter()
mob/proc
SAVEcharacter()
var/savefile/s = new("[src.ckey].sav")
s["icname"] << src.icname
s["x"] << src.x
s["y"] << src.y
s["z"] << src.z
s["mob"] << src
alert("SAVE VERB2")

mob/verb/LOAD()
alert("LOAD VERB")
LOADcharacter()
mob/proc
LOADcharacter()
if(fexists("[src.ckey].sav"))
alert("the code works area 1")
var/savefile/s = new("[src.ckey].sav")
s = new ("[src.ckey].sav")
s["icname"] >> src.icname
s["x"] >> src.x
s["y"] >> src.y
s["z"] >> src.z
s["mob"] >> src
src.loc= locate(s["x"],s["y"],s["z"])
alert("LOAD VERB2")
// winshow(src,"mainwindow",1)
You're loading s["x"], s["y"], and s["z"] to the x, y, and z, variables, which will cause movement each line and end up putting you at an invalid location, remove those 3 lines and keep the 'src.loc = ' line and it should position you properly.

You also don't need the "s = new(...)" line, the line above that handles setting the reference for you.
proc
LoadPlayer(file)
var/mob/m
var/savefile/s = new(file)
s >> m
return m

mob
proc
Save()
var/savefile/s = new("saves/[ckey].sav")
s << src

Write(savefile/F)
..()
F.cd = "saved_location"
F << x
F << y
F << z
F.cd = ".."

Read(savefile/F)
..()
F.cd = "saved_location"
var/ox,oy,oz
F >> ox
F >> oy
F >> oz
loc = locate(ox,oy,oz)
F.cd = ".."


That's it. That's all you have to do. You don't need to specify which variables are saved, because by default, all non-temporary variables are saved. If you have a variable that shouldn't save, mark it tmp.

Every example before this was overly complex and absurdly wrong.

Read my tutorial on saving for further details:

http://www.byond.com/forum/?post=1187245 (part 1)
http://www.byond.com/forum/?post=1187381 (part 2)

Nearly every example on how to save players that has been written in this community has been wrong. It's not as hard as every other saving tutorial makes it out to be.
You don't even really need use F.cd.

F["saved_location/x"] << x

Would have been fine, it's always ideal to specify where the data is going, otherwise you're forced to save/load in the same order and it's very easy to screw up and end up having data load into the wrong variable.
You don't even really need use F.cd.

Not using cd requires more tokens during compilation, so I avoid it to reduce the amount of instructions in the function. Also, the more often you specify a buffer, the longer saving and loading takes. It also bloats the file size to put everything in different buffers.

So yeah, overall, if you aren't using the hardcode default behavior, your approach is... Troublesome. Not wrong, but I personally don't prefer it.

otherwise you're forced to save/load in the same order and it's very easy to screw up and end up having data load into the wrong variable.

That's really a non-issue. If you change the buffer structure and wind up with garbage-in, it's your fault.
I can live with a little less optimization for the sake of organization and readability, thank you very much :)
Errr....guys? This thread was about Jin150's problem. I'm pretty sure he's the one who needs help, not Alex Ovide.
In response to CC233
CC233 wrote:
Errr....guys? This thread was about Jin150's problem. I'm pretty sure he's the one who needs help, not Alex Ovide.

Same problem.
Well thank you for the replies, but Tarun, my location loads fine, it wasn't my code that had the location issues.

As for saving every variable manually, wouldn't that achieve exactly the same thing as Read() and Write() ? Also, why should I not call these two procs manually, and how would I go about calling them otherwise?
Page: 1 2