Merge branch 'master' of https://github.com/Yawn-Wider/YWPolarisVore into August2020UpstreamPull

August2020UpstreamPull
This commit is contained in:
Razgriz
2020-08-09 02:58:18 -07:00
915 changed files with 253357 additions and 90809 deletions
-309
View File
@@ -1,309 +0,0 @@
/*
Asset cache quick users guide:
Make a datum at the bottom of this file with your assets for your thing.
The simple subsystem will most like be of use for most cases.
Then call get_asset_datum() with the type of the datum you created and store the return
Then call .send(client) on that stored return value.
You can set verify to TRUE if you want send() to sleep until the client has the assets.
*/
// Amount of time(ds) MAX to send per asset, if this get exceeded we cancel the sleeping.
// This is doubled for the first asset, then added per asset after
#define ASSET_CACHE_SEND_TIMEOUT 7
//When sending mutiple assets, how many before we give the client a quaint little sending resources message
#define ASSET_CACHE_TELL_CLIENT_AMOUNT 8
//When passively preloading assets, how many to send at once? Too high creates noticable lag where as too low can flood the client's cache with "verify" files
#define ASSET_CACHE_PRELOAD_CONCURRENT 3
/client
var/list/cache = list() // List of all assets sent to this client by the asset cache.
var/list/completed_asset_jobs = list() // List of all completed jobs, awaiting acknowledgement.
var/list/sending = list()
var/last_asset_job = 0 // Last job done.
//This proc sends the asset to the client, but only if it needs it.
//This proc blocks(sleeps) unless verify is set to false
/proc/send_asset(var/client/client, var/asset_name, var/verify = TRUE)
client = CLIENT_FROM_VAR(client) // Will get client from a mob, or accept a client, or return null
if(!istype(client))
return 0
if(client.cache.Find(asset_name) || client.sending.Find(asset_name))
return 0
client << browse_rsc(SSassets.cache[asset_name], asset_name)
if(!verify) // Can't access the asset cache browser, rip.
client.cache += asset_name
return 1
client.sending |= asset_name
var/job = ++client.last_asset_job
client << browse({"
<script>
window.location.href="?asset_cache_confirm_arrival=[job]"
</script>
"}, "window=asset_cache_browser")
var/t = 0
var/timeout_time = (ASSET_CACHE_SEND_TIMEOUT * client.sending.len) + ASSET_CACHE_SEND_TIMEOUT
while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic()
sleep(1) // Lock up the caller until this is received.
t++
if(client)
client.sending -= asset_name
client.cache |= asset_name
client.completed_asset_jobs -= job
return 1
//This proc blocks(sleeps) unless verify is set to false
/proc/send_asset_list(var/client/client, var/list/asset_list, var/verify = TRUE)
client = CLIENT_FROM_VAR(client) // Will get client from a mob, or accept a client, or return null
if(!istype(client))
return 0
var/list/unreceived = asset_list - (client.cache + client.sending)
if(!unreceived || !unreceived.len)
return 0
if(unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT)
to_chat(client, "Sending Resources...")
for(var/asset in unreceived)
if(asset in SSassets.cache)
client << browse_rsc(SSassets.cache[asset], asset)
if(!verify) // Can't access the asset cache browser, rip.
client.cache += unreceived
return 1
client.sending |= unreceived
var/job = ++client.last_asset_job
client << browse({"
<script>
window.location.href="?asset_cache_confirm_arrival=[job]"
</script>
"}, "window=asset_cache_browser")
var/t = 0
var/timeout_time = ASSET_CACHE_SEND_TIMEOUT * client.sending.len
while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic()
sleep(1) // Lock up the caller until this is received.
t++
if(client)
client.sending -= unreceived
client.cache |= unreceived
client.completed_asset_jobs -= job
return 1
//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start.
//The proc calls procs that sleep for long times.
/proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE)
var/concurrent_tracker = 1
for(var/file in files)
if(!client)
break
if(register_asset)
register_asset(file, files[file])
if(concurrent_tracker >= ASSET_CACHE_PRELOAD_CONCURRENT)
concurrent_tracker = 1
send_asset(client, file)
else
concurrent_tracker++
send_asset(client, file, verify = FALSE)
sleep(0) //queuing calls like this too quickly can cause issues in some client versions
//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up.
//if it's an icon or something be careful, you'll have to copy it before further use.
/proc/register_asset(var/asset_name, var/asset)
SSassets.cache[asset_name] = asset
//These datums are used to populate the asset cache, the proc "register()" does this.
//all of our asset datums, used for referring to these later
/var/global/list/asset_datums = list()
//get a assetdatum or make a new one
/proc/get_asset_datum(var/type)
if(!(type in asset_datums))
return new type()
return asset_datums[type]
/datum/asset
var/_abstract = /datum/asset // Marker so we don't instanatiate abstract types
/datum/asset/New()
asset_datums[type] = src
register()
/datum/asset/proc/register()
return
/datum/asset/proc/send(client)
return
//If you don't need anything complicated.
/datum/asset/simple
_abstract = /datum/asset/simple
var/assets = list()
var/verify = FALSE
/datum/asset/simple/register()
for(var/asset_name in assets)
register_asset(asset_name, assets[asset_name])
/datum/asset/simple/send(client)
send_asset_list(client,assets,verify)
//
// iconsheet Assets - For making lots of icon states available at once without sending a thousand tiny files.
//
/datum/asset/iconsheet
_abstract = /datum/asset/iconsheet
var/name // Name of the iconsheet. Asset will be named after this.
var/verify = FALSE
/datum/asset/iconsheet/register(var/list/sprites)
if (!name)
CRASH("iconsheet [type] cannot register without a name")
if (!islist(sprites))
CRASH("iconsheet [type] cannot register without a sprites list")
var/res_name = "iconsheet_[name].css"
var/fname = "data/iconsheets/[res_name]"
fdel(fname)
text2file(generate_css(sprites), fname)
register_asset(res_name, fcopy_rsc(fname))
fdel(fname)
/datum/asset/iconsheet/send(client/C)
if (!name)
return
send_asset_list(C, list("iconsheet_[name].css"), verify)
/datum/asset/iconsheet/proc/generate_css(var/list/sprites)
var/list/out = list(".[name]{display:inline-block;}")
for(var/sprite_id in sprites)
var/icon/I = sprites[sprite_id]
var/data_url = "'data:image/png;base64,[icon2base64(I)]'"
out += ".[name].[sprite_id]{width:[I.Width()]px;height:[I.Height()]px;background-image:url([data_url]);}"
return out.Join("\n")
/datum/asset/iconsheet/proc/build_sprite_list(icon/I, list/directions, prefix = null)
if (length(prefix))
prefix = "[prefix]-"
if (!directions)
directions = list(SOUTH)
var/sprites = list()
for (var/icon_state_name in cached_icon_states(I))
for (var/direction in directions)
var/suffix = (directions.len > 1) ? "-[dir2text(direction)]" : ""
var/sprite_name = "[prefix][icon_state_name][suffix]"
var/icon/sprite = icon(I, icon_state=icon_state_name, dir=direction, frame=1, moving=FALSE)
if (!sprite || !length(cached_icon_states(sprite))) // that direction or state doesn't exist
continue
sprites[sprite_name] = sprite
return sprites
// Get HTML link tag for including the iconsheet css file.
/datum/asset/iconsheet/proc/css_tag()
return "<link rel='stylesheet' href='iconsheet_[name].css' />"
// get HTML tag for showing an icon
/datum/asset/iconsheet/proc/icon_tag(icon_state, dir = SOUTH)
return "<span class='[name] [icon_state]-[dir2text(dir)]'></span>"
//DEFINITIONS FOR ASSET DATUMS START HERE.
/datum/asset/simple/generic
assets = list(
"search.js" = 'html/search.js',
"panels.css" = 'html/panels.css',
"loading.gif" = 'html/images/loading.gif',
"ntlogo.png" = 'html/images/ntlogo.png',
"sglogo.png" = 'html/images/sglogo.png',
"talisman.png" = 'html/images/talisman.png',
"paper_bg.png" = 'html/images/paper_bg.png',
"no_image32.png" = 'html/images/no_image32.png',
)
/datum/asset/simple/changelog
assets = list(
"88x31.png" = 'html/88x31.png',
"bug-minus.png" = 'html/bug-minus.png',
"cross-circle.png" = 'html/cross-circle.png',
"hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png',
"image-minus.png" = 'html/image-minus.png',
"image-plus.png" = 'html/image-plus.png',
"map-pencil.png" = 'html/map-pencil.png',
"music-minus.png" = 'html/music-minus.png',
"music-plus.png" = 'html/music-plus.png',
"tick-circle.png" = 'html/tick-circle.png',
"wrench-screwdriver.png" = 'html/wrench-screwdriver.png',
"spell-check.png" = 'html/spell-check.png',
"burn-exclamation.png" = 'html/burn-exclamation.png',
"chevron.png" = 'html/chevron.png',
"chevron-expand.png" = 'html/chevron-expand.png',
"changelog.css" = 'html/changelog.css',
"changelog.js" = 'html/changelog.js',
"changelog.html" = 'html/changelog.html'
)
/datum/asset/nanoui
var/list/common = list()
var/list/common_dirs = list(
"nano/css/",
"nano/images/",
"nano/images/modular_computers/",
"nano/js/"
)
var/list/template_dirs = list(
"nano/templates/"
)
/datum/asset/nanoui/register()
// Crawl the directories to find files.
for(var/path in common_dirs)
var/list/filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) != "/") // Ignore directories.
if(fexists(path + filename))
common[filename] = fcopy_rsc(path + filename)
register_asset(filename, common[filename])
// Combine all templates into a single bundle.
var/list/template_data = list()
for(var/path in template_dirs)
var/list/filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename) - 4) == ".tmpl") // Ignore directories.
template_data[filename] = file2text(path + filename)
var/template_bundle = "function nanouiTemplateBundle(){return [json_encode(template_data)];}"
var/fname = "data/nano_templates_bundle.js"
fdel(fname)
text2file(template_bundle, fname)
register_asset("nano_templates_bundle.js", fcopy_rsc(fname))
fdel(fname)
/datum/asset/nanoui/send(client)
send_asset_list(client, common)
// VOREStation Add Start - pipes iconsheet asset
/datum/asset/iconsheet/pipes
name = "pipes"
/datum/asset/iconsheet/pipes/register()
var/list/sprites = list()
for (var/each in list('icons/obj/pipe-item.dmi', 'icons/obj/pipes/disposal.dmi'))
sprites += build_sprite_list(each, global.alldirs)
..(sprites)
// VOREStation Add End
+14
View File
@@ -61,3 +61,17 @@
var/global/obj/screen/click_catcher/void
control_freak = 0 //CHOMPedit KSC 1/30/20 - This enables all clientside options for Players.
// 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
var/list/completed_asset_jobs = list()
/// Last asset send job id.
var/last_asset_job = 0
var/last_completed_asset_job = 0
///world.time they connected
var/connection_time
///world.realtime they connected
var/connection_realtime
///world.timeofday they connected
var/connection_timeofday
+28 -5
View File
@@ -34,10 +34,12 @@
#endif
// asset_cache
var/asset_cache_job
if(href_list["asset_cache_confirm_arrival"])
var/job = text2num(href_list["asset_cache_confirm_arrival"])
completed_asset_jobs += job
return
asset_cache_job = asset_cache_confirm_arrival(href_list["asset_cache_confirm_arrival"])
if (!asset_cache_job)
return
//search the href for script injection
if( findtext(href,"<script",1,0) )
@@ -46,6 +48,10 @@
//del(usr)
return
// Tgui Topic middleware
if(!tgui_Topic(href_list))
return
//Admin PM
if(href_list["priv_msg"])
var/client/C = locate(href_list["priv_msg"])
@@ -106,6 +112,15 @@
if(config && config.log_hrefs && href_logfile)
WRITE_LOG(href_logfile, "[src] (usr:[usr])</small> || [hsrc ? "[hsrc] " : ""][href]")
//byond bug ID:2256651
if (asset_cache_job && (asset_cache_job in completed_asset_jobs))
to_chat(src, "<span class='danger'>An error has been detected in how your client is receiving resources. Attempting to correct.... (If you keep seeing these messages you might want to close byond and reconnect)</span>")
src << browse("...", "window=asset_cache_browser")
return
if (href_list["asset_cache_preload_data"])
asset_cache_preload_data(href_list["asset_cache_preload_data"])
return
switch(href_list["_src_"])
if("holder") hsrc = holder
if("usr") hsrc = mob
@@ -181,6 +196,10 @@
. = ..() //calls mob.Login()
prefs.sanitize_preferences()
connection_time = world.time
connection_realtime = world.realtime
connection_timeofday = world.timeofday
if(custom_event_msg && custom_event_msg != "")
to_chat(src, "<h1 class='alert'>Custom Event</h1>")
to_chat(src, "<h2 class='alert'>A custom event is taking place. OOC Info:</h2>")
@@ -407,8 +426,12 @@
//send resources to the client. It's here in its own proc so we can move it around easiliy if need be
/client/proc/send_resources()
spawn (10) //removing this spawn causes all clients to not get verbs.
//load info on what assets the client has
src << browse('code/modules/asset_cache/validate_assets.html', "window=asset_cache_browser")
//Precache the client with all other assets slowly, so as to not block other browse() calls
getFilesSlow(src, SSassets.preload, register_asset = FALSE)
addtimer(CALLBACK(GLOBAL_PROC, /proc/getFilesSlow, src, SSassets.preload, FALSE), 5 SECONDS)
mob/proc/MayRespawn()
return 0
@@ -453,7 +476,7 @@ client/verb/character_setup()
alert(src, "You can only try to reload VChat every 10 seconds at most.")
return
verbs -= /client/proc/vchat_export_log
// YW EDIT: disabled until we can fix the lag: verbs -= /client/proc/vchat_export_log
//Log, disable
log_debug("[key_name(src)] reloaded VChat.")
@@ -19,6 +19,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["grad_green"] >> pref.g_grad
S["grad_blue"] >> pref.b_grad
S["facial_red"] >> pref.r_facial
S["grad_red"] >> pref.r_grad
S["grad_green"] >> pref.g_grad
S["grad_blue"] >> pref.b_grad
S["facial_green"] >> pref.g_facial
S["facial_blue"] >> pref.b_facial
S["skin_tone"] >> pref.s_tone
@@ -28,6 +31,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["hair_style_name"] >> pref.h_style
S["grad_style_name"] >> pref.grad_style
S["facial_style_name"] >> pref.f_style
S["grad_style_name"] >> pref.grad_style
S["eyes_red"] >> pref.r_eyes
S["eyes_green"] >> pref.g_eyes
S["eyes_blue"] >> pref.b_eyes
@@ -67,6 +71,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["hair_style_name"] << pref.h_style
S["grad_style_name"] << pref.grad_style
S["facial_style_name"] << pref.f_style
S["grad_style_name"] << pref.grad_style
S["eyes_red"] << pref.r_eyes
S["eyes_green"] << pref.g_eyes
S["eyes_blue"] << pref.b_eyes
@@ -107,6 +112,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.h_style = sanitize_inlist(pref.h_style, hair_styles_list, initial(pref.h_style))
pref.grad_style = sanitize_inlist(pref.grad_style, GLOB.hair_gradients, initial(pref.grad_style))
pref.f_style = sanitize_inlist(pref.f_style, facial_hair_styles_list, initial(pref.f_style))
pref.grad_style = sanitize_inlist(pref.grad_style, GLOB.hair_gradients, initial(pref.grad_style))
pref.r_eyes = sanitize_integer(pref.r_eyes, 0, 255, initial(pref.r_eyes))
pref.g_eyes = sanitize_integer(pref.g_eyes, 0, 255, initial(pref.g_eyes))
pref.b_eyes = sanitize_integer(pref.b_eyes, 0, 255, initial(pref.b_eyes))
@@ -144,6 +150,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
character.h_style = pref.h_style
character.grad_style= pref.grad_style
character.f_style = pref.f_style
character.grad_style= pref.grad_style
character.b_type = pref.b_type
character.synth_color = pref.synth_color
character.r_synth = pref.r_synth
@@ -359,11 +366,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(has_flag(mob_species, HAS_HAIR_COLOR))
. += "<a href='?src=\ref[src];hair_color=1'>Change Color</a> [color_square(pref.r_hair, pref.g_hair, pref.b_hair)] "
. += " Style: <a href='?src=\ref[src];hair_style_left=[pref.h_style]'><</a> <a href='?src=\ref[src];hair_style_right=[pref.h_style]''>></a> <a href='?src=\ref[src];hair_style=1'>[pref.h_style]</a><br>" //The <</a> & ></a> in this line is correct-- those extra characters are the arrows you click to switch between styles.
. += "<b>Gradient</b><br>"
. += "<a href='?src=\ref[src];grad_color=1'>Change Color</a> [color_square(pref.r_grad, pref.g_grad, pref.b_grad)] "
. += "<a href='?src=\ref[src];grad_color=1'>Change Color</a> [color_square(pref.r_grad, pref.g_grad, pref.b_grad)] "
. += " Style: <a href='?src=\ref[src];grad_style_left=[pref.grad_style]'><</a> <a href='?src=\ref[src];grad_style_right=[pref.grad_style]''>></a> <a href='?src=\ref[src];grad_style=1'>[pref.grad_style]</a><br>"
. += "<br><b>Facial</b><br>"
if(has_flag(mob_species, HAS_HAIR_COLOR))
. += "<a href='?src=\ref[src];facial_color=1'>Change Color</a> [color_square(pref.r_facial, pref.g_facial, pref.b_facial)] "
@@ -503,6 +510,16 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.b_grad = hex2num(copytext(new_grad, 6, 8))
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["grad_color"])
if(!has_flag(mob_species, HAS_HAIR_COLOR))
return TOPIC_NOACTION
var/new_grad = input(user, "Choose your character's secondary hair color:", "Character Preference", rgb(pref.r_grad, pref.g_grad, pref.b_grad)) as color|null
if(new_grad && has_flag(mob_species, HAS_HAIR_COLOR) && CanUseTopic(user))
pref.r_grad = hex2num(copytext(new_grad, 2, 4))
pref.g_grad = hex2num(copytext(new_grad, 4, 6))
pref.b_grad = hex2num(copytext(new_grad, 6, 8))
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["hair_style"])
var/list/valid_hairstyles = pref.get_valid_hairstyles()
@@ -519,6 +536,14 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.grad_style = new_grad_style
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["grad_style"])
var/list/valid_gradients = GLOB.hair_gradients
var/new_grad_style = input(user, "Choose a color pattern for your hair:", "Character Preference", pref.grad_style) as null|anything in valid_gradients
if(new_grad_style && CanUseTopic(user))
pref.grad_style = new_grad_style
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["hair_style_left"])
var/H = href_list["hair_style_left"]
var/list/valid_hairstyles = pref.get_valid_hairstyles()
@@ -977,6 +1002,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
dat += "</br><b>Does not have a respiratory system.</b>"
if(current_species.flags & NO_SCAN)
dat += "</br><b>Does not have DNA.</b>"
if(current_species.flags & NO_DEFIB)
dat += "</br><b>Cannot be defibrillated.</b>"
if(current_species.flags & NO_PAIN)
dat += "</br><b>Does not feel pain.</b>"
if(current_species.flags & NO_SLIP)
@@ -9,6 +9,8 @@
S["ooccolor"] >> pref.ooccolor
S["tooltipstyle"] >> pref.tooltipstyle
S["client_fps"] >> pref.client_fps
S["tgui_fancy"] >> pref.tgui_fancy
S["tgui_lock"] >> pref.tgui_lock
/datum/category_item/player_setup_item/player_global/ui/save_preferences(var/savefile/S)
S["UI_style"] << pref.UI_style
@@ -17,6 +19,8 @@
S["ooccolor"] << pref.ooccolor
S["tooltipstyle"] << pref.tooltipstyle
S["client_fps"] << pref.client_fps
S["tgui_fancy"] << pref.tgui_fancy
S["tgui_lock"] << pref.tgui_lock
/datum/category_item/player_setup_item/player_global/ui/sanitize_preferences()
pref.UI_style = sanitize_inlist(pref.UI_style, all_ui_styles, initial(pref.UI_style))
@@ -25,20 +29,24 @@
pref.ooccolor = sanitize_hexcolor(pref.ooccolor, initial(pref.ooccolor))
pref.tooltipstyle = sanitize_inlist(pref.tooltipstyle, all_tooltip_styles, initial(pref.tooltipstyle))
pref.client_fps = sanitize_integer(pref.client_fps, 0, MAX_CLIENT_FPS, initial(pref.client_fps))
pref.tgui_fancy = sanitize_integer(pref.tgui_fancy, 0, 1, initial(pref.tgui_fancy))
pref.tgui_lock = sanitize_integer(pref.tgui_lock, 0, 1, initial(pref.tgui_lock))
/datum/category_item/player_setup_item/player_global/ui/content(var/mob/user)
. = "<b>UI Style:</b> <a href='?src=\ref[src];select_style=1'><b>[pref.UI_style]</b></a><br>"
. += "<b>Custom UI</b> (recommended for White UI):<br>"
. += "-Color: <a href='?src=\ref[src];select_color=1'><b>[pref.UI_style_color]</b></a> [color_square(hex = pref.UI_style_color)] <a href='?src=\ref[src];reset=ui'>reset</a><br>"
. += "-Alpha(transparency): <a href='?src=\ref[src];select_alpha=1'><b>[pref.UI_style_alpha]</b></a> <a href='?src=\ref[src];reset=alpha'>reset</a><br>"
. += "-Color: <a href='?src=\ref[src];select_color=1'><b>[pref.UI_style_color]</b></a>[color_square(hex = pref.UI_style_color)]<a href='?src=\ref[src];reset=ui'>reset</a><br>"
. += "-Alpha(transparency): <a href='?src=\ref[src];select_alpha=1'><b>[pref.UI_style_alpha]</b></a><a href='?src=\ref[src];reset=alpha'>reset</a><br>"
. += "<b>Tooltip Style:</b> <a href='?src=\ref[src];select_tooltip_style=1'><b>[pref.tooltipstyle]</b></a><br>"
. += "<b>Client FPS:</b> <a href='?src=\ref[src];select_client_fps=1'><b>[pref.client_fps]</b></a><br>"
. += "<b>tgui Window Mode:</b> <a href='?src=\ref[src];tgui_fancy=1'><b>[(pref.tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"]</b></a><br>"
. += "<b>tgui Window Placement:</b> <a href='?src=\ref[src];tgui_lock=1'><b>[(pref.tgui_lock) ? "Primary Monitor" : "Free (default)"]</b></a><br>"
if(can_select_ooc_color(user))
. += "<b>OOC Color:</b> "
. += "<b>OOC Color:</b>"
if(pref.ooccolor == initial(pref.ooccolor))
. += "<a href='?src=\ref[src];select_ooc_color=1'><b>Using Default</b></a><br>"
else
. += "<a href='?src=\ref[src];select_ooc_color=1'><b>[pref.ooccolor]</b></a> [color_square(hex = pref.ooccolor)] <a href='?src=\ref[src];reset=ooc'>reset</a><br>"
. += "<a href='?src=\ref[src];select_ooc_color=1'><b>[pref.ooccolor]</b></a> [color_square(hex = pref.ooccolor)]<a href='?src=\ref[src];reset=ooc'>reset</a><br>"
/datum/category_item/player_setup_item/player_global/ui/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["select_style"])
@@ -80,6 +88,14 @@
pref.client.fps = fps_new
return TOPIC_REFRESH
else if(href_list["tgui_fancy"])
pref.tgui_fancy = !pref.tgui_fancy
return TOPIC_REFRESH
else if(href_list["tgui_lock"])
pref.tgui_lock = !pref.tgui_lock
return TOPIC_REFRESH
else if(href_list["reset"])
switch(href_list["reset"])
if("ui")
@@ -266,6 +266,18 @@ var/list/_client_preferences_by_type
enabled_description = "Enabled"
disabled_description = "Disabled"
/datum/client_preference/status_indicators
description = "Status Indicators"
key = "SHOW_STATUS"
enabled_description = "Show"
disabled_description = "Hide"
/datum/client_preference/status_indicators/toggled(mob/preference_mob, enabled)
. = ..()
if(preference_mob && preference_mob.plane_holder)
var/datum/plane_holder/PH = preference_mob.plane_holder
PH.set_vis(VIS_STATUS, enabled)
/********************
* Staff Preferences *
********************/
@@ -279,3 +279,7 @@
/datum/gear/accessory/cowledvest
display_name = "cowled vest"
path = /obj/item/clothing/accessory/cowledvest
/datum/gear/accessory/asymovercoat
display_name = "orange asymmetrical overcoat"
path = /obj/item/clothing/accessory/asymovercoat
@@ -627,6 +627,14 @@
// J CKEYS
// K CKEYS
//kbraid
//Eili
/datum/gear/fluff/kbraidgoggles
path = /obj/item/clothing/glasses/fluff/avigoggles_yw
display_name = "K'braid Aviation Goggles"
description = "You're such a goggle head!"
ckeywhitelist = list("kbraid")
character_name = list("Eili") //Character name. this variable is required, or the item doesn't show in loadout. Change to "character_name = null" if not character restricted.
// L CKEYS
@@ -977,4 +985,4 @@
// Y CKEYS
// Z CKEYS
// Z CKEYS
@@ -0,0 +1,12 @@
/datum/gear/ball
display_name = "tennis ball selection"
description = "Choose from a num- BALL!"
path = /obj/item/toy/tennis
/datum/gear/ball/New()
..()
var/list/balls = list()
for(var/ball in typesof(/obj/item/toy/tennis/))
var/obj/item/toy/tennis/ball_type = ball
balls[initial(ball_type.name)] = ball_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(balls))
@@ -366,4 +366,20 @@
/datum/gear/head/jingasa
display_name = "jingasa"
path = /obj/item/clothing/head/jingasa
path = /obj/item/clothing/head/jingasa
/datum/gear/head/sunflower_crown
display_name = "sunflower crown"
path = /obj/item/clothing/head/sunflower_crown
/datum/gear/head/lavender_crown
display_name = "lavender crown"
path = /obj/item/clothing/head/lavender_crown
/datum/gear/head/poppy_crown
display_name = "poppy crown"
path = /obj/item/clothing/head/poppy_crown
/datum/gear/head/rose_crown
display_name = "rose crown"
path = /obj/item/clothing/head/rose_crown
@@ -20,4 +20,8 @@
/datum/gear/mask/sterile
display_name = "sterile mask"
path = /obj/item/clothing/mask/surgical
cost = 2
cost = 2
/datum/gear/mask/veil
display_name = "black veil"
path = /obj/item/clothing/mask/veil
@@ -556,4 +556,36 @@
/datum/gear/uniform/haltertop
display_name = "halter top"
path = /obj/item/clothing/under/haltertop
path = /obj/item/clothing/under/haltertop
/datum/gear/uniform/revealingdress
display_name = "revealing dress"
path = /obj/item/clothing/under/dress/revealingdress
/datum/gear/uniform/rippedpunk
display_name = "ripped punk jeans"
path = /obj/item/clothing/under/rippedpunk
/datum/gear/uniform/gothic
display_name = "gothic dress"
path = /obj/item/clothing/under/dress/gothic
/datum/gear/uniform/formalred
display_name = "formal red dress"
path = /obj/item/clothing/under/dress/formalred
/datum/gear/uniform/pentagram
display_name = "pentagram dress"
path = /obj/item/clothing/under/dress/pentagram
/datum/gear/uniform/yellowswoop
display_name = "yellow swooped dress"
path = /obj/item/clothing/under/dress/yellowswoop
/datum/gear/uniform/greenasym
display_name = "green asymmetrical jumpsuit"
path = /obj/item/clothing/under/greenasym
/datum/gear/uniform/cyberpunkharness
display_name = "cyberpunk strapped harness"
path = /obj/item/clothing/under/cyberpunkharness
@@ -32,4 +32,188 @@
for(var/cloak in typesof(/obj/item/clothing/suit/storage/hooded/teshari/standard))
var/obj/item/clothing/suit/storage/seromi/cloak/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/beltcloak
display_name = "belted cloak selection (Teshari)"
path = /obj/item/clothing/suit/storage/seromi/beltcloak/standard
whitelisted = SPECIES_TESHARI
sort_category = "Xenowear"
/datum/gear/suit/beltcloak/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/beltcloak/standard))
var/obj/item/clothing/suit/storage/seromi/beltcloak/standard/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/uniform/beltcloakcolor/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)
/datum/gear/suit/cloakcolor
display_name = "belted cloak, recolorable (Teshari)"
path = /obj/item/clothing/suit/storage/seromi/beltcloak/standard/white_grey
whitelisted = SPECIES_TESHARI
sort_category = "Xenowear"
/datum/gear/suit/dept/beltcloak/
whitelisted = SPECIES_TESHARI
sort_category = "Xenowear"
/datum/gear/suit/dept/beltcloak/wrdn
display_name = "warden belted cloak (Teshari)"
path = /obj/item/clothing/suit/storage/seromi/beltcloak/jobs/wrdn
allowed_roles = list("Head of Security","Warden")
/datum/gear/suit/dept/beltcloak/hos
display_name = "Chief of Security belted cloak (Teshari)"
path = /obj/item/clothing/suit/storage/seromi/beltcloak/jobs/hos
allowed_roles = list("Head of Security")
/datum/gear/suit/dept/beltcloak/jani
display_name = "janitor belted cloak (Teshari)"
path = /obj/item/clothing/suit/storage/seromi/beltcloak/jobs/jani
allowed_roles = list("Janitor")
/datum/gear/suit/dept/cloak/command/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/command,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/command))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/cargo/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/cargo,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cargo))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/mining/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/mining,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/mining))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/qm/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/qm,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/qm))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/security/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/sec,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/sec))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/service/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/service,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/service))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/ce/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/ce,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/ce))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/engineer/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/eningeer,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/eningeer))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/atmos/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/atmos,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/atmos))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/research/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/sci,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/sci))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/robo/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/robo,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/robo))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/cmo/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/cmo,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cmo))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/medical/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/medical,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/medical))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/chemistry/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/chemistry,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/chemistry))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/virology/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/viro,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/viro))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/paramedic/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/para,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/para))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/suit/dept/cloak/iaa/New()
..()
var/list/cloaks = list()
for(var/cloak in typesof(/obj/item/clothing/suit/storage/seromi/cloak/jobs/iaa,/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/iaa))
var/obj/item/clothing/suit/storage/seromi/beltcloak/jobs/cloak_type = cloak
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/uniform/harness_white
display_name = "white gear harness (Full Body Prosthetic, Diona)"
path = /obj/item/clothing/under/harness_white
sort_category = "Xenowear"
+3
View File
@@ -24,6 +24,9 @@ datum/preferences
var/tooltipstyle = "Midnight" //Style for popup tooltips
var/client_fps = 0
var/tgui_fancy = TRUE
var/tgui_lock = FALSE
//character preferences
var/real_name //our character's name
var/be_random_name = 0 //whether we are a random name every round
@@ -334,6 +334,19 @@
You will have to reload VChat and/or reconnect to the server for these changes to take place. \
VChat message persistence is not guaranteed if you change this again before the start of the next round.")
/client/verb/toggle_status_indicators()
set name = "Toggle Status Indicators"
set category = "Preferences"
set desc = "Enable/Disable seeing status indicators over peoples' heads."
var/pref_path = /datum/client_preference/status_indicators
toggle_preference(pref_path)
SScharacter_setup.queue_preferences_save(prefs)
to_chat(src, "You will now [(is_preference_enabled(/datum/client_preference/status_indicators)) ? "see" : "not see"] status indicators.")
feedback_add_details("admin_verb","TStatusIndicators")
// Not attached to a pref datum because those are strict binary toggles
/client/verb/toggle_examine_mode()