ID:2029601
 
(See the best response by Ter13.)
Code:
var/list/_races = list("Human"=/mob/characters/Human, "Mage"=/mob/characters/Mage) //obviously, modify this to suit your races.

client
proc
Save()
if(mob.savable)
var/savefile/savefile = new("players/[copytext(ckey, 1, 2)]/[ckey].sav")
savefile["/[ckey]/[ckey(mob.name)]"] << mob

mob/other/choosing_character
var
list/characters = list()
savefile/savefile
Login()
client.eye = locate(rand(1,150),rand(1,150),1)
client.perspective = EYE_PERSPECTIVE
spawn()
ChooseCharacter()

proc
ChooseCharacter()
//we don't need to reload the savefile more than once. Store it and keep the chars list around
savefile = new("players/[copytext(ckey, 1, 2)]/[ckey].sav")
savefile.cd = "/[ckey]"
characters = savefile.dir
var/list/menu //it's best to define these outside of a loop where possible. There are reasons.
var/result
while(client)
menu = characters + "New Character" + "Delete Character"

result=input("Choose an option", "One Punch Man") as anything in menu
switch(result)
if("New Character")
CreateNewCharacter()
if("Delete Character")
DeleteCharacter()
else
LoadCharacter(result)

DeleteCharacter()
var/result = input("Delete character", "Character Creation") as null|anything in characters

if (result)
savefile.dir.Remove(result)
characters -= result

CreateNewCharacter()
var/char_name
do
char_name = input(src, "What is your name?","New Character") as null|text
if(!char_name)
return
if (ckey(char_name) in characters)
alert("This name isn't acceptable.")
char_name = null
while(!char_name)

var/char_race = input(src, "What race do you wish to be?", "New Character", "Human", "Mage") in _races
var/rtype = _races[char_race]
var/mob/new_mob = new rtype()
if(prob(10))
src<<"You were born with some of saitamas bloos inside of you, giving you the potential to be like him!"
src.potential = "All"
else
src<<"You were born as a commoner, tough luck!"
src.potential = "???"
play_cutscene()
new_mob.client = client //after creating the new character, you need to set the new mob's client to end the character creation process and suspend the loop.
new_mob.savable = 1
new_mob.name = char_name
savefile[ckey(char_name)] << new_mob //save the character in the savefile before this mob is garbage collected.

LoadCharacter(char)
var/mob/m
savefile[char] >> m
m.savable = 1 //shouldn't be necessary, but in case you don't want to purge your savefiles.
if(client) m.client = client //this should never happen, but just in case something goes wrong we'll put it here anyway to be safe


mob
var
savable = 0

Login()
src.loc=locate(44,39,1)
src.icon_state = ""
src.sight = 0
client.eye = src
client.perspective = MOB_PERSPECTIVE
src << output("<b><font color = red>Welcome to One Punch Man The Game, we owe no affiliation to one punch man so don't sue us XD</font>","system")
world << output("<font color=purple><b>[usr.name] has joined the ranks</b></font>", "chatbox")
sample_report()

Logout()
if(client)
client.Save()
del src

Write(savefile/F)
if(!savable) return
..()

F["last_x"] << x
F["last_y"] << y
F["last_z"] << z

Read(savefile/F)
..()

var/last_x
var/last_y
var/last_z
F["last_x"] >> last_x
F["last_y"] >> last_y
F["last_z"] >> last_z
loc = locate(last_x, last_y, last_z)

proc
sample_report()
src << output("<b><font size = 1><font color = silver><center>By: Dragonpear321","system")
src << output("<b>Beta Testing One Punch Man","system")


