Files
CHOMPStation2/code/modules/client/preferences.dm
2024-08-13 18:59:25 -04:00

500 lines
16 KiB
Plaintext

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/UI_style_color = "#ffffff"
var/UI_style_alpha = 255
var/tooltipstyle = "Midnight" //Style for popup tooltips
var/client_fps = 40
var/ambience_freq = 5 // How often we're playing repeating ambience to a client.
var/ambience_chance = 35 // What's the % chance we'll play ambience (in conjunction with the above frequency)
var/tgui_fancy = TRUE
var/tgui_lock = FALSE
var/tgui_input_mode = FALSE // All the Input Boxes (Text,Number,List,Alert)
var/tgui_large_buttons = TRUE
var/tgui_swapped_buttons = FALSE
var/obfuscate_key = FALSE
var/obfuscate_job = FALSE
var/chat_timestamp = FALSE
//character preferences
var/real_name //our character's name
var/be_random_name = 0 //whether we are a random name every round
var/nickname //our character's nickname
var/age = 30 //age of character
var/bday_month = 0 //Birthday month
var/bday_day = 0 //Birthday day
var/last_birthday_notification = 0 //The last year we were notified about our birthday
var/bday_announce = FALSE //Public announcement for birthdays
var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2).
var/b_type = "A+" //blood type (not-chooseable)
var/blood_reagents = "default" //blood restoration reagents
var/backbag = 2 //backpack type
var/pdachoice = 1 //PDA type
//var/shoe_hater = FALSE //RS ADD - if true, will spawn with no shoes //CHOMPRemove, remove RS No shoes
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/grad_style = "none" //Gradient style
var/r_grad = 0 //Gradient color
var/g_grad = 0 //Gradient color
var/b_grad = 0 //Gradient 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 = -75 //Skin tone
var/r_skin = 238 //Skin color // Vorestation edit, so color multi sprites can aren't BLACK AS THE VOID by default.
var/g_skin = 206 //Skin color // Vorestation edit, so color multi sprites can aren't BLACK AS THE VOID by default.
var/b_skin = 179 //Skin color // Vorestation edit, so color multi sprites can aren't BLACK AS THE VOID by default.
var/r_eyes = 0 //Eye color
var/g_eyes = 0 //Eye color
var/b_eyes = 0 //Eye color
var/species = 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() //Language prefix keys
var/list/language_custom_keys = list() //Language custom call keys
var/list/gear //Left in for Legacy reasons, will no longer save.
var/list/gear_list = list() //Custom/fluff item loadouts.
var/gear_slot = 1 //The current gear save slot
var/list/traits //Traits which modifier characters for better or worse (mostly worse).
var/synth_color = 0 //Lets normally uncolorable synth parts be colorable.
var/r_synth //Used with synth_color to color synth parts that normaly can't be colored.
var/g_synth //Same as above
var/b_synth //Same as above
var/synth_markings = 1 //Enable/disable markings on synth parts. //VOREStation Edit - 1 by default
var/digitigrade = 0
//Some faction information.
var/home_system = "Unset" //Current home or residence.
var/birthplace = "Unset" //Location of birth.
var/citizenship = "None" //Government or similar entity with which you hold citizenship.
var/faction = "None" //General associated faction.
var/religion = "None" //Religious association.
var/antag_faction = "None" //Antag associated faction.
var/antag_vis = "Hidden" //How visible antag association is to others.
//Mob preview
var/list/char_render_holders //Should only be a key-value list of north/south/east/west = obj/screen.
var/static/list/preview_screen_locs = list(
"1" = "character_preview_map:2,7",
"2" = "character_preview_map:2,5",
"4" = "character_preview_map:2,3",
"8" = "character_preview_map:2,1",
"BG" = "character_preview_map:1,1 to 3,8",
"PMH" = "character_preview_map:2,7"
)
//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 = 1
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/body_markings = list() // "name" = "#rgbcolor" //VOREStation Edit: "name" = list(BP_HEAD = list("on" = <enabled>, "color" = "#rgbcolor"), BP_TORSO = ...)
var/list/flavor_texts = list()
var/list/flavour_texts_robot = list()
var/custom_link = null
var/list/body_descriptors = list()
var/med_record = ""
var/sec_record = ""
var/gen_record = ""
var/exploit_record = ""
var/disabilities = 0
var/economic_status = "Average"
var/uplinklocation = "PDA"
// OOC Metadata:
var/metadata = ""
var/metadata_likes = ""
var/metadata_dislikes = ""
var/list/ignored_players = list()
var/client/client = null
var/client_ckey = null
// Communicator identity data
var/communicator_visibility = 0
/// Default ringtone for character; if blank, use job default.
var/ringtone = null
var/datum/category_collection/player_setup_collection/player_setup
var/datum/browser/panel
var/lastnews // Hash of last seen lobby news content.
var/lastlorenews //ID of last seen lore news article.
var/examine_text_mode = 0 // Just examine text, include usage (description_info), switch to examine panel.
var/multilingual_mode = 0 // Default behaviour, delimiter-key-space, delimiter-key-delimiter, off
var/list/volume_channels = list()
///If they are currently in the process of swapping slots, don't let them open 999 windows for it and get confused
var/selecting_slots = FALSE
/datum/preferences/New(client/C)
player_setup = new(src)
set_biological_gender(pick(MALE, FEMALE))
real_name = random_name(identifying_gender,species)
b_type = RANDOM_BLOOD_TYPE
gear = list()
gear_list = list()
gear_slot = 1
if(istype(C))
client = C
client_ckey = C.ckey
if(!IsGuestKey(C.key))
load_path(C.ckey)
if(load_preferences())
load_character()
/datum/preferences/Destroy()
. = ..()
QDEL_LIST_ASSOC_VAL(char_render_holders)
/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
if(!get_mob_by_key(client_ckey))
to_chat(user, "<span class='danger'>No mob exists for the given client!</span>")
return
if(!char_render_holders)
update_preview_icon()
show_character_previews()
var/dat = "<html><body><center>"
if(path)
dat += "Slot - "
dat += "<a href='?src=\ref[src];load=1'>Load slot</a> - "
dat += "<a href='?src=\ref[src];save=1'>Save slot</a> - "
dat += "<a href='?src=\ref[src];reload=1'>Reload slot</a> - "
dat += "<a href='?src=\ref[src];resetslot=1'>Reset slot</a> - "
dat += "<a href='?src=\ref[src];copy=1'>Copy 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=635x736")
winshow(user, "preferences_window", TRUE)
var/datum/browser/popup = new(user, "preferences_browser", "Character Setup", 800, 800)
popup.set_content(dat)
popup.open(FALSE) // Skip registring onclose on the browser pane
onclose(user, "preferences_window", src) // We want to register on the window itself
/datum/preferences/proc/update_character_previews(var/mob/living/carbon/human/mannequin)
if(!client)
return
var/obj/screen/setup_preview/pm_helper/PMH = LAZYACCESS(char_render_holders, "PMH")
if(!PMH)
PMH = new
LAZYSET(char_render_holders, "PMH", PMH)
client.screen |= PMH
PMH.screen_loc = preview_screen_locs["PMH"]
var/obj/screen/setup_preview/bg/BG = LAZYACCESS(char_render_holders, "BG")
if(!BG)
BG = new
BG.plane = TURF_PLANE
BG.icon = 'icons/effects/setup_backgrounds_vr.dmi'
BG.pref = src
LAZYSET(char_render_holders, "BG", BG)
client.screen |= BG
BG.icon_state = bgstate
BG.screen_loc = preview_screen_locs["BG"]
for(var/D in global.cardinal)
var/obj/screen/setup_preview/O = LAZYACCESS(char_render_holders, "[D]")
if(!O)
O = new
O.pref = src
LAZYSET(char_render_holders, "[D]", O)
client.screen |= O
mannequin.set_dir(D)
mannequin.update_tail_showing()
mannequin.ImmediateOverlayUpdate()
var/mutable_appearance/MA = new(mannequin)
O.appearance = MA
O.screen_loc = preview_screen_locs["[D]"]
/datum/preferences/proc/show_character_previews()
if(!client || !char_render_holders)
return
for(var/render_holder in char_render_holders)
client.screen |= char_render_holders[render_holder]
/datum/preferences/proc/clear_character_previews()
for(var/index in char_render_holders)
var/obj/screen/S = char_render_holders[index]
client?.screen -= S
qdel(S)
char_render_holders = null
/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_GET(string/forumurl)) // CHOMPEdit
user << link(CONFIG_GET(string/forumurl)) // CHOMPEdit
else
to_chat(user, "<span class='danger'>The forum URL is not set in the server configuration.</span>")
return
ShowChoices(user) //ChompEDIT - usr removal
return 1
/datum/preferences/Topic(href, list/href_list)
if(..())
return 1
if(href_list["save"])
save_preferences()
save_character()
else if(href_list["reload"])
load_preferences()
load_character()
attempt_vr(client.prefs_vr,"load_vore","") //VOREStation Edit
sanitize_preferences()
else if(href_list["load"])
if(!IsGuestKey(usr.key))
open_load_dialog(usr)
return 1
else if(href_list["resetslot"])
if("Yes" != tgui_alert(usr, "This will reset the current slot. Continue?", "Reset current slot?", list("No", "Yes")))
return 0
if("Yes" != tgui_alert(usr, "Are you completely sure that you want to reset this character slot?", "Reset current slot?", list("No", "Yes")))
return 0
load_character(SAVE_RESET)
sanitize_preferences()
else if(href_list["copy"])
if(!IsGuestKey(usr.key))
open_copy_dialog(usr)
return 1
else if(href_list["close"])
// User closed preferences window, cleanup anything we need to.
clear_character_previews()
return 1
else
return 0
ShowChoices(usr)
return 1
/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = TRUE)
// Sanitizing rather than saving as someone might still be editing when copy_to occurs.
player_setup.sanitize_setup()
// This needs to happen before anything else becuase it sets some variables.
character.set_species(species)
// Special Case: This references variables owned by two different datums, so do it here.
if(be_random_name)
real_name = random_name(identifying_gender,species)
// Ask the preferences datums to apply their own settings to the new mob
player_setup.copy_to_mob(character)
// VOREStation Edit - Sync up all their organs and species one final time
character.force_update_organs()
if(icon_updates)
character.force_update_limbs()
character.update_icons_body()
character.update_mutations()
character.update_underwear()
character.update_hair()
if(LAZYLEN(character.descriptors))
for(var/entry in body_descriptors)
character.descriptors[entry] = body_descriptors[entry]
/datum/preferences/proc/open_load_dialog(mob/user)
if(selecting_slots)
to_chat(user, "<span class='warning'>You already have a slot selection dialog open!</span>")
return
var/savefile/S = new /savefile(path)
if(!S)
error("Somehow missing savefile path?! [path]")
return
var/name
var/nickname //vorestation edit - This set appends nicknames to the save slot
var/list/charlist = list()
var/default //VOREStation edit
for(var/i = 1, i <= CONFIG_GET(number/character_slots), i++) // CHOMPEdit
S.cd = "/character[i]"
S["real_name"] >> name
S["nickname"] >> nickname //vorestation edit
if(!name)
name = "[i] - \[Unused Slot\]"
else if(i == default_slot)
name = "►[i] - [name]"
else
name = "[i] - [name]"
if (i == default_slot) //VOREStation edit
default = "[name][nickname ? " ([nickname])" : ""]"
charlist["[name][nickname ? " ([nickname])" : ""]"] = i
selecting_slots = TRUE
var/choice = tgui_input_list(user, "Select a character to load:", "Load Slot", charlist, default)
selecting_slots = FALSE
if(!choice)
return
var/slotnum = charlist[choice]
if(!slotnum)
error("Player picked [choice] slot to load, but that wasn't one we sent.")
return
load_character(slotnum)
attempt_vr(user.client?.prefs_vr,"load_vore","") //VOREStation Edit
sanitize_preferences()
ShowChoices(user)
/datum/preferences/proc/open_copy_dialog(mob/user)
if(selecting_slots)
to_chat(user, "<span class='warning'>You already have a slot selection dialog open!</span>")
return
var/savefile/S = new /savefile(path)
if(!S)
error("Somehow missing savefile path?! [path]")
return
var/name
var/nickname //vorestation edit - This set appends nicknames to the save slot
var/list/charlist = list()
for(var/i = 1, i <= CONFIG_GET(number/character_slots), i++) // CHOMPEdit
S.cd = "/character[i]"
S["real_name"] >> name
S["nickname"] >> nickname //vorestation edit
if(!name)
name = "[i] - \[Unused Slot\]"
if(i == default_slot)
name = "►[i] - [name]"
else
name = "[i] - [name]"
charlist["[name][nickname ? " ([nickname])" : ""]"] = i
selecting_slots = TRUE
var/choice = tgui_input_list(user, "Select a character to COPY TO:", "Copy Slot", charlist)
selecting_slots = FALSE
if(!choice)
return
var/slotnum = charlist[choice]
if(!slotnum)
error("Player picked [choice] slot to copy to, but that wasn't one we sent.")
return
overwrite_character(slotnum)
sanitize_preferences()
ShowChoices(user)