Merge branch 'master' into language-tab
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
var/datum/preferences/prefs = null
|
||||
var/last_turn = 0
|
||||
var/move_delay = 0
|
||||
var/last_move = 0
|
||||
var/area = null
|
||||
|
||||
/// Last time we Click()ed. No clicking twice in one tick!
|
||||
@@ -89,6 +90,8 @@
|
||||
|
||||
var/list/char_render_holders //Should only be a key-value list of north/south/east/west = obj/screen.
|
||||
|
||||
/// Last time they used fix macros
|
||||
var/last_macro_fix = 0
|
||||
/// Keys currently held
|
||||
var/list/keys_held = list()
|
||||
/// These next two vars are to apply movement for keypresses and releases made while move delayed.
|
||||
@@ -126,9 +129,8 @@
|
||||
|
||||
/// Messages currently seen by this client
|
||||
var/list/seen_messages
|
||||
|
||||
/// datum wrapper for client view
|
||||
var/datum/view_data/view_size
|
||||
/// viewsize datum for holding our view size
|
||||
var/datum/viewData/view_size
|
||||
|
||||
/// our current tab
|
||||
var/stat_tab
|
||||
@@ -162,6 +164,14 @@
|
||||
var/parallax_layers_max = 3
|
||||
var/parallax_animate_timer
|
||||
|
||||
/**
|
||||
* Assoc list with all the active maps - when a screen obj is added to
|
||||
* a map, it's put in here as well.
|
||||
*
|
||||
* Format: list(<mapname> = list(/obj/screen))
|
||||
*/
|
||||
var/list/screen_maps = list()
|
||||
|
||||
// List of all asset filenames sent to this client by the asset cache, along with their assoicated md5s
|
||||
var/list/sent_assets = list()
|
||||
/// List of all completed blocking send jobs awaiting acknowledgement by send_asset
|
||||
|
||||
@@ -76,9 +76,15 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
to_chat(src, "<span class='danger'>Your previous action was ignored because you've done too many in a second</span>")
|
||||
return
|
||||
|
||||
//Logs all hrefs, except chat pings
|
||||
if(!(href_list["_src_"] == "chat" && href_list["proc"] == "ping" && LAZYLEN(href_list) == 2))
|
||||
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
|
||||
|
||||
// Tgui Topic middleware
|
||||
if(tgui_Topic(href_list))
|
||||
if(CONFIG_GET(flag/emergency_tgui_logging))
|
||||
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
|
||||
return
|
||||
|
||||
//Logs all hrefs
|
||||
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
|
||||
|
||||
//byond bug ID:2256651
|
||||
if (asset_cache_job && (asset_cache_job in completed_asset_jobs))
|
||||
@@ -101,8 +107,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
keyUp(keycode)
|
||||
return
|
||||
|
||||
// Tgui Topic middleware
|
||||
if(tgui_Topic(href_list))
|
||||
if(href_list["statpanel_item_target"])
|
||||
handle_statpanel_click(href_list)
|
||||
return
|
||||
|
||||
// Admin PM
|
||||
@@ -141,6 +147,12 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
|
||||
..() //redirect to hsrc.Topic()
|
||||
|
||||
/client/proc/handle_statpanel_click(list/href_list)
|
||||
var/atom/target = locate(href_list["statpanel_item_target"])
|
||||
if(!target)
|
||||
return
|
||||
Click(target, target.loc, null, "[href_list["statpanel_item_shiftclick"]?"shift=1;":null][href_list["statpanel_item_ctrlclick"]?"ctrl=1;":null]&alt=[href_list["statpanel_item_altclick"]?"alt=1;":null]", FALSE, "statpanel")
|
||||
|
||||
/client/proc/is_content_unlocked()
|
||||
if(!prefs.unlock_content)
|
||||
to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. Only 10 bucks for 3 months! <a href=\"https://secure.byond.com/membership\">Click Here to find out more</a>.")
|
||||
@@ -268,7 +280,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
else
|
||||
prefs = new /datum/preferences(src)
|
||||
GLOB.preferences_datums[ckey] = prefs
|
||||
addtimer(CALLBACK(src, .proc/ensure_keys_set), 0) //prevents possible race conditions
|
||||
|
||||
addtimer(CALLBACK(src, .proc/ensure_keys_set, prefs), 10) //prevents possible race conditions
|
||||
|
||||
prefs.last_ip = address //these are gonna be used for banning
|
||||
prefs.last_id = computer_id //these are gonna be used for banning
|
||||
@@ -336,10 +349,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// if(SSinput.initialized) placed here on tg.
|
||||
// set_macros()
|
||||
// update_movement_keys()
|
||||
|
||||
// Initialize tgui panel
|
||||
tgui_panel.initialize()
|
||||
src << browse(file('html/statbrowser.html'), "window=statbrowser")
|
||||
@@ -446,7 +455,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them.
|
||||
to_chat(src, "<span class='warning'>Unable to access asset cache browser, if you are using a custom skin file, please allow DS to download the updated version, if you are not, then make a bug report. This is not a critical issue but can cause issues with resource downloading, as it is impossible to know when extra resources arrived to you.</span>")
|
||||
|
||||
|
||||
//This is down here because of the browse() calls in tooltip/New()
|
||||
if(!tooltips)
|
||||
tooltips = new /datum/tooltip(src)
|
||||
@@ -472,17 +480,12 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if (menuitem)
|
||||
menuitem.Load_checked(src)
|
||||
|
||||
// view_size = new(src, getScreenSize(prefs.widescreenpref))
|
||||
// view_size.resetFormat()
|
||||
// view_size.setZoomMode()
|
||||
// fit_viewport()
|
||||
view_size = new(src, getScreenSize(prefs.widescreenpref))
|
||||
view_size.resetFormat()
|
||||
view_size.setZoomMode()
|
||||
fit_viewport()
|
||||
Master.UpdateTickRate()
|
||||
|
||||
/client/proc/ensure_keys_set()
|
||||
if(SSinput.initialized)
|
||||
set_macros()
|
||||
update_movement_keys(prefs)
|
||||
|
||||
//////////////
|
||||
//DISCONNECT//
|
||||
//////////////
|
||||
@@ -497,7 +500,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
GLOB.directory -= ckey
|
||||
log_access("Logout: [key_name(src)]")
|
||||
GLOB.ahelp_tickets.ClientLogout(src)
|
||||
// SSserver_maint.UpdateHubStatus()
|
||||
SSserver_maint.UpdateHubStatus()
|
||||
if(credits)
|
||||
QDEL_LIST(credits)
|
||||
if(holder)
|
||||
@@ -564,36 +567,49 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if(!query_client_in_db.Execute())
|
||||
qdel(query_client_in_db)
|
||||
return
|
||||
if(!query_client_in_db.NextRow())
|
||||
if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough))
|
||||
log_access("Failed Login: [key] - New account attempting to connect during panic bunker")
|
||||
message_admins("<span class='adminnotice'>Failed Login: [key] - New account attempting to connect during panic bunker</span>")
|
||||
to_chat(src, "<span class='notice'>You must first join the Discord to verify your account before joining this server.<br>To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: <a href='https://discord.gg/E6SQuhz'>https://discord.gg/E6SQuhz</a><br>If you have already done so, wait a few minutes then try again; sometimes the server needs to fully load before you can join.</span>") //CIT CHANGE - makes the panic bunker disconnect message point to the discord
|
||||
var/list/connectiontopic_a = params2list(connectiontopic)
|
||||
var/list/panic_addr = CONFIG_GET(string/panic_server_address)
|
||||
if(panic_addr && !connectiontopic_a["redirect"])
|
||||
var/panic_name = CONFIG_GET(string/panic_server_name)
|
||||
to_chat(src, "<span class='notice'>Sending you to [panic_name ? panic_name : panic_addr].</span>")
|
||||
winset(src, null, "command=.options")
|
||||
src << link("[panic_addr]?redirect=1")
|
||||
qdel(query_client_in_db)
|
||||
qdel(src)
|
||||
return
|
||||
if(!query_client_in_db.NextRow()) //new user detected
|
||||
if(!holder && !GLOB.deadmins[ckey])
|
||||
if(CONFIG_GET(flag/panic_bunker) && !(ckey in GLOB.bunker_passthrough))
|
||||
log_access("Failed Login: [key] - New account attempting to connect during panic bunker")
|
||||
message_admins("<span class='adminnotice'>Failed Login: [key] - New account attempting to connect during panic bunker</span>")
|
||||
to_chat(src, "<span class='notice'>You must first join the Discord to verify your account before joining this server.<br>To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: <a href='https://discord.gg/E6SQuhz'>https://discord.gg/E6SQuhz</a><br>If you have already done so, wait a few minutes then try again; sometimes the server needs to fully load before you can join.</span>") //CIT CHANGE - makes the panic bunker disconnect message point to the discord
|
||||
var/list/connectiontopic_a = params2list(connectiontopic)
|
||||
var/list/panic_addr = CONFIG_GET(string/panic_server_address)
|
||||
if(panic_addr && !connectiontopic_a["redirect"])
|
||||
var/panic_name = CONFIG_GET(string/panic_server_name)
|
||||
to_chat(src, "<span class='notice'>Sending you to [panic_name ? panic_name : panic_addr].</span>")
|
||||
winset(src, null, "command=.options")
|
||||
src << link("[panic_addr]?redirect=1")
|
||||
qdel(query_client_in_db)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
new_player = 1
|
||||
account_join_date = sanitizeSQL(findJoinDate())
|
||||
var/sql_key = sanitizeSQL(key)
|
||||
var/datum/DBQuery/query_add_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (`ckey`, `byond_key`, `firstseen`, `firstseen_round_id`, `lastseen`, `lastseen_round_id`, `ip`, `computerid`, `lastadminrank`, `accountjoindate`) VALUES ('[sql_ckey]', '[sql_key]', Now(), '[GLOB.round_id]', Now(), '[GLOB.round_id]', INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]', [account_join_date ? "'[account_join_date]'" : "NULL"])")
|
||||
if(!query_add_player.Execute())
|
||||
qdel(query_client_in_db)
|
||||
new_player = 1
|
||||
account_join_date = sanitizeSQL(findJoinDate())
|
||||
var/sql_key = sanitizeSQL(key)
|
||||
var/datum/DBQuery/query_add_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (`ckey`, `byond_key`, `firstseen`, `firstseen_round_id`, `lastseen`, `lastseen_round_id`, `ip`, `computerid`, `lastadminrank`, `accountjoindate`) VALUES ('[sql_ckey]', '[sql_key]', Now(), '[GLOB.round_id]', Now(), '[GLOB.round_id]', INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]', [account_join_date ? "'[account_join_date]'" : "NULL"])")
|
||||
if(!query_add_player.Execute())
|
||||
qdel(query_client_in_db)
|
||||
qdel(query_add_player)
|
||||
return
|
||||
qdel(query_add_player)
|
||||
return
|
||||
qdel(query_add_player)
|
||||
if(!account_join_date)
|
||||
account_join_date = "Error"
|
||||
account_age = -1
|
||||
else if(ckey in GLOB.bunker_passthrough)
|
||||
GLOB.bunker_passthrough -= ckey
|
||||
if(!account_join_date)
|
||||
account_join_date = "Error"
|
||||
account_age = -1
|
||||
else if(ckey in GLOB.bunker_passthrough)
|
||||
GLOB.bunker_passthrough -= ckey
|
||||
if(CONFIG_GET(flag/age_verification)) //setup age verification
|
||||
if(!set_db_player_flags())
|
||||
message_admins(usr, "<span class='danger'>ERROR: Unable to read player flags from database. Please check logs.</span>")
|
||||
return
|
||||
else
|
||||
var/dbflags = prefs.db_flags
|
||||
if(!(dbflags & DB_FLAG_AGE_CONFIRMATION_COMPLETE)) //they have not completed age verification
|
||||
if((ckey in GLOB.bunker_passthrough)) //they're verified in the panic bunker though
|
||||
update_flag_db(DB_FLAG_AGE_CONFIRMATION_COMPLETE, TRUE)
|
||||
else
|
||||
update_flag_db(DB_FLAG_AGE_CONFIRMATION_INCOMPLETE, TRUE)
|
||||
|
||||
qdel(query_client_in_db)
|
||||
var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT firstseen, DATEDIFF(Now(),firstseen), accountjoindate, DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
|
||||
if(!query_get_client_age.Execute())
|
||||
@@ -630,7 +646,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
query_log_connection.Execute()
|
||||
qdel(query_log_connection)
|
||||
|
||||
// SSserver_maint.UpdateHubStatus()
|
||||
SSserver_maint.UpdateHubStatus()
|
||||
|
||||
if(new_player)
|
||||
player_age = -1
|
||||
@@ -794,7 +810,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
message_admins("<span class='adminnotice'>Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.</span>")
|
||||
ip_intel = res.intel
|
||||
|
||||
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE)
|
||||
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE, extra_info)
|
||||
if(last_click > world.time - world.tick_lag)
|
||||
return
|
||||
last_click = world.time
|
||||
@@ -847,7 +863,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
return
|
||||
|
||||
if(prefs.log_clicks)
|
||||
log_click(object, location, control, params, src)
|
||||
log_click(object, location, control, params, src, extra_info? "clicked ([extra_info])" : null)
|
||||
|
||||
if (prefs.hotkeys)
|
||||
// If hotkey mode is enabled, then clicking the map will automatically
|
||||
@@ -914,46 +930,37 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
return FALSE
|
||||
if (NAMEOF(src, key))
|
||||
return FALSE
|
||||
if(NAMEOF(src, view))
|
||||
change_view(var_value)
|
||||
if (NAMEOF(src, view))
|
||||
view_size.setDefault(var_value)
|
||||
return TRUE
|
||||
if(NAMEOF(src, computer_id))
|
||||
return FALSE
|
||||
if(NAMEOF(src, address))
|
||||
return FALSE
|
||||
. = ..()
|
||||
|
||||
/client/vv_get_var(var_name)
|
||||
. = ..()
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, computer_id))
|
||||
if(!check_rights(R_SENSITIVE, FALSE))
|
||||
return "SENSITIVE"
|
||||
if(NAMEOF(src, address))
|
||||
if(!check_rights(R_SENSITIVE, FALSE))
|
||||
return "SENSITIVE"
|
||||
|
||||
/client/proc/rescale_view(change, min, max)
|
||||
var/viewscale = getviewsize(view)
|
||||
var/x = viewscale[1]
|
||||
var/y = viewscale[2]
|
||||
x = clamp(x+change, min, max)
|
||||
y = clamp(y+change, min,max)
|
||||
change_view("[x]x[y]")
|
||||
|
||||
/client/proc/update_movement_keys(datum/preferences/direct_prefs)
|
||||
var/datum/preferences/D = prefs || direct_prefs
|
||||
if(!D?.key_bindings)
|
||||
return
|
||||
movement_keys = list()
|
||||
for(var/key in D.key_bindings)
|
||||
for(var/kb_name in D.key_bindings[key])
|
||||
switch(kb_name)
|
||||
if("North")
|
||||
movement_keys[key] = NORTH
|
||||
if("East")
|
||||
movement_keys[key] = EAST
|
||||
if("West")
|
||||
movement_keys[key] = WEST
|
||||
if("South")
|
||||
movement_keys[key] = SOUTH
|
||||
view_size.setDefault("[x]x[y]")
|
||||
|
||||
/client/proc/change_view(new_size)
|
||||
if (isnull(new_size))
|
||||
CRASH("change_view called without argument.")
|
||||
|
||||
//CIT CHANGES START HERE - makes change_view change DEFAULT_VIEW to 15x15 depending on preferences
|
||||
if(prefs && CONFIG_GET(string/default_view))
|
||||
if(!prefs.widescreenpref && new_size == CONFIG_GET(string/default_view))
|
||||
new_size = "15x15"
|
||||
//END OF CIT CHANGES
|
||||
|
||||
var/list/old_view = getviewsize(view)
|
||||
view = new_size
|
||||
var/list/actualview = getviewsize(view)
|
||||
@@ -1021,3 +1028,25 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
verb_tabs |= verb_to_init.category
|
||||
verblist[++verblist.len] = list(verb_to_init.category, verb_to_init.name)
|
||||
src << output("[url_encode(json_encode(verb_tabs))];[url_encode(json_encode(verblist))]", "statbrowser:init_verbs")
|
||||
|
||||
//increment progress for an unlockable loadout item
|
||||
/client/proc/increment_progress(key, amount)
|
||||
if(prefs)
|
||||
var/savefile/S = new /savefile(prefs.path)
|
||||
var/list/unlockable_loadout_data = prefs.unlockable_loadout_data
|
||||
if(!length(unlockable_loadout_data))
|
||||
unlockable_loadout_data = list()
|
||||
unlockable_loadout_data[key] = amount
|
||||
WRITE_FILE(S["unlockable_loadout"], safe_json_encode(unlockable_loadout_data))
|
||||
prefs.unlockable_loadout_data = unlockable_loadout_data
|
||||
return TRUE
|
||||
else
|
||||
if(unlockable_loadout_data[key])
|
||||
unlockable_loadout_data[key] += amount
|
||||
else
|
||||
unlockable_loadout_data[key] = amount
|
||||
WRITE_FILE(S["unlockable_loadout"], safe_json_encode(unlockable_loadout_data))
|
||||
prefs.unlockable_loadout_data = unlockable_loadout_data
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -7,4 +7,4 @@ GLOBAL_LIST_EMPTY(clientmessages)
|
||||
var/list/L = GLOB.clientmessages[ckey]
|
||||
if(!L)
|
||||
GLOB.clientmessages[ckey] = L = list()
|
||||
L += message
|
||||
L += message
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
var/list/logging = list()
|
||||
var/list/post_login_callbacks = list()
|
||||
var/list/post_logout_callbacks = list()
|
||||
var/byond_version = "Unknown"
|
||||
var/byond_version = "Unknown"
|
||||
|
||||
+417
-142
@@ -10,13 +10,31 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/path
|
||||
var/vr_path
|
||||
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
|
||||
var/max_save_slots = 16
|
||||
var/max_save_slots = 24
|
||||
|
||||
//non-preference stuff
|
||||
var/muted = 0
|
||||
// Intra-round persistence begin
|
||||
/// Flags for admin mutes
|
||||
var/muted = NONE
|
||||
/// Last IP the person was seen on
|
||||
var/last_ip
|
||||
/// Last CID the person was seen on
|
||||
var/last_id
|
||||
/// Do we log their clicks to disk?
|
||||
var/log_clicks = FALSE
|
||||
/// Characters they have joined the round under - Lazylist of names
|
||||
var/list/characters_joined_as
|
||||
/// Slots they have joined the round under - Lazylist of numbers
|
||||
var/list/slots_joined_as
|
||||
/// Are we currently subject to respawn restrictions? Usually set by us using the "respawn" verb, but can be lifted by admins.
|
||||
var/respawn_restrictions_active = FALSE
|
||||
/// time of death we consider for respawns
|
||||
var/respawn_time_of_death = -INFINITY
|
||||
/// did they DNR? used to prevent respawns.
|
||||
var/dnr_triggered = FALSE
|
||||
/// did they cryo on their last ghost?
|
||||
var/respawn_did_cryo = FALSE
|
||||
|
||||
// Intra-round persistence end
|
||||
|
||||
var/icon/custom_holoform_icon
|
||||
var/list/cached_holoform_icons
|
||||
@@ -53,7 +71,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
/// List with a key string associated to a list of keybindings. Unlike key_bindings, this one operates on raw key, allowing for binding a key that triggers regardless of if a modifier is depressed as long as the raw key is sent.
|
||||
var/list/modless_key_bindings = list()
|
||||
|
||||
|
||||
var/tgui_fancy = TRUE
|
||||
var/tgui_lock = TRUE
|
||||
var/windowflashing = TRUE
|
||||
@@ -82,6 +99,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/be_random_body = 0 //whether we'll have a random body every round
|
||||
var/gender = MALE //gender of character (well duh)
|
||||
var/age = 30 //age of character
|
||||
var/language = "Random" //bonus language
|
||||
var/choselanguage = "Random" //language appearance
|
||||
var/underwear = "Nude" //underwear type
|
||||
var/undie_color = "FFFFFF"
|
||||
var/undershirt = "Nude" //undershirt type
|
||||
@@ -98,72 +117,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/use_custom_skin_tone = FALSE
|
||||
var/left_eye_color = "000000" //Eye color
|
||||
var/right_eye_color = "000000"
|
||||
var/eye_type = DEFAULT_EYES_TYPE //Eye type
|
||||
var/split_eye_colors = FALSE
|
||||
var/datum/species/pref_species = new /datum/species/human() //Mutant race
|
||||
var/list/features = list("mcolor" = "FFFFFF",
|
||||
"mcolor2" = "FFFFFF",
|
||||
"mcolor3" = "FFFFFF",
|
||||
"tail_lizard" = "Smooth",
|
||||
"tail_human" = "None",
|
||||
"snout" = "Round",
|
||||
"horns" = "None",
|
||||
"horns_color" = "85615a",
|
||||
"ears" = "None",
|
||||
"wings" = "None",
|
||||
"wings_color" = "FFF",
|
||||
"frills" = "None",
|
||||
"deco_wings" = "None",
|
||||
"spines" = "None",
|
||||
"body_markings" = "None",
|
||||
"legs" = "Plantigrade",
|
||||
"insect_wings" = "Plain",
|
||||
"insect_fluff" = "None",
|
||||
"insect_markings" = "None",
|
||||
"mam_body_markings" = "Plain",
|
||||
"mam_ears" = "None",
|
||||
"mam_snouts" = "None",
|
||||
"mam_tail" = "None",
|
||||
"mam_tail_animated" = "None",
|
||||
"xenodorsal" = "Standard",
|
||||
"xenohead" = "Standard",
|
||||
"xenotail" = "Xenomorph Tail",
|
||||
"taur" = "None",
|
||||
"genitals_use_skintone" = FALSE,
|
||||
"has_cock" = FALSE,
|
||||
"cock_shape" = DEF_COCK_SHAPE,
|
||||
"cock_length" = COCK_SIZE_DEF,
|
||||
"cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF,
|
||||
"cock_color" = "ffffff",
|
||||
"cock_taur" = FALSE,
|
||||
"has_balls" = FALSE,
|
||||
"balls_color" = "ffffff",
|
||||
"balls_shape" = DEF_BALLS_SHAPE,
|
||||
"balls_size" = BALLS_SIZE_DEF,
|
||||
"balls_cum_rate" = CUM_RATE,
|
||||
"balls_cum_mult" = CUM_RATE_MULT,
|
||||
"balls_efficiency" = CUM_EFFICIENCY,
|
||||
"has_breasts" = FALSE,
|
||||
"breasts_color" = "ffffff",
|
||||
"breasts_size" = BREASTS_SIZE_DEF,
|
||||
"breasts_shape" = DEF_BREASTS_SHAPE,
|
||||
"breasts_producing" = FALSE,
|
||||
"has_vag" = FALSE,
|
||||
"vag_shape" = DEF_VAGINA_SHAPE,
|
||||
"vag_color" = "ffffff",
|
||||
"has_womb" = FALSE,
|
||||
"balls_visibility" = GEN_VISIBLE_NO_UNDIES,
|
||||
"breasts_visibility"= GEN_VISIBLE_NO_UNDIES,
|
||||
"cock_visibility" = GEN_VISIBLE_NO_UNDIES,
|
||||
"vag_visibility" = GEN_VISIBLE_NO_UNDIES,
|
||||
"ipc_screen" = "Sunburst",
|
||||
"ipc_antenna" = "None",
|
||||
"flavor_text" = "",
|
||||
"silicon_flavor_text" = "",
|
||||
"ooc_notes" = "",
|
||||
"meat_type" = "Mammalian",
|
||||
"body_model" = MALE,
|
||||
"body_size" = RESIZE_DEFAULT_SIZE
|
||||
)
|
||||
var/list/features = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF", "mcolor3" = "FFFFFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "horns_color" = "85615a", "ears" = "None", "wings" = "None", "wings_color" = "FFF", "frills" = "None", "deco_wings" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Plantigrade", "insect_wings" = "Plain", "insect_fluff" = "None", "insect_markings" = "None", "arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain", "mam_body_markings" = "Plain", "mam_ears" = "None", "mam_snouts" = "None", "mam_tail" = "None", "mam_tail_animated" = "None", "xenodorsal" = "Standard", "xenohead" = "Standard", "xenotail" = "Xenomorph Tail", "taur" = "None", "genitals_use_skintone" = FALSE, "has_cock" = FALSE, "cock_shape" = DEF_COCK_SHAPE, "cock_length" = COCK_SIZE_DEF, "cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF, "cock_color" = "ffffff", "cock_taur" = FALSE, "has_balls" = FALSE, "balls_color" = "ffffff", "balls_shape" = DEF_BALLS_SHAPE, "balls_size" = BALLS_SIZE_DEF, "balls_cum_rate" = CUM_RATE, "balls_cum_mult" = CUM_RATE_MULT, "balls_efficiency" = CUM_EFFICIENCY, "has_breasts" = FALSE, "breasts_color" = "ffffff", "breasts_size" = BREASTS_SIZE_DEF, "breasts_shape" = DEF_BREASTS_SHAPE, "breasts_producing" = FALSE, "has_vag" = FALSE, "vag_shape" = DEF_VAGINA_SHAPE, "vag_color" = "ffffff", "has_womb" = FALSE, "balls_visibility" = GEN_VISIBLE_NO_UNDIES, "breasts_visibility"= GEN_VISIBLE_NO_UNDIES, "cock_visibility" = GEN_VISIBLE_NO_UNDIES, "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", "silicon_flavor_text" = "", "ooc_notes" = "", "meat_type" = "Mammalian", "body_model" = MALE, "body_size" = RESIZE_DEFAULT_SIZE, "color_scheme" = OLD_CHARACTER_COLORING)
|
||||
|
||||
var/custom_speech_verb = "default" //if your say_mod is to be something other than your races
|
||||
var/custom_tongue = "default" //if your tongue is to be something other than your races
|
||||
var/additional_language = "None" //additional language your character has
|
||||
@@ -201,7 +159,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/parallax
|
||||
|
||||
var/ambientocclusion = TRUE
|
||||
var/auto_fit_viewport = TRUE
|
||||
///Should we automatically fit the viewport?
|
||||
var/auto_fit_viewport = FALSE
|
||||
///Should we be in the widescreen mode set by the config?
|
||||
var/widescreenpref = TRUE
|
||||
|
||||
///What size should pixels be displayed as? 0 is strech to fit
|
||||
var/pixel_size = 0
|
||||
///What scaling method should we use?
|
||||
var/scaling_method = "normal"
|
||||
|
||||
var/uplink_spawn_loc = UPLINK_PDA
|
||||
|
||||
@@ -234,14 +200,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
///loadout stuff
|
||||
var/gear_points = 10
|
||||
var/list/gear_categories
|
||||
var/list/chosen_gear = list()
|
||||
var/list/loadout_data = list()
|
||||
var/list/unlockable_loadout_data = list()
|
||||
var/loadout_slot = 1 //goes from 1 to MAXIMUM_LOADOUT_SAVES
|
||||
var/gear_category
|
||||
var/gear_subcategory
|
||||
|
||||
var/screenshake = 100
|
||||
var/damagescreenshake = 2
|
||||
var/arousable = TRUE
|
||||
var/widescreenpref = TRUE
|
||||
var/autostand = TRUE
|
||||
var/auto_ooc = FALSE
|
||||
|
||||
@@ -254,6 +221,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
var/hide_ckey = FALSE //pref for hiding if your ckey shows round-end or not
|
||||
|
||||
var/list/tcg_cards = list()
|
||||
var/list/tcg_decks = list()
|
||||
|
||||
/datum/preferences/New(client/C)
|
||||
parent = C
|
||||
|
||||
@@ -266,7 +236,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
load_path(C.ckey)
|
||||
unlock_content = C.IsByondMember()
|
||||
if(unlock_content)
|
||||
max_save_slots = 24
|
||||
max_save_slots = 32
|
||||
var/loaded_preferences_successfully = load_preferences()
|
||||
if(loaded_preferences_successfully)
|
||||
if(load_character())
|
||||
@@ -274,7 +244,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
//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.
|
||||
key_bindings = deepCopyList(GLOB.hotkey_keybinding_list_by_key) // give them default keybinds and update their movement keys
|
||||
C?.update_movement_keys(src)
|
||||
C?.ensure_keys_set(src)
|
||||
real_name = pref_species.random_name(gender,1)
|
||||
if(!loaded_preferences_successfully)
|
||||
save_preferences()
|
||||
@@ -288,7 +258,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
/datum/preferences/proc/ShowChoices(mob/user)
|
||||
if(!user || !user.client)
|
||||
return
|
||||
update_preview_icon(current_tab != 2)
|
||||
update_preview_icon(current_tab)
|
||||
var/list/dat = list("<center>")
|
||||
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=0' [current_tab == 0 ? "class='linkOn'" : ""]>Character Settings</a>"
|
||||
@@ -345,6 +315,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender;task=input'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
|
||||
dat += "<b>Age:</b> <a style='display:block;width:30px' href='?_src_=prefs;preference=age;task=input'>[age]</a><BR>"
|
||||
dat += "<b>Language:</b> <a href='?_src_=prefs;preference=language;task=input'>[choselanguage]</a><BR>"
|
||||
|
||||
dat += "<b>Special Names:</b><BR>"
|
||||
var/old_group
|
||||
@@ -461,6 +432,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(!use_skintones)
|
||||
dat += APPEARANCE_CATEGORY_COLUMN
|
||||
|
||||
dat += "<h3>Advanced Coloring</h3>"
|
||||
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=color_scheme;task=input'>[(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) ? "Enabled" : "Disabled"]</a>"
|
||||
|
||||
dat += "<h2>Body Colors</h2>"
|
||||
|
||||
dat += "<b>Primary Color:</b><BR>"
|
||||
@@ -473,28 +447,30 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[features["mcolor3"]];'> </span> <a href='?_src_=prefs;preference=mutant_color3;task=input'>Change</a><BR>"
|
||||
mutant_colors = TRUE
|
||||
|
||||
if (CONFIG_GET(number/body_size_min) != CONFIG_GET(number/body_size_max))
|
||||
dat += "<b>Sprite Size:</b> <a href='?_src_=prefs;preference=body_size;task=input'>[features["body_size"]*100]%</a><br>"
|
||||
|
||||
if((EYECOLOR in pref_species.species_traits) && !(NOEYES in pref_species.species_traits))
|
||||
if(!use_skintones && !mutant_colors)
|
||||
dat += APPEARANCE_CATEGORY_COLUMN
|
||||
if(left_eye_color != right_eye_color)
|
||||
split_eye_colors = TRUE
|
||||
dat += "<h3>Heterochromia</h3>"
|
||||
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=toggle_split_eyes;task=input'>[split_eye_colors ? "Enabled" : "Disabled"]</a>"
|
||||
if(!split_eye_colors)
|
||||
dat += "<h3>Eye Color</h3>"
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[left_eye_color];'> </span> <a href='?_src_=prefs;preference=eyes;task=input'>Change</a>"
|
||||
if(!(NOEYES in pref_species.species_traits))
|
||||
dat += "<h3>Eye Type</h3>"
|
||||
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=eye_type;task=input'>[eye_type]</a><BR>"
|
||||
if((EYECOLOR in pref_species.species_traits))
|
||||
if(!use_skintones && !mutant_colors)
|
||||
dat += APPEARANCE_CATEGORY_COLUMN
|
||||
if(left_eye_color != right_eye_color)
|
||||
split_eye_colors = TRUE
|
||||
dat += "<h3>Heterochromia</h3>"
|
||||
dat += "</b><a style='display:block;width:100px' href='?_src_=prefs;preference=toggle_split_eyes;task=input'>[split_eye_colors ? "Enabled" : "Disabled"]</a>"
|
||||
if(!split_eye_colors)
|
||||
dat += "<h3>Eye Color</h3>"
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[left_eye_color];'> </span> <a href='?_src_=prefs;preference=eyes;task=input'>Change</a>"
|
||||
dat += "</td>"
|
||||
else
|
||||
dat += "<h3>Left Eye Color</h3>"
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[left_eye_color];'> </span> <a href='?_src_=prefs;preference=eye_left;task=input'>Change</a>"
|
||||
dat += "<h3>Right Eye Color</h3>"
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[right_eye_color];'> </span> <a href='?_src_=prefs;preference=eye_right;task=input'>Change</a><BR>"
|
||||
dat += "</td>"
|
||||
else if(use_skintones || mutant_colors)
|
||||
dat += "</td>"
|
||||
else
|
||||
dat += "<h3>Left Eye Color</h3>"
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[left_eye_color];'> </span> <a href='?_src_=prefs;preference=eye_left;task=input'>Change</a>"
|
||||
dat += "<h3>Right Eye Color</h3>"
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[right_eye_color];'> </span> <a href='?_src_=prefs;preference=eye_right;task=input'>Change</a><BR>"
|
||||
dat += "</td>"
|
||||
else if(use_skintones || mutant_colors)
|
||||
dat += "</td>"
|
||||
|
||||
if(HAIR in pref_species.species_traits)
|
||||
|
||||
@@ -533,6 +509,52 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/color_type = GLOB.colored_mutant_parts[mutant_part] //if it can be coloured, show the appropriate button
|
||||
if(color_type)
|
||||
dat += "<span style='border:1px solid #161616; background-color: #[features[color_type]];'> </span> <a href='?_src_=prefs;preference=[color_type];task=input'>Change</a><BR>"
|
||||
else
|
||||
if(features["color_scheme"] == ADVANCED_CHARACTER_COLORING) //advanced individual part colouring system
|
||||
//is it matrixed or does it have extra parts to be coloured?
|
||||
var/find_part = features[mutant_part] || pref_species.mutant_bodyparts[mutant_part]
|
||||
var/find_part_list = GLOB.mutant_reference_list[mutant_part]
|
||||
if(find_part && find_part != "None" && find_part_list)
|
||||
var/datum/sprite_accessory/accessory = find_part_list[find_part]
|
||||
if(accessory)
|
||||
if(accessory.color_src == MATRIXED || accessory.color_src == MUTCOLORS || accessory.color_src == MUTCOLORS2 || accessory.color_src == MUTCOLORS3) //mutcolors1-3 are deprecated now, please don't rely on these in the future
|
||||
var/mutant_string = accessory.mutant_part_string
|
||||
if(istype(accessory, /datum/sprite_accessory/mam_body_markings) || istype(accessory, /datum/sprite_accessory/body_markings))
|
||||
continue
|
||||
var/primary_feature = "[mutant_string]_primary"
|
||||
var/secondary_feature = "[mutant_string]_secondary"
|
||||
var/tertiary_feature = "[mutant_string]_tertiary"
|
||||
if(!features[primary_feature])
|
||||
features[primary_feature] = features["mcolor"]
|
||||
if(!features[secondary_feature])
|
||||
features[secondary_feature] = features["mcolor2"]
|
||||
if(!features[tertiary_feature])
|
||||
features[tertiary_feature] = features["mcolor3"]
|
||||
|
||||
var/matrixed_sections = accessory.matrixed_sections
|
||||
if(accessory.color_src == MATRIXED && !matrixed_sections)
|
||||
message_admins("Sprite Accessory Failure (customization): Accessory [accessory.type] is a matrixed item without any matrixed sections set!")
|
||||
continue
|
||||
else if(accessory.color_src == MATRIXED)
|
||||
switch(matrixed_sections)
|
||||
if(MATRIX_GREEN) //only composed of a green section
|
||||
primary_feature = secondary_feature //swap primary for secondary, so it properly assigns the second colour, reserved for the green section
|
||||
if(MATRIX_BLUE)
|
||||
primary_feature = tertiary_feature //same as above, but the tertiary feature is for the blue section
|
||||
if(MATRIX_RED_BLUE) //composed of a red and blue section
|
||||
secondary_feature = tertiary_feature //swap secondary for tertiary, as blue should always be tertiary
|
||||
if(MATRIX_GREEN_BLUE) //composed of a green and blue section
|
||||
primary_feature = secondary_feature //swap primary for secondary, as first option is green, which is linked to the secondary
|
||||
secondary_feature = tertiary_feature //swap secondary for tertiary, as second option is blue, which is linked to the tertiary
|
||||
dat += "<b>Primary Color</b><BR>"
|
||||
dat += "<span style='border:1px solid #161616; background-color: #[features[primary_feature]];'> </span> <a href='?_src_=prefs;preference=[primary_feature];task=input'>Change</a><BR>"
|
||||
if((accessory.color_src == MATRIXED && (matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL)) || (accessory.extra && (accessory.extra_color_src == MUTCOLORS || accessory.extra_color_src == MUTCOLORS2 || accessory.extra_color_src == MUTCOLORS3)))
|
||||
dat += "<b>Secondary Color</b><BR>"
|
||||
dat += "<span style='border:1px solid #161616; background-color: #[features[secondary_feature]];'> </span> <a href='?_src_=prefs;preference=[secondary_feature];task=input'>Change</a><BR>"
|
||||
if((accessory.color_src == MATRIXED && matrixed_sections == MATRIX_ALL) || (accessory.extra2 && (accessory.extra2_color_src == MUTCOLORS || accessory.extra2_color_src == MUTCOLORS2 || accessory.extra2_color_src == MUTCOLORS3)))
|
||||
dat += "<b>Tertiary Color</b><BR>"
|
||||
dat += "<span style='border:1px solid #161616; background-color: #[features[tertiary_feature]];'> </span> <a href='?_src_=prefs;preference=[tertiary_feature];task=input'>Change</a><BR>"
|
||||
|
||||
mutant_category++
|
||||
if(mutant_category >= MAX_MUTANT_ROWS)
|
||||
dat += "</td>"
|
||||
@@ -775,6 +797,20 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>HUD Button Flashes:</b> <a href='?_src_=prefs;preference=hud_toggle_flash'>[hud_toggle_flash ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>HUD Button Flash Color:</b> <span style='border: 1px solid #161616; background-color: [hud_toggle_color];'> </span> <a href='?_src_=prefs;preference=hud_toggle_color;task=input'>Change</a><br>"
|
||||
|
||||
/* CITADEL EDIT - We're using top menu instead
|
||||
button_name = pixel_size
|
||||
dat += "<b>Pixel Scaling:</b> <a href='?_src_=prefs;preference=pixel_size'>[(button_name) ? "Pixel Perfect [button_name]x" : "Stretch to fit"]</a><br>"
|
||||
|
||||
switch(scaling_method)
|
||||
if(SCALING_METHOD_NORMAL)
|
||||
button_name = "Nearest Neighbor"
|
||||
if(SCALING_METHOD_DISTORT)
|
||||
button_name = "Point Sampling"
|
||||
if(SCALING_METHOD_BLUR)
|
||||
button_name = "Bilinear"
|
||||
dat += "<b>Scaling Method:</b> <a href='?_src_=prefs;preference=scaling_method'>[button_name]</a><br>"
|
||||
*/
|
||||
|
||||
if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation))
|
||||
var/p_map = preferred_map
|
||||
if (!p_map)
|
||||
@@ -821,6 +857,19 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<br>"
|
||||
|
||||
if(4)
|
||||
//calculate your gear points from the chosen item
|
||||
gear_points = CONFIG_GET(number/initial_gear_points)
|
||||
var/list/chosen_gear = loadout_data["SAVE_[loadout_slot]"]
|
||||
if(chosen_gear)
|
||||
for(var/loadout_item in chosen_gear)
|
||||
var/loadout_item_path = loadout_item[LOADOUT_ITEM]
|
||||
if(loadout_item_path)
|
||||
var/datum/gear/loadout_gear = text2path(loadout_item_path)
|
||||
if(loadout_gear)
|
||||
gear_points -= initial(loadout_gear.cost)
|
||||
else
|
||||
chosen_gear = list()
|
||||
|
||||
dat += "<table align='center' width='100%'>"
|
||||
dat += "<tr><td colspan=4><center><b><font color='[gear_points == 0 ? "#E62100" : "#CCDDFF"]'>[gear_points]</font> loadout points remaining.</b> \[<a href='?_src_=prefs;preference=gear;clear_loadout=1'>Clear Loadout</a>\]</center></td></tr>"
|
||||
dat += "<tr><td colspan=4><center>You can only choose one item per category, unless it's an item that spawns in your backpack or hands.</center></td></tr>"
|
||||
@@ -876,15 +925,33 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(donoritem && !gear.donator_ckey_check(user.ckey))
|
||||
continue
|
||||
var/class_link = ""
|
||||
if(gear.type in chosen_gear)
|
||||
var/list/loadout_item = has_loadout_gear(loadout_slot, "[gear.type]")
|
||||
var/extra_loadout_data = ""
|
||||
if(loadout_item)
|
||||
class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'"
|
||||
else if(gear_points <= 0)
|
||||
if(gear.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC)
|
||||
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color_polychromic=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
|
||||
for(var/loadout_color in loadout_item[LOADOUT_COLOR])
|
||||
extra_loadout_data += "<span style='border: 1px solid #161616; background-color: [loadout_color];'> </span>"
|
||||
else
|
||||
var/loadout_color_non_poly = "#FFFFFF"
|
||||
if(length(loadout_item[LOADOUT_COLOR]))
|
||||
loadout_color_non_poly = loadout_item[LOADOUT_COLOR][1]
|
||||
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_color=1;loadout_gear_name=[html_encode(gear.name)];'>Color</a>"
|
||||
extra_loadout_data += "<span style='border: 1px solid #161616; background-color: [loadout_color_non_poly];'> </span>"
|
||||
if(gear.loadout_flags & LOADOUT_CAN_NAME)
|
||||
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_rename=1;loadout_gear_name=[html_encode(gear.name)];'>Name</a> [loadout_item[LOADOUT_CUSTOM_NAME] ? loadout_item[LOADOUT_CUSTOM_NAME] : "N/A"]"
|
||||
if(gear.loadout_flags & LOADOUT_CAN_DESCRIPTION)
|
||||
extra_loadout_data += "<BR><a href='?_src_=prefs;preference=gear;loadout_redescribe=1;loadout_gear_name=[html_encode(gear.name)];'>Description</a>"
|
||||
else if((gear_points - gear.cost) < 0)
|
||||
class_link = "style='white-space:normal;' class='linkOff'"
|
||||
else if(donoritem)
|
||||
class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'"
|
||||
else
|
||||
else if(!istype(gear, /datum/gear/unlockable) || can_use_unlockable(gear))
|
||||
class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'"
|
||||
dat += "<tr style='vertical-align:top;'><td width=15%><a [class_link]>[name]</a></td>"
|
||||
else
|
||||
class_link = "style='white-space:normal;background:#eb2e2e;' class='linkOff'"
|
||||
dat += "<tr style='vertical-align:top;'><td width=15%><a [class_link]>[name]</a>[extra_loadout_data]</td>"
|
||||
dat += "<td width = 5% style='vertical-align:top'>[gear.cost]</td><td>"
|
||||
if(islist(gear.restricted_roles))
|
||||
if(gear.restricted_roles.len)
|
||||
@@ -896,7 +963,17 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<font size=2>"
|
||||
dat += gear.restricted_roles.Join(";")
|
||||
dat += "</font>"
|
||||
dat += "</td><td><font size=2><i>[gear.description]</i></font></td></tr>"
|
||||
if(!istype(gear, /datum/gear/unlockable))
|
||||
// the below line essentially means "if the loadout item is picked by the user and has a custom description, give it the custom description, otherwise give it the default description"
|
||||
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description]</i></font></td></tr>"
|
||||
else
|
||||
//we add the user's progress to the description assuming they have progress
|
||||
var/datum/gear/unlockable/unlockable = gear
|
||||
var/progress_made = unlockable_loadout_data[unlockable.progress_key]
|
||||
if(!progress_made)
|
||||
progress_made = 0
|
||||
dat += "</td><td><font size=2><i>[loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required]</i></font></td></tr>"
|
||||
|
||||
dat += "</table>"
|
||||
if(5) // Content preferences
|
||||
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
|
||||
@@ -917,6 +994,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Breast Enlargement:</b> <a href='?_src_=prefs;preference=breast_enlargement'>[(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Penis Enlargement:</b> <a href='?_src_=prefs;preference=penis_enlargement'>[(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Hypno:</b> <a href='?_src_=prefs;preference=never_hypno'>[(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]</a><br>"
|
||||
dat += "<b>Aphrodisiacs:</b> <a href='?_src_=prefs;preference=aphro'>[(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"]</a><br>"
|
||||
dat += "<b>Ass Slapping:</b> <a href='?_src_=prefs;preference=ass_slap'>[(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]</a><br>"
|
||||
dat += "<b>Automatic Wagging:</b> <a href='?_src_=prefs;preference=auto_wag'>[(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]</a><br>"
|
||||
dat += "</tr></table>"
|
||||
@@ -966,7 +1044,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/list/default_keys = hotkeys ? kb.hotkey_keys : kb.classic_keys
|
||||
if(LAZYLEN(default_keys))
|
||||
dat += "| Default: [default_keys.Join(", ")]"
|
||||
dat += "</span><span class='independent'>Independent Binding: <a href='?_src_=prefs;preference=keybindings_capture;keybinding=[kb.name];old_key=[current_independent_binding];independent=1'>[current_independent_binding]</a></span>"
|
||||
dat += "</span>"
|
||||
if(!kb.special && !kb.clientside)
|
||||
dat += "<span class='independent'>Independent Binding: <a href='?_src_=prefs;preference=keybindings_capture;keybinding=[kb.name];old_key=[current_independent_binding];independent=1'>[current_independent_binding]</a></span>"
|
||||
dat += "<br>"
|
||||
else
|
||||
var/bound_key = user_binds[kb.name][1]
|
||||
@@ -979,7 +1059,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/list/default_keys = hotkeys ? kb.classic_keys : kb.hotkey_keys
|
||||
if(LAZYLEN(default_keys))
|
||||
dat += "| Default: [default_keys.Join(", ")]"
|
||||
dat += "</span><span class='independent'>Independent Binding: <a href='?_src_=prefs;preference=keybindings_capture;keybinding=[kb.name];old_key=[current_independent_binding];independent=1'>[current_independent_binding]</a></span>"
|
||||
dat += "</span>"
|
||||
if(!kb.special && !kb.clientside)
|
||||
dat += "<span class='independent'>Independent Binding: <a href='?_src_=prefs;preference=keybindings_capture;keybinding=[kb.name];old_key=[current_independent_binding];independent=1'>[current_independent_binding]</a></span>"
|
||||
dat += "<br>"
|
||||
|
||||
dat += "<br><br>"
|
||||
@@ -1005,7 +1087,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
#undef APPEARANCE_CATEGORY_COLUMN
|
||||
#undef MAX_MUTANT_ROWS
|
||||
|
||||
/datum/preferences/proc/CaptureKeybinding(mob/user, datum/keybinding/kb, old_key, independent = FALSE)
|
||||
/datum/preferences/proc/CaptureKeybinding(mob/user, datum/keybinding/kb, old_key, independent = FALSE, special = FALSE)
|
||||
var/HTML = {"
|
||||
<div id='focus' style="outline: 0;" tabindex=0>Keybinding: [kb.full_name]<br>[kb.description]<br><br><b>Press any key to change<br>Press ESC to clear</b></div>
|
||||
<script>
|
||||
@@ -1017,7 +1099,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var shift = e.shiftKey ? 1 : 0;
|
||||
var numpad = (95 < e.keyCode && e.keyCode < 112) ? 1 : 0;
|
||||
var escPressed = e.keyCode == 27 ? 1 : 0;
|
||||
var url = 'byond://?_src_=prefs;preference=keybindings_set;keybinding=[kb.name];old_key=[old_key];[independent?"independent=1":""];clear_key='+escPressed+';key='+e.key+';alt='+alt+';ctrl='+ctrl+';shift='+shift+';numpad='+numpad+';key_code='+e.keyCode;
|
||||
var url = 'byond://?_src_=prefs;preference=keybindings_set;keybinding=[kb.name];old_key=[old_key];[independent?"independent=1;":""][special?"special=1;":""]clear_key='+escPressed+';key='+e.key+';alt='+alt+';ctrl='+ctrl+';shift='+shift+';numpad='+numpad+';key_code='+e.keyCode;
|
||||
window.location=url;
|
||||
deedDone = true;
|
||||
}
|
||||
@@ -1549,10 +1631,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/prosthetic_type = input(user, "Choose the type of prosthetic", "Character Preference") as null|anything in (list("prosthetic") + GLOB.prosthetic_limb_types)
|
||||
if(prosthetic_type)
|
||||
var/number_of_prosthetics = 0
|
||||
for(var/modification in modified_limbs)
|
||||
if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC)
|
||||
for(var/modified_limb in modified_limbs)
|
||||
if(modified_limbs[modified_limb][1] == LOADOUT_LIMB_PROSTHETIC && modified_limb != limb_type)
|
||||
number_of_prosthetics += 1
|
||||
if(number_of_prosthetics >= MAXIMUM_LOADOUT_PROSTHETICS && !(limb_type in modified_limbs && modified_limbs[limb_type][1] == LOADOUT_LIMB_PROSTHETIC))
|
||||
if(number_of_prosthetics > MAXIMUM_LOADOUT_PROSTHETICS)
|
||||
to_chat(user, "<span class='danger'>You can only have up to two prosthetic limbs!</span>")
|
||||
else
|
||||
//save the actual prosthetic data
|
||||
@@ -1609,6 +1691,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_eyes)
|
||||
right_eye_color = sanitize_hexcolor(new_eyes, 6)
|
||||
|
||||
if("eye_type")
|
||||
var/new_eye_type = input(user, "Choose your character's eye type.", "Character Preference") as null|anything in GLOB.eye_types
|
||||
if(new_eye_type)
|
||||
eye_type = new_eye_type
|
||||
|
||||
if("toggle_split_eyes")
|
||||
split_eye_colors = !split_eye_colors
|
||||
right_eye_color = left_eye_color
|
||||
@@ -1642,6 +1729,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(features["mcolor3"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
|
||||
features["mcolor3"] = pref_species.default_color
|
||||
|
||||
//switch to the type of eyes the species uses
|
||||
eye_type = pref_species.eye_type
|
||||
|
||||
if("custom_species")
|
||||
var/new_species = reject_bad_name(input(user, "Choose your species subtype, if unique. This will show up on examinations and health scans. Do not abuse this:", "Character Preference", custom_species) as null|text)
|
||||
if(new_species)
|
||||
@@ -1707,6 +1797,24 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_ipc_antenna)
|
||||
features["ipc_antenna"] = new_ipc_antenna
|
||||
|
||||
if("arachnid_legs")
|
||||
var/new_arachnid_legs
|
||||
new_arachnid_legs = input(user, "Choose your character's variant of arachnid legs:", "Character Preference") as null|anything in GLOB.arachnid_legs_list
|
||||
if(new_arachnid_legs)
|
||||
features["arachnid_legs"] = new_arachnid_legs
|
||||
|
||||
if("arachnid_spinneret")
|
||||
var/new_arachnid_spinneret
|
||||
new_arachnid_spinneret = input(user, "Choose your character's spinneret markings:", "Character Preference") as null|anything in GLOB.arachnid_spinneret_list
|
||||
if(new_arachnid_spinneret)
|
||||
features["arachnid_spinneret"] = new_arachnid_spinneret
|
||||
|
||||
if("arachnid_mandibles")
|
||||
var/new_arachnid_mandibles
|
||||
new_arachnid_mandibles = input(user, "Choose your character's variant of mandibles:", "Character Preference") as null|anything in GLOB.arachnid_mandibles_list
|
||||
if (new_arachnid_mandibles)
|
||||
features["arachnid_mandibles"] = new_arachnid_mandibles
|
||||
|
||||
if("tail_lizard")
|
||||
var/new_tail
|
||||
new_tail = input(user, "Choose your character's tail:", "Character Preference") as null|anything in GLOB.tails_list_lizard
|
||||
@@ -1872,6 +1980,24 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_insect_markings)
|
||||
features["insect_markings"] = new_insect_markings
|
||||
|
||||
if("arachnid_legs")
|
||||
var/new_arachnid_legs
|
||||
new_arachnid_legs = input(user, "Choose your character's variant of arachnid legs:", "Character Preference") as null|anything in GLOB.arachnid_legs_list
|
||||
if(new_arachnid_legs)
|
||||
features["arachnid_legs"] = new_arachnid_legs
|
||||
|
||||
if("arachnid_spinneret")
|
||||
var/new_arachnid_spinneret
|
||||
new_arachnid_spinneret = input(user, "Choose your character's spinneret markings:", "Character Preference") as null|anything in GLOB.arachnid_spinneret_list
|
||||
if(new_arachnid_spinneret)
|
||||
features["arachnid_spinneret"] = new_arachnid_spinneret
|
||||
|
||||
if("arachnid_mandibles")
|
||||
var/new_arachnid_mandibles
|
||||
new_arachnid_mandibles = input(user, "Choose your character's variant of mandibles:", "Character Preference") as null|anything in GLOB.arachnid_mandibles_list
|
||||
if (new_arachnid_mandibles)
|
||||
features["arachnid_mandibles"] = new_arachnid_mandibles
|
||||
|
||||
if("s_tone")
|
||||
var/list/choices = GLOB.skin_tones - GLOB.nonstandard_skin_tones
|
||||
if(CONFIG_GET(flag/allow_custom_skintones))
|
||||
@@ -1911,6 +2037,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
features["xenotail"] = "None"
|
||||
features["tail_human"] = "None"
|
||||
features["tail_lizard"] = "None"
|
||||
features["arachnid_spinneret"] = "None"
|
||||
|
||||
if("ears")
|
||||
var/list/snowflake_ears_list = list()
|
||||
@@ -1986,6 +2113,30 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_dors)
|
||||
features["xenodorsal"] = new_dors
|
||||
|
||||
//every single primary/secondary/tertiary colouring done at once
|
||||
if("xenodorsal_primary","xenodorsal_secondary","xenodorsal_tertiary","xhead_primary","xhead_secondary","xhead_tertiary","tail_primary","tail_secondary","tail_tertiary","insect_markings_primary","insect_markings_secondary","insect_markings_tertiary","body_markings_primary","body_markings_secondary","body_markings_tertiary","insect_fluff_primary","insect_fluff_secondary","insect_fluff_tertiary","ears_primary","ears_secondary","ears_tertiary","frills_primary","frills_secondary","frills_tertiary","ipc_antenna_primary","ipc_antenna_secondary","ipc_antenna_tertiary","taur_primary","taur_secondary","taur_tertiary","snout_primary","snout_secondary","snout_tertiary","spines_primary","spines_secondary","spines_tertiary", "mam_body_markings_primary", "mam_body_markings_secondary", "mam_body_markings_tertiary")
|
||||
var/the_feature = features[href_list["preference"]]
|
||||
if(!the_feature)
|
||||
features[href_list["preference"]] = "FFFFFF"
|
||||
the_feature = "FFFFFF"
|
||||
var/new_feature_color = input(user, "Choose your character's mutant part colour:", "Character Preference","#"+features[href_list["preference"]]) as color|null
|
||||
if(new_feature_color)
|
||||
var/temp_hsv = RGBtoHSV(new_feature_color)
|
||||
if(new_feature_color == "#000000")
|
||||
features[href_list["preference"]] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3])
|
||||
features[href_list["preference"]] = sanitize_hexcolor(new_feature_color, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
|
||||
//advanced color mode toggle
|
||||
if("color_scheme")
|
||||
if(features["color_scheme"] == ADVANCED_CHARACTER_COLORING)
|
||||
features["color_scheme"] = OLD_CHARACTER_COLORING
|
||||
else
|
||||
features["color_scheme"] = ADVANCED_CHARACTER_COLORING
|
||||
|
||||
//Genital code
|
||||
if("cock_color")
|
||||
var/new_cockcolor = input(user, "Penis color:", "Character Preference","#"+features["cock_color"]) as color|null
|
||||
@@ -2196,22 +2347,33 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
features["body_model"] = chosengender
|
||||
gender = chosengender
|
||||
|
||||
if("language")
|
||||
choselanguage = input(user, "Select a language.", "Language", language) as null|anything in list("Beachtongue","Draconic","Dwarven",
|
||||
"Chimpanzee","Space Sign Language","Random")
|
||||
if(!choselanguage)
|
||||
return
|
||||
switch(choselanguage)
|
||||
if("Rachidian")
|
||||
language = /datum/language/arachnid
|
||||
if("Beachtongue")
|
||||
language = /datum/language/beachbum
|
||||
if("Draconic")
|
||||
language = /datum/language/draconic
|
||||
if("Dwarven")
|
||||
language = /datum/language/dwarf
|
||||
if("Chimpanzee")
|
||||
language = /datum/language/monkey
|
||||
if("Space Sign Language")
|
||||
language = /datum/language/signlanguage
|
||||
if("Random")
|
||||
language = pick(list("Rachidian", "Beachtongue","Draconic","Dwarven",
|
||||
"Chimpanzee","Space Sign Language"))
|
||||
|
||||
if("body_size")
|
||||
var/min = CONFIG_GET(number/body_size_min)
|
||||
var/max = CONFIG_GET(number/body_size_max)
|
||||
var/danger = CONFIG_GET(number/threshold_body_size_slowdown)
|
||||
var/new_body_size = input(user, "Choose your desired sprite size: ([min*100]%-[max*100]%)\nWarning: This may make your character look distorted[danger > min ? "! Additionally, a proportional movement speed penalty will be applied to characters smaller than [danger*100]%." : "!"]", "Character Preference", features["body_size"]*100) as num|null
|
||||
if (new_body_size)
|
||||
new_body_size = clamp(new_body_size * 0.01, min, max)
|
||||
var/dorfy
|
||||
if((new_body_size + 0.01) < danger) // Adding 0.01 as a dumb fix to prevent the warning message from appearing when exactly at threshold... Not sure why that happens in the first place.
|
||||
dorfy = alert(user, "You have chosen a size below the slowdown threshold of [danger*100]%. For balancing purposes, the further you go below this percentage, the slower your character will be. Do you wish to keep this size?", "Speed Penalty Alert", "Yes", "Move it to the threshold", "No")
|
||||
if(dorfy == "Move it to the threshold")
|
||||
new_body_size = danger
|
||||
if(!dorfy) //Aborts if this var is somehow empty
|
||||
return
|
||||
if(dorfy != "No")
|
||||
features["body_size"] = new_body_size
|
||||
var/new_body_size = input(user, "Choose your desired sprite size: (90-125%)\nWarning: This may make your character look distorted. Additionally, any size under 100% takes a 10% maximum health penalty", "Character Preference", features["body_size"]*100) as num|null
|
||||
if(new_body_size)
|
||||
features["body_size"] = clamp(new_body_size * 0.01, CONFIG_GET(number/body_size_min), CONFIG_GET(number/body_size_max))
|
||||
|
||||
if("tongue")
|
||||
var/selected_custom_tongue = input(user, "Choose your desired tongue (none means your species tongue)", "Character Preference") as null|anything in GLOB.roundstart_tongues
|
||||
if(selected_custom_tongue)
|
||||
@@ -2258,7 +2420,32 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
features["has_womb"] = !features["has_womb"]
|
||||
if("widescreenpref")
|
||||
widescreenpref = !widescreenpref
|
||||
user.client.change_view(CONFIG_GET(string/default_view))
|
||||
user.client.view_size.setDefault(getScreenSize(widescreenpref))
|
||||
|
||||
if("pixel_size")
|
||||
switch(pixel_size)
|
||||
if(PIXEL_SCALING_AUTO)
|
||||
pixel_size = PIXEL_SCALING_1X
|
||||
if(PIXEL_SCALING_1X)
|
||||
pixel_size = PIXEL_SCALING_1_2X
|
||||
if(PIXEL_SCALING_1_2X)
|
||||
pixel_size = PIXEL_SCALING_2X
|
||||
if(PIXEL_SCALING_2X)
|
||||
pixel_size = PIXEL_SCALING_3X
|
||||
if(PIXEL_SCALING_3X)
|
||||
pixel_size = PIXEL_SCALING_AUTO
|
||||
user.client.view_size.apply() //Let's winset() it so it actually works
|
||||
|
||||
if("scaling_method")
|
||||
switch(scaling_method)
|
||||
if(SCALING_METHOD_NORMAL)
|
||||
scaling_method = SCALING_METHOD_DISTORT
|
||||
if(SCALING_METHOD_DISTORT)
|
||||
scaling_method = SCALING_METHOD_BLUR
|
||||
if(SCALING_METHOD_BLUR)
|
||||
scaling_method = SCALING_METHOD_NORMAL
|
||||
user.client.view_size.setZoomMode()
|
||||
|
||||
if("autostand")
|
||||
autostand = !autostand
|
||||
if("auto_ooc")
|
||||
@@ -2291,11 +2478,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
if("hotkeys")
|
||||
hotkeys = !hotkeys
|
||||
user.client.set_macros()
|
||||
user.client.ensure_keys_set(src)
|
||||
|
||||
if("keybindings_capture")
|
||||
var/datum/keybinding/kb = GLOB.keybindings_by_name[href_list["keybinding"]]
|
||||
CaptureKeybinding(user, kb, href_list["old_key"], text2num(href_list["independent"]))
|
||||
CaptureKeybinding(user, kb, href_list["old_key"], text2num(href_list["independent"]), kb.special || kb.clientside)
|
||||
return
|
||||
|
||||
if("keybindings_set")
|
||||
@@ -2315,9 +2502,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
else
|
||||
if(key_bindings[old_key])
|
||||
key_bindings[old_key] -= kb_name
|
||||
LAZYADD(key_bindings["Unbound"], kb_name)
|
||||
if(!length(key_bindings[old_key]))
|
||||
key_bindings -= old_key
|
||||
user << browse(null, "window=capturekeypress")
|
||||
if(href_list["special"]) // special keys need a full reset
|
||||
user.client.ensure_keys_set(src)
|
||||
save_preferences()
|
||||
ShowChoices(user)
|
||||
return
|
||||
@@ -2352,7 +2542,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
key_bindings -= old_key
|
||||
key_bindings[full_key] += list(kb_name)
|
||||
key_bindings[full_key] = sortList(key_bindings[full_key])
|
||||
user.client.update_movement_keys()
|
||||
if(href_list["special"]) // special keys need a full reset
|
||||
user.client.ensure_keys_set(src)
|
||||
user << browse(null, "window=capturekeypress")
|
||||
save_preferences()
|
||||
|
||||
@@ -2364,7 +2555,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
hotkeys = (choice == "Hotkey")
|
||||
key_bindings = (hotkeys) ? deepCopyList(GLOB.hotkey_keybinding_list_by_key) : deepCopyList(GLOB.classic_keybinding_list_by_key)
|
||||
modless_key_bindings = list()
|
||||
user.client.update_movement_keys()
|
||||
user.client.ensure_keys_set(src)
|
||||
|
||||
if("chat_on_map")
|
||||
chat_on_map = !chat_on_map
|
||||
@@ -2539,8 +2730,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
current_tab = text2num(href_list["tab"])
|
||||
if(href_list["preference"] == "gear")
|
||||
if(href_list["clear_loadout"])
|
||||
chosen_gear = list()
|
||||
gear_points = CONFIG_GET(number/initial_gear_points)
|
||||
loadout_data["SAVE_[loadout_slot]"] = list()
|
||||
save_preferences()
|
||||
if(href_list["select_category"])
|
||||
gear_category = html_decode(href_list["select_category"])
|
||||
@@ -2553,19 +2743,76 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(!G)
|
||||
return
|
||||
var/toggle = text2num(href_list["toggle_gear"])
|
||||
if(!toggle && (G.type in chosen_gear))//toggling off and the item effectively is in chosen gear)
|
||||
chosen_gear -= G.type
|
||||
gear_points += initial(G.cost)
|
||||
else if(toggle && (!(is_type_in_ref_list(G, chosen_gear))))
|
||||
if(!toggle && has_loadout_gear(loadout_slot, "[G.type]"))//toggling off and the item effectively is in chosen gear)
|
||||
remove_gear_from_loadout(loadout_slot, "[G.type]")
|
||||
else if(toggle && !(has_loadout_gear(loadout_slot, "[G.type]")))
|
||||
if(!is_loadout_slot_available(G.category))
|
||||
to_chat(user, "<span class='danger'>You cannot take this loadout, as you've already chosen too many of the same category!</span>")
|
||||
return
|
||||
if(G.donoritem && !G.donator_ckey_check(user.ckey))
|
||||
to_chat(user, "<span class='danger'>This is an item intended for donator use only. You are not authorized to use this item.</span>")
|
||||
return
|
||||
if(istype(G, /datum/gear/unlockable) && !can_use_unlockable(G))
|
||||
to_chat(user, "<span class='danger'>To use this item, you need to meet the defined requirements!</span>")
|
||||
return
|
||||
if(gear_points >= initial(G.cost))
|
||||
chosen_gear += G.type
|
||||
gear_points -= initial(G.cost)
|
||||
var/list/new_loadout_data = list(LOADOUT_ITEM = "[G.type]")
|
||||
if(length(G.loadout_initial_colors))
|
||||
new_loadout_data[LOADOUT_COLOR] = G.loadout_initial_colors
|
||||
else
|
||||
new_loadout_data[LOADOUT_COLOR] = list("#FFFFFF")
|
||||
if(loadout_data["SAVE_[loadout_slot]"])
|
||||
loadout_data["SAVE_[loadout_slot]"] += list(new_loadout_data) //double packed because it does the union of the CONTENTS of the lists
|
||||
else
|
||||
loadout_data["SAVE_[loadout_slot]"] = list(new_loadout_data) //double packed because you somehow had no save slot in your loadout?
|
||||
|
||||
if(href_list["loadout_color"] || href_list["loadout_color_polychromic"] || href_list["loadout_rename"] || href_list["loadout_redescribe"])
|
||||
//if the gear doesn't exist, or they don't have it, ignore the request
|
||||
var/name = html_decode(href_list["loadout_gear_name"])
|
||||
var/datum/gear/G = GLOB.loadout_items[gear_category][gear_subcategory][name]
|
||||
if(!G)
|
||||
return
|
||||
var/user_gear = has_loadout_gear(loadout_slot, "[G.type]")
|
||||
if(!user_gear)
|
||||
return
|
||||
|
||||
//possible requests: recolor, recolor (polychromic), rename, redescribe
|
||||
//always make sure the gear allows said request before proceeding
|
||||
|
||||
//non-poly coloring can only be done by non-poly items
|
||||
if(href_list["loadout_color"] && !(G.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC))
|
||||
if(!length(user_gear[LOADOUT_COLOR]))
|
||||
user_gear[LOADOUT_COLOR] = list("#FFFFFF")
|
||||
var/current_color = user_gear[LOADOUT_COLOR][1]
|
||||
var/new_color = input(user, "Polychromic options", "Choose Color", current_color) as color|null
|
||||
user_gear[LOADOUT_COLOR][1] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
|
||||
|
||||
//poly coloring can only be done by poly items
|
||||
if(href_list["loadout_color_polychromic"] && (G.loadout_flags & LOADOUT_CAN_COLOR_POLYCHROMIC))
|
||||
var/list/color_options = list()
|
||||
for(var/i=1, i<=length(G.loadout_initial_colors), i++)
|
||||
color_options += "Color [i]"
|
||||
var/color_to_change = input(user, "Polychromic options", "Recolor [name]") as null|anything in color_options
|
||||
if(color_to_change)
|
||||
var/color_index = text2num(copytext(color_to_change, 7))
|
||||
var/current_color = user_gear[LOADOUT_COLOR][color_index]
|
||||
var/new_color = input(user, "Polychromic options", "Choose [color_to_change] Color", current_color) as color|null
|
||||
if(new_color)
|
||||
user_gear[LOADOUT_COLOR][color_index] = sanitize_hexcolor(new_color, 6, TRUE, current_color)
|
||||
|
||||
//both renaming and redescribing strip the input to stop html injection
|
||||
|
||||
//renaming is only allowed if it has the flag for it
|
||||
if(href_list["loadout_rename"] && (G.loadout_flags & LOADOUT_CAN_NAME))
|
||||
var/new_name = stripped_input(user, "Enter new name for item. Maximum [MAX_NAME_LEN] characters.", "Loadout Item Naming", null, MAX_NAME_LEN)
|
||||
if(new_name)
|
||||
user_gear[LOADOUT_CUSTOM_NAME] = new_name
|
||||
|
||||
//redescribing is only allowed if it has the flag for it
|
||||
if(href_list["loadout_redescribe"] && (G.loadout_flags & LOADOUT_CAN_DESCRIPTION)) //redescribe isnt a real word but i can't think of the right term to use
|
||||
var/new_description = stripped_input(user, "Enter new description for item. Maximum 500 characters.", "Loadout Item Redescribing", null, 500)
|
||||
if(new_description)
|
||||
user_gear[LOADOUT_CUSTOM_DESCRIPTION] = new_description
|
||||
|
||||
ShowChoices(user)
|
||||
return 1
|
||||
@@ -2586,6 +2833,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
else if(firstspace == name_length)
|
||||
real_name += "[pick(GLOB.last_names)]"
|
||||
|
||||
//reset size if applicable
|
||||
if(character.dna.features["body_size"])
|
||||
var/initial_old_size = character.dna.features["body_size"]
|
||||
character.dna.features["body_size"] = RESIZE_DEFAULT_SIZE
|
||||
character.dna.update_body_size(initial_old_size)
|
||||
|
||||
character.real_name = nameless ? "[real_name] #[rand(10000, 99999)]" : real_name
|
||||
character.name = character.real_name
|
||||
character.nameless = nameless
|
||||
@@ -2628,16 +2881,19 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
pref_species = new /datum/species/human
|
||||
save_character()
|
||||
|
||||
var/old_size = character.dna.features["body_size"]
|
||||
|
||||
character.dna.features = features.Copy()
|
||||
character.set_species(chosen_species, icon_update = FALSE, pref_load = TRUE)
|
||||
character.dna.species.eye_type = eye_type
|
||||
if(chosen_limb_id && (chosen_limb_id in character.dna.species.allowed_limb_ids))
|
||||
character.dna.species.mutant_bodyparts["limbs_id"] = chosen_limb_id
|
||||
character.dna.real_name = character.real_name
|
||||
character.dna.nameless = character.nameless
|
||||
character.dna.custom_species = character.custom_species
|
||||
|
||||
var/old_size = RESIZE_DEFAULT_SIZE
|
||||
if(isdwarf(character))
|
||||
character.dna.features["body_size"] = RESIZE_DEFAULT_SIZE
|
||||
|
||||
if((parent && parent.can_have_part("meat_type")) || pref_species.mutant_bodyparts["meat_type"])
|
||||
character.type_of_meat = GLOB.meat_types[features["meat_type"]]
|
||||
|
||||
@@ -2676,7 +2932,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(initial_spawn)
|
||||
//delete any existing prosthetic limbs to make sure no remnant prosthetics are left over - But DO NOT delete those that are species-related
|
||||
for(var/obj/item/bodypart/part in character.bodyparts)
|
||||
if(part.status == BODYPART_ROBOTIC && !part.render_like_organic)
|
||||
if(part.is_robotic_limb(FALSE))
|
||||
qdel(part)
|
||||
character.regenerate_limbs() //regenerate limbs so now you only have normal limbs
|
||||
for(var/modified_limb in modified_limbs)
|
||||
@@ -2699,8 +2955,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
new_limb.replace_limb(character)
|
||||
qdel(old_part)
|
||||
|
||||
character.regenerate_icons()
|
||||
|
||||
SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks)
|
||||
|
||||
//let's be sure the character updates
|
||||
@@ -2761,23 +3015,27 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
cached_holoform_icons[filter_type] = process_holoform_icon_filter(custom_holoform_icon, filter_type)
|
||||
return cached_holoform_icons[filter_type]
|
||||
|
||||
//Used in savefile update 32, can be removed once that is no longer relevant.
|
||||
/// Resets the client's keybindings. Asks them for which
|
||||
/datum/preferences/proc/force_reset_keybindings()
|
||||
var/choice = tgalert(parent.mob, "Your basic keybindings need to be reset, emotes will remain as before. Would you prefer 'hotkey' or 'classic' mode?", "Reset keybindings", "Hotkey", "Classic")
|
||||
hotkeys = (choice != "Classic")
|
||||
force_reset_keybindings_direct(hotkeys)
|
||||
|
||||
/// Does the actual reset
|
||||
/datum/preferences/proc/force_reset_keybindings_direct(hotkeys = TRUE)
|
||||
var/list/oldkeys = key_bindings
|
||||
key_bindings = (hotkeys) ? deepCopyList(GLOB.hotkey_keybinding_list_by_key) : deepCopyList(GLOB.classic_keybinding_list_by_key)
|
||||
|
||||
for(var/key in oldkeys)
|
||||
if(!key_bindings[key])
|
||||
key_bindings[key] = oldkeys[key]
|
||||
parent.update_movement_keys()
|
||||
parent?.ensure_keys_set(src)
|
||||
|
||||
/datum/preferences/proc/is_loadout_slot_available(slot)
|
||||
var/list/L
|
||||
LAZYINITLIST(L)
|
||||
for(var/i in chosen_gear)
|
||||
var/datum/gear/G = i
|
||||
for(var/i in loadout_data["SAVE_[loadout_slot]"])
|
||||
var/datum/gear/G = i[LOADOUT_ITEM]
|
||||
var/occupied_slots = L[initial(G.category)] ? L[initial(G.category)] + 1 : 1
|
||||
LAZYSET(L, initial(G.category), occupied_slots)
|
||||
switch(slot)
|
||||
@@ -2791,6 +3049,23 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(L[slot] < DEFAULT_SLOT_AMT)
|
||||
return TRUE
|
||||
|
||||
/datum/preferences/proc/has_loadout_gear(save_slot, gear_type)
|
||||
var/list/gear_list = loadout_data["SAVE_[save_slot]"]
|
||||
for(var/loadout_gear in gear_list)
|
||||
if(loadout_gear[LOADOUT_ITEM] == gear_type)
|
||||
return loadout_gear
|
||||
return FALSE
|
||||
|
||||
/datum/preferences/proc/remove_gear_from_loadout(save_slot, gear_type)
|
||||
var/find_gear = has_loadout_gear(save_slot, gear_type)
|
||||
if(find_gear)
|
||||
loadout_data["SAVE_[save_slot]"] -= list(find_gear)
|
||||
|
||||
/datum/preferences/proc/can_use_unlockable(datum/gear/unlockable/unlockable_gear)
|
||||
if(unlockable_loadout_data[unlockable_gear.progress_key] >= unlockable_gear.progress_required)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
#undef DEFAULT_SLOT_AMT
|
||||
#undef HANDS_SLOT_AMT
|
||||
#undef BACKPACK_SLOT_AMT
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// You do not need to raise this if you are adding new values that have sane defaults.
|
||||
// Only raise this value when changing the meaning/format/name/layout of an existing value
|
||||
// where you would want the updater procs below to run
|
||||
#define SAVEFILE_VERSION_MAX 36
|
||||
#define SAVEFILE_VERSION_MAX 48
|
||||
|
||||
/*
|
||||
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
|
||||
@@ -42,7 +42,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
//if your savefile is 3 months out of date, then 'tough shit'.
|
||||
|
||||
/datum/preferences/proc/update_preferences(current_version, savefile/S)
|
||||
if(current_version < 32) //If you remove this, remove force_reset_keybindings() too.
|
||||
if(current_version < 46) //If you remove this, remove force_reset_keybindings() too.
|
||||
force_reset_keybindings_direct(TRUE)
|
||||
addtimer(CALLBACK(src, .proc/force_reset_keybindings), 30) //No mob available when this is run, timer allows user choice.
|
||||
|
||||
/datum/preferences/proc/update_character(current_version, savefile/S)
|
||||
@@ -204,24 +205,104 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
if(S["species"] == "lizard")
|
||||
features["mam_snouts"] = features["snout"]
|
||||
|
||||
if(current_version < 36)
|
||||
if(current_version < 36) //introduction of heterochromia
|
||||
left_eye_color = S["eye_color"]
|
||||
right_eye_color = S["eye_color"]
|
||||
|
||||
if(current_version < 37) //introduction of chooseable eye types/sprites
|
||||
if(S["species"] == "insect")
|
||||
left_eye_color = "#000000"
|
||||
right_eye_color = "#000000"
|
||||
if(chosen_limb_id == "moth" || chosen_limb_id == "moth_not_greyscale") //these actually have slightly different eyes!
|
||||
eye_type = "moth"
|
||||
else
|
||||
eye_type = "insect"
|
||||
|
||||
if(current_version < 38) //further eye sprite changes
|
||||
if(S["species"] == "plasmaman")
|
||||
left_eye_color = "#FFC90E"
|
||||
right_eye_color = "#FFC90E"
|
||||
else
|
||||
if(S["species"] == "skeleton")
|
||||
left_eye_color = "#BAB99E"
|
||||
right_eye_color = "#BAB99E"
|
||||
|
||||
if(current_version < 43) //extreme changes to how things are coloured (the introduction of the advanced coloring system)
|
||||
features["color_scheme"] = OLD_CHARACTER_COLORING //disable advanced coloring system by default
|
||||
for(var/feature in features)
|
||||
var/feature_value = features[feature]
|
||||
if(feature_value)
|
||||
var/ref_list = GLOB.mutant_reference_list[feature]
|
||||
if(ref_list)
|
||||
var/datum/sprite_accessory/accessory = ref_list[feature_value]
|
||||
if(accessory)
|
||||
var/mutant_string = accessory.mutant_part_string
|
||||
if(!mutant_string)
|
||||
if(istype(accessory, /datum/sprite_accessory/mam_body_markings))
|
||||
mutant_string = "mam_body_markings"
|
||||
var/primary_string = "[mutant_string]_primary"
|
||||
var/secondary_string = "[mutant_string]_secondary"
|
||||
var/tertiary_string = "[mutant_string]_tertiary"
|
||||
if(accessory.color_src == MATRIXED && !accessory.matrixed_sections && feature_value != "None")
|
||||
message_admins("Sprite Accessory Failure (migration from [current_version] to 39): Accessory [accessory.type] is a matrixed item without any matrixed sections set!")
|
||||
continue
|
||||
var/primary_exists = features[primary_string]
|
||||
var/secondary_exists = features[secondary_string]
|
||||
var/tertiary_exists = features[tertiary_string]
|
||||
if(accessory.color_src == MATRIXED && !primary_exists && !secondary_exists && !tertiary_exists)
|
||||
features[primary_string] = features["mcolor"]
|
||||
features[secondary_string] = features["mcolor2"]
|
||||
features[tertiary_string] = features["mcolor3"]
|
||||
else if(accessory.color_src == MUTCOLORS && !primary_exists)
|
||||
features[primary_string] = features["mcolor"]
|
||||
else if(accessory.color_src == MUTCOLORS2 && !secondary_exists)
|
||||
features[secondary_string] = features["mcolor2"]
|
||||
else if(accessory.color_src == MUTCOLORS3 && !tertiary_exists)
|
||||
features[tertiary_string] = features["mcolor3"]
|
||||
|
||||
features["color_scheme"] = OLD_CHARACTER_COLORING //advanced is off by default
|
||||
|
||||
if(current_version < 47) //loadout save gets changed to json
|
||||
var/text_to_load
|
||||
S["loadout"] >> text_to_load
|
||||
var/list/saved_loadout_paths = splittext(text_to_load, "|")
|
||||
//MAXIMUM_LOADOUT_SAVES save slots per loadout now
|
||||
for(var/i=1, i<= MAXIMUM_LOADOUT_SAVES, i++)
|
||||
loadout_data["SAVE_[i]"] = list()
|
||||
for(var/some_gear_item in saved_loadout_paths)
|
||||
if(!ispath(text2path(some_gear_item)))
|
||||
log_game("Failed to copy item [some_gear_item] to new loadout system when migrating from version [current_version] to 40, issue: item is not a path")
|
||||
continue
|
||||
var/datum/gear/gear_item = text2path(some_gear_item)
|
||||
if(!(initial(gear_item.loadout_flags) & LOADOUT_CAN_COLOR_POLYCHROMIC))
|
||||
loadout_data["SAVE_1"] += list(list(LOADOUT_ITEM = some_gear_item)) //for the migration we put their old save into the first save slot, which is loaded by default!
|
||||
else
|
||||
//the same but we setup some new polychromic data (you can't get the initial value for a list so we have to do this horrible thing here)
|
||||
var/datum/gear/temporary_gear_item = new gear_item
|
||||
loadout_data["SAVE_1"] += list(list(LOADOUT_ITEM = some_gear_item, LOADOUT_COLOR = temporary_gear_item.loadout_initial_colors))
|
||||
qdel(temporary_gear_item)
|
||||
//it's double packed into a list because += will union the two lists contents
|
||||
|
||||
S["loadout"] = safe_json_encode(loadout_data)
|
||||
|
||||
if(current_version < 48) //unlockable loadout items but we need to clear bad data from a mistake
|
||||
S["unlockable_loadout"] = list()
|
||||
|
||||
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
|
||||
if(!ckey)
|
||||
return
|
||||
path = "data/player_saves/[ckey[1]]/[ckey]/[filename]"
|
||||
vr_path = "data/player_saves/[ckey[1]]/[ckey]/vore"
|
||||
|
||||
/datum/preferences/proc/load_preferences()
|
||||
/datum/preferences/proc/load_preferences(bypass_cooldown = FALSE)
|
||||
if(!path)
|
||||
return FALSE
|
||||
if(world.time < loadprefcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to load your preferences a little too fast. Wait half a second, then try again.</span>")
|
||||
return FALSE
|
||||
loadprefcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
if(!bypass_cooldown)
|
||||
if(world.time < loadprefcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to load your preferences a little too fast. Wait half a second, then try again.</span>")
|
||||
return FALSE
|
||||
loadprefcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
if(!fexists(path))
|
||||
return FALSE
|
||||
|
||||
@@ -271,6 +352,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["parallax"] >> parallax
|
||||
S["ambientocclusion"] >> ambientocclusion
|
||||
S["auto_fit_viewport"] >> auto_fit_viewport
|
||||
S["widescreenpref"] >> widescreenpref
|
||||
S["pixel_size"] >> pixel_size
|
||||
S["scaling_method"] >> scaling_method
|
||||
S["hud_toggle_flash"] >> hud_toggle_flash
|
||||
S["hud_toggle_color"] >> hud_toggle_color
|
||||
S["menuoptions"] >> menuoptions
|
||||
@@ -288,7 +372,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["arousable"] >> arousable
|
||||
S["screenshake"] >> screenshake
|
||||
S["damagescreenshake"] >> damagescreenshake
|
||||
S["widescreenpref"] >> widescreenpref
|
||||
S["autostand"] >> autostand
|
||||
S["cit_toggles"] >> cit_toggles
|
||||
S["preferred_chaos"] >> preferred_chaos
|
||||
@@ -304,8 +387,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
fcopy(S, bacpath) //byond helpfully lets you use a savefile for the first arg.
|
||||
update_preferences(needs_update, S) //needs_update = savefile_version if we need an update (positive integer)
|
||||
|
||||
|
||||
|
||||
//Sanitize
|
||||
ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor)))
|
||||
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
||||
@@ -324,6 +405,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
|
||||
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
|
||||
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
|
||||
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
|
||||
pixel_size = sanitize_integer(pixel_size, PIXEL_SCALING_AUTO, PIXEL_SCALING_3X, initial(pixel_size))
|
||||
scaling_method = sanitize_text(scaling_method, initial(scaling_method))
|
||||
hud_toggle_flash = sanitize_integer(hud_toggle_flash, 0, 1, initial(hud_toggle_flash))
|
||||
hud_toggle_color = sanitize_hexcolor(hud_toggle_color, 6, 1, initial(hud_toggle_color))
|
||||
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
|
||||
@@ -337,7 +421,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
pda_skin = sanitize_inlist(pda_skin, GLOB.pda_reskins, PDA_SKIN_ALT)
|
||||
screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake))
|
||||
damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
|
||||
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
|
||||
autostand = sanitize_integer(autostand, 0, 1, initial(autostand))
|
||||
cit_toggles = sanitize_integer(cit_toggles, 0, 16777215, initial(cit_toggles))
|
||||
auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc))
|
||||
@@ -347,6 +430,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
verify_keybindings_valid() // one of these days this will runtime and you'll be glad that i put it in a different proc so no one gets their saves wiped
|
||||
|
||||
if(S["unlockable_loadout"])
|
||||
unlockable_loadout_data = safe_json_decode(S["unlockable_loadout"])
|
||||
else
|
||||
unlockable_loadout_data = list()
|
||||
|
||||
if(needs_update >= 0) //save the updated version
|
||||
var/old_default_slot = default_slot
|
||||
var/old_max_save_slots = max_save_slots
|
||||
@@ -359,11 +447,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
continue
|
||||
max_save_slots = max(max_save_slots, slotnum) //so we can still update byond member slots after they lose memeber status
|
||||
default_slot = slotnum
|
||||
if (load_character()) // this updtates char slots
|
||||
save_character()
|
||||
if (load_character(null, TRUE)) // this updtates char slots
|
||||
save_character(TRUE)
|
||||
default_slot = old_default_slot
|
||||
max_save_slots = old_max_save_slots
|
||||
save_preferences()
|
||||
save_preferences(TRUE)
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -385,14 +473,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
if(!GLOB.keybindings_by_name[bindname])
|
||||
modless_key_bindings -= key
|
||||
|
||||
/datum/preferences/proc/save_preferences()
|
||||
/datum/preferences/proc/save_preferences(bypass_cooldown = FALSE)
|
||||
if(!path)
|
||||
return 0
|
||||
if(world.time < saveprefcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to save your preferences a little too fast. Wait half a second, then try again.</span>")
|
||||
return 0
|
||||
saveprefcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
if(!bypass_cooldown)
|
||||
if(world.time < saveprefcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to save your preferences a little too fast. Wait half a second, then try again.</span>")
|
||||
return 0
|
||||
saveprefcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(!S)
|
||||
return 0
|
||||
@@ -451,21 +540,29 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["auto_ooc"], auto_ooc)
|
||||
WRITE_FILE(S["no_tetris_storage"], no_tetris_storage)
|
||||
|
||||
if(length(unlockable_loadout_data))
|
||||
WRITE_FILE(S["unlockable_loadout"], safe_json_encode(unlockable_loadout_data))
|
||||
else
|
||||
WRITE_FILE(S["unlockable_loadout"], safe_json_encode(list()))
|
||||
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/load_character(slot)
|
||||
/datum/preferences/proc/load_character(slot, bypass_cooldown = FALSE)
|
||||
if(!path)
|
||||
return FALSE
|
||||
if(world.time < loadcharcooldown) //This is before the check to see if the filepath exists to ensure that BYOND can't get hung up on read attempts when the hard drive is a little slow
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to load your character a little too fast. Wait half a second, then try again.</span>")
|
||||
return "SLOW THE FUCK DOWN" //the reason this isn't null is to make sure that people don't have their character slots overridden by random chars if they accidentally double-click a slot
|
||||
loadcharcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
if(!bypass_cooldown)
|
||||
if(world.time < loadcharcooldown) //This is before the check to see if the filepath exists to ensure that BYOND can't get hung up on read attempts when the hard drive is a little slow
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to load your character a little too fast. Wait half a second, then try again.</span>")
|
||||
return "SLOW THE FUCK DOWN" //the reason this isn't null is to make sure that people don't have their character slots overridden by random chars if they accidentally double-click a slot
|
||||
loadcharcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
if(!fexists(path))
|
||||
return FALSE
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(!S)
|
||||
return FALSE
|
||||
features = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF", "mcolor3" = "FFFFFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "horns_color" = "85615a", "ears" = "None", "wings" = "None", "wings_color" = "FFF", "frills" = "None", "deco_wings" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Plantigrade", "insect_wings" = "Plain", "insect_fluff" = "None", "insect_markings" = "None", "arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain", "mam_body_markings" = "Plain", "mam_ears" = "None", "mam_snouts" = "None", "mam_tail" = "None", "mam_tail_animated" = "None", "xenodorsal" = "Standard", "xenohead" = "Standard", "xenotail" = "Xenomorph Tail", "taur" = "None", "genitals_use_skintone" = FALSE, "has_cock" = FALSE, "cock_shape" = DEF_COCK_SHAPE, "cock_length" = COCK_SIZE_DEF, "cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF, "cock_color" = "ffffff", "cock_taur" = FALSE, "has_balls" = FALSE, "balls_color" = "ffffff", "balls_shape" = DEF_BALLS_SHAPE, "balls_size" = BALLS_SIZE_DEF, "balls_cum_rate" = CUM_RATE, "balls_cum_mult" = CUM_RATE_MULT, "balls_efficiency" = CUM_EFFICIENCY, "has_breasts" = FALSE, "breasts_color" = "ffffff", "breasts_size" = BREASTS_SIZE_DEF, "breasts_shape" = DEF_BREASTS_SHAPE, "breasts_producing" = FALSE, "has_vag" = FALSE, "vag_shape" = DEF_VAGINA_SHAPE, "vag_color" = "ffffff", "has_womb" = FALSE, "balls_visibility" = GEN_VISIBLE_NO_UNDIES, "breasts_visibility"= GEN_VISIBLE_NO_UNDIES, "cock_visibility" = GEN_VISIBLE_NO_UNDIES, "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", "silicon_flavor_text" = "", "ooc_notes" = "", "meat_type" = "Mammalian", "body_model" = MALE, "body_size" = RESIZE_DEFAULT_SIZE, "color_scheme" = OLD_CHARACTER_COLORING)
|
||||
|
||||
S.cd = "/"
|
||||
if(!slot)
|
||||
slot = default_slot
|
||||
@@ -507,8 +604,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["body_model"] >> features["body_model"]
|
||||
S["body_size"] >> features["body_size"]
|
||||
S["age"] >> age
|
||||
S["language"] >> language
|
||||
S["choselanguage"] >> choselanguage
|
||||
S["hair_color"] >> hair_color
|
||||
S["facial_hair_color"] >> facial_hair_color
|
||||
S["eye_type"] >> eye_type
|
||||
S["left_eye_color"] >> left_eye_color
|
||||
S["right_eye_color"] >> right_eye_color
|
||||
S["use_custom_skin_tone"] >> use_custom_skin_tone
|
||||
@@ -541,8 +641,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["feature_insect_wings"] >> features["insect_wings"]
|
||||
S["feature_insect_fluff"] >> features["insect_fluff"]
|
||||
S["feature_insect_markings"] >> features["insect_markings"]
|
||||
S["feature_arachnid_legs"] >> features["arachnid_legs"]
|
||||
S["feature_arachnid_spinneret"] >> features["arachnid_spinneret"]
|
||||
S["feature_arachnid_mandibles"] >> features["arachnid_mandibles"]
|
||||
S["feature_horns_color"] >> features["horns_color"]
|
||||
S["feature_wings_color"] >> features["wings_color"]
|
||||
S["feature_color_scheme"] >> features["color_scheme"]
|
||||
S["persistent_scars"] >> persistent_scars
|
||||
S["scars1"] >> scars_list["1"]
|
||||
S["scars2"] >> scars_list["2"]
|
||||
@@ -555,6 +659,21 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
modified_limbs = safe_json_decode(limbmodstr)
|
||||
else
|
||||
modified_limbs = list()
|
||||
|
||||
var/tcgcardstr
|
||||
S["tcg_cards"] >> tcgcardstr
|
||||
if(length(tcgcardstr))
|
||||
tcg_cards = safe_json_decode(tcgcardstr)
|
||||
else
|
||||
tcg_cards = list()
|
||||
|
||||
var/tcgdeckstr
|
||||
S["tcg_decks"] >> tcgdeckstr
|
||||
if(length(tcgdeckstr))
|
||||
tcg_decks = safe_json_decode(tcgdeckstr)
|
||||
else
|
||||
tcg_decks = list()
|
||||
|
||||
S["chosen_limb_id"] >> chosen_limb_id
|
||||
S["hide_ckey"] >> hide_ckey //saved per-character
|
||||
|
||||
@@ -568,6 +687,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
//Jobs
|
||||
S["joblessrole"] >> joblessrole
|
||||
|
||||
//Load prefs
|
||||
S["job_preferences"] >> job_preferences
|
||||
|
||||
@@ -620,6 +740,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["feature_vag_visibility"] >> features["vag_visibility"]
|
||||
//womb features
|
||||
S["feature_has_womb"] >> features["has_womb"]
|
||||
|
||||
//flavor text
|
||||
//Let's make our players NOT cry desperately as we wipe their savefiles of their special snowflake texts:
|
||||
if((S["flavor_text"] != "") && (S["flavor_text"] != null) && S["flavor_text"]) //If old text isn't null and isn't "" but still exists.
|
||||
@@ -644,20 +765,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
var/list/json_from_file = json_decode(file2text(char_vr_path))
|
||||
if(json_from_file)
|
||||
belly_prefs = json_from_file["belly_prefs"]
|
||||
|
||||
//gear loadout
|
||||
var/text_to_load
|
||||
S["loadout"] >> text_to_load
|
||||
var/list/saved_loadout_paths = splittext(text_to_load, "|")
|
||||
chosen_gear = list()
|
||||
gear_points = CONFIG_GET(number/initial_gear_points)
|
||||
for(var/i in saved_loadout_paths)
|
||||
var/datum/gear/path = text2path(i)
|
||||
if(path)
|
||||
var/init_cost = initial(path.cost)
|
||||
if(init_cost > gear_points)
|
||||
continue
|
||||
chosen_gear += path
|
||||
gear_points -= init_cost
|
||||
if(S["loadout"])
|
||||
loadout_data = safe_json_decode(S["loadout"])
|
||||
else
|
||||
loadout_data = list()
|
||||
|
||||
//try to fix any outdated data if necessary
|
||||
//preference updating will handle saving the updated data for us.
|
||||
@@ -693,6 +806,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
|
||||
hair_color = sanitize_hexcolor(hair_color, 6, FALSE)
|
||||
facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE)
|
||||
eye_type = sanitize_inlist(eye_type, GLOB.eye_types, DEFAULT_EYES_TYPE)
|
||||
left_eye_color = sanitize_hexcolor(left_eye_color, 6, FALSE)
|
||||
right_eye_color = sanitize_hexcolor(right_eye_color, 6, FALSE)
|
||||
|
||||
@@ -724,6 +838,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
features["insect_fluff"] = sanitize_inlist(features["insect_fluff"], GLOB.insect_fluffs_list)
|
||||
features["insect_markings"] = sanitize_inlist(features["insect_markings"], GLOB.insect_markings_list, "None")
|
||||
features["insect_wings"] = sanitize_inlist(features["insect_wings"], GLOB.insect_wings_list)
|
||||
features["arachnid_legs"] = sanitize_inlist(features["arachnid_legs"], GLOB.arachnid_legs_list, "Plain")
|
||||
features["arachnid_spinneret"] = sanitize_inlist(features["arachnid_spinneret"], GLOB.arachnid_spinneret_list, "Plain")
|
||||
features["arachnid_mandibles"] = sanitize_inlist(features["arachnid_mandibles"], GLOB.arachnid_mandibles_list, "Plain")
|
||||
|
||||
var/static/size_min
|
||||
if(!size_min)
|
||||
@@ -774,6 +891,32 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN)
|
||||
features["ooc_notes"] = copytext(features["ooc_notes"], 1, MAX_FLAVOR_LEN)
|
||||
|
||||
//load every advanced coloring mode thing in one go
|
||||
//THIS MUST BE DONE AFTER ALL FEATURE SAVES OR IT WILL NOT WORK
|
||||
for(var/feature in features)
|
||||
var/feature_value = features[feature]
|
||||
if(feature_value)
|
||||
var/ref_list = GLOB.mutant_reference_list[feature]
|
||||
if(ref_list)
|
||||
var/datum/sprite_accessory/accessory = ref_list[feature_value]
|
||||
if(accessory)
|
||||
var/mutant_string = accessory.mutant_part_string
|
||||
if(!mutant_string)
|
||||
if(istype(accessory, /datum/sprite_accessory/mam_body_markings))
|
||||
mutant_string = "mam_body_markings"
|
||||
var/primary_string = "[mutant_string]_primary"
|
||||
var/secondary_string = "[mutant_string]_secondary"
|
||||
var/tertiary_string = "[mutant_string]_tertiary"
|
||||
if(accessory.color_src == MATRIXED && !accessory.matrixed_sections && feature_value != "None")
|
||||
message_admins("Sprite Accessory Failure (loading data): Accessory [accessory.type] is a matrixed item without any matrixed sections set!")
|
||||
continue
|
||||
if(S["feature_[primary_string]"])
|
||||
S["feature_[primary_string]"] >> features[primary_string]
|
||||
if(S["feature_[secondary_string]"])
|
||||
S["feature_[secondary_string]"] >> features[secondary_string]
|
||||
if(S["feature_[tertiary_string]"])
|
||||
S["feature_[tertiary_string]"] >> features[tertiary_string]
|
||||
|
||||
persistent_scars = sanitize_integer(persistent_scars)
|
||||
scars_list["1"] = sanitize_text(scars_list["1"])
|
||||
scars_list["2"] = sanitize_text(scars_list["2"])
|
||||
@@ -797,14 +940,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/save_character()
|
||||
/datum/preferences/proc/save_character(bypass_cooldown = FALSE)
|
||||
if(!path)
|
||||
return 0
|
||||
if(world.time < savecharcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to save your character a little too fast. Wait half a second, then try again.</span>")
|
||||
return 0
|
||||
savecharcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
if(!bypass_cooldown)
|
||||
if(world.time < savecharcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to save your character a little too fast. Wait half a second, then try again.</span>")
|
||||
return 0
|
||||
savecharcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(!S)
|
||||
return 0
|
||||
@@ -822,8 +966,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["body_model"] , features["body_model"])
|
||||
WRITE_FILE(S["body_size"] , features["body_size"])
|
||||
WRITE_FILE(S["age"] , age)
|
||||
WRITE_FILE(S["language"] , language)
|
||||
WRITE_FILE(S["choselanguage"] , choselanguage)
|
||||
WRITE_FILE(S["hair_color"] , hair_color)
|
||||
WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
|
||||
WRITE_FILE(S["eye_type"] , eye_type)
|
||||
WRITE_FILE(S["left_eye_color"] , left_eye_color)
|
||||
WRITE_FILE(S["right_eye_color"] , right_eye_color)
|
||||
WRITE_FILE(S["use_custom_skin_tone"] , use_custom_skin_tone)
|
||||
@@ -864,6 +1011,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["feature_insect_wings"] , features["insect_wings"])
|
||||
WRITE_FILE(S["feature_insect_fluff"] , features["insect_fluff"])
|
||||
WRITE_FILE(S["feature_insect_markings"] , features["insect_markings"])
|
||||
WRITE_FILE(S["feature_arachnid_legs"] , features["arachnid_legs"])
|
||||
WRITE_FILE(S["feature_arachnid_spinneret"] , features["arachnid_spinneret"])
|
||||
WRITE_FILE(S["feature_arachnid_mandibles"] , features["arachnid_mandibles"])
|
||||
WRITE_FILE(S["feature_meat"] , features["meat_type"])
|
||||
|
||||
WRITE_FILE(S["feature_has_cock"], features["has_cock"])
|
||||
@@ -894,6 +1044,33 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
WRITE_FILE(S["feature_ooc_notes"], features["ooc_notes"])
|
||||
|
||||
WRITE_FILE(S["feature_color_scheme"], features["color_scheme"])
|
||||
|
||||
//save every advanced coloring mode thing in one go
|
||||
for(var/feature in features)
|
||||
var/feature_value = features[feature]
|
||||
if(feature_value)
|
||||
var/ref_list = GLOB.mutant_reference_list[feature]
|
||||
if(ref_list)
|
||||
var/datum/sprite_accessory/accessory = ref_list[feature_value]
|
||||
if(accessory)
|
||||
var/mutant_string = accessory.mutant_part_string
|
||||
if(!mutant_string)
|
||||
if(istype(accessory, /datum/sprite_accessory/mam_body_markings))
|
||||
mutant_string = "mam_body_markings"
|
||||
var/primary_string = "[mutant_string]_primary"
|
||||
var/secondary_string = "[mutant_string]_secondary"
|
||||
var/tertiary_string = "[mutant_string]_tertiary"
|
||||
if(accessory.color_src == MATRIXED && !accessory.matrixed_sections && feature_value != "None")
|
||||
message_admins("Sprite Accessory Failure (saving data): Accessory [accessory.type] is a matrixed item without any matrixed sections set!")
|
||||
continue
|
||||
if(features[primary_string])
|
||||
WRITE_FILE(S["feature_[primary_string]"], features[primary_string])
|
||||
if(features[secondary_string])
|
||||
WRITE_FILE(S["feature_[secondary_string]"], features[secondary_string])
|
||||
if(features[tertiary_string])
|
||||
WRITE_FILE(S["feature_[tertiary_string]"], features[tertiary_string])
|
||||
|
||||
//Custom names
|
||||
for(var/custom_name_id in GLOB.preferences_custom_names)
|
||||
var/savefile_slot_name = custom_name_id + "_name" //TODO remove this
|
||||
@@ -931,11 +1108,20 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
|
||||
//gear loadout
|
||||
if(chosen_gear.len)
|
||||
var/text_to_save = chosen_gear.Join("|")
|
||||
S["loadout"] << text_to_save
|
||||
if(length(loadout_data))
|
||||
S["loadout"] << safe_json_encode(loadout_data)
|
||||
else
|
||||
S["loadout"] << "" //empty string to reset the value
|
||||
S["loadout"] << safe_json_encode(list())
|
||||
|
||||
if(length(tcg_cards))
|
||||
S["tcg_cards"] << safe_json_encode(tcg_cards)
|
||||
else
|
||||
S["tcg_cards"] << safe_json_encode(list())
|
||||
|
||||
if(length(tcg_decks))
|
||||
S["tcg_decks"] << safe_json_encode(tcg_decks)
|
||||
else
|
||||
S["tcg_decks"] << safe_json_encode(list())
|
||||
|
||||
cit_character_pref_save(S)
|
||||
|
||||
|
||||
@@ -386,7 +386,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
||||
//Admin Preferences
|
||||
/client/proc/toggleadminhelpsound()
|
||||
set name = "Hear/Silence Adminhelps"
|
||||
set category = "Preferences"
|
||||
set category = "Preferences.Admin"
|
||||
set desc = "Toggle hearing a notification when admin PMs are received"
|
||||
if(!holder)
|
||||
return
|
||||
@@ -397,7 +397,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
||||
|
||||
/client/proc/toggleannouncelogin()
|
||||
set name = "Do/Don't Announce Login"
|
||||
set category = "Preferences"
|
||||
set category = "Preferences.Admin"
|
||||
set desc = "Toggle if you want an announcement to admins when you login during a round"
|
||||
if(!holder)
|
||||
return
|
||||
@@ -408,7 +408,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
||||
|
||||
/client/proc/toggle_hear_radio()
|
||||
set name = "Show/Hide Radio Chatter"
|
||||
set category = "Preferences"
|
||||
set category = "Preferences.Admin"
|
||||
set desc = "Toggle seeing radiochatter from nearby radios and speakers"
|
||||
if(!holder)
|
||||
return
|
||||
@@ -419,7 +419,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
||||
|
||||
/client/proc/deadchat()
|
||||
set name = "Show/Hide Deadchat"
|
||||
set category = "Preferences"
|
||||
set category = "Preferences.Admin"
|
||||
set desc ="Toggles seeing deadchat"
|
||||
prefs.chat_toggles ^= CHAT_DEAD
|
||||
prefs.save_preferences()
|
||||
@@ -428,7 +428,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
||||
|
||||
/client/proc/toggleprayers()
|
||||
set name = "Show/Hide Prayers"
|
||||
set category = "Preferences"
|
||||
set category = "Preferences.Admin"
|
||||
set desc = "Toggles seeing prayers"
|
||||
prefs.chat_toggles ^= CHAT_PRAYER
|
||||
prefs.save_preferences()
|
||||
|
||||
@@ -17,7 +17,7 @@ GLOBAL_VAR_INIT(normal_looc_colour, "#6699CC")
|
||||
if(!msg)
|
||||
return
|
||||
|
||||
if(!(prefs.toggles & CHAT_OOC))
|
||||
if(!(prefs.chat_toggles & CHAT_OOC))
|
||||
to_chat(src, "<span class='danger'> You have OOC muted.</span>")
|
||||
return
|
||||
if(jobban_isbanned(mob, "OOC"))
|
||||
@@ -50,7 +50,7 @@ GLOBAL_VAR_INIT(normal_looc_colour, "#6699CC")
|
||||
|
||||
msg = emoji_parse(msg)
|
||||
|
||||
mob.log_talk(msg,LOG_OOC, tag="(LOOC)")
|
||||
mob.log_talk(msg,LOG_OOC, tag="LOOC")
|
||||
|
||||
var/list/heard = get_hearers_in_view(7, get_top_level_mob(src.mob))
|
||||
for(var/mob/M in heard)
|
||||
@@ -63,14 +63,14 @@ GLOBAL_VAR_INIT(normal_looc_colour, "#6699CC")
|
||||
if (isobserver(M))
|
||||
continue //Also handled later.
|
||||
|
||||
if(C.prefs.toggles & CHAT_OOC)
|
||||
if(C.prefs.chat_toggles & CHAT_OOC)
|
||||
if(GLOB.LOOC_COLOR)
|
||||
to_chat(C, "<font color='[GLOB.LOOC_COLOR]'><b><span class='prefix'>LOOC:</span> <EM>[src.mob.name]:</EM> <span class='message'>[msg]</span></b></font>")
|
||||
else
|
||||
to_chat(C, "<span class='looc'><span class='prefix'>LOOC:</span> <EM>[src.mob.name]:</EM> <span class='message'>[msg]</span></span>")
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(C.prefs.toggles & CHAT_OOC)
|
||||
if(C.prefs.chat_toggles & CHAT_OOC)
|
||||
var/prefix = "(R)LOOC"
|
||||
if (C.mob in heard)
|
||||
prefix = "LOOC"
|
||||
|
||||
@@ -111,16 +111,16 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
|
||||
/client/proc/set_ooc(newColor as color)
|
||||
set name = "Set Player OOC Color"
|
||||
set desc = "Modifies player OOC Color"
|
||||
set category = "Fun"
|
||||
set category = "Admin.Fun"
|
||||
GLOB.OOC_COLOR = sanitize_ooccolor(newColor)
|
||||
|
||||
/client/proc/reset_ooc()
|
||||
set name = "Reset Player OOC Color"
|
||||
set desc = "Returns player OOC Color to default"
|
||||
set category = "Fun"
|
||||
set category = "Admin.Fun"
|
||||
GLOB.OOC_COLOR = null
|
||||
|
||||
/client/verb/colorooc()
|
||||
/client/verb/colorooc() //this is admin and people who bought byond.
|
||||
set name = "Set Your OOC Color"
|
||||
set category = "Preferences"
|
||||
|
||||
@@ -179,7 +179,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
|
||||
to_chat(usr, "<span class='notice'>Sorry, that function is not enabled on this server.</span>")
|
||||
return
|
||||
|
||||
browse_messages(null, usr.ckey, null, TRUE)
|
||||
browse_messages(null, usr.ckey, null, TRUE, override = TRUE)
|
||||
|
||||
/client/proc/self_playtime()
|
||||
set name = "View tracked playtime"
|
||||
|
||||
@@ -87,4 +87,4 @@
|
||||
msg += "<span class='info'>Adminhelps are also sent to Discord. If no admins are available in game adminhelp anyways and an admin on Discord will see it and respond.</span>"
|
||||
to_chat(src, msg)
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user