Problem description:
So all of a sudden it just stopped saving, the location stats level do not save, the only thing that saves is the name(Yeah I know the probability thing isn't going to work)!
client is null in Logout(), so this approach isn't going to work.

Although it's not relevant to your issue, you also have usr abuse in Login().
I think that's my bad.

...That's really irritating, actually. There's no way to reliably detect which client the mob lost during logout()...
Best response
var/list/_races = list("Human"=/mob/characters/Human, "Mage"=/mob/characters/Mage) //obviously, modify this to suit your races.

client
var/tmp
mob/oldmob
proc
Save()
if(oldmob&&oldmob.savable)
var/savefile/savefile = new("players/[copytext(ckey, 1, 2)]/[ckey].sav")
savefile["/[ckey]/[ckey(mob.name)]"] << oldmob
Del()
Save()
..()

mob/other/choosing_character
var
list/characters = list()
savefile/savefile
Login()
client.eye = locate(rand(1,150),rand(1,150),1)
client.perspective = EYE_PERSPECTIVE
spawn()
ChooseCharacter()

proc
ChooseCharacter()
//we don't need to reload the savefile more than once. Store it and keep the chars list around
savefile = new("players/[copytext(ckey, 1, 2)]/[ckey].sav")
savefile.cd = "/[ckey]"
characters = savefile.dir
var/list/menu //it's best to define these outside of a loop where possible. There are reasons.
var/result
while(client)
menu = characters + "New Character" + "Delete Character"

result=input("Choose an option", "One Punch Man") as anything in menu
switch(result)
if("New Character")
CreateNewCharacter()
if("Delete Character")
DeleteCharacter()
else
LoadCharacter(result)

DeleteCharacter()
var/result = input("Delete character", "Character Creation") as null|anything in characters

if (result)
savefile.dir.Remove(result)
characters -= result

CreateNewCharacter()
var/char_name
do
char_name = input(src, "What is your name?","New Character") as null|text
if(!char_name)
return
if (ckey(char_name) in characters)
alert("This name isn't acceptable.")
char_name = null
while(!char_name)

var/char_race = input(src, "What race do you wish to be?", "New Character", "Human", "Mage") in _races
var/rtype = _races[char_race]
var/mob/new_mob = new rtype()
if(prob(10))
src<<"You were born with some of saitamas bloos inside of you, giving you the potential to be like him!"
src.potential = "All"
else
src<<"You were born as a commoner, tough luck!"
src.potential = "???"
play_cutscene()
new_mob.client = client //after creating the new character, you need to set the new mob's client to end the character creation process and suspend the loop.
new_mob.savable = 1
new_mob.name = char_name
savefile[ckey(char_name)] << new_mob //save the character in the savefile before this mob is garbage collected.

LoadCharacter(char)
var/mob/m
savefile[char] >> m
m.savable = 1 //shouldn't be necessary, but in case you don't want to purge your savefiles.
if(client) m.client = client //this should never happen, but just in case something goes wrong we'll put it here anyway to be safe


mob
var
savable = 0

Login()
if(client.oldmob) client.Save()
client.oldmob = src
src.loc=locate(44,39,1)
src.icon_state = ""
src.sight = 0
client.eye = src
client.perspective = MOB_PERSPECTIVE
src << output("<b><font color = red>Welcome to One Punch Man The Game, we owe no affiliation to one punch man so don't sue us XD</font>","system")
world << output("<font color=purple><b>[usr.name] has joined the ranks</b></font>", "chatbox")
sample_report()

Logout()
del src

Write(savefile/F)
if(!savable) return
..()

F["last_x"] << x
F["last_y"] << y
F["last_z"] << z

Read(savefile/F)
..()

var/last_x
var/last_y
var/last_z
F["last_x"] >> last_x
F["last_y"] >> last_y
F["last_z"] >> last_z
loc = locate(last_x, last_y, last_z)

proc
sample_report()
src << output("<b><font size = 1><font color = silver><center>By: Dragonpear321","system")
src << output("<b>Beta Testing One Punch Man","system")


I'm like, 20% sure that should fix the problem.
In response to Ter13
Thanx and all (and im really greateful), but why are u making an old mob?

Edit:Also got this runetime error: runtime error: Cannot read .client
proc name: LoadCharacter (/mob/other/choosing_character/proc/LoadCharacter)
source file: Start.dm,97
usr: null
src:
call stack:
LoadCharacter("asca")
ChooseCharacter()
Login()
Uh... that... Wow. I've never seen that runtime error in quite that way before. I'm kind of at a loss here.

why are u making an old mob?

To bypass what I consider to be a botched implementation based on BYOND's rather asinine client handling flow.

Login() <- client has already left the mob.

Logout() <- client has already left the mob.

The lifetime should have parity. Login() is the entry point, and Logout() is the exit point.

For Login() to happen after the client's initialization, and for Logout() to happen after the client's destruction means that there is no parity to the lifecycle.

Good programming is as much about good grammar as it is mathematics. Parity is a GOP/GOOD principles (Grammar Oriented Programming) and (Grammar-Oriented Object Design). These are two subjects that I personally believe sort out a good API/language from a bad one. Unfortunately, BYOND falls rather short of this in several places because I don't believe GOP/GOOD were ever subjects of study for either Dan/Tom or Lummox.

There are several ways you can have parity in an architecture. You can have temporal parity, in which the grammar informs the relationship between functions by relating them to tense grammar patterns:

I.E. Exit() and Exited(). That's temporal parity. These two functions are related in that Exit() is called as the Exit is functioning, and Exited() is called after the Exit has functioned.

Then there's another form of parity where you have antonyms to describe a lifecycle:

I.E. New() and Del(), or Login() and Logout(). These two function are related in that they deal with the beginning or end of a temporary behavior cycle for something.

New() is called after the object has already been created, and Del() is called shortly before the object will be destroyed. These have an inner-parity, in that if you look at the lifecycle:

Object is created -> New() calls -> stuff happens -> Del() calls -> Object is deleted.

The cycle is a mirror image of itself, in that the events happen according to a sequence wherein one function's position in the temporal chain mirrors the other's.

When you have bad design, though, something like this happens:

Client connects to mob -> Login() calls -> stuff happens -> client disconnects from mob -> Logout() calls

You see, the temporal chain is all out of order and doesn't respect parity. If we want Login() and Logout() to be antonyms of one another, we can't because Login() may rely on the client being there already, so anything that needs to be undone that was done in Login() can't be undone in Logout() because the client is already gone. This is the consequence of refusing to obey parity as a firm rule. Your userbase will assume the opposite action will logically be valid in the function's antonym, but because you are a giant dingus, your users are wrong, make an assumption, and then break everything.

TL;DR:

Tracking the last mob connected to a client allows us to bypass the problem of a mobswap preventing saving of the character, while also accounting for the problems related to client.

I have no idea what that runtime error is, though. Which is line 97?
In response to Ter13
LoadCharacter(char)
var/mob/m
savefile[char] >> m
m.savable = 1 //shouldn't be necessary, but in case you don't want to purge your savefiles.
if(client) m.client = client //this should never happen, but just in case something goes wrong we'll put it here anyway to be safe

The last line is line 97. If that should theoretically never happen would it be better to remove it permanently.
Um... Yeah, do you have more than one runtime error? Because if that line errored, it should have been erroring before line 97. The only way that line 97 could have runtimed like that is if m is failing to load completely, in which case something is wrong with that savefile and line 96 should have thrown an error too.
In response to Ter13
Well if Ter13 can't figure it out then I might as well recycle it, the whole game was a failure anyway with my limited knowledge, thanks for taking your time to help though!
Well, this is actually sort of my fault. I believe that's my code. I can figure it out, it's just gonna take a minute or two to figure out what's wrong. Try temporarily moving the savefile and starting the account fresh to see if it is still happening. My guess is that my flawed approach led to something going awry and we're dealing with the consequences of flailing.
In response to Ter13
So I removed line 97 and miraculously everything worked! No rune time error or anything, that's probably a bug that should be looked into!
That's completely bizarre. Then again, you are giving me too much credit for not being able to figure it out. Apparently, I wasn't aware of the lack of parity on Login()/Logout() despite 15 years' experience with DM.

That's deeply troubling. I kind of wonder how much bad advice and how many buggy lines of code I wrote not knowing about that problem.