mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-21 04:57:57 +01:00
Refactored underwear to use datum/sprite_accessory/underwear similar to hair and facial_hair.
People may select any underwear (regardless of gender) at a dresser, but not in preferences. random_underwear(gender) will return a random pair of underwear suitable for your gender. Removed an unused variable in sprite_accessory The new_player preferences screen now randomizes character slots for which there is no data (so no more bald, fat, white guys in diapers greeting new players) datum/preferences character settings are randomised at New(). replaced /datum/preferences/proc/randomize_appearance_for(human/H) with /datum/preferences/proc/random_character(), it does the same stuff without the copying to a mob. Basically, now when you want to make a random character you just do var/datum/preferences/A = new(); A.copy_to(human_mob), randomisation of appearance and name will already be done. Easy. Reworked the savefile updating/versioning code to make it easier to work with. I've used it to update underwear preferences to the new system as an example. Signed-off-by: carnie <elly1989@rocketmail.com>
This commit is contained in:
@@ -24,7 +24,6 @@ datum/preferences
|
||||
//doohickeys for savefiles
|
||||
var/path
|
||||
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
|
||||
var/savefile_version = 0
|
||||
|
||||
//non-preference stuff
|
||||
var/warns = 0
|
||||
@@ -45,7 +44,7 @@ datum/preferences
|
||||
var/gender = MALE //gender of character (well duh)
|
||||
var/age = 30 //age of character
|
||||
var/b_type = "A+" //blood type (not-chooseable)
|
||||
var/underwear = 1 //underwear type
|
||||
var/underwear = "Nude" //underwear type
|
||||
var/backbag = 2 //backpack type
|
||||
var/h_style = "Bald" //Hair type
|
||||
var/r_hair = 0 //Hair color
|
||||
@@ -91,11 +90,17 @@ datum/preferences
|
||||
if(istype(C))
|
||||
if(!IsGuestKey(C.key))
|
||||
load_path(C.ckey)
|
||||
if(load_preferences())
|
||||
if(load_character())
|
||||
return
|
||||
gender = pick(MALE, FEMALE)
|
||||
var/loaded_preferences_successfully = load_preferences()
|
||||
if(loaded_preferences_successfully)
|
||||
if(load_character())
|
||||
return
|
||||
//we couldn't load character data so just randomize the character appearance + name
|
||||
random_character() //let's create a random character then - rather than a fat, bald and naked man.
|
||||
real_name = random_name(gender)
|
||||
if(!loaded_preferences_successfully)
|
||||
save_preferences()
|
||||
save_character() //let's save this new random character so it doesn't keep generating new ones.
|
||||
return
|
||||
|
||||
/datum/preferences
|
||||
proc/ShowChoices(mob/user)
|
||||
@@ -157,12 +162,7 @@ datum/preferences
|
||||
|
||||
dat += "<b>Blood Type:</b> [b_type]<BR>"
|
||||
dat += "<b>Skin Tone:</b><BR><a href='?_src_=prefs;preference=s_tone;task=input'>[-s_tone + 35]/220</a><BR>"
|
||||
|
||||
if(gender == MALE)
|
||||
dat += "<b>Underwear:</b><BR><a href ='?_src_=prefs;preference=underwear;task=input'>[underwear_m[underwear]]</a><BR>"
|
||||
else
|
||||
dat += "<b>Underwear:</b><BR><a href ='?_src_=prefs;preference=underwear;task=input'>[underwear_f[underwear]]</a><BR>"
|
||||
|
||||
dat += "<b>Underwear:</b><BR><a href ='?_src_=prefs;preference=underwear;task=input'>[underwear]</a><BR>"
|
||||
dat += "<b>Backpack:</b><BR><a href ='?_src_=prefs;preference=bag;task=input'>[backbaglist[backbag]]</a><BR>"
|
||||
|
||||
|
||||
@@ -497,7 +497,7 @@ datum/preferences
|
||||
if("f_style")
|
||||
f_style = random_facial_hair_style(gender)
|
||||
if("underwear")
|
||||
underwear = rand(1,underwear_m.len)
|
||||
underwear = random_underwear(gender)
|
||||
if("eyes")
|
||||
r_eyes = rand(0,255)
|
||||
g_eyes = rand(0,255)
|
||||
@@ -507,7 +507,7 @@ datum/preferences
|
||||
if("bag")
|
||||
backbag = rand(1,3)
|
||||
if("all")
|
||||
randomize_appearance_for() //no params needed
|
||||
random_character()
|
||||
|
||||
if("input")
|
||||
switch(href_list["preference"])
|
||||
@@ -561,7 +561,7 @@ datum/preferences
|
||||
|
||||
var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_options
|
||||
if(new_underwear)
|
||||
underwear = underwear_options.Find(new_underwear)
|
||||
underwear = new_underwear
|
||||
|
||||
if("eyes")
|
||||
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference") as color|null
|
||||
@@ -591,6 +591,8 @@ datum/preferences
|
||||
gender = FEMALE
|
||||
else
|
||||
gender = MALE
|
||||
underwear = random_underwear(gender)
|
||||
|
||||
|
||||
if("hear_adminhelps")
|
||||
toggles ^= SOUND_ADMINHELP
|
||||
@@ -636,7 +638,10 @@ datum/preferences
|
||||
load_character()
|
||||
|
||||
if("changeslot")
|
||||
load_character(text2num(href_list["num"]))
|
||||
if(!load_character(text2num(href_list["num"])))
|
||||
random_character()
|
||||
real_name = random_name(gender)
|
||||
save_character()
|
||||
|
||||
if("tab")
|
||||
if (href_list["tab"])
|
||||
@@ -645,9 +650,9 @@ datum/preferences
|
||||
ShowChoices(user)
|
||||
return 1
|
||||
|
||||
proc/copy_to(mob/living/carbon/human/character, safety = 0)
|
||||
proc/copy_to(mob/living/carbon/human/character)
|
||||
if(be_random_name)
|
||||
real_name = random_name()
|
||||
real_name = random_name(gender)
|
||||
|
||||
if(config.humans_need_surnames)
|
||||
var/firstspace = findtext(real_name, " ")
|
||||
@@ -679,21 +684,19 @@ datum/preferences
|
||||
character.b_facial = b_facial
|
||||
|
||||
character.s_tone = s_tone
|
||||
|
||||
character.h_style = h_style
|
||||
character.f_style = f_style
|
||||
|
||||
if(underwear > underwear_m.len || underwear < 1)
|
||||
underwear = 1 //I'm sure this is 100% unnecessary, but I'm paranoid... sue me.
|
||||
character.underwear = underwear
|
||||
|
||||
if(backbag > 3 || backbag < 1)
|
||||
backbag = 1 //Same as above
|
||||
character.backbag = backbag
|
||||
|
||||
/*
|
||||
//Debugging report to track down a bug, which randomly assigned the plural gender to people.
|
||||
if(character.gender in list(PLURAL, NEUTER))
|
||||
if(isliving(src)) //Ghosts get neuter by default
|
||||
message_admins("[character] ([character.ckey]) has spawned with their gender as plural or neuter. Please notify coders.")
|
||||
character.gender = MALE
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,51 +1,108 @@
|
||||
//This is the lowest supported version, anything below this is completely obsolete and the entire savefile will be wiped.
|
||||
#define SAVEFILE_VERSION_MIN 8
|
||||
#define SAVEFILE_VERSION_MAX 8
|
||||
|
||||
//handles converting savefiles to new formats
|
||||
//MAKE SURE YOU KEEP THIS UP TO DATE!
|
||||
//If the sanity checks are capable of handling any issues. Only increase SAVEFILE_VERSION_MAX,
|
||||
//this will mean that savefile_version will still be over SAVEFILE_VERSION_MIN, meaning
|
||||
//this savefile update doesn't run everytime we load from the savefile.
|
||||
//This is mainly for format changes, such as the bitflags in toggles changing order or something.
|
||||
//if a file can't be updated, return 0 to delete it and start again
|
||||
//if a file was updated, return 1
|
||||
/datum/preferences/proc/savefile_update()
|
||||
if(savefile_version < 8) //lazily delete everything + additional files so they can be saved in the new format
|
||||
for(var/ckey in preferences_datums)
|
||||
var/datum/preferences/D = preferences_datums[ckey]
|
||||
if(D == src)
|
||||
var/delpath = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/"
|
||||
if(delpath && fexists(delpath))
|
||||
fdel(delpath)
|
||||
break
|
||||
return 0
|
||||
//This is the current version, anything below this will attempt to update (if it's not obsolete)
|
||||
#define SAVEFILE_VERSION_MAX 9
|
||||
|
||||
if(savefile_version == SAVEFILE_VERSION_MAX) //update successful.
|
||||
save_preferences()
|
||||
save_character()
|
||||
return 1
|
||||
return 0
|
||||
/*//This will allow you to print savefiles
|
||||
/client/verb/read_savefile(client/C in clients)
|
||||
var/savefile/S = new /savefile(prefs.path)
|
||||
S.ExportText("/",file("savefile.txt"))
|
||||
*/
|
||||
|
||||
/*
|
||||
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
|
||||
This proc checks if the current directory of the savefile S needs updating
|
||||
It is to be used by the load_character and load_preferences procs.
|
||||
(S.cd=="/" is preferences, S.cd=="/character[integer]" is a character slot, etc)
|
||||
|
||||
if the current directory's version is below SAVEFILE_VERSION_MIN it will simply wipe everything in that directory
|
||||
(if we're at root "/" then it'll just wipe the entire savefile, for instance.)
|
||||
|
||||
if its version is below SAVEFILE_VERSION_MAX but above the minimum, it will load data but later call the
|
||||
respective update_preferences() or update_character() proc.
|
||||
Those procs allow coders to specify format changes so users do not lose their setups and have to redo them again.
|
||||
|
||||
Failing all that, the standard sanity checks are performed. They simply check the data is suitable, reverting to
|
||||
initial() values if necessary.
|
||||
*/
|
||||
/datum/preferences/proc/savefile_needs_update(savefile/S)
|
||||
var/savefile_version
|
||||
S["version"] >> savefile_version
|
||||
|
||||
if(savefile_version < SAVEFILE_VERSION_MIN)
|
||||
S.dir.Cut()
|
||||
return -2
|
||||
if(savefile_version < SAVEFILE_VERSION_MAX)
|
||||
return savefile_version
|
||||
return -1
|
||||
|
||||
/datum/preferences/proc/update_preferences(current_version)
|
||||
return
|
||||
|
||||
//should this proc get fairly long (say 3 versions long),
|
||||
//just increase SAVEFILE_VERSION_MIN so it's not as far behind
|
||||
//SAVEFILE_VERSION_MAX and then delete any obsolete if clauses
|
||||
//from this proc.
|
||||
//It's only really meant to avoid annoying frequent players
|
||||
//if your savefile is 3 months out of date, then 'tough shit'.
|
||||
/datum/preferences/proc/update_character(current_version)
|
||||
if(current_version < 9) //an example, underwear were an index for a hardcoded list, converting to a string
|
||||
if(gender == MALE)
|
||||
switch(underwear)
|
||||
if(1) underwear = "Mens White"
|
||||
if(2) underwear = "Mens Grey"
|
||||
if(3) underwear = "Mens Green"
|
||||
if(4) underwear = "Mens Blue"
|
||||
if(5) underwear = "Mens Black"
|
||||
if(6) underwear = "Mankini"
|
||||
if(7) underwear = "Mens Hearts Boxer"
|
||||
if(8) underwear = "Mens Black Boxer"
|
||||
if(9) underwear = "Mens Grey Boxer"
|
||||
if(10) underwear = "Mens Striped Boxer"
|
||||
if(11) underwear = "Mens Kinky"
|
||||
if(12) underwear = "Mens Red"
|
||||
if(13) underwear = "Nude"
|
||||
else
|
||||
switch(underwear)
|
||||
if(1) underwear = "Ladies Red"
|
||||
if(2) underwear = "Ladies White"
|
||||
if(3) underwear = "Ladies Yellow"
|
||||
if(4) underwear = "Ladies Blue"
|
||||
if(5) underwear = "Ladies Black"
|
||||
if(6) underwear = "Ladies Thong"
|
||||
if(7) underwear = "Babydoll"
|
||||
if(8) underwear = "Ladies Baby-Blue"
|
||||
if(9) underwear = "Ladies Green"
|
||||
if(10) underwear = "Ladies Pink"
|
||||
if(11) underwear = "Ladies Kinky"
|
||||
if(12) underwear = "Tankini"
|
||||
if(13) underwear = "Nude"
|
||||
|
||||
/*
|
||||
if(current_version < 10) //would be the step to upgrade 9 to 10
|
||||
//do stuff
|
||||
if(current_version < 11) //and so on...
|
||||
//more stuff
|
||||
*/
|
||||
|
||||
return
|
||||
|
||||
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
|
||||
if(!ckey) return
|
||||
path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/[filename]"
|
||||
savefile_version = SAVEFILE_VERSION_MAX
|
||||
|
||||
/datum/preferences/proc/load_preferences()
|
||||
if(!path) return 0
|
||||
if(!fexists(path)) return 0
|
||||
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(!S) return 0
|
||||
S.cd = "/"
|
||||
|
||||
S["version"] >> savefile_version
|
||||
//Conversion
|
||||
if(!savefile_version || !isnum(savefile_version) || savefile_version < SAVEFILE_VERSION_MIN || savefile_version > SAVEFILE_VERSION_MAX)
|
||||
if(!savefile_update()) //handles updates
|
||||
savefile_version = SAVEFILE_VERSION_MAX
|
||||
save_preferences()
|
||||
save_character()
|
||||
return 0
|
||||
|
||||
var/needs_update = savefile_needs_update(S)
|
||||
if(needs_update == -2) //fatal, can't load any data
|
||||
return 0
|
||||
|
||||
//general preferences
|
||||
S["ooccolor"] >> ooccolor
|
||||
@@ -55,6 +112,10 @@
|
||||
S["default_slot"] >> default_slot
|
||||
S["toggles"] >> toggles
|
||||
|
||||
//try to fix any outdated data if necessary
|
||||
if(needs_update >= 0)
|
||||
update_preferences(needs_update) //needs_update = savefile_version if we need an update (positive integer)
|
||||
|
||||
//Sanitize
|
||||
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
|
||||
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
||||
@@ -71,7 +132,7 @@
|
||||
if(!S) return 0
|
||||
S.cd = "/"
|
||||
|
||||
S["version"] << savefile_version
|
||||
S["version"] << SAVEFILE_VERSION_MAX //updates (or failing that the sanity checks) will ensure data is not invalid at load. Assume up-to-date
|
||||
|
||||
//general preferences
|
||||
S["ooccolor"] << ooccolor
|
||||
@@ -94,7 +155,11 @@
|
||||
if(slot != default_slot)
|
||||
default_slot = slot
|
||||
S["default_slot"] << slot
|
||||
|
||||
S.cd = "/character[slot]"
|
||||
var/needs_update = savefile_needs_update(S)
|
||||
if(needs_update == -2) //fatal, can't load any data
|
||||
return 0
|
||||
|
||||
//Character
|
||||
S["OOC_Notes"] >> metadata
|
||||
@@ -130,12 +195,24 @@
|
||||
S["job_engsec_med"] >> job_engsec_med
|
||||
S["job_engsec_low"] >> job_engsec_low
|
||||
|
||||
//try to fix any outdated data if necessary
|
||||
if(needs_update >= 0)
|
||||
update_character(needs_update) //needs_update == savefile_version if we need an update (positive integer)
|
||||
|
||||
//Sanitize
|
||||
metadata = sanitize_text(metadata, initial(metadata))
|
||||
real_name = reject_bad_name(real_name)
|
||||
if(!real_name) real_name = random_name()
|
||||
if(!real_name) real_name = random_name(gender)
|
||||
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
|
||||
gender = sanitize_gender(gender)
|
||||
if(gender == MALE)
|
||||
h_style = sanitize_inlist(h_style, hair_styles_male_list)
|
||||
f_style = sanitize_inlist(f_style, facial_hair_styles_male_list)
|
||||
underwear = sanitize_inlist(underwear, underwear_m)
|
||||
else
|
||||
h_style = sanitize_inlist(h_style, hair_styles_female_list)
|
||||
f_style = sanitize_inlist(f_style, facial_hair_styles_female_list)
|
||||
underwear = sanitize_inlist(underwear, underwear_f)
|
||||
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
|
||||
r_hair = sanitize_integer(r_hair, 0, 255, initial(r_hair))
|
||||
g_hair = sanitize_integer(g_hair, 0, 255, initial(g_hair))
|
||||
@@ -144,12 +221,9 @@
|
||||
g_facial = sanitize_integer(g_facial, 0, 255, initial(g_facial))
|
||||
b_facial = sanitize_integer(b_facial, 0, 255, initial(b_facial))
|
||||
s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone))
|
||||
h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style))
|
||||
f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style))
|
||||
r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes))
|
||||
g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes))
|
||||
b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes))
|
||||
underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear))
|
||||
backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag))
|
||||
|
||||
userandomjob = sanitize_integer(userandomjob, 0, 1, initial(userandomjob))
|
||||
@@ -170,6 +244,8 @@
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(!S) return 0
|
||||
S.cd = "/character[default_slot]"
|
||||
|
||||
S["version"] << SAVEFILE_VERSION_MAX //load_character will sanitize any bad data, so assume up-to-date.
|
||||
|
||||
//Character
|
||||
S["OOC_Notes"] << metadata
|
||||
|
||||
Reference in New Issue
Block a user