ID:2076939
 
(See the best response by Nadrew.)
I am almost finished with my test project before I begin to work on my real project. I have scoured the internet and forums looking for a way to name your character, set an auto save to save your information when you log out, and a way to log in and log out. From what I have found to make a title screen you use another map layer, add a background with New and Login and create a turf, area, or object, and put it over the words.


What I want is when you hit New, for an alert to come up asking you to name your character, that only appears the first time you log in. Then I want a log out verb that saves your character as you log out and sends you back to the title screen.

I appreciate any help.
-BIGBROYO
Maybe this will help you help me.


Code:
mob
var
savefile/F = new("SF/playerdata")

Logout()
var/savefile/F = new(ckey)
Write(F)
del(src)

Login()
var/savefile/F = new(ckey)
Read(F)
return ..()


What's happening is a file named guest308764653.file is appearing in my projects folder instead of in the SF folder, while the playerdata.file is appearing in the SF folder every time I run the game.

I have a code that asks you to name yourself on log in. However it continues to ask even though there are save files. I don't know if it's my save file coding that is wrong, if I am missing something, or my name coding is wrong.
Code:
    Login()
loc = locate(/turf/start)
while (!usr_name)
usr_name = input(src, "What would you like to be your name?", "Name")

name = "[usr_name]"

src << "Your name is [name]."
return ..()


Hope this helps you help me.

-BIGBROYO
Best response
Your problem is that you're defining F as both as local variable and a mob variable. You can remove the first definition under /mob entirely. The path of the file is defined as the argument of savefile/New().

Nextly you shouldn't be calling Read() and Write() directly, instead you should rely on the behavior of the << and >> operators when applied to savefiles.

mob
Login()
if(fexists("SF/[src.ckey].sav"))
var/savefile/F = new("SF/[src.ckey].sav")
F["player"] >> src
else
// No previous save, do stuff here
..()

Logout()
var/savefile/F = new("SF/[src.ckey].sav")
F["player"] << src
del(src)


You'll notice above that I included a comment where the code is reached if the player doesn't have a previous save, this is where you'd want to handle naming and things of that nature.

Of course this is just a basic example of things, there's a lot of better ways to go about this, such as defining procs to handle saving and loading and calling those as needed (which allows easier saving and loading in multiple places in the code), and defining multiple mob types to better handle situations before and after the player has been loaded. That comes later on though, once you've gotten a better handle on the basic concepts like the above.
That worked perfectly. I am still sort of new so I do not quite understand the << and >> operators yet. Would the DM guide be a good place to brush up on what exactly they would do in this situation? I don't understand what they are doing. everything else in your code makes sense to me.

Thanks for the help! I really appreciate it, this post has been here for like 2 days now.

-BIGBROYO
Now I'm running into another problem. Two scenarios: if I use the /turf/start in the code below and run it and it starts out fine, then instead of saving the x,y,z loc it returns to the /turf/start instead of to the saved location, if I run it one more time it gives me a black screen for a map. The second scenario is not using the /turf/start, the first time I run it it works fine starting at 1,1,1 the second time it's a black screen for my map just like the 3rd time from the previous scenario.

Code:
mob
Login()
loc = locate(/turf/start)
if(fexists("SF/[src.ckey].sav"))
var/savefile/F = new("SF/[src.ckey].sav")
var/X,Y,Z
F["player"] >> src
F["temp_x"] >> X
F["temp_y"] >> Y
F["temp_z"] >> Z
loc = locate(X, Y, Z)
else
var
usr_name = src.ckey
usr_name = input(src, "What would you like to be your name?", "Name")
name = "[usr_name]"
src << "Your name is [name]."
return ..()
..()

Logout()
var/savefile/F = new("SF/[src.ckey].sav")
var/X,Y,Z
F["player"] << src
F["temp_x"] << X
F["temp_y"] << Y
F["temp_z"] << Z
loc = locate(X,Y,Z)
del(src)
..()


Any help will be appreciated.

