mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Adds client verb to access the character setup screen from anywhere. Moves name validation to species level, making it possible for IPCs to have numbers in their name. Adds gender validation, also adds support to add neuter/plural genders in the future if ever desired. Now sanitizes preferences before applying them to a mob. Fixes #11433. (cherry picked from commit e40246e9dfc9feb28b8c5a0a7ce765fd063c4f7e)
369 lines
11 KiB
Plaintext
369 lines
11 KiB
Plaintext
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
|
|
|
|
var/list/preferences_datums = list()
|
|
|
|
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
|
|
var/muted = 0
|
|
var/last_ip
|
|
var/last_id
|
|
|
|
//game-preferences
|
|
var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
|
|
var/ooccolor = "#010000" //Whatever this is set to acts as 'reset' color and is thus unusable as an actual custom color
|
|
var/be_special = 0 //Special role selection
|
|
var/UI_style = "Midnight"
|
|
var/toggles = TOGGLES_DEFAULT
|
|
var/UI_style_color = "#ffffff"
|
|
var/UI_style_alpha = 255
|
|
|
|
//character preferences
|
|
var/real_name //our character's name
|
|
var/be_random_name = 0 //whether we are a random name every round
|
|
var/gender = MALE //gender of character (well duh)
|
|
var/age = 30 //age of character
|
|
var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2).
|
|
var/b_type = "A+" //blood type (not-chooseable)
|
|
var/underwear //underwear type
|
|
var/undershirt //undershirt type
|
|
var/backbag = 2 //backpack type
|
|
var/h_style = "Bald" //Hair type
|
|
var/r_hair = 0 //Hair color
|
|
var/g_hair = 0 //Hair color
|
|
var/b_hair = 0 //Hair color
|
|
var/f_style = "Shaved" //Face hair type
|
|
var/r_facial = 0 //Face hair color
|
|
var/g_facial = 0 //Face hair color
|
|
var/b_facial = 0 //Face hair color
|
|
var/s_tone = 0 //Skin tone
|
|
var/r_skin = 0 //Skin color
|
|
var/g_skin = 0 //Skin color
|
|
var/b_skin = 0 //Skin color
|
|
var/r_eyes = 0 //Eye color
|
|
var/g_eyes = 0 //Eye color
|
|
var/b_eyes = 0 //Eye color
|
|
var/species = "Human" //Species datum to use.
|
|
var/species_preview //Used for the species selection window.
|
|
var/list/alternate_languages = list() //Secondary language(s)
|
|
var/list/language_prefixes = list() //Kanguage prefix keys
|
|
var/list/gear //Custom/fluff item loadout.
|
|
|
|
//Some faction information.
|
|
var/home_system = "Unset" //System of birth.
|
|
var/citizenship = "None" //Current home system.
|
|
var/faction = "None" //Antag faction/general associated faction.
|
|
var/religion = "None" //Religious association.
|
|
|
|
//Mob preview
|
|
var/icon/preview_icon = null
|
|
var/icon/preview_icon_front = null
|
|
var/icon/preview_icon_side = null
|
|
|
|
//Jobs, uses bitflags
|
|
var/job_civilian_high = 0
|
|
var/job_civilian_med = 0
|
|
var/job_civilian_low = 0
|
|
|
|
var/job_medsci_high = 0
|
|
var/job_medsci_med = 0
|
|
var/job_medsci_low = 0
|
|
|
|
var/job_engsec_high = 0
|
|
var/job_engsec_med = 0
|
|
var/job_engsec_low = 0
|
|
|
|
//Keeps track of preferrence for not getting any wanted jobs
|
|
var/alternate_option = 0
|
|
|
|
var/used_skillpoints = 0
|
|
var/skill_specialization = null
|
|
var/list/skills = list() // skills can range from 0 to 3
|
|
|
|
// maps each organ to either null(intact), "cyborg" or "amputated"
|
|
// will probably not be able to do this for head and torso ;)
|
|
var/list/organ_data = list()
|
|
var/list/rlimb_data = list()
|
|
var/list/player_alt_titles = new() // the default name of a job like "Medical Doctor"
|
|
|
|
var/list/flavor_texts = list()
|
|
var/list/flavour_texts_robot = list()
|
|
|
|
var/med_record = ""
|
|
var/sec_record = ""
|
|
var/gen_record = ""
|
|
var/exploit_record = ""
|
|
var/disabilities = 0
|
|
|
|
var/nanotrasen_relation = "Neutral"
|
|
|
|
var/uplinklocation = "PDA"
|
|
|
|
// OOC Metadata:
|
|
var/metadata = ""
|
|
|
|
var/client/client = null
|
|
|
|
var/datum/category_collection/player_setup_collection/player_setup
|
|
|
|
/datum/preferences/New(client/C)
|
|
player_setup = new(src)
|
|
gender = pick(MALE, FEMALE)
|
|
real_name = random_name(gender,species)
|
|
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
|
|
|
|
gear = list()
|
|
|
|
if(istype(C))
|
|
client = C
|
|
if(!IsGuestKey(C.key))
|
|
load_path(C.ckey)
|
|
if(load_preferences())
|
|
if(load_character())
|
|
return
|
|
|
|
/datum/preferences/proc/ZeroSkills(var/forced = 0)
|
|
for(var/V in SKILLS) for(var/datum/skill/S in SKILLS[V])
|
|
if(!skills.Find(S.ID) || forced)
|
|
skills[S.ID] = SKILL_NONE
|
|
|
|
/datum/preferences/proc/CalculateSkillPoints()
|
|
used_skillpoints = 0
|
|
for(var/V in SKILLS) for(var/datum/skill/S in SKILLS[V])
|
|
var/multiplier = 1
|
|
switch(skills[S.ID])
|
|
if(SKILL_NONE)
|
|
used_skillpoints += 0 * multiplier
|
|
if(SKILL_BASIC)
|
|
used_skillpoints += 1 * multiplier
|
|
if(SKILL_ADEPT)
|
|
// secondary skills cost less
|
|
if(S.secondary)
|
|
used_skillpoints += 1 * multiplier
|
|
else
|
|
used_skillpoints += 3 * multiplier
|
|
if(SKILL_EXPERT)
|
|
// secondary skills cost less
|
|
if(S.secondary)
|
|
used_skillpoints += 3 * multiplier
|
|
else
|
|
used_skillpoints += 6 * multiplier
|
|
|
|
/datum/preferences/proc/GetSkillClass(points)
|
|
return CalculateSkillClass(points, age)
|
|
|
|
/proc/CalculateSkillClass(points, age)
|
|
if(points <= 0) return "Unconfigured"
|
|
// skill classes describe how your character compares in total points
|
|
points -= min(round((age - 20) / 2.5), 4) // every 2.5 years after 20, one extra skillpoint
|
|
if(age > 30)
|
|
points -= round((age - 30) / 5) // every 5 years after 30, one extra skillpoint
|
|
switch(points)
|
|
if(-1000 to 3)
|
|
return "Terrifying"
|
|
if(4 to 6)
|
|
return "Below Average"
|
|
if(7 to 10)
|
|
return "Average"
|
|
if(11 to 14)
|
|
return "Above Average"
|
|
if(15 to 18)
|
|
return "Exceptional"
|
|
if(19 to 24)
|
|
return "Genius"
|
|
if(24 to 1000)
|
|
return "God"
|
|
|
|
/datum/preferences/proc/ShowChoices(mob/user)
|
|
if(!user || !user.client) return
|
|
var/dat = "<html><body><center>"
|
|
|
|
if(path)
|
|
dat += "Slot - "
|
|
dat += "<a href=\"byond://?src=\ref[user];preference=open_load_dialog\">Load slot</a> - "
|
|
dat += "<a href=\"byond://?src=\ref[user];preference=save\">Save slot</a> - "
|
|
dat += "<a href=\"byond://?src=\ref[user];preference=reload\">Reload slot</a>"
|
|
|
|
else
|
|
dat += "Please create an account to save your preferences."
|
|
|
|
dat += "<br>"
|
|
dat += player_setup.header()
|
|
dat += "<br><HR></center>"
|
|
dat += player_setup.content(user)
|
|
|
|
dat += "</html></body>"
|
|
user << browse(dat, "window=preferences;size=625x736")
|
|
|
|
/datum/preferences/proc/process_link(mob/user, list/href_list)
|
|
if(!user) return
|
|
|
|
if(!istype(user, /mob/new_player)) return
|
|
|
|
if(href_list["preference"] == "open_whitelist_forum")
|
|
if(config.forumurl)
|
|
user << link(config.forumurl)
|
|
else
|
|
user << "<span class='danger'>The forum URL is not set in the server configuration.</span>"
|
|
return
|
|
else
|
|
switch(href_list["preference"])
|
|
if("save")
|
|
save_preferences()
|
|
save_character()
|
|
|
|
if("reload")
|
|
load_preferences()
|
|
load_character()
|
|
|
|
if("open_load_dialog")
|
|
if(!IsGuestKey(user.key))
|
|
open_load_dialog(user)
|
|
return 1
|
|
|
|
if("changeslot")
|
|
load_character(text2num(href_list["num"]))
|
|
close_load_dialog(user)
|
|
|
|
ShowChoices(user)
|
|
return 1
|
|
|
|
/datum/preferences/proc/copy_to(mob/living/carbon/human/character, safety = 0)
|
|
// Sanitizing rather than saving as someone might still be editing when copy_to occurs.
|
|
player_setup.sanitize_setup()
|
|
if(be_random_name)
|
|
real_name = random_name(gender,species)
|
|
|
|
if(config.humans_need_surnames)
|
|
var/firstspace = findtext(real_name, " ")
|
|
var/name_length = length(real_name)
|
|
if(!firstspace) //we need a surname
|
|
real_name += " [pick(last_names)]"
|
|
else if(firstspace == name_length)
|
|
real_name += "[pick(last_names)]"
|
|
|
|
character.real_name = real_name
|
|
character.name = character.real_name
|
|
if(character.dna)
|
|
character.dna.real_name = character.real_name
|
|
|
|
character.flavor_texts["general"] = flavor_texts["general"]
|
|
character.flavor_texts["head"] = flavor_texts["head"]
|
|
character.flavor_texts["face"] = flavor_texts["face"]
|
|
character.flavor_texts["eyes"] = flavor_texts["eyes"]
|
|
character.flavor_texts["torso"] = flavor_texts["torso"]
|
|
character.flavor_texts["arms"] = flavor_texts["arms"]
|
|
character.flavor_texts["hands"] = flavor_texts["hands"]
|
|
character.flavor_texts["legs"] = flavor_texts["legs"]
|
|
character.flavor_texts["feet"] = flavor_texts["feet"]
|
|
|
|
character.med_record = med_record
|
|
character.sec_record = sec_record
|
|
character.gen_record = gen_record
|
|
character.exploit_record = exploit_record
|
|
|
|
character.gender = gender
|
|
character.age = age
|
|
character.b_type = b_type
|
|
|
|
character.r_eyes = r_eyes
|
|
character.g_eyes = g_eyes
|
|
character.b_eyes = b_eyes
|
|
|
|
character.r_hair = r_hair
|
|
character.g_hair = g_hair
|
|
character.b_hair = b_hair
|
|
|
|
character.r_facial = r_facial
|
|
character.g_facial = g_facial
|
|
character.b_facial = b_facial
|
|
|
|
character.r_skin = r_skin
|
|
character.g_skin = g_skin
|
|
character.b_skin = b_skin
|
|
|
|
character.s_tone = s_tone
|
|
|
|
character.h_style = h_style
|
|
character.f_style = f_style
|
|
|
|
character.home_system = home_system
|
|
character.citizenship = citizenship
|
|
character.personal_faction = faction
|
|
character.religion = religion
|
|
|
|
character.skills = skills
|
|
character.used_skillpoints = used_skillpoints
|
|
|
|
// Destroy/cyborgize organs
|
|
|
|
for(var/name in organ_data)
|
|
|
|
var/status = organ_data[name]
|
|
var/obj/item/organ/external/O = character.organs_by_name[name]
|
|
if(O)
|
|
O.status = 0
|
|
if(status == "amputated")
|
|
character.organs_by_name[O.limb_name] = null
|
|
character.organs -= O
|
|
if(O.children) // This might need to become recursive.
|
|
for(var/obj/item/organ/external/child in O.children)
|
|
character.organs_by_name[child.limb_name] = null
|
|
character.organs -= child
|
|
|
|
else if(status == "cyborg")
|
|
if(rlimb_data[name])
|
|
O.robotize(rlimb_data[name])
|
|
else
|
|
O.robotize()
|
|
else
|
|
var/obj/item/organ/I = character.internal_organs_by_name[name]
|
|
if(I)
|
|
if(status == "assisted")
|
|
I.mechassist()
|
|
else if(status == "mechanical")
|
|
I.robotize()
|
|
|
|
character.underwear = underwear
|
|
|
|
character.undershirt = undershirt
|
|
|
|
if(backbag > 4 || 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
|
|
|
|
/datum/preferences/proc/open_load_dialog(mob/user)
|
|
var/dat = "<body>"
|
|
dat += "<tt><center>"
|
|
|
|
var/savefile/S = new /savefile(path)
|
|
if(S)
|
|
dat += "<b>Select a character slot to load</b><hr>"
|
|
var/name
|
|
for(var/i=1, i<= config.character_slots, i++)
|
|
S.cd = "/character[i]"
|
|
S["real_name"] >> name
|
|
if(!name) name = "Character[i]"
|
|
if(i==default_slot)
|
|
name = "<b>[name]</b>"
|
|
dat += "<a href='?_src_=prefs;preference=changeslot;num=[i];'>[name]</a><br>"
|
|
|
|
dat += "<hr>"
|
|
dat += "<a href='byond://?src=\ref[user];preference=close_load_dialog'>Close</a><br>"
|
|
dat += "</center></tt>"
|
|
user << browse(dat, "window=saves;size=300x390")
|
|
|
|
/datum/preferences/proc/close_load_dialog(mob/user)
|
|
user << browse(null, "window=saves")
|