-BIGBROYO
You're saving nothing for the location, inside of Logout() instead of using X, Y, Z, you can ditch those variables and use x, y, z (note the lowercase) to save the location. You also don't need the locate() inside of Logout(). Now inside of Login() you're pretty much correct, you should be checking if X, Y, and Z have values before moving the player to them though, and if they don't you move them to a default location.
In response to Nadrew
Nadrew wrote:
you should be checking if X, Y, and Z have values before moving the player to them though, and if they don't you move them to a default location.

This part confused me a bit. I did my best guess and I am still having a black screen problem.

Code:
mob
Login()
if(fexists("SF/[src.ckey].sav"))
var/savefile/F = new("SF/[src.ckey].sav")
var/X,Y,Z
F["player"] >> src
F["temp_x"] >> X
F["temp_y"] >> Y
F["temp_z"] >> Z
loc = locate(X, Y, Z)
else
var
usr_name = src.ckey
usr_name = input(src, "What would you like to be your name?", "Name")
name = "[usr_name]"
src << "Your name is [name]."
loc = locate(/turf/start)
return ..()
..()

Logout()
var/savefile/F = new("SF/[src.ckey].sav")
var/x,y,z
F["player"] << src
F["temp_x"] << x
F["temp_y"] << y
F["temp_z"] << z
del(src)
..()

You should try outputting the values of X, Y, and Z to see if they're being set as you expected. You don't need ..() in Logout() either, but from the looks of the code you posted, ..() isn't even in the block it should be (it's not indented far enough in either proc).

Are you having a black screen the first time you login without a save or is it only happening after a save and reload?
I am having the black screen when loading a save. I know it is a save because it saves the name of the character and I have say/ooc verbs to use to check it.

When I indent ..() once it gives me an indentation error. Is it supposed to be within the else branch? That does not make sense to me.

-BIGBROYO
So I edited the code a bit and found a different solution. Basically I had to get rid of the var F in the Login. It was causing the black screen. Then I just put in coordinates for the spawn if existing file was found and it worked.

Here it is in code

Code:
mob
Login()
if(fexists("SF/[src.ckey].sav"))
loc = locate(29, 1, 1)
else
var
usr_name = src.ckey
usr_name = input(src, "What would you like to be your name?", "Name")
name = "[usr_name]"
src << "Your name is [name]."
loc = locate(/turf/start)
return ..()
..()

Logout()
var/savefile/F = new("SF/[src.ckey].sav")
F["player"] >> src
del(src)
..()

Except now you're not loading anything. You should have kept what you had and output the values being pulled from the save so you'd know why it wasn't loading your location properly. At this point it seems like you're working backwards and not really understanding the concepts I'm trying to teach you. I recommend reading the DM Guide.
A few things:

1) Your ..() calls aren't indented far enough. I would also advise calling ..() right up front in Login(), not at the end.

2) For clarity, change usr_name to user_name, just so you don't get tempted to put usr in procs.

3) Make sure you provide src.key as the default choice for the player's name.

4) Look for name conflicts; you don't want two users running around with the same name. You might need to track that in a separate savefile.

I would also suggest changing up your login scheme, so that you don't have to do the fexists() check. Basically here's what you do:

world/mob = /mob/newplayer

mob/newplayer
Login()
..()
loc = locate(/turf/start)

var/mob/player/M = new // start building a new player mob
// ask name, etc., or load from a file
...
M.key = key // switch over to the new mob

// do not call ..() here
Logout()
key = null
loc = null

mob/player
var/tmp/savekey

Login()
..()
savekey = ckey // hold onto this in case ckey gets lost in Logout()
loc = locate(29,1,1) // you may want to use a tag instead of raw coords

Logout()
Save(savekey)
del(src)

In this example, /mob/newplayer is a temporary mob used when you're logging in. It handles your character creation process. /mob/player handles the actual players. The two types are siblings, so they don't inherit from one another.
Ok, I have read the DM guide and tried using Lummox's method.

question:

why aren't you using read() write() and when does it call for this?

What is an expected end of statement error?

What do you mean in your comment where you say "you may want to use a tag instead of raw coords"

Here is my code so far

world/mob=/mob/player

wold/mob = /mob/newplayer

mob/newplayer
Login()
..()
loc = locate(/turf/start)
var/mob/player/M = new
user_name = src.ckey
user_name = input(src, "What would you like to be your name?", "Name")
Name = "[user_name]"
src << "Your name is [Name]."
...
M.key = key

Logout()
key = null
loc = null

mob/player
var/tmp/savekey

Login()
..()
savekey = ckey
loc = locate(29,1,1)

Logout()
Save(savekey)
del(src)


I am getting a expected end of statement error on line 14 where ... is.
In response to BIGBROYO
BIGBROYO wrote:
why aren't you using read() write() and when does it call for this?

I didn't show that part, but basically a load would open a savefile and use the >> operator, and a save would open a savefile and use <<

What do you mean in your comment where you say "you may want to use a tag instead of raw coords"

I mean for instance what if you move things around so players who just loaded up don't start at 29,1,1 necessarily. If you set the tag var for the turf where you want them to start, for instance setting it to "spawn_turf", then locate("spawn_turf") will find it for you. It's just a way of future-proofing your code.

I am getting a expected end of statement error on line 14 where ... is.

That's because the ... wasn't actual code; it's just a placeholder for code you would fill in.
In response to Lummox JR
Lummox JR wrote:
That's because the ... wasn't actual code; it's just a placeholder for code you would fill in.


Sorry I should have said this before. I had already tried getting rid of it, if I do I get the same error for the line below :

code\save.dm:16:error: M: expected end of statement

Here's what I have:

world/mob=/mob/player


mob/newplayer
Login()
..()
loc = locate(/turf/start)
var/mob/player/M = new
user_name = src.ckey
user_name = input(src, "What would you like to be your name?", "Name")
if(user_name==T)
usr << "That name is taken."
else
Name = "[user_name]"
src << "Your name is [Name]."
M.key = key

Logout()
key = null
loc = null

mob/player
var/tmp/savekey

Login()
..()
savekey = ckey
loc = locate(29,1,1)

Logout()
Save(savekey)
del(src)
Your indentation is still off. BYOND is very picky about how far you indent things, from the looks of things everything below user_name = src.ckey (which isn't what Lummox was talking about) is indented too far.

Looking at the code though, you've taken what Lummox showed you and completely broke it, you're taking multiple concepts and blending them together incorrectly. We can't really help you if you aren't grasping even the basics of the language.
In response to Nadrew
Nadrew wrote:
Your indentation is still off. BYOND is very picky about how far you indent things, from the looks of things everything below user_name = src.ckey (which isn't what Lummox was talking about) is indented too far.

Looking at the code though, you've taken what Lummox showed you and completely broke it, you're taking multiple concepts and blending them together incorrectly. We can't really help you if you aren't grasping even the basics of the language.

You are right. If I do not understand then I have no choice but to work on understanding the "basics". I have read and reread multiple tutorials and the DM guide, as well as worked with DM reference. Most of them are not exactly "user friendly" if even the correct way to go about it, and even more are poorly done. I appreciate the constructive criticism however. I want to be a coder and saving is my last hurdle before completing my first game and beginning work on my real project. If you have any tips, resources, or advice to share I would greatly appreciate it.

I tried working on the indentations and that just caused more errors. I thought I could take a break from it and come back and get it done, but apparently I have more learning to do. For now I will put this on hold and work on something even more basic, my hair verb.

Thanks

-BIGBROYO


PS-I know the name check is wrong as is, I just wanted to show you guys what I had so far.
BIGBROYO wrote:
You are right. If I do not understand then I have no choice be to work on understanding the "basics". I have read and reread multiple tutorials and the DM guide, as well as worked with DM reference. Most of them are not exactly "user friendly" if even the correct way to go about it, and even more are poorly done. I appreciate the constructive criticism however.

I tried getting rid of the in

The guide is outdated, but the basics are more or less the same. I'm glad you're aware of the DM reference, because I'm going to help you with a small part of what Lummox suggested and how it was misunderstood.

Lummox JR wrote:
3) Make sure you provide src.key as the default choice for the player's name.

He wasn't saying to make the variable src.key by default as you did here:
user_name = src.ckey

He was talking about the optional value within input(Usr=usr,Message,Title,Default)
user_name = input(src, "What would you like to be your name?", "Name", src.key)