diff --git a/.travis.yml b/.travis.yml index cea5f854c91..09cefa27b32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,13 +4,10 @@ language: c env: global: - BASENAME="vorestation" # $BASENAME.dmb, $BASENAME.dme, etc. - - BYOND_MAJOR="513" - - BYOND_MINOR="1520" - - MACRO_COUNT=4 cache: directories: - - $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR} + - $HOME/BYOND addons: apt: @@ -37,13 +34,17 @@ jobs: include: - stage: "File Tests" #This is the odd man out, with specific installs and stuff. name: "Validate Files" - install: #Need python for some of the tag matching stuff - - pip install --user PyYaml -q - - pip install --user beautifulsoup4 -q - script: ./tools/travis/validate_files.sh addons: apt: - packages: ~ # Don't need any packages for this + packages: + - python3 + - python3-pip + - python3-setuptools + install: #Need python for some of the tag matching stuff + - tools/travis/install_build_deps.sh + script: + - tools/travis/validate_files.sh + - tools/travis/build_tgui.sh - stage: "Unit Tests" env: TEST_DEFINE="UNIT_TEST" TEST_FILE="code/_unit_tests.dm" RUN="1" name: "Compile normally (unit tests)" diff --git a/_build_dependencies.sh b/_build_dependencies.sh new file mode 100644 index 00000000000..b33548a58a0 --- /dev/null +++ b/_build_dependencies.sh @@ -0,0 +1,13 @@ +# This file has all the information on what versions of libraries are thrown into the code +# For dreamchecker +export SPACEMANDMM_TAG=suite-1.4 +# For NanoUI + TGUI +export NODE_VERSION=12 +# For the scripts in tools +export PHP_VERSION=5.6 +# Byond Major +export BYOND_MAJOR=513 +# Byond Minor +export BYOND_MINOR=1526 +# Macro Count +export MACRO_COUNT=4 \ No newline at end of file diff --git a/code/__defines/species_languages_vr.dm b/code/__defines/species_languages_vr.dm index 831df5253dd..54362278d4d 100644 --- a/code/__defines/species_languages_vr.dm +++ b/code/__defines/species_languages_vr.dm @@ -1,5 +1,6 @@ #define SPECIES_WHITELIST_SELECTABLE 0x20 // Can select and customize, but not join as +#define LANGUAGE_DRUDAKAR "D'Rudak'Ar" #define LANGUAGE_SLAVIC "Pan-Slavic" #define LANGUAGE_BIRDSONG "Birdsong" #define LANGUAGE_SAGARU "Sagaru" diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index 0fa2532bf9b..94228f34399 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -100,6 +100,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define FIRE_PRIORITY_TICKER 60 #define FIRE_PRIORITY_PLANETS 75 #define FIRE_PRIORITY_MACHINES 100 +#define FIRE_PRIORITY_TGUI 110 #define FIRE_PRIORITY_PROJECTILES 150 #define FIRE_PRIORITY_CHAT 400 #define FIRE_PRIORITY_OVERLAYS 500 diff --git a/code/__defines/tgui.dm b/code/__defines/tgui.dm new file mode 100644 index 00000000000..a6708c8bb7a --- /dev/null +++ b/code/__defines/tgui.dm @@ -0,0 +1,19 @@ +/// Maximum number of windows that can be suspended/reused +#define TGUI_WINDOW_SOFT_LIMIT 5 +/// Maximum number of open windows +#define TGUI_WINDOW_HARD_LIMIT 9 + +/// Maximum ping timeout allowed to detect zombie windows +#define TGUI_PING_TIMEOUT 4 SECONDS + +/// Window does not exist +#define TGUI_WINDOW_CLOSED 0 +/// Window was just opened, but is still not ready to be sent data +#define TGUI_WINDOW_LOADING 1 +/// Window is free and ready to receive data +#define TGUI_WINDOW_READY 2 + +/// Get a window id based on the provided pool index +#define TGUI_WINDOW_ID(index) "tgui-window-[index]" +/// Get a pool index of the provided window id +#define TGUI_WINDOW_INDEX(window_id) text2num(copytext(window_id, 13)) \ No newline at end of file diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm index 6ec3ccb9662..194ec86d3d9 100644 --- a/code/_helpers/game.dm +++ b/code/_helpers/game.dm @@ -615,4 +615,25 @@ datum/projectile_data /proc/window_flash(var/client_or_usr) if (!client_or_usr) return - winset(client_or_usr, "mainwindow", "flash=5") \ No newline at end of file + winset(client_or_usr, "mainwindow", "flash=5") + +/** + * Get a bounding box of a list of atoms. + * + * Arguments: + * - atoms - List of atoms. Can accept output of view() and range() procs. + * + * Returns: list(x1, y1, x2, y2) + */ +/proc/get_bbox_of_atoms(list/atoms) + var/list/list_x = list() + var/list/list_y = list() + for(var/_a in atoms) + var/atom/a = _a + list_x += a.x + list_y += a.y + return list( + min(list_x), + min(list_y), + max(list_x), + max(list_y)) \ No newline at end of file diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm index d27abcbf7e2..757555f0375 100644 --- a/code/_helpers/logging.dm +++ b/code/_helpers/logging.dm @@ -176,6 +176,22 @@ /proc/log_unit_test(text) to_world_log("## UNIT_TEST: [text]") +/proc/log_tgui(user_or_client, text) + var/entry = "" + if(!user_or_client) + entry += "no user" + else if(istype(user_or_client, /mob)) + var/mob/user = user_or_client + entry += "[user.ckey] (as [user])" + else if(istype(user_or_client, /client)) + var/client/client = user_or_client + entry += "[client.ckey]" + entry += ":\n[text]" + WRITE_LOG(diary, entry) + +/proc/log_asset(text) + WRITE_LOG(diary, "ASSET: [text]") + /proc/report_progress(var/progress_message) admin_notice("[progress_message]", R_DEBUG) to_world_log(progress_message) diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm index 67844cf4a2d..1b028e117b7 100644 --- a/code/_helpers/text.dm +++ b/code/_helpers/text.dm @@ -138,6 +138,19 @@ /proc/sanitize_old(var/t,var/list/repl_chars = list("\n"="#","\t"="#")) return html_encode(replace_characters(t,repl_chars)) + +//Removes a few problematic characters +/proc/sanitize_simple(t,list/repl_chars = list("\n"="#","\t"="#")) + for(var/char in repl_chars) + var/index = findtext(t, char) + while(index) + t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index + length(char)) + index = findtext(t, char, index + length(char)) + return t + +/proc/sanitize_filename(t) + return sanitize_simple(t, list("\n"="", "\t"="", "/"="", "\\"="", "?"="", "%"="", "*"="", ":"="", "|"="", "\""="", "<"="", ">"="")) + /* * Text searches */ diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index e218727049b..99a313e4544 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -1571,6 +1571,14 @@ var/mob/dview/dview_mob = new /datum/proc/stack_trace(msg) CRASH(msg) +GLOBAL_REAL_VAR(list/stack_trace_storage) +/proc/gib_stack_trace() + stack_trace_storage = list() + stack_trace() + stack_trace_storage.Cut(1, min(3,stack_trace_storage.len)) + . = stack_trace_storage + stack_trace_storage = null + // \ref behaviour got changed in 512 so this is necesary to replicate old behaviour. // If it ever becomes necesary to get a more performant REF(), this lies here in wait // #define REF(thing) (thing && istype(thing, /datum) && (thing:datum_flags & DF_USE_TAG) && thing:tag ? "[thing:tag]" : "\ref[thing]") diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 7060451b275..f0a959c6a7b 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -123,8 +123,3 @@ /obj/screen/fullscreen/fishbed icon_state = "fishbed" - -#undef FULLSCREEN_LAYER -#undef BLIND_LAYER -#undef DAMAGE_LAYER -#undef CRIT_LAYER \ No newline at end of file diff --git a/code/_onclick/hud/map_popups.dm b/code/_onclick/hud/map_popups.dm new file mode 100644 index 00000000000..aae5c808c97 --- /dev/null +++ b/code/_onclick/hud/map_popups.dm @@ -0,0 +1,171 @@ +/client + /** + * 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( = list(/obj/screen)) + */ + var/list/screen_maps = list() + +/obj/screen + /** + * Map name assigned to this object. + * Automatically set by /client/proc/register_map_obj. + */ + var/assigned_map + /** + * Mark this object as garbage-collectible after you clean the map + * it was registered on. + * + * This could probably be changed to be a proc, for conditional removal. + * But for now, this works. + */ + var/del_on_map_removal = TRUE + +/** + * A screen object, which acts as a container for turfs and other things + * you want to show on the map, which you usually attach to "vis_contents". + */ +/obj/screen/map_view + icon_state = "blank" + // Map view has to be on the lowest plane to enable proper lighting + layer = SPACE_PLANE + plane = SPACE_PLANE + +/** + * A generic background object. + * It is also implicitly used to allocate a rectangle on the map, which will + * be used for auto-scaling the map. + */ +/obj/screen/background + name = "background" + icon = 'icons/mob/map_backgrounds.dmi' + icon_state = "clear" + layer = SPACE_PLANE + plane = SPACE_PLANE + +/** + * Sets screen_loc of this screen object, in form of point coordinates, + * with optional pixel offset (px, py). + * + * If applicable, "assigned_map" has to be assigned before this proc call. + */ +/obj/screen/proc/set_position(x, y, px = 0, py = 0) + if(assigned_map) + screen_loc = "[assigned_map]:[x]:[px],[y]:[py]" + else + screen_loc = "[x]:[px],[y]:[py]" + +/** + * Sets screen_loc to fill a rectangular area of the map. + * + * If applicable, "assigned_map" has to be assigned before this proc call. + */ +/obj/screen/proc/fill_rect(x1, y1, x2, y2) + if(assigned_map) + screen_loc = "[assigned_map]:[x1],[y1] to [x2],[y2]" + else + screen_loc = "[x1],[y1] to [x2],[y2]" + +/** + * Registers screen obj with the client, which makes it visible on the + * assigned map, and becomes a part of the assigned map's lifecycle. + */ +/client/proc/register_map_obj(obj/screen/screen_obj) + if(!screen_obj.assigned_map) + CRASH("Can't register [screen_obj] without 'assigned_map' property.") + if(!screen_maps[screen_obj.assigned_map]) + screen_maps[screen_obj.assigned_map] = list() + // NOTE: Possibly an expensive operation + var/list/screen_map = screen_maps[screen_obj.assigned_map] + if(!screen_map.Find(screen_obj)) + screen_map += screen_obj + if(!screen.Find(screen_obj)) + screen += screen_obj + +/** + * Clears the map of registered screen objects. + * + * Not really needed most of the time, as the client's screen list gets reset + * on relog. any of the buttons are going to get caught by garbage collection + * anyway. they're effectively qdel'd. + */ +/client/proc/clear_map(map_name) + if(!map_name || !(map_name in screen_maps)) + return FALSE + for(var/obj/screen/screen_obj in screen_maps[map_name]) + screen_maps[map_name] -= screen_obj + if(screen_obj.del_on_map_removal) + qdel(screen_obj) + screen_maps -= map_name + +/** + * Clears all the maps of registered screen objects. + */ +/client/proc/clear_all_maps() + for(var/map_name in screen_maps) + clear_map(map_name) + +/** + * Creates a popup window with a basic map element in it, without any + * further initialization. + * + * Ratio is how many pixels by how many pixels (keep it simple). + * + * Returns a map name. + */ +/client/proc/create_popup(name, ratiox = 100, ratioy = 100) + winclone(src, "popupwindow", name) + var/list/winparams = list() + winparams["size"] = "[ratiox]x[ratioy]" + winparams["on-close"] = "handle-popup-close [name]" + winset(src, "[name]", list2params(winparams)) + winshow(src, "[name]", 1) + + var/list/params = list() + params["parent"] = "[name]" + params["type"] = "map" + params["size"] = "[ratiox]x[ratioy]" + params["anchor1"] = "0,0" + params["anchor2"] = "[ratiox],[ratioy]" + winset(src, "[name]_map", list2params(params)) + + return "[name]_map" + +/** + * Create the popup, and get it ready for generic use by giving + * it a background. + * + * Width and height are multiplied by 64 by default. + */ +/client/proc/setup_popup(popup_name, width = 9, height = 9, \ + tilesize = 2, bg_icon) + if(!popup_name) + return + clear_map("[popup_name]_map") + var/x_value = world.icon_size * tilesize * width + var/y_value = world.icon_size * tilesize * height + var/map_name = create_popup(popup_name, x_value, y_value) + + var/obj/screen/background/background = new + background.assigned_map = map_name + background.fill_rect(1, 1, width, height) + if(bg_icon) + background.icon_state = bg_icon + register_map_obj(background) + + return map_name + +/** + * Closes a popup. + */ +/client/proc/close_popup(popup) + winshow(src, popup, 0) + handle_popup_close(popup) + +/** + * When the popup closes in any way (player or proc call) it calls this. + */ +/client/verb/handle_popup_close(window_id as text) + set hidden = TRUE + clear_map("[window_id]_map") diff --git a/code/_onclick/hud/skybox.dm b/code/_onclick/hud/skybox.dm index f055ea86936..efd11798915 100644 --- a/code/_onclick/hud/skybox.dm +++ b/code/_onclick/hud/skybox.dm @@ -3,17 +3,20 @@ #define SKYBOX_TURFS (SKYBOX_PIXELS/WORLD_ICON_SIZE) // Skybox screen object. -/obj/skybox +/obj/screen/skybox name = "skybox" + icon = null + appearance_flags = TILE_BOUND|PIXEL_SCALE mouse_opacity = 0 anchored = TRUE simulated = FALSE screen_loc = "CENTER,CENTER" + layer = OBJ_LAYER plane = SKYBOX_PLANE blend_mode = BLEND_MULTIPLY // You actually need to do it this way or you see it in occlusion. // Adjust transform property to scale for client's view var. We assume the skybox is 736x736 px -/obj/skybox/proc/scale_to_view(var/view) +/obj/screen/skybox/proc/scale_to_view(var/view) var/matrix/M = matrix() // Translate to center the icon over us! M.Translate(-(SKYBOX_PIXELS - WORLD_ICON_SIZE) / 2) @@ -23,7 +26,7 @@ src.transform = M /client - var/obj/skybox/skybox + var/obj/screen/skybox/skybox /client/proc/update_skybox(rebuild) if(!skybox) diff --git a/code/controllers/subsystems/ai.dm b/code/controllers/subsystems/ai.dm index 0641453f2ba..4ed43a34811 100644 --- a/code/controllers/subsystems/ai.dm +++ b/code/controllers/subsystems/ai.dm @@ -32,7 +32,7 @@ SUBSYSTEM_DEF(ai) while(currentrun.len) var/datum/ai_holder/A = currentrun[currentrun.len] --currentrun.len - if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick + if(!A || QDELETED(A) || !A.holder?.loc || A.busy) // Doesn't exist or won't exist soon or not doing it this tick continue if(process_z[get_z(A.holder)]) diff --git a/code/controllers/subsystems/mobs.dm b/code/controllers/subsystems/mobs.dm index 8fb2bf3f891..1ae1d647579 100644 --- a/code/controllers/subsystems/mobs.dm +++ b/code/controllers/subsystems/mobs.dm @@ -43,7 +43,7 @@ SUBSYSTEM_DEF(mobs) if(!M || QDELETED(M)) mob_list -= M continue - else if(M.low_priority && !(process_z[get_z(M)])) + else if(M.low_priority && !(M.loc && process_z[get_z(M)])) slept_mobs++ continue diff --git a/code/controllers/subsystems/skybox.dm b/code/controllers/subsystems/skybox.dm index 03f41f0f33d..6befac0b605 100644 --- a/code/controllers/subsystems/skybox.dm +++ b/code/controllers/subsystems/skybox.dm @@ -132,7 +132,7 @@ SUBSYSTEM_DEF(skybox) for(var/z in zlevels) skybox_cache["[z]"] = generate_skybox(z) - for(var/client/C) + for(var/client/C in GLOB.clients) var/their_z = get_z(C.mob) if(!their_z) //Nullspace continue diff --git a/code/controllers/subsystems/tgui.dm b/code/controllers/subsystems/tgui.dm new file mode 100644 index 00000000000..91533a77833 --- /dev/null +++ b/code/controllers/subsystems/tgui.dm @@ -0,0 +1,343 @@ + /** + * tgui subsystem + * + * Contains all tgui state and subsystem code. + **/ + + +SUBSYSTEM_DEF(tgui) + name = "TGUI" + wait = 9 + flags = SS_NO_INIT + priority = FIRE_PRIORITY_TGUI + runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT + + /// A list of UIs scheduled to process + var/list/current_run = list() + /// A list of open UIs + var/list/open_uis = list() + /// A list of open UIs, grouped by src_object and ui_key. + var/list/open_uis_by_src = list() + /// The HTML base used for all UIs. + var/basehtml + +/datum/controller/subsystem/tgui/PreInit() + basehtml = file2text('tgui/packages/tgui/public/tgui.html') + +/datum/controller/subsystem/tgui/Shutdown() + close_all_uis() + +/datum/controller/subsystem/tgui/stat_entry() + ..("P:[open_uis.len]") + +/datum/controller/subsystem/tgui/fire(resumed = 0) + if(!resumed) + src.current_run = open_uis.Copy() + // Cache for sanic speed (lists are references anyways) + var/list/current_run = src.current_run + while(current_run.len) + var/datum/tgui/ui = current_run[current_run.len] + current_run.len-- + // TODO: Move user/src_object check to process() + if(ui && ui.user && ui.src_object) + ui.process() + else + open_uis.Remove(ui) + if(MC_TICK_CHECK) + return + +/** + * public + * + * Requests a usable tgui window from the pool. + * Returns null if pool was exhausted. + * + * required user mob + * return datum/tgui + */ +/datum/controller/subsystem/tgui/proc/request_pooled_window(mob/user) + if(!user.client) + return null + var/list/windows = user.client.tgui_windows + var/window_id + var/datum/tgui_window/window + var/window_found = FALSE + // Find a usable window + for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT) + window_id = TGUI_WINDOW_ID(i) + window = windows[window_id] + // As we are looping, create missing window datums + if(!window) + window = new(user.client, window_id, pooled = TRUE) + // Skip windows with acquired locks + if(window.locked) + continue + if(window.status == TGUI_WINDOW_READY) + return window + if(window.status == TGUI_WINDOW_CLOSED) + window.status = TGUI_WINDOW_LOADING + window_found = TRUE + break + if(!window_found) + return null + return window + +/** + * public + * + * Force closes all tgui windows. + * + * required user mob + */ +/datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user) + if(user.client) + user.client.tgui_windows = list() + for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT) + var/window_id = TGUI_WINDOW_ID(i) + user << browse(null, "window=[window_id]") + +/** + * public + * + * Force closes the tgui window by window_id. + * + * required user mob + * required window_id string + */ +/datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id) + // Close all tgui datums based on window_id. + for(var/datum/tgui/ui in user.tgui_open_uis) + if(ui.window && ui.window.id == window_id) + ui.close(can_be_suspended = FALSE) + // Unset machine just to be sure. + user.unset_machine() + // Close window directly just to be sure. + user << browse(null, "window=[window_id]") + + /** + * public + * + * Get a open UI given a user, src_object, and ui_key and try to update it with data. + * + * required user mob The mob who opened/is using the UI. + * required src_object datum The object/datum which owns the UI. + * required ui_key string The ui_key of the UI. + * + * return datum/tgui The found UI. + **/ +/datum/controller/subsystem/tgui/proc/try_update_ui( + mob/user, + datum/src_object, + datum/tgui/ui) + // Look up a UI if it wasn't passed. + if(isnull(ui)) + ui = get_open_ui(user, src_object) + // Couldn't find a UI. + if(isnull(ui)) + return null + ui.process_status() + // UI ended up with the closed status + // or is actively trying to close itself. + // FIXME: Doesn't actually fix the paper bug. + if(ui.status <= STATUS_CLOSE) + ui.close() + return null + ui.send_update() + return ui + + /** + * private + * + * Get a open UI given a user, src_object, and ui_key. + * + * required user mob The mob who opened/is using the UI. + * required src_object datum The object/datum which owns the UI. + * required ui_key string The ui_key of the UI. + * + * return datum/tgui The found UI. + **/ +/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object) + var/key = "[REF(src_object)]" + // No UIs opened for this src_object + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + return null // No UIs open. + for(var/datum/tgui/ui in open_uis_by_src[key]) // Find UIs for this object. + // Make sure we have the right user + if(ui.user == user) + return ui + return null // Couldn't find a UI! + + /** + * private + * + * Update all UIs attached to src_object. + * + * required src_object datum The object/datum which owns the UIs. + * + * return int The number of UIs updated. + **/ +/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object) + var/count = 0 + var/key = "[REF(src_object)]" + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + return count // Couldn't find any UIs for this object. + for(var/datum/tgui/ui in open_uis_by_src[key]) + // Check the UI is valid. + if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) + ui.process(force = 1) // Update the UI. + count++ // Count each UI we update. + return count + + /** + * private + * + * Close all UIs attached to src_object. + * + * required src_object datum The object/datum which owns the UIs. + * + * return int The number of UIs closed. + **/ +/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object) + var/count = 0 + var/key = "[REF(src_object)]" + // No UIs opened for this src_object + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + return count + for(var/datum/tgui/ui in open_uis_by_src[key]) + if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) // Check the UI is valid. + ui.close() // Close the UI. + count++ // Count each UI we close. + return count + + /** + * private + * + * Close all UIs regardless of their attachment to src_object. + * + * return int The number of UIs closed. + **/ +/datum/controller/subsystem/tgui/proc/close_all_uis() + var/count = 0 + for(var/key in open_uis_by_src) + for(var/datum/tgui/ui in open_uis_by_src[key]) + if(ui && ui.src_object && ui.user && ui.src_object.tgui_host(ui.user)) // Check the UI is valid. + ui.close() // Close the UI. + count++ // Count each UI we close. + return count + + /** + * private + * + * Update all UIs belonging to a user. + * + * required user mob The mob who opened/is using the UI. + * optional src_object datum If provided, only update UIs belonging this src_object. + * + * return int The number of UIs updated. + **/ +/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object) + var/count = 0 + if(length(user?.tgui_open_uis) == 0) + return count + for(var/datum/tgui/ui in user.tgui_open_uis) + if(isnull(src_object) || ui.src_object == src_object) + ui.process(force = 1) + count++ + return count + + /** + * private + * + * Close all UIs belonging to a user. + * + * required user mob The mob who opened/is using the UI. + * optional src_object datum If provided, only close UIs belonging this src_object. + * + * return int The number of UIs closed. + **/ +/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object) + var/count = 0 + if(length(user?.tgui_open_uis) == 0) + return count + for(var/datum/tgui/ui in user.tgui_open_uis) + if(isnull(src_object) || ui.src_object == src_object) + ui.close() + count++ + return count + + /** + * private + * + * Add a UI to the list of open UIs. + * + * required ui datum/tgui The UI to be added. + **/ +/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui) + var/key = "[REF(ui.src_object)]" + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + open_uis_by_src[key] = list() + ui.user.tgui_open_uis |= ui + var/list/uis = open_uis_by_src[key] + uis |= ui + open_uis |= ui + + /** + * private + * + * Remove a UI from the list of open UIs. + * + * required ui datum/tgui The UI to be removed. + * + * return bool If the UI was removed or not. + **/ +/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui) + var/key = "[REF(ui.src_object)]" + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + return FALSE + // Remove it from the list of processing UIs. + open_uis.Remove(ui) + // If the user exists, remove it from them too. + if(ui.user) + ui.user.tgui_open_uis.Remove(ui) + var/list/uis = open_uis_by_src[key] + uis.Remove(ui) + if(length(uis) == 0) + open_uis_by_src.Remove(key) + return TRUE + + /** + * private + * + * Handle client logout, by closing all their UIs. + * + * required user mob The mob which logged out. + * + * return int The number of UIs closed. + **/ +/datum/controller/subsystem/tgui/proc/on_logout(mob/user) + return close_user_uis(user) + + /** + * private + * + * Handle clients switching mobs, by transferring their UIs. + * + * required user source The client's original mob. + * required user target The client's new mob. + * + * return bool If the UIs were transferred. + **/ +/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target) + // The old mob had no open UIs. + if(length(source?.tgui_open_uis) == 0) + return FALSE + if(isnull(target.tgui_open_uis) || !istype(target.tgui_open_uis, /list)) + target.tgui_open_uis = list() + // Transfer all the UIs. + for(var/datum/tgui/ui in source.tgui_open_uis) + // Inform the UIs of their new owner. + ui.user = target + target.tgui_open_uis.Add(ui) + // Clear the old list. + source.tgui_open_uis.Cut() + return TRUE \ No newline at end of file diff --git a/code/datums/repositories/cameras.dm b/code/datums/repositories/cameras.dm index d5161133948..e69de29bb2d 100644 --- a/code/datums/repositories/cameras.dm +++ b/code/datums/repositories/cameras.dm @@ -1,49 +0,0 @@ -var/global/datum/repository/cameras/camera_repository = new() - -/proc/invalidateCameraCache() - camera_repository.networks.Cut() - camera_repository.invalidated = 1 - camera_repository.camera_cache_id = (++camera_repository.camera_cache_id % 999999) - -/datum/repository/cameras - var/list/networks - var/invalidated = 1 - var/camera_cache_id = 1 - -/datum/repository/cameras/New() - networks = list() - ..() - -/datum/repository/cameras/proc/cameras_in_network(var/network, var/list/zlevels) - setup_cache() - var/list/network_list = networks[network] - if(LAZYLEN(zlevels)) - var/list/filtered_cameras = list() - for(var/list/C in network_list) - //Camera is marked as always-visible - if(C["omni"]) - filtered_cameras[++filtered_cameras.len] = C - continue - //Camera might be in an adjacent zlevel - var/camz = C["z"] - if(!camz) //It's inside something (helmet, communicator, etc) or nullspace or who knows - camz = get_z(locate(C["camera"]) in cameranet.cameras) - if(camz in zlevels) - filtered_cameras[++filtered_cameras.len] = C //Can't add lists to lists with += - return filtered_cameras - else - return network_list - -/datum/repository/cameras/proc/setup_cache() - if(!invalidated) - return - invalidated = 0 - - cameranet.process_sort() - for(var/obj/machinery/camera/C in cameranet.cameras) - var/cam = C.nano_structure() - for(var/network in C.network) - if(!networks[network]) - networks[network] = list() - var/list/netlist = networks[network] - netlist[++netlist.len] = cam diff --git a/code/datums/repositories/crew.dm b/code/datums/repositories/crew.dm index f67a17ca75b..7a748049bc2 100644 --- a/code/datums/repositories/crew.dm +++ b/code/datums/repositories/crew.dm @@ -51,6 +51,7 @@ var/global/datum/repository/crew/crew_repository = new() crewmemberData["area"] = sanitize(A.get_name()) crewmemberData["x"] = pos.x crewmemberData["y"] = pos.y + crewmemberData["realZ"] = pos.z crewmemberData["z"] = using_map.get_zlevel_name(pos.z) crewmembers[++crewmembers.len] = crewmemberData diff --git a/code/datums/supplypacks/atmospherics.dm b/code/datums/supplypacks/atmospherics.dm index cf102f129db..fb5d4a0e597 100644 --- a/code/datums/supplypacks/atmospherics.dm +++ b/code/datums/supplypacks/atmospherics.dm @@ -11,42 +11,42 @@ name = "Inflatable barriers" contains = list(/obj/item/weapon/storage/briefcase/inflatable = 3) cost = 20 - containertype = /obj/structure/closet/crate/engineering + containertype = /obj/structure/closet/crate/aether containername = "Inflatable Barrier Crate" /datum/supply_pack/atmos/canister_empty name = "Empty gas canister" cost = 7 containername = "Empty gas canister crate" - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/aether contains = list(/obj/machinery/portable_atmospherics/canister) /datum/supply_pack/atmos/canister_air name = "Air canister" cost = 10 containername = "Air canister crate" - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/aether contains = list(/obj/machinery/portable_atmospherics/canister/air) /datum/supply_pack/atmos/canister_oxygen name = "Oxygen canister" cost = 15 containername = "Oxygen canister crate" - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/aether contains = list(/obj/machinery/portable_atmospherics/canister/oxygen) /datum/supply_pack/atmos/canister_nitrogen name = "Nitrogen canister" cost = 10 containername = "Nitrogen canister crate" - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/aether contains = list(/obj/machinery/portable_atmospherics/canister/nitrogen) /datum/supply_pack/atmos/canister_phoron name = "Phoron gas canister" cost = 60 containername = "Phoron gas canister crate" - containertype = /obj/structure/closet/crate/secure/large + containertype = /obj/structure/closet/crate/secure/large/aether access = access_atmospherics contains = list(/obj/machinery/portable_atmospherics/canister/phoron) @@ -54,7 +54,7 @@ name = "N2O gas canister" cost = 15 containername = "N2O gas canister crate" - containertype = /obj/structure/closet/crate/secure/large + containertype = /obj/structure/closet/crate/secure/large/aether access = access_atmospherics contains = list(/obj/machinery/portable_atmospherics/canister/sleeping_agent) @@ -62,7 +62,7 @@ name = "Carbon dioxide gas canister" cost = 15 containername = "CO2 canister crate" - containertype = /obj/structure/closet/crate/secure/large + containertype = /obj/structure/closet/crate/secure/large/aether access = access_atmospherics contains = list(/obj/machinery/portable_atmospherics/canister/carbon_dioxide) @@ -70,7 +70,7 @@ contains = list(/obj/machinery/pipedispenser/orderable) name = "Pipe Dispenser" cost = 25 - containertype = /obj/structure/closet/crate/secure/large + containertype = /obj/structure/closet/crate/secure/large/aether containername = "Pipe Dispenser Crate" access = access_atmospherics @@ -78,7 +78,7 @@ contains = list(/obj/machinery/pipedispenser/disposal/orderable) name = "Disposals Pipe Dispenser" cost = 25 - containertype = /obj/structure/closet/crate/secure/large + containertype = /obj/structure/closet/crate/secure/large/aether containername = "Disposal Dispenser Crate" access = access_atmospherics @@ -89,7 +89,7 @@ /obj/item/weapon/tank/air = 3 ) cost = 10 - containertype = /obj/structure/closet/crate/internals + containertype = /obj/structure/closet/crate/aether containername = "Internals crate" /datum/supply_pack/atmos/evacuation @@ -104,5 +104,5 @@ /obj/item/clothing/mask/gas = 4 ) cost = 35 - containertype = /obj/structure/closet/crate/internals + containertype = /obj/structure/closet/crate/aether containername = "Emergency crate" diff --git a/code/datums/supplypacks/contraband.dm b/code/datums/supplypacks/contraband.dm index 7b266b2a76f..7d8616a8ad0 100644 --- a/code/datums/supplypacks/contraband.dm +++ b/code/datums/supplypacks/contraband.dm @@ -28,7 +28,7 @@ /obj/item/weapon/grenade/chem_grenade/incendiary ) cost = 25 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/weapon containername = "Special Ops crate" contraband = 1 @@ -39,7 +39,7 @@ /obj/item/weapon/reagent_containers/food/snacks/unajerky = 4 ) cost = 25 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/unathi containername = "Moghes imports crate" contraband = 1 @@ -51,7 +51,7 @@ ) cost = 50 contraband = 1 - containertype = /obj/structure/closet/crate/secure/weapon + containertype = /obj/structure/closet/crate/hedberg containername = "Ballistic weapons crate" /datum/supply_pack/randomised/misc/telecrate //you get something awesome, a couple of decent things, and a few weak/filler things @@ -103,5 +103,5 @@ ) cost = 250 //more than a hat crate!, contraband = 1 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large containername = "Suspicious crate" diff --git a/code/datums/supplypacks/costumes.dm b/code/datums/supplypacks/costumes.dm index 879d5accd0c..f9b61d95723 100644 --- a/code/datums/supplypacks/costumes.dm +++ b/code/datums/supplypacks/costumes.dm @@ -1,6 +1,6 @@ /* * Here is where any supply packs -* related to weapons live. +* related to costumes live. */ @@ -19,7 +19,7 @@ /obj/item/clothing/head/wizard/fake ) cost = 20 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/nanothreads containername = "Wizard costume crate" /datum/supply_pack/randomised/costumes/hats @@ -48,8 +48,8 @@ ) name = "Collectable hat crate!" cost = 200 - containertype = /obj/structure/closet/crate - containername = "Collectable hats crate! Brought to you by Bass.inc!" + containertype = /obj/structure/closet/crate/nanothreads + containername = "Collectable hats crate" /datum/supply_pack/randomised/costumes/costume num_contained = 3 @@ -84,7 +84,7 @@ ) name = "Costumes crate" cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/nanothreads containername = "Actor Costumes" /datum/supply_pack/costumes/formal_wear @@ -104,15 +104,15 @@ /obj/item/clothing/shoes/leather, /obj/item/clothing/accessory/wcoat ) - name = "Formalwear closet" + name = "Formalwear (Suits)" cost = 30 - containertype = /obj/structure/closet - containername = "Formalwear for the best occasions." + containertype = /obj/structure/closet/crate/gilthari + containername = "Formal suit crate" datum/supply_pack/costumes/witch name = "Witch costume" containername = "Witch costume" - containertype = /obj/structure/closet + containertype = /obj/structure/closet/crate/nanothreads cost = 20 contains = list( /obj/item/clothing/suit/wizrobe/marisa/fake, @@ -124,7 +124,7 @@ datum/supply_pack/costumes/witch /datum/supply_pack/randomised/costumes/costume_hats name = "Costume hats" containername = "Actor hats crate" - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/nanothreads cost = 10 num_contained = 3 contains = list( @@ -147,9 +147,9 @@ datum/supply_pack/costumes/witch ) /datum/supply_pack/randomised/costumes/dresses - name = "Womens formal dress locker" - containername = "Pretty dress locker" - containertype = /obj/structure/closet + name = "Formalwear (Dresses)" + containername = "Formal dress crate" + containertype = /obj/structure/closet/crate/gilthari cost = 15 num_contained = 3 contains = list( diff --git a/code/datums/supplypacks/engineering.dm b/code/datums/supplypacks/engineering.dm index 5ffa26d7117..5d2bc99089a 100644 --- a/code/datums/supplypacks/engineering.dm +++ b/code/datums/supplypacks/engineering.dm @@ -11,30 +11,72 @@ name = "Replacement lights" contains = list(/obj/item/weapon/storage/box/lights/mixed = 3) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/galaksi containername = "Replacement lights" /datum/supply_pack/eng/smescoil name = "Superconducting Magnetic Coil" contains = list(/obj/item/weapon/smes_coil) cost = 75 - containertype = /obj/structure/closet/crate/engineering + containertype = /obj/structure/closet/crate/focalpoint containername = "Superconducting Magnetic Coil crate" /datum/supply_pack/eng/smescoil/super_capacity name = "Superconducting Capacitance Coil" contains = list(/obj/item/weapon/smes_coil/super_capacity) cost = 90 - containertype = /obj/structure/closet/crate/engineering + containertype = /obj/structure/closet/crate/focalpoint containername = "Superconducting Capacitance Coil crate" /datum/supply_pack/eng/smescoil/super_io name = "Superconducting Transmission Coil" contains = list(/obj/item/weapon/smes_coil/super_io) cost = 90 - containertype = /obj/structure/closet/crate/engineering + containertype = /obj/structure/closet/crate/focalpoint containername = "Superconducting Transmission Coil crate" +/datum/supply_pack/eng/shield_capacitor + name = "Shield Capacitor" + contains = list(/obj/machinery/shield_capacitor) + cost = 20 + containertype = /obj/structure/closet/crate/focalpoint + containername = "shield capacitor crate" + +/datum/supply_pack/eng/shield_capacitor/advanced + name = "Advanced Shield Capacitor" + contains = list(/obj/machinery/shield_capacitor/advanced) + cost = 30 + containertype = /obj/structure/closet/crate/focalpoint + containername = "advanced shield capacitor crate" + +/datum/supply_pack/eng/bubble_shield + name = "Bubble Shield Generator" + contains = list(/obj/machinery/shield_gen) + cost = 40 + containertype =/obj/structure/closet/crate/focalpoint + containername = "shield bubble generator crate" + +/datum/supply_pack/eng/bubble_shield/advanced + name = "Advanced Bubble Shield Generator" + contains = list(/obj/machinery/shield_gen/advanced) + cost = 60 + containertype = /obj/structure/closet/crate/focalpoint + containername = "advanced bubble shield generator crate" + +/datum/supply_pack/eng/hull_shield + name = "Hull Shield Generator" + contains = list(/obj/machinery/shield_gen/external) + cost = 80 + containertype = /obj/structure/closet/crate/focalpoint + containername = "shield hull generator crate" + +/datum/supply_pack/eng/hull_shield/advanced + name = "Advanced Hull Shield Generator" + contains = list(/obj/machinery/shield_gen/external/advanced) + cost = 120 + containertype = /obj/structure/closet/crate/focalpoint + containername = "advanced hull shield generator crate" + /datum/supply_pack/eng/electrical name = "Electrical maintenance crate" contains = list( @@ -44,7 +86,7 @@ /obj/item/weapon/cell/high = 2 ) cost = 10 - containertype = /obj/structure/closet/crate/engineering/electrical + containertype = /obj/structure/closet/crate/ward containername = "Electrical maintenance crate" /datum/supply_pack/eng/e_welders @@ -53,7 +95,7 @@ /obj/item/weapon/weldingtool/electric = 3 ) cost = 15 - containertype = /obj/structure/closet/crate/engineering/electrical + containertype = /obj/structure/closet/crate/ward containername = "Electric welder crate" /datum/supply_pack/eng/mechanical @@ -65,14 +107,14 @@ /obj/item/clothing/head/hardhat ) cost = 10 - containertype = /obj/structure/closet/crate/engineering + containertype = /obj/structure/closet/crate/xion containername = "Mechanical maintenance crate" /datum/supply_pack/eng/fueltank name = "Fuel tank crate" contains = list(/obj/structure/reagent_dispensers/fueltank) cost = 10 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/nanotrasen containername = "fuel tank crate" /datum/supply_pack/eng/solar @@ -84,35 +126,35 @@ /obj/item/weapon/paper/solar ) cost = 20 - containertype = /obj/structure/closet/crate/engineering + containertype = /obj/structure/closet/crate/einstein containername = "Solar pack crate" /datum/supply_pack/eng/engine name = "Emitter crate" contains = list(/obj/machinery/power/emitter = 2) cost = 10 - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/einstein containername = "Emitter crate" access = access_ce /datum/supply_pack/eng/engine/field_gen name = "Field Generator crate" contains = list(/obj/machinery/field_generator = 2) - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/xion containername = "Field Generator crate" access = access_ce /datum/supply_pack/eng/engine/sing_gen name = "Singularity Generator crate" contains = list(/obj/machinery/the_singularitygen) - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/einstein containername = "Singularity Generator crate" access = access_ce /datum/supply_pack/eng/engine/collector name = "Collector crate" contains = list(/obj/machinery/power/rad_collector = 3) - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/einstein containername = "Collector crate" /datum/supply_pack/eng/engine/PA @@ -127,23 +169,33 @@ /obj/structure/particle_accelerator/power_box, /obj/structure/particle_accelerator/end_cap ) - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/einstein containername = "Particle Accelerator crate" access = access_ce -/datum/supply_pack/eng/shield_generator - name = "Shield Generator Construction Kit" - contains = list( - /obj/item/weapon/circuitboard/shield_generator, - /obj/item/weapon/stock_parts/capacitor, - /obj/item/weapon/stock_parts/micro_laser, - /obj/item/weapon/smes_coil, - /obj/item/weapon/stock_parts/console_screen, - /obj/item/weapon/stock_parts/subspace/amplifier - ) - cost = 80 - containertype = /obj/structure/closet/crate/engineering - containername = "shield generator construction kit crate" +/datum/supply_pack/eng/shield_gen + contains = list(/obj/item/weapon/circuitboard/shield_gen) + name = "Bubble shield generator circuitry" + cost = 30 + containertype = /obj/structure/closet/crate/secure/focalpoint + containername = "bubble shield generator circuitry crate" + access = access_ce + +/datum/supply_pack/eng/shield_gen_ex + contains = list(/obj/item/weapon/circuitboard/shield_gen_ex) + name = "Hull shield generator circuitry" + cost = 30 + containertype = /obj/structure/closet/crate/secure/focalpoint + containername = "hull shield generator circuitry crate" + access = access_ce + +/datum/supply_pack/eng/shield_cap + contains = list(/obj/item/weapon/circuitboard/shield_cap) + name = "Bubble shield capacitor circuitry" + cost = 30 + containertype = /obj/structure/closet/crate/secure/focalpoint + containername = "shield capacitor circuitry crate" + access = access_ce /datum/supply_pack/eng/smbig name = "Supermatter Core" @@ -157,7 +209,7 @@ contains = list(/obj/machinery/power/generator) name = "Mark I Thermoelectric Generator" cost = 40 - containertype = /obj/structure/closet/crate/secure/large + containertype = /obj/structure/closet/crate/secure/large/einstein containername = "Mk1 TEG crate" access = access_engine @@ -165,7 +217,7 @@ contains = list(/obj/machinery/atmospherics/binary/circulator) name = "Binary atmospheric circulator" cost = 20 - containertype = /obj/structure/closet/crate/secure/large + containertype = /obj/structure/closet/crate/secure/large/einstein containername = "Atmospheric circulator crate" access = access_engine @@ -183,7 +235,7 @@ name = "P.A.C.M.A.N. portable generator parts" cost = 25 containername = "P.A.C.M.A.N. Portable Generator Construction Kit" - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/focalpoint access = access_tech_storage contains = list( /obj/item/weapon/stock_parts/micro_laser, @@ -196,7 +248,7 @@ name = "Super P.A.C.M.A.N. portable generator parts" cost = 35 containername = "Super P.A.C.M.A.N. portable generator construction kit" - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/focalpoint access = access_tech_storage contains = list( /obj/item/weapon/stock_parts/micro_laser, @@ -209,7 +261,7 @@ name = "R-UST Mk. 8 Tokamak fusion core crate" cost = 50 containername = "R-UST Mk. 8 Tokamak Fusion Core crate" - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/einstein access = access_engine contains = list( /obj/item/weapon/book/manual/rust_engine, @@ -221,7 +273,7 @@ name = "R-UST Mk. 8 fuel injector crate" cost = 30 containername = "R-UST Mk. 8 fuel injector crate" - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/einstein access = access_engine contains = list( /obj/machinery/fusion_fuel_injector, @@ -233,7 +285,7 @@ name = "Gyrotron crate" cost = 15 containername = "Gyrotron Crate" - containertype = /obj/structure/closet/crate/secure/engineering + containertype = /obj/structure/closet/crate/secure/einstein access = access_engine contains = list( /obj/machinery/power/emitter/gyrotron, @@ -244,12 +296,12 @@ name = "Fusion Fuel Compressor circuitry crate" cost = 10 containername = "Fusion Fuel Compressor circuitry crate" - containertype = /obj/structure/closet/crate/engineering + containertype = /obj/structure/closet/crate/einstein contains = list(/obj/item/weapon/circuitboard/fusion_fuel_compressor) /datum/supply_pack/eng/tritium name = "Tritium crate" cost = 75 containername = "Tritium crate" - containertype = /obj/structure/closet/crate/engineering + containertype = /obj/structure/closet/crate/einstein contains = list(/obj/fiftyspawner/tritium) diff --git a/code/datums/supplypacks/engineering_vr.dm b/code/datums/supplypacks/engineering_vr.dm index 273d3f65585..61c0f0e1803 100644 --- a/code/datums/supplypacks/engineering_vr.dm +++ b/code/datums/supplypacks/engineering_vr.dm @@ -1,3 +1,17 @@ +/datum/supply_pack/eng/modern_shield + name = "Modern Shield Construction Kit" + contains = list( + /obj/item/weapon/circuitboard/shield_generator, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/micro_laser, + /obj/item/weapon/smes_coil, + /obj/item/weapon/stock_parts/console_screen, + /obj/item/weapon/stock_parts/subspace/amplifier + ) + cost = 80 + containertype = /obj/structure/closet/crate/focalpoint + containername = "shield generator construction kit crate" + /datum/supply_pack/eng/thermoregulator contains = list(/obj/machinery/power/thermoregulator) name = "Thermal Regulator" diff --git a/code/datums/supplypacks/hospitality.dm b/code/datums/supplypacks/hospitality.dm index fa7f09ebd9f..2c9bbbce518 100644 --- a/code/datums/supplypacks/hospitality.dm +++ b/code/datums/supplypacks/hospitality.dm @@ -23,7 +23,7 @@ /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer = 4, ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/gilthari containername = "Party equipment" /datum/supply_pack/hospitality/barsupplies @@ -43,7 +43,7 @@ /obj/item/weapon/storage/box/glass_extras/sticks ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/gilthari containername = "crate of bar supplies" /datum/supply_pack/hospitality/cookingoil @@ -67,7 +67,7 @@ ) name = "Surprise pack of five pizzas" cost = 15 - containertype = /obj/structure/closet/crate/freezer + containertype = /obj/structure/closet/crate/freezer/centauri containername = "Pizza crate" /datum/supply_pack/hospitality/gifts @@ -81,5 +81,5 @@ /obj/item/weapon/paper/card/flower ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/allico containername = "crate of gifts" \ No newline at end of file diff --git a/code/datums/supplypacks/hydroponics.dm b/code/datums/supplypacks/hydroponics.dm index 4341a696ad9..069911606e5 100644 --- a/code/datums/supplypacks/hydroponics.dm +++ b/code/datums/supplypacks/hydroponics.dm @@ -11,7 +11,7 @@ name = "Monkey crate" contains = list (/obj/item/weapon/storage/box/monkeycubes) cost = 20 - containertype = /obj/structure/closet/crate/freezer + containertype = /obj/structure/closet/crate/freezer/nanotrasen containername = "Monkey crate" /datum/supply_pack/hydro/farwa @@ -110,7 +110,7 @@ /obj/item/seeds/sugarcaneseed ) cost = 10 - containertype = /obj/structure/closet/crate/hydroponics + containertype = /obj/structure/closet/crate/carp containername = "Seeds crate" access = access_hydroponics @@ -124,7 +124,7 @@ /obj/item/weapon/material/twohanded/fireaxe/scythe ) cost = 45 - containertype = /obj/structure/closet/crate/hydroponics + containertype = /obj/structure/closet/crate/grayson containername = "Weed control crate" access = access_hydroponics @@ -132,7 +132,7 @@ name = "Water tank crate" contains = list(/obj/structure/reagent_dispensers/watertank) cost = 10 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/aether containername = "water tank crate" /datum/supply_pack/hydro/bee_keeper @@ -144,14 +144,14 @@ /obj/item/bee_pack ) cost = 40 - containertype = /obj/structure/closet/crate/hydroponics + containertype = /obj/structure/closet/crate/carp containername = "Beekeeping crate" access = access_hydroponics /datum/supply_pack/hydro/tray name = "Empty hydroponics trays" cost = 50 - containertype = /obj/structure/closet/crate/hydroponics + containertype = /obj/structure/closet/crate/aether containername = "Hydroponics tray crate" contains = list(/obj/machinery/portable_atmospherics/hydroponics{anchored = 0} = 3) access = access_hydroponics diff --git a/code/datums/supplypacks/materials.dm b/code/datums/supplypacks/materials.dm index cd799a235b1..95f15caa6d1 100644 --- a/code/datums/supplypacks/materials.dm +++ b/code/datums/supplypacks/materials.dm @@ -11,40 +11,40 @@ name = "50 metal sheets" contains = list(/obj/fiftyspawner/steel) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/grayson containername = "Metal sheets crate" /datum/supply_pack/materials/glass50 name = "50 glass sheets" contains = list(/obj/fiftyspawner/glass) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/grayson containername = "Glass sheets crate" /datum/supply_pack/materials/wood50 name = "50 wooden planks" contains = list(/obj/fiftyspawner/wood) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/grayson containername = "Wooden planks crate" /datum/supply_pack/materials/plastic50 name = "50 plastic sheets" contains = list(/obj/fiftyspawner/plastic) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/grayson containername = "Plastic sheets crate" /datum/supply_pack/materials/cardboard_sheets contains = list(/obj/fiftyspawner/cardboard) name = "50 cardboard sheets" cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/grayson containername = "Cardboard sheets crate" /datum/supply_pack/materials/carpet name = "Imported carpet" - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/grayson containername = "Imported carpet crate" cost = 15 contains = list( @@ -55,7 +55,7 @@ /datum/supply_pack/misc/linoleum name = "Linoleum" - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/grayson containername = "Linoleum crate" cost = 15 contains = list(/obj/fiftyspawner/linoleum) \ No newline at end of file diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm index 1b164a2cdf3..3edcbed2008 100644 --- a/code/datums/supplypacks/medical.dm +++ b/code/datums/supplypacks/medical.dm @@ -22,28 +22,28 @@ /obj/item/weapon/storage/box/autoinjectors ) cost = 10 - containertype = /obj/structure/closet/crate/medical + containertype = /obj/structure/closet/crate/zenghu containername = "Medical crate" /datum/supply_pack/med/bloodpack name = "BloodPack crate" contains = list(/obj/item/weapon/storage/box/bloodpacks = 3) cost = 10 - containertype = /obj/structure/closet/crate/medical + containertype = /obj/structure/closet/crate/nanocare containername = "BloodPack crate" /datum/supply_pack/med/bodybag name = "Body bag crate" contains = list(/obj/item/weapon/storage/box/bodybags = 3) cost = 10 - containertype = /obj/structure/closet/crate/medical + containertype = /obj/structure/closet/crate/nanocare containername = "Body bag crate" /datum/supply_pack/med/cryobag name = "Stasis bag crate" contains = list(/obj/item/bodybag/cryobag = 3) cost = 40 - containertype = /obj/structure/closet/crate/medical + containertype = /obj/structure/closet/crate/nanocare containername = "Stasis bag crate" /datum/supply_pack/med/surgery @@ -62,7 +62,7 @@ /obj/item/weapon/surgical/circular_saw ) cost = 25 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/veymed containername = "Surgery crate" access = access_medical @@ -73,7 +73,7 @@ /obj/item/weapon/storage/box/cdeathalarm_kit ) cost = 40 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/ward containername = "Death Alarm crate" access = access_medical @@ -83,7 +83,7 @@ /obj/item/weapon/storage/firstaid/clotting ) cost = 100 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/zenghu containername = "Clotting Medicine crate" access = access_medical @@ -97,7 +97,7 @@ /obj/item/weapon/storage/belt/medical = 3 ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/veymed containername = "Sterile equipment crate" /datum/supply_pack/med/extragear @@ -109,7 +109,7 @@ /obj/item/clothing/suit/storage/hooded/wintercoat/medical = 3 ) cost = 10 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Medical surplus equipment" access = access_medical @@ -133,7 +133,7 @@ /obj/item/weapon/reagent_containers/syringe ) cost = 50 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Chief medical officer equipment" access = access_cmo @@ -156,7 +156,7 @@ /obj/item/weapon/reagent_containers/syringe ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Medical Doctor equipment" access = access_medical_equip @@ -179,7 +179,7 @@ /obj/item/weapon/reagent_containers/syringe ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Chemist equipment" access = access_chemistry @@ -207,7 +207,7 @@ /obj/item/clothing/accessory/storage/white_vest ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Paramedic equipment" access = access_medical_equip @@ -226,7 +226,7 @@ /obj/item/weapon/cartridge/medical ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Psychiatrist equipment" access = access_psychiatrist @@ -247,7 +247,7 @@ /obj/item/weapon/storage/box/gloves ) cost = 10 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Medical scrubs crate" access = access_medical_equip @@ -264,7 +264,7 @@ /obj/item/weapon/pen ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/veymed containername = "Autopsy equipment crate" access = access_morgue @@ -291,7 +291,7 @@ /obj/item/weapon/storage/box/gloves ) cost = 10 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Medical uniform crate" access = access_medical_equip @@ -309,7 +309,7 @@ /obj/item/weapon/storage/box/gloves ) cost = 50 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Medical biohazard equipment" access = access_medical_equip @@ -317,7 +317,7 @@ name = "Portable freezers crate" contains = list(/obj/item/weapon/storage/box/freezer = 7) cost = 25 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/veymed containername = "Portable freezers" access = access_medical_equip @@ -325,7 +325,7 @@ name = "Virus sample crate" contains = list(/obj/item/weapon/virusdish/random = 4) cost = 25 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/zenghu containername = "Virus sample crate" access = access_cmo @@ -333,40 +333,40 @@ name = "Defibrillator crate" contains = list(/obj/item/device/defib_kit = 2) cost = 30 - containertype = /obj/structure/closet/crate/medical + containertype = /obj/structure/closet/crate/veymed containername = "Defibrillator crate" /datum/supply_pack/med/distillery name = "Chemical distiller crate" contains = list(/obj/machinery/portable_atmospherics/powered/reagent_distillery = 1) cost = 50 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/nanotrasen containername = "Chemical distiller crate" /datum/supply_pack/med/advdistillery name = "Industrial Chemical distiller crate" contains = list(/obj/machinery/portable_atmospherics/powered/reagent_distillery/industrial = 1) cost = 150 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/xion containername = "Industrial Chemical distiller crate" /datum/supply_pack/med/oxypump name = "Oxygen pump crate" contains = list(/obj/machinery/oxygen_pump/mobile = 1) cost = 125 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/xion containername = "Oxygen pump crate" /datum/supply_pack/med/anestheticpump name = "Anesthetic pump crate" contains = list(/obj/machinery/oxygen_pump/mobile/anesthetic = 1) cost = 130 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/nanotrasen containername = "Anesthetic pump crate" /datum/supply_pack/med/stablepump name = "Portable stabilizer crate" contains = list(/obj/machinery/oxygen_pump/mobile/stabilizer = 1) cost = 175 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/nanotrasen containername = "Portable stabilizer crate" diff --git a/code/datums/supplypacks/misc.dm b/code/datums/supplypacks/misc.dm index 1e5890f0c8b..db46de1e047 100644 --- a/code/datums/supplypacks/misc.dm +++ b/code/datums/supplypacks/misc.dm @@ -20,7 +20,7 @@ ) name = "Trading Card Crate" cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/oculum containername = "cards crate" /datum/supply_pack/randomised/misc/dnd @@ -36,7 +36,7 @@ ) name = "Miniatures Crate" cost = 200 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/oculum containername = "Miniature Crate" /datum/supply_pack/randomised/misc/plushies @@ -88,14 +88,14 @@ //VOREStation Add End name = "Plushies Crate" cost = 15 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/allico containername = "Plushies Crate" /datum/supply_pack/misc/eftpos contains = list(/obj/item/device/eftpos) name = "EFTPOS scanner" cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/nanotrasen containername = "EFTPOS crate" /datum/supply_pack/misc/chaplaingear @@ -113,7 +113,7 @@ /obj/item/weapon/storage/fancy/candle_box = 3 ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/gilthari containername = "Chaplain equipment crate" /datum/supply_pack/misc/hoverpod @@ -136,14 +136,14 @@ /obj/item/clothing/accessory/storage/webbing ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/nanothreads containername = "Webbing crate" /datum/supply_pack/misc/holoplant name = "Holoplant Pot" contains = list(/obj/machinery/holoplant/shipped) cost = 15 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/thinktronic containername = "Holoplant crate" /datum/supply_pack/misc/glucose_hypos @@ -152,7 +152,7 @@ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5 ) cost = 25 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/zenghu containername = "Glucose Hypo Crate" /datum/supply_pack/misc/mre_rations @@ -169,7 +169,7 @@ /obj/item/weapon/storage/mre/menu9, /obj/item/weapon/storage/mre/menu10) cost = 50 - containertype = /obj/structure/closet/crate/freezer + containertype = /obj/structure/closet/crate/centauri containername = "ready to eat rations" /datum/supply_pack/misc/paste_rations @@ -178,7 +178,7 @@ /obj/item/weapon/storage/mre/menu11 = 2 ) cost = 25 - containertype = /obj/structure/closet/crate/freezer + containertype = /obj/structure/closet/crate/freezer/centauri containername = "emergency rations" /datum/supply_pack/misc/medical_rations @@ -187,5 +187,5 @@ /obj/item/weapon/storage/mre/menu13 = 2 ) cost = 40 - containertype = /obj/structure/closet/crate/freezer + containertype = /obj/structure/closet/crate/zenghu containername = "emergency rations" diff --git a/code/datums/supplypacks/recreation.dm b/code/datums/supplypacks/recreation.dm index 134ae76e303..9bb6b1a4429 100644 --- a/code/datums/supplypacks/recreation.dm +++ b/code/datums/supplypacks/recreation.dm @@ -20,7 +20,7 @@ /obj/item/weapon/material/twohanded/fireaxe/foam = 2 ) cost = 50 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/allico containername = "foam weapon crate" /datum/supply_pack/recreation/lasertag @@ -31,8 +31,8 @@ /obj/item/weapon/gun/energy/lasertag/blue, /obj/item/clothing/suit/bluetag ) - containertype = /obj/structure/closet - containername = "Lasertag Closet" + containertype = /obj/structure/closet/crate/ward + containername = "Lasertag Supplies" cost = 10 /datum/supply_pack/recreation/artscrafts @@ -55,14 +55,14 @@ /obj/item/weapon/wrapping_paper = 3 ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/allico containername = "Arts and Crafts crate" /datum/supply_pack/recreation/painters name = "Station Painting Supplies" cost = 10 containername = "station painting supplies crate" - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/grayson contains = list( /obj/item/device/pipe_painter = 2, /obj/item/device/floor_painter = 2, @@ -82,7 +82,7 @@ name = "Deluxe Fishing Bait" cost = 40 containername = "deluxe bait crate" - containertype = /obj/structure/closet/crate/freezer + containertype = /obj/structure/closet/crate/carp num_contained = 8 contains = list( /obj/item/weapon/storage/box/wormcan, @@ -93,7 +93,7 @@ name = "Laser Tag Turrets" cost = 40 containername = "laser tag turret crate" - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/ward contains = list( /obj/machinery/porta_turret/lasertag/blue, /obj/machinery/porta_turret/lasertag/red diff --git a/code/datums/supplypacks/robotics.dm b/code/datums/supplypacks/robotics.dm index 757d38b9535..5f8cf6337c8 100644 --- a/code/datums/supplypacks/robotics.dm +++ b/code/datums/supplypacks/robotics.dm @@ -20,7 +20,7 @@ /obj/item/weapon/cell/high = 2 ) cost = 10 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Robotics assembly" access = access_robotics @@ -56,7 +56,7 @@ name = "Morpheus robolimb blueprints" contains = list(/obj/item/weapon/disk/limb/morpheus) cost = 20 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/morpheus containername = "Robolimb blueprints (Morpheus)" access = access_robotics @@ -64,7 +64,7 @@ name = "Cyber Solutions robolimb blueprints" contains = list(/obj/item/weapon/disk/limb/cybersolutions) cost = 20 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/cybersolutions containername = "Robolimb blueprints (Cyber Solutions)" access = access_robotics @@ -72,7 +72,7 @@ name = "Xion robolimb blueprints" contains = list(/obj/item/weapon/disk/limb/xion) cost = 20 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/xion containername = "Robolimb blueprints (Xion)" access = access_robotics @@ -80,7 +80,7 @@ name = "Grayson robolimb blueprints" contains = list(/obj/item/weapon/disk/limb/grayson) cost = 30 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/grayson containername = "Robolimb blueprints (Grayson)" access = access_robotics @@ -88,7 +88,7 @@ name = "Hephaestus robolimb blueprints" contains = list(/obj/item/weapon/disk/limb/hephaestus) cost = 35 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/heph containername = "Robolimb blueprints (Hephaestus)" access = access_robotics @@ -96,7 +96,7 @@ name = "Ward-Takahashi robolimb blueprints" contains = list(/obj/item/weapon/disk/limb/wardtakahashi) cost = 35 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/ward containername = "Robolimb blueprints (Ward-Takahashi)" access = access_robotics @@ -104,7 +104,7 @@ name = "Zeng Hu robolimb blueprints" contains = list(/obj/item/weapon/disk/limb/zenghu) cost = 35 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/zenghu containername = "Robolimb blueprints (Zeng Hu)" access = access_robotics @@ -112,7 +112,7 @@ name = "Bishop robolimb blueprints" contains = list(/obj/item/weapon/disk/limb/bishop) cost = 70 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/bishop containername = "Robolimb blueprints (Bishop)" access = access_robotics @@ -133,7 +133,7 @@ /obj/item/weapon/circuitboard/mecha/ripley/peripherals ) cost = 25 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/xion containername = "APLU \"Ripley\" Circuit Crate" access = access_robotics @@ -144,7 +144,7 @@ /obj/item/weapon/circuitboard/mecha/odysseus/main ) cost = 25 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/veymed containername = "\"Odysseus\" Circuit Crate" access = access_robotics @@ -158,7 +158,7 @@ ) name = "Random APLU modkit" cost = 200 - containertype = /obj/structure/closet/crate/science + containertype = /obj/structure/closet/crate/xion containername = "heavy crate" /datum/supply_pack/randomised/robotics/exosuit_mod/durand @@ -168,6 +168,7 @@ /obj/item/device/kit/paint/durand/phazon ) name = "Random Durand exosuit modkit" + containertype = /obj/structure/closet/crate/heph /datum/supply_pack/randomised/robotics/exosuit_mod/gygax contains = list( @@ -176,6 +177,7 @@ /obj/item/device/kit/paint/gygax/recitence ) name = "Random Gygax exosuit modkit" + containertype = /obj/structure/closet/crate/heph /datum/supply_pack/robotics/jumper_cables name = "Jumper kit crate" @@ -183,7 +185,7 @@ /obj/item/device/defib_kit/jumper_kit = 2 ) cost = 30 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/einstein containername = "Jumper kit crate" access = access_robotics diff --git a/code/datums/supplypacks/science.dm b/code/datums/supplypacks/science.dm index ab55b8571e8..c4c03ffd047 100644 --- a/code/datums/supplypacks/science.dm +++ b/code/datums/supplypacks/science.dm @@ -9,7 +9,7 @@ name = "Coolant tank crate" contains = list(/obj/structure/reagent_dispensers/coolanttank) cost = 15 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/aether containername = "coolant tank crate" /datum/supply_pack/sci/phoron @@ -39,7 +39,7 @@ /obj/item/seeds/kudzuseed ) cost = 15 - containertype = /obj/structure/closet/crate/hydroponics + containertype = /obj/structure/closet/crate/carp containername = "Exotic Seeds crate" access = access_hydroponics @@ -47,14 +47,14 @@ name = "Integrated circuit printer" contains = list(/obj/item/device/integrated_circuit_printer = 2) cost = 15 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/ward containername = "Integrated circuit crate" /datum/supply_pack/sci/integrated_circuit_printer_upgrade name = "Integrated circuit printer upgrade - advanced designs" contains = list(/obj/item/weapon/disk/integrated_circuit/upgrade/advanced) cost = 30 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/ward containername = "Integrated circuit crate" /datum/supply_pack/sci/xenoarch @@ -75,6 +75,6 @@ /obj/item/weapon/storage/bag/fossils, /obj/item/weapon/hand_labeler) cost = 100 - containertype = /obj/structure/closet/crate/secure/science + containertype = /obj/structure/closet/crate/secure/xion containername = "Xenoarchaeology Tech crate" access = access_research \ No newline at end of file diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm index cd523475834..5fd24a473fe 100644 --- a/code/datums/supplypacks/security.dm +++ b/code/datums/supplypacks/security.dm @@ -53,11 +53,11 @@ /obj/item/clothing/accessory/storage/pouches/blue, ) cost = 30 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/heph containername = "Plate Carrier crate" /datum/supply_pack/security/carriersgreen - name = "Armor - Blue modular armor" + name = "Armor - Green modular armor" contains = list( /obj/item/clothing/suit/armor/pcarrier/green, /obj/item/clothing/accessory/armor/armguards/green, @@ -65,7 +65,7 @@ /obj/item/clothing/accessory/storage/pouches/green, ) cost = 30 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/heph containername = "Plate Carrier crate" /datum/supply_pack/security/carriersnavy @@ -77,7 +77,7 @@ /obj/item/clothing/accessory/storage/pouches/navy, ) cost = 30 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/heph containername = "Plate Carrier crate" /datum/supply_pack/security/carrierstan @@ -89,7 +89,7 @@ /obj/item/clothing/accessory/storage/pouches/tan, ) cost = 30 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/heph containername = "Plate Carrier crate" /datum/supply_pack/security/armorplate @@ -98,7 +98,7 @@ /obj/item/clothing/accessory/armor/armorplate, ) cost = 5 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/lawson containername = "Armor plate crate" /datum/supply_pack/security/armorplatestab @@ -107,7 +107,7 @@ /obj/item/clothing/accessory/armor/armorplate/stab, ) cost = 10 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/lawson containername = "Armor plate crate" /datum/supply_pack/security/armorplatemedium @@ -116,7 +116,7 @@ /obj/item/clothing/accessory/armor/armorplate/medium, ) cost = 10 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/lawson containername = "Armor plate crate" /datum/supply_pack/security/armorplatetac @@ -125,7 +125,7 @@ /obj/item/clothing/accessory/armor/armorplate/tactical, ) cost = 15 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/heph containername = "Armor plate crate" /datum/supply_pack/randomised/security/carriers @@ -140,7 +140,7 @@ /obj/item/clothing/suit/armor/pcarrier/press ) cost = 10 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/scg containername = "Plate Carrier crate" /datum/supply_pack/security/carriertags @@ -158,7 +158,7 @@ /obj/item/clothing/accessory/armor/tag/abneg ) cost = 20 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/scg containername = "Plate Carrier crate" /datum/supply_pack/security/helmcovers @@ -174,7 +174,7 @@ /obj/item/clothing/accessory/armor/helmcover/tan ) cost = 20 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/scg containername = "Helmet Covers crate" /datum/supply_pack/randomised/security/armorplates @@ -193,7 +193,7 @@ /obj/item/clothing/accessory/armor/armorplate/bulletproof ) cost = 40 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/scg containername = "Armor plate crate" /datum/supply_pack/randomised/security/carrierarms @@ -210,7 +210,7 @@ /obj/item/clothing/accessory/armor/armguards/bulletproof ) cost = 40 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/scg containername = "Armor plate crate" /datum/supply_pack/randomised/security/carrierlegs @@ -227,7 +227,7 @@ /obj/item/clothing/accessory/armor/legguards/bulletproof ) cost = 40 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/scg containername = "Armor plate crate" /datum/supply_pack/randomised/security/carrierbags @@ -246,7 +246,7 @@ /obj/item/clothing/accessory/storage/pouches/large/tan ) cost = 50 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/scg containername = "Armor plate crate" /datum/supply_pack/security/riot_gear @@ -260,7 +260,7 @@ /obj/item/weapon/storage/box/handcuffs ) cost = 40 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/lawson containername = "Riot gear crate" access = access_armory @@ -273,7 +273,7 @@ /obj/item/clothing/shoes/leg_guard/riot ) cost = 30 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/lawson containername = "Riot armor crate" access = access_armory @@ -287,7 +287,7 @@ /obj/item/clothing/accessory/armor/legguards/riot ) cost = 40 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/lawson containername = "Riot armor crate" access = access_armory @@ -300,7 +300,7 @@ /obj/item/clothing/shoes/leg_guard/laserproof ) cost = 40 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/lawson containername = "Ablative armor crate" access = access_armory @@ -314,7 +314,7 @@ /obj/item/clothing/accessory/armor/legguards/laserproof ) cost = 50 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/lawson containername = "Ablative armor crate" access = access_armory @@ -327,7 +327,7 @@ /obj/item/clothing/shoes/leg_guard/bulletproof ) cost = 40 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/heph containername = "Ballistic armor crate" access = access_armory /* VOREStation Removal - Howabout no ERT armor being orderable? @@ -342,7 +342,7 @@ /obj/item/clothing/accessory/armor/legguards/bulletproof ) cost = 50 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/heph containername = "Ballistic armor crate" access = access_armory @@ -355,13 +355,13 @@ /obj/item/clothing/shoes/leg_guard/combat ) cost = 40 - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/saare containername = "Combat armor crate" access = access_armory /datum/supply_pack/security/tactical name = "Armor - Tactical" - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/saare containername = "Tactical armor crate" cost = 40 access = access_armory @@ -387,7 +387,7 @@ /datum/supply_pack/security/flexitac name = "Armor - Tactical Light" - containertype = /obj/structure/closet/crate/secure/gear + containertype = /obj/structure/closet/crate/secure/saare containername = "Tactical Light armor crate" cost = 75 access = access_armory @@ -412,15 +412,14 @@ name = "Misc - Security Barriers" contains = list(/obj/machinery/deployable/barrier = 4) cost = 20 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/secure/heph containername = "Security barrier crate" - access = null /datum/supply_pack/security/securityshieldgen name = "Misc - Wall shield generators" contains = list(/obj/machinery/shieldwallgen = 4) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/heph containername = "Wall shield generators crate" access = access_teleporter @@ -434,7 +433,7 @@ /obj/item/clothing/accessory/holster/hip ) cost = 15 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/hedberg containername = "Holster crate" /datum/supply_pack/security/extragear @@ -446,7 +445,7 @@ /obj/item/clothing/suit/storage/hooded/wintercoat/security = 3 ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/nanothreads containername = "Security surplus equipment" /datum/supply_pack/security/detectivegear @@ -473,7 +472,7 @@ /obj/item/weapon/storage/bag/detective ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Forensic equipment" access = access_forensics_lockers @@ -486,7 +485,7 @@ /obj/item/device/detective_scanner ) cost = 60 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/ward containername = "Forensic equipment" access = access_forensics_lockers @@ -508,7 +507,7 @@ /obj/item/clothing/gloves/black = 2 ) cost = 10 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Investigation clothing" access = access_forensics_lockers @@ -538,7 +537,7 @@ /obj/item/device/flashlight/maglight ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Officer equipment" access = access_brig @@ -567,7 +566,7 @@ /obj/item/device/flashlight/maglight ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Warden equipment" access = access_armory @@ -594,7 +593,7 @@ /obj/item/device/flashlight/maglight ) cost = 50 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Head of security equipment" access = access_hos @@ -613,7 +612,7 @@ /obj/item/weapon/storage/box/holobadge ) cost = 10 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Security uniform crate" /datum/supply_pack/security/navybluesecurityclothing @@ -634,7 +633,7 @@ /obj/item/weapon/storage/box/holobadge ) cost = 10 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Navy blue security uniform crate" /datum/supply_pack/security/corporatesecurityclothing @@ -654,7 +653,7 @@ /obj/item/weapon/storage/box/holobadge ) cost = 10 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Corporate security uniform crate" /datum/supply_pack/security/biosuit @@ -670,7 +669,7 @@ /obj/item/weapon/storage/box/gloves ) cost = 25 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Security biohazard gear" access = access_security @@ -680,6 +679,6 @@ /obj/item/weapon/contraband/poster/nanotrasen = 6 ) cost = 20 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanotrasen containername = "Morale Posters" access = access_maint_tunnels diff --git a/code/datums/supplypacks/supply.dm b/code/datums/supplypacks/supply.dm index b58c5960457..0863ec8cbb7 100644 --- a/code/datums/supplypacks/supply.dm +++ b/code/datums/supplypacks/supply.dm @@ -18,14 +18,14 @@ /obj/item/weapon/reagent_containers/food/condiment/yeast = 3 ) cost = 10 - containertype = /obj/structure/closet/crate/freezer + containertype = /obj/structure/closet/crate/freezer/centauri containername = "Food crate" /datum/supply_pack/supply/toner name = "Toner cartridges" contains = list(/obj/item/device/toner = 6) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/ummarcar containername = "Toner cartridges" /datum/supply_pack/supply/janitor @@ -48,7 +48,7 @@ /obj/structure/mopbucket ) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/galaksi containername = "Janitorial supplies" /datum/supply_pack/supply/shipping @@ -62,7 +62,7 @@ /obj/item/weapon/tool/wirecutters, /obj/item/weapon/tape_roll = 2) cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/ummarcar containername = "Shipping supplies crate" /datum/supply_pack/supply/bureaucracy @@ -82,13 +82,13 @@ ) name = "Office supplies" cost = 15 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/ummarcar containername = "Office supplies crate" /datum/supply_pack/supply/spare_pda name = "Spare PDAs" cost = 10 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/thinktronic containername = "Spare PDA crate" contains = list(/obj/item/device/pda = 3) @@ -112,7 +112,7 @@ /obj/item/clothing/glasses/meson ) cost = 10 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/xion containername = "Shaft miner equipment" access = access_mining /* //VOREStation Edit - Pointless on Tether. @@ -127,12 +127,12 @@ name = "Cargo Train Tug" contains = list(/obj/vehicle/train/engine) cost = 35 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/xion containername = "Cargo Train Tug Crate" /datum/supply_pack/supply/cargotrailer name = "Cargo Train Trolley" contains = list(/obj/vehicle/train/trolley) cost = 15 - containertype = /obj/structure/largecrate + containertype = /obj/structure/closet/crate/large/xion containername = "Cargo Train Trolley Crate" diff --git a/code/datums/supplypacks/voidsuits.dm b/code/datums/supplypacks/voidsuits.dm index 6ab3fa9d858..a867b20255a 100644 --- a/code/datums/supplypacks/voidsuits.dm +++ b/code/datums/supplypacks/voidsuits.dm @@ -17,7 +17,7 @@ /obj/item/weapon/tank/oxygen = 2, ) cost = 40 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/aether containername = "Atmospheric voidsuit crate" access = access_atmospherics @@ -31,7 +31,7 @@ /obj/item/weapon/tank/oxygen = 2, ) cost = 50 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/aether containername = "Heavy Duty Atmospheric voidsuit crate" access = access_atmospherics @@ -45,7 +45,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/xion containername = "Engineering voidsuit crate" access = access_engine_equip @@ -59,7 +59,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/xion containername = "Engineering Construction voidsuit crate" access = access_engine_equip @@ -73,7 +73,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 45 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/xion containername = "Engineering Hazmat voidsuit crate" access = access_engine_equip @@ -87,7 +87,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 50 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/xion containername = "Reinforced Engineering voidsuit crate" access = access_engine_equip @@ -101,7 +101,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/veymed containername = "Medical voidsuit crate" access = access_medical_equip @@ -115,7 +115,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/veymed containername = "Medical EMT voidsuit crate" access = access_medical_equip @@ -129,7 +129,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 45 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/nanocare containername = "Medical Biohazard voidsuit crate" access = access_medical_equip @@ -143,7 +143,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 60 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/veymed containername = "Vey-Med Autoadaptive voidsuit (humanoid) crate" access = access_medical_equip @@ -168,7 +168,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/heph containername = "Security voidsuit crate" /datum/supply_pack/voidsuits/security/crowd @@ -181,7 +181,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 60 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/heph containername = "Security Crowd Control voidsuit crate" access = access_armory @@ -195,7 +195,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 60 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/heph containername = "Security EVA voidsuit crate" access = access_armory @@ -208,7 +208,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/xion containername = "Mining voidsuit crate" access = access_mining @@ -221,7 +221,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 50 - containertype = /obj/structure/closet/crate/secure + containertype = /obj/structure/closet/crate/secure/grayson containername = "Frontier Mining voidsuit crate" access = access_mining @@ -232,6 +232,6 @@ /obj/item/clothing/mask/gas/zaddat = 1 ) cost = 30 - containertype = /obj/structure/closet/crate + containertype = /obj/structure/closet/crate/nanotrasen containername = "Zaddat Shroud crate" access = null \ No newline at end of file diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 01f5e687d87..09b226a076b 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,6 +1,6 @@ /atom/movable layer = OBJ_LAYER - appearance_flags = TILE_BOUND|PIXEL_SCALE + appearance_flags = TILE_BOUND|PIXEL_SCALE|KEEP_TOGETHER glide_size = 8 var/last_move = null //The direction the atom last moved var/anchored = 0 @@ -24,7 +24,7 @@ var/datum/riding/riding_datum = null var/does_spin = TRUE // Does the atom spin when thrown (of course it does :P) var/movement_type = NONE - + var/cloaked = FALSE //If we're cloaked or not var/image/cloaked_selfimage //The image we use for our client to let them see where we are @@ -107,7 +107,7 @@ glide_for(movetime) loc = newloc . = TRUE - + // So objects can be informed of z-level changes if (old_z != dest_z) onTransitZ(old_z, dest_z) @@ -133,7 +133,7 @@ var/atom/movable/thing = i // We don't call parent so we are calling this for byond thing.Crossed(src) - + // We're a multi-tile object (multiple locs) else if(. && newloc) . = doMove(newloc) @@ -282,7 +282,7 @@ glide_for(movetime) last_move = isnull(direction) ? 0 : direction loc = destination - + // Unset this in case it was set in some other proc. We're no longer moving diagonally for sure. moving_diagonally = 0 @@ -294,27 +294,27 @@ // If it's not the same area, Exited() it if(old_area && old_area != destarea) old_area.Exited(src, destination) - + // Uncross everything where we left for(var/i in oldloc) var/atom/movable/AM = i if(AM == src) continue AM.Uncrossed(src) - + // Information about turf and z-levels for source and dest collected var/turf/oldturf = get_turf(oldloc) var/turf/destturf = get_turf(destination) var/old_z = (oldturf ? oldturf.z : null) var/dest_z = (destturf ? destturf.z : null) - + // So objects can be informed of z-level changes if (old_z != dest_z) onTransitZ(old_z, dest_z) - + // Destination atom Entered destination.Entered(src, oldloc) - + // Entered() the new area if it's not the same area if(destarea && old_area != destarea) destarea.Entered(src, oldloc) @@ -366,7 +366,7 @@ glide_size = initial(glide_size) else glide_size = initial(glide_size) - + ///////////////////////////////////////////////////////////////// //called when src is thrown into hit_atom @@ -623,7 +623,7 @@ /atom/movable/proc/cloak_animation(var/length = 1 SECOND) //Save these var/initial_alpha = alpha - + //Animate alpha fade animate(src, alpha = 0, time = length) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 454025d4259..b57e1f5a0cb 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -232,12 +232,6 @@ else to_chat(O, "[U] holds \a [itemname] up to one of your cameras ...") O << browse(text("[][]", itemname, info), text("window=[]", itemname)) - for(var/mob/O in player_list) - if (istype(O.machine, /obj/machinery/computer/security)) - var/obj/machinery/computer/security/S = O.machine - if (S.current_camera == src) - to_chat(O, "[U] holds \a [itemname] up to one of the cameras ...") - O << browse(text("[][]", itemname, info), text("window=[]", itemname)) else if (istype(W, /obj/item/weapon/camera_bug)) if (!src.can_use()) @@ -494,8 +488,6 @@ else cameranet.updateVisibility(src, 0) - invalidateCameraCache() - // Resets the camera's wires to fully operational state. Used by one of Malfunction abilities. /obj/machinery/camera/proc/reset_wires() if(!wires) diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index ab5d82b3a5f..bb3cdfb4edb 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -173,7 +173,6 @@ var/global/list/engineering_networks = list( var/number = my_area.len c_tag = "[A.name] #[number]" - invalidateCameraCache() /obj/machinery/camera/autoname/Destroy() var/area/A = get_area(src) diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index daca64cc42d..c3041344a0f 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -1,142 +1,132 @@ /obj/machinery/computer/aifixer name = "\improper AI system integrity restorer" - desc = "Restores AI units to working condition, assuming you have one inside!" - icon_keyboard = "rd_key" - icon_screen = "ai-fixer" - light_color = "#a97faa" - circuit = /obj/item/weapon/circuitboard/aifixer + desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order." req_one_access = list(access_robotics, access_heads) - var/mob/living/silicon/ai/occupant = null - var/active = 0 + circuit = /obj/item/weapon/circuitboard/aifixer + icon_keyboard = "tech_key" + icon_screen = "ai-fixer" + light_color = LIGHT_COLOR_PINK + + active_power_usage = 1000 -/obj/machinery/computer/aifixer/New() - ..() - update_icon() - -/obj/machinery/computer/aifixer/proc/load_ai(var/mob/living/silicon/ai/transfer, var/obj/item/device/aicard/card, var/mob/user) - - if(!transfer) - return - - // Transfer over the AI. - to_chat(transfer, "You have been transferred into a stationary terminal. Sadly, there is no remote access from here.") - to_chat(user, "Transfer successful: [transfer.name] placed within stationary terminal.") - - transfer.loc = src - transfer.cancel_camera() - transfer.control_disabled = 1 - occupant = transfer - - if(card) - card.clear() - - update_icon() - -/obj/machinery/computer/aifixer/attackby(I as obj, user as mob) + /// Variable containing transferred AI + var/mob/living/silicon/ai/occupier + /// Variable dictating if we are in the process of restoring the occupier AI + var/restoring = FALSE +/obj/machinery/computer/aifixer/attackby(obj/item/I, mob/living/user) + if(I.is_screwdriver()) + if(occupier) + if(stat & (NOPOWER|BROKEN)) + to_chat(user, "The screws on [name]'s screen won't budge.") + else + to_chat(user, "The screws on [name]'s screen won't budge and it emits a warning beep.") + return if(istype(I, /obj/item/device/aicard)) - if(stat & (NOPOWER|BROKEN)) - to_chat(user, "This terminal isn't functioning right now.") + to_chat(user, "This terminal isn't functioning right now.") + return + if(restoring) + to_chat(user, "Terminal is busy restoring [occupier] right now.") return var/obj/item/device/aicard/card = I - var/mob/living/silicon/ai/comp_ai = locate() in src - var/mob/living/silicon/ai/card_ai = locate() in card + if(occupier) + if(card.grab_ai(occupier, user)) + occupier = null + else if(card.carded_ai) + var/mob/living/silicon/ai/new_occupant = card.carded_ai + to_chat(new_occupant, "You have been transferred into a stationary terminal. Sadly there is no remote access from here.") + to_chat(user, "Transfer Successful: [new_occupant] placed within stationary terminal.") + new_occupant.forceMove(src) + new_occupant.cancel_camera() + new_occupant.control_disabled = TRUE + occupier = new_occupant + card.clear() + update_icon() + else + to_chat(user, "There is no AI loaded onto this computer, and no AI loaded onto [I]. What exactly are you trying to do here?") + return ..() - if(istype(comp_ai)) - if(active) - to_chat(user, "ERROR: Reconstruction in progress.") - return - card.grab_ai(comp_ai, user) - if(!(locate(/mob/living/silicon/ai) in src)) occupant = null - else if(istype(card_ai)) - load_ai(card_ai,card,user) - occupant = locate(/mob/living/silicon/ai) in src - - update_icon() +/obj/machinery/computer/aifixer/attack_hand(mob/user) + if(stat & (NOPOWER|BROKEN)) return - ..() - return + tgui_interact(user) -/obj/machinery/computer/aifixer/attack_ai(var/mob/user as mob) - return attack_hand(user) +/obj/machinery/computer/aifixer/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AiRestorer", name) + ui.open() -/obj/machinery/computer/aifixer/attack_hand(var/mob/user as mob) +/obj/machinery/computer/aifixer/tgui_data(mob/user) + var/list/data = list() + + data["ejectable"] = FALSE + data["AI_present"] = FALSE + data["error"] = null + if(!occupier) + data["error"] = "Please transfer an AI unit." + else + data["AI_present"] = TRUE + data["name"] = occupier.name + data["restoring"] = restoring + data["health"] = (occupier.health + 100) / 2 + data["isDead"] = occupier.stat == DEAD + var/list/laws = list() + for(var/datum/ai_law/law in occupier.laws.all_laws()) + laws += "[law.get_index()]: [law.law]" + data["laws"] = laws + + return data + +/obj/machinery/computer/aifixer/tgui_act(action, params) if(..()) return + if(!occupier) + restoring = FALSE - user.set_machine(src) - var/dat = "

AI System Integrity Restorer



" + switch(action) + if("PRG_beginReconstruction") + if(occupier?.health < 100) + to_chat(usr, "Reconstruction in progress. This will take several minutes.") + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE) + restoring = TRUE + var/mob/observer/dead/ghost = occupier.get_ghost() + if(ghost) + ghost.notify_revive("Your core files are being restored!", source = src) + . = TRUE - if (src.occupant) - var/laws - dat += "Stored AI: [src.occupant.name]
System integrity: [src.occupant.hardware_integrity()]%
Backup Capacitor: [src.occupant.backup_capacitor()]%
" +/obj/machinery/computer/aifixer/proc/Fix() + use_power(active_power_usage) + occupier.adjustOxyLoss(-5, 0, FALSE) + occupier.adjustFireLoss(-5, 0, FALSE) + occupier.adjustBruteLoss(-5, 0) + if(occupier.health >= 0 && occupier.stat == DEAD) + occupier.revive() - for (var/datum/ai_law/law in occupant.laws.all_laws()) - laws += "[law.get_index()]: [law.law]
" - - dat += "Laws:
[laws]
" - - if (src.occupant.stat == 2) - dat += "AI nonfunctional" - else - dat += "AI functional" - if (!src.active) - dat += {"

Begin Reconstruction"} - else - dat += "

Reconstruction in process, please wait.
" - dat += {" Close"} - - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return + return occupier.health < 100 /obj/machinery/computer/aifixer/process() if(..()) - src.updateDialog() - return - -/obj/machinery/computer/aifixer/Topic(href, href_list) - if(..()) - return 1 - if (href_list["fix"]) - src.active = 1 - src.overlays += image(icon, "ai-fixer-on") - while (src.occupant.getOxyLoss() > 0 || src.occupant.getFireLoss() > 0 || src.occupant.getToxLoss() > 0 || src.occupant.getBruteLoss() > 0) - src.occupant.adjustOxyLoss(-1) - src.occupant.adjustFireLoss(-1) - src.occupant.adjustToxLoss(-1) - src.occupant.adjustBruteLoss(-1) - src.occupant.updatehealth() - if (src.occupant.health >= 0 && src.occupant.stat == DEAD) - src.occupant.set_stat(CONSCIOUS) - src.occupant.lying = 0 - dead_mob_list -= src.occupant - living_mob_list += src.occupant - src.overlays -= image(icon, "ai-fixer-404") - src.overlays += image(icon, "ai-fixer-full") - src.occupant.add_ai_verbs() - src.updateUsrDialog() - sleep(10) - src.active = 0 - src.overlays -= image(icon, "ai-fixer-on") - - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - + if(restoring) + var/oldstat = occupier.stat + restoring = Fix() + if(oldstat != occupier.stat) + update_icon() /obj/machinery/computer/aifixer/update_icon() - ..() - if((stat & BROKEN) || (stat & NOPOWER)) + . = ..() + if(stat & (NOPOWER|BROKEN)) return - if(occupant) - if(occupant.stat) - add_overlay("ai-fixer-404") - else - add_overlay("ai-fixer-full") + if(restoring) + . += "ai-fixer-on" + if (occupier) + switch (occupier.stat) + if (CONSCIOUS) + . += "ai-fixer-full" + if (UNCONSCIOUS) + . += "ai-fixer-404" else - add_overlay("ai-fixer-empty") + . += "ai-fixer-empty" \ No newline at end of file diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index e695173efd4..f87d69a9a7b 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -3,201 +3,44 @@ /obj/machinery/computer/security name = "security camera monitor" desc = "Used to access the various cameras on the station." + icon_keyboard = "security_key" icon_screen = "cameras" light_color = "#a91515" - var/current_network = null - var/obj/machinery/camera/current_camera = null - var/last_pic = 1.0 - var/list/network - var/mapping = 0//For the overview file, interesting bit of code. - var/cache_id = 0 circuit = /obj/item/weapon/circuitboard/security -/obj/machinery/computer/security/New() - if(!network) + var/mapping = 0//For the overview file, interesting bit of code. + var/list/network = list() + + var/datum/tgui_module/camera/camera + +/obj/machinery/computer/security/Initialize() + . = ..() + if(!LAZYLEN(network)) network = using_map.station_networks.Copy() - ..() - if(network.len) - current_network = network[1] + camera = new(src, network) -/obj/machinery/computer/security/attack_ai(var/mob/user as mob) - return attack_hand(user) +/obj/machinery/computer/security/Destroy() + QDEL_NULL(camera) + return ..() -/obj/machinery/computer/security/check_eye(var/mob/user as mob) - if (user.stat || ((get_dist(user, src) > 1 || !( user.canmove ) || user.blinded) && !istype(user, /mob/living/silicon))) //user can't see - not sure why canmove is here. - return -1 - if(!current_camera) - return 0 - var/viewflag = current_camera.check_eye(user) - if ( viewflag < 0 ) //camera doesn't work - reset_current() - return viewflag +/obj/machinery/computer/security/tgui_interact(mob/user, datum/tgui/ui = null) + camera.tgui_interact(user, ui) -/obj/machinery/computer/security/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) - if(stat & (NOPOWER|BROKEN)) return - if(user.stat) return - - var/data[0] - - data["current_camera"] = current_camera ? current_camera.nano_structure() : null - data["current_network"] = current_network - data["networks"] = network ? network : list() - - var/map_levels = using_map.get_map_levels(src.z, TRUE, om_range = DEFAULT_OVERMAP_RANGE) - data["map_levels"] = map_levels - - if(current_network) - data["cameras"] = camera_repository.cameras_in_network(current_network, map_levels) - if(current_camera) - switch_to_camera(user, current_camera) - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "sec_camera.tmpl", "Camera Console", 900, 800) - - // adding a template with the key "mapContent" enables the map ui functionality - ui.add_template("mapContent", "sec_camera_map_content.tmpl") - // adding a template with the key "mapHeader" replaces the map header content - ui.add_template("mapHeader", "sec_camera_map_header.tmpl") - - ui.set_initial_data(data) - ui.open() - -/obj/machinery/computer/security/Topic(href, href_list) - if(..()) - return 1 - if(href_list["switch_camera"]) - if(stat&(NOPOWER|BROKEN)) return //VOREStation Edit - Removed zlevel check - if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return - var/obj/machinery/camera/C = locate(href_list["switch_camera"]) in cameranet.cameras - if(!C) - return - if(!(current_network in C.network)) - return - - switch_to_camera(usr, C) - return 1 - else if(href_list["switch_network"]) - if(stat&(NOPOWER|BROKEN)) return //VOREStation Edit - Removed zlevel check - if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return - if(href_list["switch_network"] in network) - current_network = href_list["switch_network"] - return 1 - else if(href_list["reset"]) - if(stat&(NOPOWER|BROKEN)) return //VOREStation Edit - Removed zlevel check - if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return - reset_current() - usr.reset_view(current_camera) - return 1 - else - . = ..() - -/obj/machinery/computer/security/attack_hand(var/mob/user as mob) - if(stat & (NOPOWER|BROKEN)) return - - if(!isAI(user)) - user.set_machine(src) - ui_interact(user) - -/obj/machinery/computer/security/proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C) - //don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras. - if(isAI(user)) - var/mob/living/silicon/ai/A = user - // Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise. - if(!A.is_in_chassis()) - return 0 - - A.eyeobj.setLoc(get_turf(C)) - A.client.eye = A.eyeobj - return 1 - - if (!C.can_use() || user.stat || (get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) && !istype(user, /mob/living/silicon))) - return 0 - set_current(C) - user.reset_view(current_camera) - check_eye(user) - return 1 - -/obj/machinery/computer/security/relaymove(mob/user,direct) - var/turf/T = get_turf(current_camera) - for(var/i; i < 10; i++) - T = get_step(T, direct) - jump_on_click(user, T) - -//Camera control: moving. -/obj/machinery/computer/security/proc/jump_on_click(var/mob/user,var/A) - if(user.machine != src) +/obj/machinery/computer/security/attack_hand(mob/user) + add_fingerprint(user) + if(stat & (BROKEN|NOPOWER)) return - var/obj/machinery/camera/jump_to - if(istype(A,/obj/machinery/camera)) - jump_to = A - else if(ismob(A)) - if(ishuman(A)) - jump_to = locate() in A:head - else if(isrobot(A)) - jump_to = A:camera - else if(isobj(A)) - jump_to = locate() in A - else if(isturf(A)) - var/best_dist = INFINITY - for(var/obj/machinery/camera/camera in get_area(A)) - if(!camera.can_use()) - continue - if(!can_access_camera(camera)) - continue - var/dist = get_dist(camera,A) - if(dist < best_dist) - best_dist = dist - jump_to = camera - if(isnull(jump_to)) - return - if(can_access_camera(jump_to)) - switch_to_camera(user,jump_to) + tgui_interact(user) -/obj/machinery/computer/security/process() - if(cache_id != camera_repository.camera_cache_id) - cache_id = camera_repository.camera_cache_id - SSnanoui.update_uis(src) +/obj/machinery/computer/security/attack_ai(mob/user) + to_chat(user, "You realise its kind of stupid to access a camera console when you have the entire camera network at your metaphorical fingertips") + return -/obj/machinery/computer/security/proc/can_access_camera(var/obj/machinery/camera/C) - var/list/shared_networks = src.network & C.network - if(shared_networks.len) - return 1 - return 0 - -/obj/machinery/computer/security/proc/set_current(var/obj/machinery/camera/C) - if(current_camera == C) - return - - if(current_camera) - reset_current() - - src.current_camera = C - if(current_camera) - current_camera.camera_computers_using_this.Add(src) - update_use_power(USE_POWER_ACTIVE) - var/mob/living/L = current_camera.loc - if(istype(L)) - L.tracking_initiated() - -/obj/machinery/computer/security/proc/reset_current() - if(current_camera) - current_camera.camera_computers_using_this.Remove(src) - var/mob/living/L = current_camera.loc - if(istype(L)) - L.tracking_cancelled() - current_camera = null - update_use_power(USE_POWER_IDLE) - -//Camera control: mouse. -/* Oh my god -/atom/DblClick() - ..() - if(istype(usr.machine,/obj/machinery/computer/security)) - var/obj/machinery/computer/security/console = usr.machine - console.jump_on_click(usr,src) -*/ +/obj/machinery/computer/security/proc/set_network(list/new_network) + network = new_network + camera.network = network + camera.access_based = FALSE //Camera control: arrow keys. /obj/machinery/computer/security/telescreen diff --git a/code/game/machinery/computer/camera_circuit.dm b/code/game/machinery/computer/camera_circuit.dm deleted file mode 100644 index 2bbe82ee1b8..00000000000 --- a/code/game/machinery/computer/camera_circuit.dm +++ /dev/null @@ -1,116 +0,0 @@ - -//the researchable camera circuit that can connect to any camera network - -/obj/item/weapon/circuitboard/camera - //name = "Circuit board (Camera)" - var/secured = 1 - var/authorised = 0 - var/possibleNets[0] - var/network = "" - build_path = null - -//when adding a new camera network, you should only need to update these two procs - New() - possibleNets["Engineering"] = access_ce - possibleNets["SS13"] = access_hos - possibleNets["Mining"] = access_mining - possibleNets["Cargo"] = access_qm - possibleNets["Research"] = access_rd - possibleNets["Medbay"] = access_cmo - ..() - - proc/updateBuildPath() - build_path = null - if(authorised && secured) - switch(network) - if("SS13") - build_path = /obj/machinery/computer/security - if("Engineering") - build_path = /obj/machinery/computer/security/engineering - if("Mining") - build_path = /obj/machinery/computer/security/mining - if("Research") - build_path = /obj/machinery/computer/security/research - if("Medbay") - build_path = /obj/machinery/computer/security/medbay - if("Cargo") - build_path = /obj/machinery/computer/security/cargo - - attackby(var/obj/item/I, var/mob/user)//if(health > 50) - ..() - else if(I.is_screwdriver()) - secured = !secured - user.visible_message("The [src] can [secured ? "no longer" : "now"] be modified.") - playsound(src, I.usesound, 50, 1) - updateBuildPath() - return - - attack_self(var/mob/user) - if(!secured && ishuman(user)) - user.machine = src - interact(user, 0) - - proc/interact(var/mob/user, var/ai=0) - if(secured) - return - if (!ishuman(user)) - return ..(user) - var/t = "Circuitboard Console - Camera Monitoring Computer
" - t += "Close
" - t += "
Please select a camera network:
" - - for(var/curNet in possibleNets) - if(network == curNet) - t += "- [curNet]
" - else - t += "- [curNet]
" - t += "
" - if(network) - if(authorised) - t += "Authenticated (Clear Auth)
" - else - t += "*Authenticate* (Requires an appropriate access ID)
" - else - t += "*Authenticate* (Requires an appropriate access ID)
" - t += "Close
" - user << browse(t, "window=camcircuit;size=500x400") - onclose(user, "camcircuit") - - Topic(href, href_list) - ..() - if( href_list["close"] ) - usr << browse(null, "window=camcircuit") - usr.machine = null - return - else if(href_list["net"]) - network = href_list["net"] - authorised = 0 - else if( href_list["auth"] ) - var/mob/M = usr - var/obj/item/weapon/card/id/I = M.equipped() - if (istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - if (I && istype(I)) - if(access_captain in I.access) - authorised = 1 - else if (possibleNets[network] in I.access) - authorised = 1 - if(istype(I,/obj/item/weapon/card/emag)) - I.resolve_attackby(src, usr) - else if( href_list["removeauth"] ) - authorised = 0 - updateDialog() - - updateDialog() - if(istype(src.loc,/mob)) - attack_self(src.loc) - -/obj/item/weapon/circuitboard/camera/emag_act(var/remaining_charges, var/mob/user) - if(network) - authorised = 1 - to_chat(user, "You authorised the circuit network!") - updateDialog() - return 1 - else - to_chat(user, "You must select a camera network circuit!") diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 077c12c451f..1af31afe80d 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -8,7 +8,7 @@ idle_power_usage = 250 active_power_usage = 500 circuit = /obj/item/weapon/circuitboard/crew - var/datum/nano_module/program/crew_monitor/crew_monitor + var/datum/tgui_module/crew_monitor/crew_monitor /obj/machinery/computer/crew/New() crew_monitor = new(src) @@ -20,16 +20,16 @@ ..() /obj/machinery/computer/crew/attack_ai(mob/user) - ui_interact(user) + attack_hand(user) /obj/machinery/computer/crew/attack_hand(mob/user) add_fingerprint(user) if(stat & (BROKEN|NOPOWER)) return - ui_interact(user) + tgui_interact(user) -/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - crew_monitor.ui_interact(user, ui_key, ui, force_open) +/obj/machinery/computer/crew/tgui_interact(mob/user, datum/tgui/ui = null) + crew_monitor.tgui_interact(user, ui) /obj/machinery/computer/crew/interact(mob/user) - crew_monitor.ui_interact(user) + crew_monitor.tgui_interact(user) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 631a998a42f..a133aab9b1a 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -522,7 +522,7 @@ announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE)) //visible_message("\The [initial(name)] hums and hisses as it moves [to_despawn.real_name] into storage.", 3) - visible_message("\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2].", 3) + visible_message("\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2]", 3) //VOREStation Edit begin: Dont delete mobs-in-mobs if(to_despawn.client && to_despawn.stat<2) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 2f96fb75cc7..57a17310984 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -164,6 +164,8 @@ var/datum/action/innate/mecha/mech_switch_damtype/switch_damtype_action = new var/datum/action/innate/mecha/mech_toggle_phasing/phasing_action = new + var/weapons_only_cycle = FALSE //So combat mechs don't switch to their equipment at times. + /obj/mecha/drain_power(var/drain_check) diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm index 0d2034d790e..33307c77d3c 100644 --- a/code/game/mecha/mecha_actions.dm +++ b/code/game/mecha/mecha_actions.dm @@ -185,12 +185,15 @@ var/list/available_equipment = list() available_equipment = chassis.equipment + if(chassis.weapons_only_cycle) + available_equipment = chassis.weapon_equipment + if(available_equipment.len == 0) chassis.occupant_message("No equipment available.") return if(!chassis.selected) chassis.selected = available_equipment[1] - chassis.occupant_message("You select [chassis.selected]") + chassis.occupant_message("You select [chassis.selected]") send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) button_icon_state = "mech_cycle_equip_on" button.UpdateIcon() @@ -419,3 +422,17 @@ return +/obj/mecha/verb/toggle_weapons_only_cycle() + set category = "Exosuit Interface" + set name = "Toggle weapons only cycling" + set src = usr.loc + set popup_menu = 0 + set_weapons_only_cycle() + +/obj/mecha/proc/set_weapons_only_cycle() + if(usr!=src.occupant) + return + weapons_only_cycle = !weapons_only_cycle + src.occupant_message("En":"#f00\">Dis"]abled weapons only cycling.") + return + diff --git a/code/game/objects/items/robot/robot_upgrades_vr.dm b/code/game/objects/items/robot/robot_upgrades_vr.dm index 13f09a980d6..2bc402b355e 100644 --- a/code/game/objects/items/robot/robot_upgrades_vr.dm +++ b/code/game/objects/items/robot/robot_upgrades_vr.dm @@ -6,7 +6,8 @@ R.add_language(LANGUAGE_ECUREUILIAN, 1) R.add_language(LANGUAGE_DAEMON, 1) R.add_language(LANGUAGE_ENOCHIAN, 1) - R.add_language(LANGUAGE_SLAVIC, 1) + R.add_language(LANGUAGE_SLAVIC, 1) + R.add_language(LANGUAGE_DRUDAKAR, 1) return 1 else return 0 diff --git a/code/game/objects/items/weapons/RPD_vr.dm b/code/game/objects/items/weapons/RPD_vr.dm index b40f28701fb..9ae806f63c6 100644 --- a/code/game/objects/items/weapons/RPD_vr.dm +++ b/code/game/objects/items/weapons/RPD_vr.dm @@ -33,7 +33,7 @@ var/datum/pipe_recipe/recipe // pipe recipie selected for display/construction var/static/datum/pipe_recipe/first_atmos var/static/datum/pipe_recipe/first_disposal - var/static/datum/asset/iconsheet/pipes/icon_assets + var/static/datum/asset/spritesheet/pipes/icon_assets var/static/list/pipe_layers = list( "Regular" = PIPING_LAYER_REGULAR, "Supply" = PIPING_LAYER_SUPPLY, @@ -75,7 +75,7 @@ /obj/item/weapon/pipe_dispenser/interact(mob/user) SetupPipes() if(!icon_assets) - icon_assets = get_asset_datum(/datum/asset/iconsheet/pipes) + icon_assets = get_asset_datum(/datum/asset/spritesheet/pipes) icon_assets.send(user) var/list/lines = list() @@ -365,7 +365,7 @@ if(_dir == p_dir && flipped == p_flipped) attrs += " class=\"linkOn\"" if(icon_state) - var/img_tag = icon_assets.icon_tag(icon_state, _dir) + var/img_tag = icon_assets.icon_tag("[dirtext]-[icon_state]") return "[img_tag]" else return "[noimg]" diff --git a/code/game/objects/items/weapons/circuitboards/computer/camera_monitor.dm b/code/game/objects/items/weapons/circuitboards/computer/camera_monitor.dm index 097f465a512..0648b586277 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/camera_monitor.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/camera_monitor.dm @@ -12,7 +12,6 @@ /obj/item/weapon/circuitboard/security/New() ..() - network = using_map.station_networks /obj/item/weapon/circuitboard/security/tv name = T_BOARD("security camera monitor - television") @@ -45,7 +44,7 @@ /obj/item/weapon/circuitboard/security/construct(var/obj/machinery/computer/security/C) if (..(C)) - C.network = network.Copy() + C.set_network(network.Copy()) /obj/item/weapon/circuitboard/security/deconstruct(var/obj/machinery/computer/security/C) if (..(C)) diff --git a/code/game/objects/random/mapping.dm b/code/game/objects/random/mapping.dm index bc6d29a5a5e..230b4ff3d29 100644 --- a/code/game/objects/random/mapping.dm +++ b/code/game/objects/random/mapping.dm @@ -34,6 +34,36 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/remains/robot) +/obj/random/crate //Random 'standard' crates for variety in maintenance spawns. + name = "random crate" + desc = "This is a random crate" + icon = 'icons/obj/closets/bases/crate.dmi' + icon_state = "base" + +/obj/random/crate/item_to_spawn() //General crates, excludes some more high-grade and medical brands + return pick (/obj/structure/closet/crate/plastic, + /obj/structure/closet/crate/aether, + /obj/structure/closet/crate/centauri, + /obj/structure/closet/crate/einstein, + /obj/structure/closet/crate/focalpoint, + /obj/structure/closet/crate/gilthari, + /obj/structure/closet/crate/grayson, + /obj/structure/closet/crate/nanotrasen, + /obj/structure/closet/crate/nanothreads, + /obj/structure/closet/crate/oculum, + /obj/structure/closet/crate/ward, + /obj/structure/closet/crate/xion, + /obj/structure/closet/crate/zenghu, + /obj/structure/closet/crate/allico, + /obj/structure/closet/crate/carp, + /obj/structure/closet/crate/galaksi, + /obj/structure/closet/crate/thinktronic, + /obj/structure/closet/crate/ummarcar, + /obj/structure/closet/crate/unathi, + /obj/structure/closet/crate/hydroponics, + /obj/structure/closet/crate/engineering, + /obj/structure/closet/crate) + /obj/random/obstruction //Large objects to block things off in maintenance name = "random obstruction" desc = "This is a random obstruction." diff --git a/code/game/objects/structures/crates_lockers/_closets_appearance_definitions.dm b/code/game/objects/structures/crates_lockers/_closets_appearance_definitions.dm index c158ea0b832..b90a7961e2a 100644 --- a/code/game/objects/structures/crates_lockers/_closets_appearance_definitions.dm +++ b/code/game/objects/structures/crates_lockers/_closets_appearance_definitions.dm @@ -761,8 +761,210 @@ "lid_stripes" = COLOR_NT_RED ) +// Freezers + /decl/closet_appearance/crate/freezer + color = COLOR_OFF_WHITE + +/decl/closet_appearance/crate/freezer/centauri color = COLOR_BABY_BLUE + extra_decals = list( + "centauri" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/freezer/nanotrasen + color = COLOR_BABY_BLUE + extra_decals = list( + "nano" = COLOR_OFF_WHITE + ) + +// Corporate Branding + +/decl/closet_appearance/crate/aether + color = COLOR_YELLOW_GRAY + decals = list( + "crate_stripes" = COLOR_BLUE_LIGHT, + "aether" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/allico + color = COLOR_LIGHT_VIOLET + decals = list( + "crate_stripe" = COLOR_AMBER + ) + +/decl/closet_appearance/crate/carp + color = COLOR_PURPLE + decals = list( + "toptext" = COLOR_OFF_WHITE, + "crate_reticle" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/centauri + color = COLOR_BABY_BLUE + decals = list( + "crate_stripe" = COLOR_LUMINOL + ) + extra_decals = list( + "centauri" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/cybersolutions + color = COLOR_ALUMINIUM + extra_decals = list( + "hazard" = COLOR_DARK_GOLD, + "toptext" = COLOR_DARK_GOLD + ) + +/decl/closet_appearance/crate/einstein + color = COLOR_DARK_BLUE_GRAY + extra_decals = list( + "crate_stripe_left" = COLOR_BEIGE, + "crate_stripe_right" = COLOR_BEIGE, + "einstein" = COLOR_OFF_WHITE, + "hazard" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/focalpoint + color = COLOR_GOLD + extra_decals = list( + "crate_stripe_left" = COLOR_NAVY_BLUE, + "crate_stripe_right" = COLOR_NAVY_BLUE, + "focal" = COLOR_OFF_WHITE, + "hazard" = COLOR_NAVY_BLUE + ) + +/decl/closet_appearance/crate/galaksi + color = COLOR_OFF_WHITE + decals = list( + "lid_stripes" = COLOR_HULL, + "galaksi" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/gilthari + color = COLOR_GRAY20 + extra_decals = list( + "crate_stripe_left" = COLOR_GOLD, + "crate_stripe_right" = COLOR_GOLD, + "gilthari" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/grayson + color = COLOR_STEEL + extra_decals = list( + "crate_stripe_left" = COLOR_MAROON, + "crate_stripe_right" = COLOR_MAROON, + "grayson" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/heph + color = COLOR_GRAY20 + extra_decals = list( + "crate_stripe_left" = COLOR_NT_RED, + "crate_stripe_right" = COLOR_NT_RED, + "heph" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/morpheus + color = COLOR_ALUMINIUM + extra_decals = list( + "hazard" = COLOR_GUNMETAL, + "toptext" = COLOR_GUNMETAL + ) + +/decl/closet_appearance/crate/nanotrasen + color = COLOR_NT_RED + extra_decals = list( + "crate_stripe_left" = COLOR_OFF_WHITE, + "crate_stripe_right" = COLOR_OFF_WHITE, + "nano" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/nanotrasenclothing + color = COLOR_NT_RED + extra_decals = list( + "crate_stripe_left" = COLOR_SEDONA, + "crate_stripe_right" = COLOR_SEDONA, + "nano" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/nanotrasenmedical + color = COLOR_OFF_WHITE + extra_decals = list( + "crate_stripe" = COLOR_NT_RED, + "nano" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/oculum + color = COLOR_SURGERY_BLUE + decals = list( + "crate_stripe_left" = COLOR_OFF_WHITE, + "crate_stripe_right" = COLOR_OFF_WHITE, + "oculum" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/saare + color = COLOR_ALUMINIUM + extra_decals = list( + "hazard" = COLOR_RED, + "xion" = COLOR_GRAY40 + ) + +/decl/closet_appearance/crate/thinktronic + color = COLOR_PALE_PURPLE_GRAY + decals = list( + "toptext" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/ummarcar + color = COLOR_BEIGE + decals = list( + "crate_stripes" = COLOR_OFF_WHITE, + "toptext" = COLOR_GRAY20 + ) + +/decl/closet_appearance/crate/unathiimport + color = COLOR_SILVER + decals = list( + "crate_stripe" = COLOR_RED, + "crate_reticle" = COLOR_RED_GRAY + ) + +/decl/closet_appearance/crate/veymed + color = COLOR_OFF_WHITE + decals = list( + "crate_stripe" = COLOR_PALE_BTL_GREEN + ) + extra_decals = list( + "lid_stripes" = COLOR_RED, + "crate_cross" = COLOR_GREEN + ) + +/decl/closet_appearance/crate/ward + color = COLOR_OFF_WHITE + extra_decals = list( + "crate_stripe_left" = COLOR_COMMAND_BLUE, + "crate_stripe_right" = COLOR_COMMAND_BLUE, + "hazard" = COLOR_OFF_WHITE, + "wt" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/xion + color = COLOR_ORANGE + extra_decals = list( + "crate_stripes" = COLOR_OFF_WHITE, + "xion" = COLOR_OFF_WHITE, + "hazard" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/zenghu + color = COLOR_OFF_WHITE + extra_decals = list( + "crate_stripes" = COLOR_RED, + "zenghu" = COLOR_OFF_WHITE + ) + +// Secure Crates /decl/closet_appearance/crate/secure can_lock = TRUE @@ -775,7 +977,8 @@ extra_decals = list( "crate_stripe_left" = COLOR_OFF_WHITE, "crate_stripe_right" = COLOR_OFF_WHITE, - "toxin" = COLOR_OFF_WHITE + "toxin" = COLOR_OFF_WHITE, + "nano" = COLOR_OFF_WHITE ) /decl/closet_appearance/crate/secure/weapon @@ -789,16 +992,61 @@ "hazard" = COLOR_OFF_WHITE ) -/decl/closet_appearance/crate/secure/heph - color = COLOR_GRAY20 +// Secure corporate branding + +/decl/closet_appearance/crate/secure/aether + color = COLOR_YELLOW_GRAY decals = list( "crate_bracing" ) extra_decals = list( - "crate_stripe_left" = COLOR_NT_RED, - "crate_stripe_right" = COLOR_NT_RED, - "hazard" = COLOR_OFF_WHITE, - "heph" = COLOR_OFF_WHITE + "crate_stripes" = COLOR_BLUE_LIGHT, + "aether" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/bishop + color = COLOR_OFF_WHITE + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripe_left" = COLOR_SKY_BLUE, + "crate_stripe_right" = COLOR_SKY_BLUE, + "bishop" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/cybersolutions + color = COLOR_ALUMINIUM + decals = list( + "crate_bracing" + ) + extra_decals = list( + "hazard" = COLOR_DARK_GOLD, + "toptext" = COLOR_DARK_GOLD + ) + +/decl/closet_appearance/crate/secure/einstein + color = COLOR_DARK_BLUE_GRAY + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripe_left" = COLOR_BEIGE, + "crate_stripe_right" = COLOR_BEIGE, + "einstein" = COLOR_OFF_WHITE, + "hazard" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/focalpoint + color = COLOR_GOLD + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripe_left" = COLOR_NAVY_BLUE, + "crate_stripe_right" = COLOR_NAVY_BLUE, + "focal" = COLOR_OFF_WHITE, + "hazard" = COLOR_NAVY_BLUE ) /decl/closet_appearance/crate/secure/gilthari @@ -813,16 +1061,15 @@ "gilthari" = COLOR_OFF_WHITE ) -/decl/closet_appearance/crate/secure/ward - color = COLOR_OFF_WHITE +/decl/closet_appearance/crate/secure/grayson + color = COLOR_STEEL decals = list( "crate_bracing" ) extra_decals = list( - "crate_stripe_left" = COLOR_COMMAND_BLUE, - "crate_stripe_right" = COLOR_COMMAND_BLUE, - "hazard" = COLOR_OFF_WHITE, - "wt" = COLOR_OFF_WHITE + "crate_stripe_left" = COLOR_MAROON, + "crate_stripe_right" = COLOR_MAROON, + "grayson" = COLOR_OFF_WHITE ) /decl/closet_appearance/crate/secure/hedberg @@ -837,6 +1084,18 @@ "hedberg" = COLOR_OFF_WHITE ) +/decl/closet_appearance/crate/secure/heph + color = COLOR_GRAY20 + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripe_left" = COLOR_NT_RED, + "crate_stripe_right" = COLOR_NT_RED, + "hazard" = COLOR_OFF_WHITE, + "heph" = COLOR_OFF_WHITE + ) + /decl/closet_appearance/crate/secure/lawson color = COLOR_SAN_MARINO_BLUE decals = list( @@ -849,6 +1108,103 @@ "lawson" = COLOR_OFF_WHITE ) +/decl/closet_appearance/crate/secure/morpheus + color = COLOR_ALUMINIUM + decals = list( + "crate_bracing" + ) + extra_decals = list( + "hazard" = COLOR_GUNMETAL, + "toptext" = COLOR_GUNMETAL + ) + +/decl/closet_appearance/crate/secure/nanotrasen + color = COLOR_NT_RED + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripe_left" = COLOR_OFF_WHITE, + "crate_stripe_right" = COLOR_OFF_WHITE, + "nano" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/nanotrasenmedical + color = COLOR_OFF_WHITE + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripe" = COLOR_NT_RED, + "nano" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/saare + color = COLOR_ALUMINIUM + decals = list( + "crate_bracing" + ) + extra_decals = list( + "hazard" = COLOR_RED, + "xion" = COLOR_GRAY40 + ) + +/decl/closet_appearance/crate/secure/solgov + color = COLOR_SAN_MARINO_BLUE + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripe_left" = COLOR_OFF_WHITE, + "crate_stripes" = COLOR_OFF_WHITE, + "hazard" = COLOR_OFF_WHITE, + "scg" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/veymed + color = COLOR_OFF_WHITE + decals = list( + "crate_bracing", + "crate_stripe" = COLOR_PALE_BTL_GREEN + ) + extra_decals = list( + "lid_stripes" = COLOR_RED, + "crate_cross" = COLOR_GREEN + ) + +/decl/closet_appearance/crate/secure/ward + color = COLOR_OFF_WHITE + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripe_left" = COLOR_COMMAND_BLUE, + "crate_stripe_right" = COLOR_COMMAND_BLUE, + "hazard" = COLOR_OFF_WHITE, + "wt" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/xion + color = COLOR_ORANGE + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripes" = COLOR_OFF_WHITE, + "xion" = COLOR_OFF_WHITE, + "hazard" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/crate/secure/zenghu + color = COLOR_OFF_WHITE + decals = list( + "crate_bracing" + ) + extra_decals = list( + "crate_stripes" = COLOR_RED, + "zenghu" = COLOR_OFF_WHITE + ) + /decl/closet_appearance/crate/secure/hydroponics extra_decals = list( "crate_stripe_left" = COLOR_GREEN_GRAY, @@ -869,6 +1225,7 @@ extra_decals = null /decl/closet_appearance/large_crate/critter + color = COLOR_BEIGE decals = list( "airholes" ) @@ -882,6 +1239,42 @@ "text" = COLOR_GREEN_GRAY ) +/decl/closet_appearance/large_crate/aether + color = COLOR_YELLOW_GRAY + decals = list( + "crate_bracing" + ) + extra_decals = list( + "text" = COLOR_BLUE_LIGHT + ) + +/decl/closet_appearance/large_crate/einstein + color = COLOR_DARK_BLUE_GRAY + decals = list( + "crate_bracing" + ) + extra_decals = list( + "text" = COLOR_BEIGE + ) + +/decl/closet_appearance/large_crate/nanotrasen + color = COLOR_NT_RED + decals = list( + "crate_bracing" + ) + extra_decals = list( + "text" = COLOR_OFF_WHITE + ) + +/decl/closet_appearance/large_crate/xion + color = COLOR_ORANGE + decals = list( + "crate_bracing" + ) + extra_decals = list( + "text" = COLOR_OFF_WHITE + ) + /decl/closet_appearance/large_crate/secure can_lock = TRUE @@ -895,6 +1288,46 @@ "text_upper" = COLOR_OFF_WHITE ) +/decl/closet_appearance/large_crate/secure/aether + color = COLOR_YELLOW_GRAY + decals = list( + "crate_bracing" + ) + extra_decals = list( + "marking" = COLOR_OFF_WHITE, + "text_upper" = COLOR_BLUE_LIGHT + ) + +/decl/closet_appearance/large_crate/secure/einstein + color = COLOR_DARK_BLUE_GRAY + decals = list( + "crate_bracing" + ) + extra_decals = list( + "marking" = COLOR_OFF_WHITE, + "text_upper" = COLOR_BEIGE + ) + +/decl/closet_appearance/large_crate/secure/heph + color = COLOR_GRAY20 + decals = list( + "crate_bracing" + ) + extra_decals = list( + "marking" = COLOR_NT_RED, + "text_upper" = COLOR_NT_RED + ) + +/decl/closet_appearance/large_crate/secure/xion + color = COLOR_ORANGE + decals = list( + "crate_bracing" + ) + extra_decals = list( + "marking" = COLOR_OFF_WHITE, + "text_upper" = COLOR_OFF_WHITE + ) + // Cabinets. /decl/closet_appearance/cabinet base_icon = 'icons/obj/closets/bases/cabinet.dmi' diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index bd81b8ab761..6223061ed88 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -6,6 +6,7 @@ icon = 'icons/obj/closets/bases/crate.dmi' closet_appearance = /decl/closet_appearance/crate climbable = 1 + dir = 4 //Spawn facing 'forward' by default. var/points_per_crate = 5 var/rigged = 0 @@ -65,6 +66,26 @@ update_icon() return 1 +/obj/structure/closet/crate/verb/rotate_clockwise() + set name = "Rotate Crate Clockwise" + set category = "Object" + set src in oview(1) + + if (usr.stat || usr.restrained() || anchored) + return + + src.set_dir(turn(src.dir, 270)) + +/obj/structure/closet/crate/verb/rotate_counterclockwise() + set category = "Object" + set name = "Rotate Crate Counterclockwise" + set src in view(1) + + if (usr.stat || usr.restrained() || anchored) + return + + src.set_dir(turn(src.dir, 90)) + /obj/structure/closet/crate/attackby(obj/item/weapon/W as obj, mob/user as mob) if(opened) if(isrobot(user)) @@ -274,6 +295,14 @@ var/target_temp = T0C - 40 var/cooling_power = 40 +/obj/structure/closet/crate/freezer/centauri + desc = "A freezer stamped with the logo of Centauri Provisions." + closet_appearance = /decl/closet_appearance/crate/freezer/centauri + +/obj/structure/closet/crate/freezer/nanotrasen + desc = "A freezer stamped with the logo of NanoTrasen." + closet_appearance = /decl/closet_appearance/crate/freezer/nanotrasen + /obj/structure/closet/crate/freezer/return_air() var/datum/gas_mixture/gas = (..()) if(!gas) return null @@ -303,6 +332,11 @@ organ.preserved = 0 ..() +/obj/structure/closet/crate/weapon + name = "weapons crate" + desc = "A barely secured weapons crate." + closet_appearance = /decl/closet_appearance/crate/secure/weapon + /obj/structure/closet/crate/freezer/rations //Fpr use in the escape shuttle name = "emergency rations" desc = "A crate of emergency rations." @@ -310,14 +344,12 @@ starts_with = list( /obj/random/mre = 6) - /obj/structure/closet/crate/bin name = "large bin" desc = "A large bin." closet_appearance = null icon = 'icons/obj/closets/largebin.dmi' - /obj/structure/closet/crate/radiation name = "radioactive gear crate" desc = "A crate with a radiation sign on it." @@ -327,27 +359,145 @@ /obj/item/clothing/suit/radiation = 4, /obj/item/clothing/head/radiation = 4) +//TSCs + +/obj/structure/closet/crate/aether + desc = "A crate painted in the colours of Aether Atmospherics and Recycling." + closet_appearance = /decl/closet_appearance/crate/aether + +/obj/structure/closet/crate/centauri + desc = "A crate decorated with the logo of Centauri Provisions." + closet_appearance = /decl/closet_appearance/crate/centauri + +/obj/structure/closet/crate/einstein + desc = "A crate labelled with an Einstein Engines sticker." + closet_appearance = /decl/closet_appearance/crate/einstein + +/obj/structure/closet/crate/focalpoint + desc = "A crate marked with the decal of Focal Point Energistics." + closet_appearance = /decl/closet_appearance/crate/focalpoint + +/obj/structure/closet/crate/gilthari + desc = "A crate embossed with the logo of Gilthari Exports." + closet_appearance = /decl/closet_appearance/crate/gilthari + +/obj/structure/closet/crate/grayson + desc = "A bare metal crate spraypainted with Grayson Manufactories decals." + closet_appearance = /decl/closet_appearance/crate/grayson + +/obj/structure/closet/crate/heph + desc = "A sturdy crate marked with the logo of Hephaestus Industries." + closet_appearance = /decl/closet_appearance/crate/heph + +/obj/structure/closet/crate/morpheus + desc = "A crate crudely imprinted with 'MORPHEUS CYBERKINETICS'." + closet_appearance = /decl/closet_appearance/crate/morpheus + +/obj/structure/closet/crate/nanotrasen + desc = "A crate emblazoned with the standard NanoTrasen livery." + closet_appearance = /decl/closet_appearance/crate/nanotrasen + +/obj/structure/closet/crate/nanothreads + desc = "A crate emblazoned with the NanoThreads Garments livery, a subsidary of the NanoTrasen Corporation." + closet_appearance = /decl/closet_appearance/crate/nanotrasenclothing + +/obj/structure/closet/crate/nanocare + desc = "A crate emblazoned with the NanoCare Medical livery, a subsidary of the NanoTrasen Corporation." + closet_appearance = /decl/closet_appearance/crate/nanotrasenmedical + +/obj/structure/closet/crate/oculum + desc = "A crate minimally decorated with the logo of media giant Oculum Broadcast." + closet_appearance = /decl/closet_appearance/crate/oculum + +/obj/structure/closet/crate/veymed + desc = "A sterile crate extensively detailed in Veymed colours." + closet_appearance = /decl/closet_appearance/crate/veymed + +/obj/structure/closet/crate/ward + desc = "A crate decaled with the logo of Ward-Takahashi." + closet_appearance = /decl/closet_appearance/crate/ward + +/obj/structure/closet/crate/xion + desc = "A crate painted in Xion Manufacturing Group orange." + closet_appearance = /decl/closet_appearance/crate/xion + +/obj/structure/closet/crate/zenghu + desc = "A sterile crate marked with the logo of Zeng-Hu Pharmaceuticals." + closet_appearance = /decl/closet_appearance/crate/zenghu + +// Brands/subsidiaries + +/obj/structure/closet/crate/allico + desc = "A crate painted in the distinctive cheerful colours of AlliCo. Ltd." + closet_appearance = /decl/closet_appearance/crate/allico + +/obj/structure/closet/crate/carp + desc = "A crate painted with the garish livery of Consolidated Agricultural Resources Plc." + closet_appearance = /decl/closet_appearance/crate/carp + +/obj/structure/closet/crate/hedberg + name = "weapons crate" + desc = "A weapons crate stamped with the logo of Hedberg-Hammarstrom and the lock conspicuously absent." + closet_appearance = /decl/closet_appearance/crate/secure/hedberg + +/obj/structure/closet/crate/galaksi + desc = "A crate printed with the markings of Ward-Takahashi's Galaksi Appliance branding." + closet_appearance = /decl/closet_appearance/crate/galaksi + +/obj/structure/closet/crate/thinktronic + desc = "A crate printed with the markings of Thinktronic Systems." + closet_appearance = /decl/closet_appearance/crate/thinktronic + +/obj/structure/closet/crate/ummarcar + desc = "A flimsy crate marked labelled 'UmMarcar Office Supply'." + closet_appearance = /decl/closet_appearance/crate/ummarcar + +/obj/structure/closet/crate/unathi + name = "import crate" + desc = "A crate painted with the markings of Moghes Imported Sissalik Jerky." + closet_appearance = /decl/closet_appearance/crate/unathiimport + + +// Secure Crates /obj/structure/closet/crate/secure/weapon name = "weapons crate" desc = "A secure weapons crate." closet_appearance = /decl/closet_appearance/crate/secure/weapon +/obj/structure/closet/crate/secure/aether + desc = "A secure crate painted in the colours of Aether Atmospherics and Recycling." + closet_appearance = /decl/closet_appearance/crate/secure/aether + +/obj/structure/closet/crate/secure/bishop + desc = "A secure crate finely decorated with the emblem of Bishop Cybernetics." + closet_appearance = /decl/closet_appearance/crate/secure/bishop + +/obj/structure/closet/crate/secure/cybersolutions + desc = "An unadorned secure metal crate labelled 'Cyber Solutions'." + closet_appearance = /decl/closet_appearance/crate/secure/cybersolutions + +/obj/structure/closet/crate/secure/einstein + desc = "A secure crate labelled with an Einstein Engines sticker." + closet_appearance = /decl/closet_appearance/crate/secure/einstein + +/obj/structure/closet/crate/secure/focalpoint + desc = "A secure crate marked with the decal of Focal Point Energistics." + closet_appearance = /decl/closet_appearance/crate/secure/focalpoint + +/obj/structure/closet/crate/secure/gilthari + desc = "A secure crate embossed with the logo of Gilthari Exports." + closet_appearance = /decl/closet_appearance/crate/secure/gilthari + +/obj/structure/closet/crate/secure/grayson + desc = "A secure bare metal crate spraypainted with Grayson Manufactories decals." + closet_appearance = /decl/closet_appearance/crate/secure/grayson + /obj/structure/closet/crate/secure/hedberg name = "weapons crate" desc = "A secure weapons crate stamped with the logo of Hedberg-Hammarstrom." closet_appearance = /decl/closet_appearance/crate/secure/hedberg -/obj/structure/closet/crate/secure/gilthari - name = "weapons crate" - desc = "A secure weapons crate embossed with the logo of Gilthari Exports." - closet_appearance = /decl/closet_appearance/crate/secure/gilthari - -/obj/structure/closet/crate/secure/ward - name = "weapons crate" - desc = "A secure weapons crate decaled with the logo of Ward-Takahashi." - closet_appearance = /decl/closet_appearance/crate/secure/ward - /obj/structure/closet/crate/secure/heph name = "weapons crate" desc = "A secure weapons crate marked with the logo of Hephaestus Industries." @@ -358,9 +508,47 @@ desc = "A secure weapons crate marked with the logo of Lawson Arms." closet_appearance = /decl/closet_appearance/crate/secure/lawson +/obj/structure/closet/crate/secure/morpheus + desc = "A secure crate crudely imprinted with 'MORPHEUS CYBERKINETICS'." + closet_appearance = /decl/closet_appearance/crate/secure/morpheus + +/obj/structure/closet/crate/secure/nanotrasen + desc = "A secure crate emblazoned with the standard NanoTrasen livery." + closet_appearance = /decl/closet_appearance/crate/secure/nanotrasen + +/obj/structure/closet/crate/secure/nanocare + desc = "A secure crate emblazoned with the NanoCare Medical livery, a subsidary of the NanoTrasen Corporation." + closet_appearance = /decl/closet_appearance/crate/secure/nanotrasenmedical + +/obj/structure/closet/crate/secure/scg + name = "weapons crate" + desc = "A secure crate in the official colours of the Solar Confederate Government." + closet_appearance = /decl/closet_appearance/crate/secure/solgov + +/obj/structure/closet/crate/secure/saare + name = "weapons crate" + desc = "A secure weapons crate plainly stamped with the logo of Stealth Assault Enterprises." + closet_appearance = /decl/closet_appearance/crate/secure/saare + +/obj/structure/closet/crate/secure/veymed + desc = "A secure sterile crate extensively detailed in Veymed colours." + closet_appearance = /decl/closet_appearance/crate/secure/veymed + +/obj/structure/closet/crate/secure/ward + desc = "A secure crate decaled with the logo of Ward-Takahashi." + closet_appearance = /decl/closet_appearance/crate/secure/ward + +/obj/structure/closet/crate/secure/xion + desc = "A secure crate painted in Xion Manufacturing Group orange." + closet_appearance = /decl/closet_appearance/crate/secure/xion + +/obj/structure/closet/crate/secure/zenghu + desc = "A secure sterile crate marked with the logo of Zeng-Hu Pharmaceuticals." + closet_appearance = /decl/closet_appearance/crate/secure/zenghu + /obj/structure/closet/crate/secure/phoron name = "phoron crate" - desc = "A secure phoron crate." + desc = "A secure phoron crate painted in standard NanoTrasen livery." closet_appearance = /decl/closet_appearance/crate/secure/hazard /obj/structure/closet/crate/secure/gear @@ -368,27 +556,24 @@ desc = "A secure gear crate." closet_appearance = /decl/closet_appearance/crate/secure/weapon - /obj/structure/closet/crate/secure/hydrosec name = "secure hydroponics crate" desc = "A crate with a lock on it, painted in the scheme of the station's botanists." closet_appearance = /decl/closet_appearance/crate/secure/hydroponics - /obj/structure/closet/crate/secure/engineering desc = "A crate with a lock on it, painted in the scheme of the station's engineers." name = "secure engineering crate" - /obj/structure/closet/crate/secure/science name = "secure science crate" desc = "A crate with a lock on it, painted in the scheme of the station's scientists." - /obj/structure/closet/crate/secure/bin name = "secure bin" desc = "A secure bin." +// Large crates /obj/structure/closet/crate/large name = "large crate" @@ -414,6 +599,30 @@ break return +/obj/structure/closet/crate/large/critter + name = "animal crate" + desc = "A hefty crate for hauling animals." + closet_appearance = /decl/closet_appearance/large_crate/critter + +/obj/structure/closet/crate/large/aether + name = "large atmospherics crate" + desc = "A hefty metal crate, painted in Aether Atmospherics and Recycling colours." + closet_appearance = /decl/closet_appearance/large_crate/aether + +/obj/structure/closet/crate/large/einstein + name = "large crate" + desc = "A hefty metal crate, painted in Einstein Engines colours." + closet_appearance = /decl/closet_appearance/large_crate/einstein + +/obj/structure/closet/crate/large/nanotrasen + name = "large crate" + desc = "A hefty metal crate, painted in standard NanoTrasen livery." + closet_appearance = /decl/closet_appearance/large_crate/nanotrasen + +/obj/structure/closet/crate/large/xion + name = "large crate" + desc = "A hefty metal crate, painted in Xion Manufacturing Group orange." + closet_appearance = /decl/closet_appearance/large_crate/xion /obj/structure/closet/crate/secure/large name = "large crate" @@ -441,10 +650,30 @@ return -//fluff variant /obj/structure/closet/crate/secure/large/reinforced desc = "A hefty, reinforced metal crate with an electronic locking system." +/obj/structure/closet/crate/secure/large/aether + name = "secure atmospherics crate" + desc = "A hefty metal crate with an electronic locking system, painted in Aether Atmospherics and Recycling colours." + closet_appearance = /decl/closet_appearance/large_crate/secure/aether + +/obj/structure/closet/crate/secure/large/einstein + desc = "A hefty metal crate with an electronic locking system, painted in Einstein Engines colours." + closet_appearance = /decl/closet_appearance/large_crate/secure/einstein + +/obj/structure/closet/crate/large/secure/heph + desc = "A hefty metal crate with an electronic locking system, marked with Hephaestus Industries colours." + closet_appearance = /decl/closet_appearance/large_crate/secure/heph + +/obj/structure/closet/crate/secure/large/nanotrasen + desc = "A hefty metal crate with an electronic locking system, painted in standard NanoTrasen livery." + closet_appearance = /decl/closet_appearance/large_crate/secure/hazard + +/obj/structure/closet/crate/large/secure/xion + desc = "A hefty metal crate with an electronic locking system, painted in Xion Manufacturing Group orange." + closet_appearance = /decl/closet_appearance/large_crate/secure/xion + /obj/structure/closet/crate/engineering name = "engineering crate" diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index 29f1b231aa6..7ed37d06207 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -44,8 +44,8 @@ /obj/structure/largecrate/hoverpod name = "\improper Hoverpod assembly crate" - desc = "It comes in a box for the fabricator's sake. Where does the wood come from? ... And why is it lighter?" - icon_state = "mulecrate" + desc = "You aren't sure how this crate is so light, but the Wulf Aeronautics logo might be a hint." + icon_state = "vehiclecrate" /obj/structure/largecrate/hoverpod/attackby(obj/item/weapon/W as obj, mob/user as mob) if(W.is_crowbar()) @@ -60,7 +60,7 @@ /obj/structure/largecrate/vehicle name = "vehicle crate" - desc = "It comes in a box for the consumer's sake. ..How is this lighter?" + desc = "Wulf Aeronautics says it comes in a box for the consumer's sake... How is this so light?" icon_state = "vehiclecrate" /obj/structure/largecrate/vehicle/Initialize() @@ -74,18 +74,22 @@ /obj/structure/largecrate/vehicle/quadbike name = "\improper ATV crate" + desc = "A hefty wooden crate proudly displaying the logo of Ward-Takahashi's automotive division." starts_with = list(/obj/structure/vehiclecage/quadbike) /obj/structure/largecrate/vehicle/quadtrailer name = "\improper ATV trailer crate" + desc = "A hefty wooden crate proudly displaying the logo of Ward-Takahashi's automotive division." starts_with = list(/obj/structure/vehiclecage/quadtrailer) /obj/structure/largecrate/animal - icon_state = "lisacrate" //VOREStation Edit + icon_state = "crittercrate" + desc = "A hefty wooden crate with air holes. It is marked with the logo of NanoTrasen Pastures and the slogan, '90% less cloning defects* than competing brands**, or your money back***!'" /obj/structure/largecrate/animal/mulebot name = "Mulebot crate" - icon_state = "mulecrate" //VOREStation Edit + desc = "A hefty wooden crate labelled 'Proud Product of the Xion Manufacturing Group'" + icon_state = "mulecrate" starts_with = list(/mob/living/bot/mulebot) /obj/structure/largecrate/animal/corgi diff --git a/code/game/sound.dm b/code/game/sound.dm index 7b16e0fd801..c5846c39eb6 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -253,6 +253,10 @@ 'sound/vore/sunesound/prey/death_07.ogg','sound/vore/sunesound/prey/death_08.ogg','sound/vore/sunesound/prey/death_09.ogg', 'sound/vore/sunesound/prey/death_10.ogg') //END VORESTATION EDIT + if ("terminal_type") + soundin = pick('sound/machines/terminal_button01.ogg', 'sound/machines/terminal_button02.ogg', 'sound/machines/terminal_button03.ogg', \ + 'sound/machines/terminal_button04.ogg', 'sound/machines/terminal_button05.ogg', 'sound/machines/terminal_button06.ogg', \ + 'sound/machines/terminal_button07.ogg', 'sound/machines/terminal_button08.ogg') return soundin //Are these even used? diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 33ca558e801..90a5c26e543 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -119,3 +119,11 @@ NOTE: It checks usr by default. Supply the "user" argument if you wish to check holder.disassociate() //qdel(holder) return 1 + +//This proc checks whether subject has at least ONE of the rights specified in rights_required. +/proc/check_rights_for(client/subject, rights_required) + if(subject && subject.holder) + if(rights_required && !(rights_required & subject.holder.rights)) + return 0 + return 1 + return 0 \ No newline at end of file diff --git a/code/modules/alarm/alarm.dm b/code/modules/alarm/alarm.dm index f8d853ca8cd..30de8cc5605 100644 --- a/code/modules/alarm/alarm.dm +++ b/code/modules/alarm/alarm.dm @@ -18,7 +18,6 @@ var/list/sources = new() //List of sources triggering the alarm. Used to determine when the alarm should be cleared. var/list/sources_assoc = new() //Associative list of source triggers. Used to efficiently acquire the alarm source. var/list/cameras //List of cameras that can be switched to, if the player has that capability. - var/cache_id //ID for camera cache, changed by invalidateCameraCache(). var/area/last_area //The last acquired area, used should origin be lost (for example a destroyed borg containing an alarming camera). var/area/last_name //The last acquired name, used should origin be lost var/area/last_camera_area //The last area in which cameras where fetched, used to see if the camera list should be updated. @@ -78,15 +77,10 @@ return last_name /datum/alarm/proc/cameras() - // reset camera cache - if(camera_repository.camera_cache_id != cache_id) - cameras = null - cache_id = camera_repository.camera_cache_id // If the alarm origin has changed area, for example a borg containing an alarming camera, reset the list of cameras - else if(cameras && (last_camera_area != alarm_area())) + if(cameras && (last_camera_area != alarm_area())) cameras = null - // The list of cameras is also reset by /proc/invalidateCameraCache() if(!cameras) cameras = origin ? origin.get_alarm_cameras() : last_area.get_alarm_cameras() diff --git a/code/modules/asset_cache/asset_cache.dm b/code/modules/asset_cache/asset_cache.dm new file mode 100644 index 00000000000..53a30d4299a --- /dev/null +++ b/code/modules/asset_cache/asset_cache.dm @@ -0,0 +1,110 @@ +/* +Asset cache quick users guide: + +Make a datum in asset_list_items.dm with your assets for your thing. +Checkout asset_list.dm for the helper subclasses +The simple subclass 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. + +Note: If your code uses output() with assets you will need to call asset_flush on the client and wait for it to return before calling output(). You only need do this if .send(client) returned TRUE +*/ + +//When sending mutiple assets, how many before we give the client a quaint little sending resources message +#define ASSET_CACHE_TELL_CLIENT_AMOUNT 8 + +//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(client/client, asset_name) + return send_asset_list(client, list(asset_name)) + +/// Sends a list of assets to a client +/// This proc will no longer block, use client.asset_flush() if you to need know when the client has all assets (such as for output()). (This is not required for browse() calls as they use the same message queue as asset sends) +/// client - a client or mob +/// asset_list - A list of asset filenames to be sent to the client. +/// Returns TRUE if any assets were sent. +/proc/send_asset_list(client/client, list/asset_list) + if(!istype(client)) + if(ismob(client)) + var/mob/M = client + if(M.client) + client = M.client + else + return + else + return + + var/list/unreceived = list() + + for (var/asset_name in asset_list) + var/datum/asset_cache_item/asset = SSassets.cache[asset_name] + if (!asset) + continue + var/asset_file = asset.resource + if (!asset_file) + continue + + var/asset_md5 = asset.md5 + if (client.sent_assets[asset_name] == asset_md5) + continue + unreceived[asset_name] = asset_md5 + + if (unreceived.len) + if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT) + to_chat(client, "Sending Resources...") + + for(var/asset in unreceived) + var/datum/asset_cache_item/ACI + if ((ACI = SSassets.cache[asset])) + log_asset("Sending asset [asset] to client [client]") + client << browse_rsc(ACI.resource, asset) + + client.sent_assets |= unreceived + addtimer(CALLBACK(client, /client/proc/asset_cache_update_json), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) + return TRUE + return FALSE + +//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(client/client, list/files, register_asset = TRUE, filerate = 3) + var/startingfilerate = filerate + for(var/file in files) + if (!client) + break + if (register_asset) + register_asset(file, files[file]) + + if (send_asset(client, file)) + if (!(--filerate)) + filerate = startingfilerate + client.asset_flush() + stoplag(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. +//icons and virtual assets get copied to the dyn rsc before use +/proc/register_asset(asset_name, asset) + var/datum/asset_cache_item/ACI = new(asset_name, asset) + + //this is technically never something that was supported and i want metrics on how often it happens if at all. + if (SSassets.cache[asset_name]) + var/datum/asset_cache_item/OACI = SSassets.cache[asset_name] + if (OACI.md5 != ACI.md5) + stack_trace("ERROR: new asset added to the asset cache with the same name as another asset: [asset_name] existing asset md5: [OACI.md5] new asset md5:[ACI.md5]") + else + var/list/stacktrace = gib_stack_trace() + log_asset("WARNING: dupe asset added to the asset cache: [asset_name] existing asset md5: [OACI.md5] new asset md5:[ACI.md5]\n[stacktrace.Join("\n")]") + SSassets.cache[asset_name] = ACI + return ACI + +/// Returns the url of the asset, currently this is just its name, here to allow further work cdn'ing assets. +/// Can be given an asset as well, this is just a work around for buggy edge cases where two assets may have the same name, doesn't matter now, but it will when the cdn comes. +/proc/get_asset_url(asset_name, asset = null) + var/datum/asset_cache_item/ACI = SSassets.cache[asset_name] + return ACI?.url + +//Generated names do not include file extention. +//Used mainly for code that deals with assets in a generic way +//The same asset will always lead to the same asset name +/proc/generate_asset_name(file) + return "asset.[md5(fcopy_rsc(file))]" + diff --git a/code/modules/asset_cache/asset_cache_client.dm b/code/modules/asset_cache/asset_cache_client.dm new file mode 100644 index 00000000000..0f51520f13a --- /dev/null +++ b/code/modules/asset_cache/asset_cache_client.dm @@ -0,0 +1,51 @@ + +/// Process asset cache client topic calls for "asset_cache_confirm_arrival=[INT]" +/client/proc/asset_cache_confirm_arrival(job_id) + var/asset_cache_job = round(text2num(job_id)) + //because we skip the limiter, we have to make sure this is a valid arrival and not somebody tricking us into letting them append to a list without limit. + if (asset_cache_job > 0 && asset_cache_job <= last_asset_job && !(completed_asset_jobs["[asset_cache_job]"])) + completed_asset_jobs["[asset_cache_job]"] = TRUE + last_completed_asset_job = max(last_completed_asset_job, asset_cache_job) + else + return asset_cache_job || TRUE + + +/// Process asset cache client topic calls for "asset_cache_preload_data=[HTML+JSON_STRING] +/client/proc/asset_cache_preload_data(data) + /*var/jsonend = findtextEx(data, "{{{ENDJSONDATA}}}") + if (!jsonend) + CRASH("invalid asset_cache_preload_data, no jsonendmarker")*/ + //var/json = html_decode(copytext(data, 1, jsonend)) + var/json = data + var/list/preloaded_assets = json_decode(json) + + for (var/preloaded_asset in preloaded_assets) + if (copytext(preloaded_asset, findlasttext(preloaded_asset, ".")+1) in list("js", "jsm", "htm", "html")) + preloaded_assets -= preloaded_asset + continue + sent_assets |= preloaded_assets + + +/// Updates the client side stored html/json combo file used to keep track of what assets the client has between restarts/reconnects. +/client/proc/asset_cache_update_json(verify = FALSE, list/new_assets = list()) + if (world.time - connection_time < 10 SECONDS) //don't override the existing data file on a new connection + return + if (!islist(new_assets)) + new_assets = list("[new_assets]" = md5(SSassets.cache[new_assets])) + + src << browse(json_encode(new_assets|sent_assets), "file=asset_data.json&display=0") + +/// Blocks until all currently sending browser assets have been sent. +/// Due to byond limitations, this proc will sleep for 1 client round trip even if the client has no pending asset sends. +/// This proc will return an untrue value if it had to return before confirming the send, such as timeout or the client going away. +/client/proc/asset_flush(timeout = 50) + var/job = ++last_asset_job + var/t = 0 + var/timeout_time = timeout + src << browse({""}, "window=asset_cache_browser&file=asset_cache_send_verify.htm") + + while(!completed_asset_jobs["[job]"] && t < timeout_time) // Reception is handled in Topic() + stoplag(1) // Lock up the caller until this is received. + t++ + if (t < timeout_time) + return TRUE diff --git a/code/modules/asset_cache/asset_cache_item.dm b/code/modules/asset_cache/asset_cache_item.dm new file mode 100644 index 00000000000..5f02e561c6f --- /dev/null +++ b/code/modules/asset_cache/asset_cache_item.dm @@ -0,0 +1,23 @@ +/** + * # asset_cache_item + * + * An internal datum containing info on items in the asset cache. Mainly used to cache md5 info for speed. +**/ +/datum/asset_cache_item + var/name + var/url + var/md5 + var/resource + +/datum/asset_cache_item/New(name, file) + if (!isfile(file)) + file = fcopy_rsc(file) + md5 = md5(file) + if (!md5) + md5 = md5(fcopy_rsc(file)) + if (!md5) + CRASH("invalid asset sent to asset cache") + log_world("asset cache unexpected success of second fcopy_rsc") + src.name = name + url = name + resource = file diff --git a/code/modules/asset_cache/asset_list.dm b/code/modules/asset_cache/asset_list.dm new file mode 100644 index 00000000000..5cc16d06bc7 --- /dev/null +++ b/code/modules/asset_cache/asset_list.dm @@ -0,0 +1,260 @@ + +//These datums are used to populate the asset cache, the proc "register()" does this. +//Place any asset datums you create in asset_list_items.dm + +//all of our asset datums, used for referring to these later +GLOBAL_LIST_EMPTY(asset_datums) + +//get an assetdatum or make a new one +/proc/get_asset_datum(type) + return GLOB.asset_datums[type] || new type() + +/datum/asset + var/_abstract = /datum/asset + +/datum/asset/New() + GLOB.asset_datums[type] = src + register() + +/datum/asset/proc/get_url_mappings() + return list() + +/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() + +/datum/asset/simple/register() + for(var/asset_name in assets) + assets[asset_name] = register_asset(asset_name, assets[asset_name]) + +/datum/asset/simple/send(client) + . = send_asset_list(client, assets) + +/datum/asset/simple/get_url_mappings() + . = list() + for (var/asset_name in assets) + var/datum/asset_cache_item/ACI = assets[asset_name] + if (!ACI) + continue + .[asset_name] = ACI.url + + +// For registering or sending multiple others at once +/datum/asset/group + _abstract = /datum/asset/group + var/list/children + +/datum/asset/group/register() + for(var/type in children) + get_asset_datum(type) + +/datum/asset/group/send(client/C) + for(var/type in children) + var/datum/asset/A = get_asset_datum(type) + . = A.send(C) || . + +/datum/asset/group/get_url_mappings() + . = list() + for(var/type in children) + var/datum/asset/A = get_asset_datum(type) + . += A.get_url_mappings() + +// spritesheet implementation - coalesces various icons into a single .png file +// and uses CSS to select icons out of that file - saves on transferring some +// 1400-odd individual PNG files +#define SPR_SIZE 1 +#define SPR_IDX 2 +#define SPRSZ_COUNT 1 +#define SPRSZ_ICON 2 +#define SPRSZ_STRIPPED 3 + +/datum/asset/spritesheet + _abstract = /datum/asset/spritesheet + var/name + var/list/sizes = list() // "32x32" -> list(10, icon/normal, icon/stripped) + var/list/sprites = list() // "foo_bar" -> list("32x32", 5) + +/datum/asset/spritesheet/register() + if (!name) + CRASH("spritesheet [type] cannot register without a name") + ensure_stripped() + for(var/size_id in sizes) + var/size = sizes[size_id] + register_asset("[name]_[size_id].png", size[SPRSZ_STRIPPED]) + var/res_name = "spritesheet_[name].css" + var/fname = "data/spritesheets/[res_name]" + fdel(fname) + text2file(generate_css(), fname) + register_asset(res_name, fcopy_rsc(fname)) + fdel(fname) + +/datum/asset/spritesheet/send(client/C) + if (!name) + return + var/all = list("spritesheet_[name].css") + for(var/size_id in sizes) + all += "[name]_[size_id].png" + . = send_asset_list(C, all) + +/datum/asset/spritesheet/get_url_mappings() + if (!name) + return + . = list("spritesheet_[name].css" = get_asset_url("spritesheet_[name].css")) + for(var/size_id in sizes) + .["[name]_[size_id].png"] = get_asset_url("[name]_[size_id].png") + + + +/datum/asset/spritesheet/proc/ensure_stripped(sizes_to_strip = sizes) + for(var/size_id in sizes_to_strip) + var/size = sizes[size_id] + if (size[SPRSZ_STRIPPED]) + continue + + #ifdef RUST_G + // save flattened version + var/fname = "data/spritesheets/[name]_[size_id].png" + fcopy(size[SPRSZ_ICON], fname) + var/error = call(RUST_G, "dmi_strip_metadata")(fname) + if(length(error)) + stack_trace("Failed to strip [name]_[size_id].png: [error]") + size[SPRSZ_STRIPPED] = icon(fname) + fdel(fname) + #else + #warn It looks like you don't have RUST_G enabled. Without RUST_G, the RPD icons will not function, so it strongly recommended you reenable it. + #endif + +/datum/asset/spritesheet/proc/generate_css() + var/list/out = list() + + for (var/size_id in sizes) + var/size = sizes[size_id] + var/icon/tiny = size[SPRSZ_ICON] + out += ".[name][size_id]{display:inline-block;width:[tiny.Width()]px;height:[tiny.Height()]px;background:url('[get_asset_url("[name]_[size_id].png")]') no-repeat;}" + + for (var/sprite_id in sprites) + var/sprite = sprites[sprite_id] + var/size_id = sprite[SPR_SIZE] + var/idx = sprite[SPR_IDX] + var/size = sizes[size_id] + + var/icon/tiny = size[SPRSZ_ICON] + var/icon/big = size[SPRSZ_STRIPPED] + var/per_line = big.Width() / tiny.Width() + var/x = (idx % per_line) * tiny.Width() + var/y = round(idx / per_line) * tiny.Height() + + out += ".[name][size_id].[sprite_id]{background-position:-[x]px -[y]px;}" + + return out.Join("\n") + +/datum/asset/spritesheet/proc/Insert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE) + I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving) + if (!I || !length(icon_states(I))) // that direction or state doesn't exist + return + var/size_id = "[I.Width()]x[I.Height()]" + var/size = sizes[size_id] + + if (sprites[sprite_name]) + CRASH("duplicate sprite \"[sprite_name]\" in sheet [name] ([type])") + + if (size) + var/position = size[SPRSZ_COUNT]++ + var/icon/sheet = size[SPRSZ_ICON] + size[SPRSZ_STRIPPED] = null + sheet.Insert(I, icon_state=sprite_name) + sprites[sprite_name] = list(size_id, position) + else + sizes[size_id] = size = list(1, I, null) + sprites[sprite_name] = list(size_id, 0) + +/datum/asset/spritesheet/proc/InsertAll(prefix, icon/I, list/directions) + if (length(prefix)) + prefix = "[prefix]-" + + if (!directions) + directions = list(SOUTH) + + for (var/icon_state_name in icon_states(I)) + for (var/direction in directions) + var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]-" : "" + Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction) + +/datum/asset/spritesheet/proc/css_tag() + return {""} + +/datum/asset/spritesheet/proc/css_filename() + return get_asset_url("spritesheet_[name].css") + +/datum/asset/spritesheet/proc/icon_tag(sprite_name) + var/sprite = sprites[sprite_name] + if (!sprite) + return null + var/size_id = sprite[SPR_SIZE] + return {""} + +/datum/asset/spritesheet/proc/icon_class_name(sprite_name) + var/sprite = sprites[sprite_name] + if (!sprite) + return null + var/size_id = sprite[SPR_SIZE] + return {"[name][size_id] [sprite_name]"} + +#undef SPR_SIZE +#undef SPR_IDX +#undef SPRSZ_COUNT +#undef SPRSZ_ICON +#undef SPRSZ_STRIPPED + + +/datum/asset/spritesheet/simple + _abstract = /datum/asset/spritesheet/simple + var/list/assets + +/datum/asset/spritesheet/simple/register() + for (var/key in assets) + Insert(key, assets[key]) + ..() + +//Generates assets based on iconstates of a single icon +/datum/asset/simple/icon_states + _abstract = /datum/asset/simple/icon_states + var/icon + var/list/directions = list(SOUTH) + var/frame = 1 + var/movement_states = FALSE + + var/prefix = "default" //asset_name = "[prefix].[icon_state_name].png" + var/generic_icon_names = FALSE //generate icon filenames using generate_asset_name() instead the above format + +/datum/asset/simple/icon_states/register(_icon = icon) + for(var/icon_state_name in icon_states(_icon)) + for(var/direction in directions) + var/asset = icon(_icon, icon_state_name, direction, frame, movement_states) + if (!asset) + continue + asset = fcopy_rsc(asset) //dedupe + var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]." : "" + var/asset_name = sanitize_filename("[prefix].[prefix2][icon_state_name].png") + if (generic_icon_names) + asset_name = "[generate_asset_name(asset)].png" + + register_asset(asset_name, asset) + +/datum/asset/simple/icon_states/multiple_icons + _abstract = /datum/asset/simple/icon_states/multiple_icons + var/list/icons + +/datum/asset/simple/icon_states/multiple_icons/register() + for(var/i in icons) + ..(i) + + diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm new file mode 100644 index 00000000000..2b90000ea0c --- /dev/null +++ b/code/modules/asset_cache/asset_list_items.dm @@ -0,0 +1,445 @@ +//DEFINITIONS FOR ASSET DATUMS START HERE. + +/datum/asset/simple/tgui + assets = list( + "tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js', + "tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css', + ) + +// /datum/asset/simple/headers +// assets = list( +// "alarm_green.gif" = 'icons/program_icons/alarm_green.gif', +// "alarm_red.gif" = 'icons/program_icons/alarm_red.gif', +// "batt_5.gif" = 'icons/program_icons/batt_5.gif', +// "batt_20.gif" = 'icons/program_icons/batt_20.gif', +// "batt_40.gif" = 'icons/program_icons/batt_40.gif', +// "batt_60.gif" = 'icons/program_icons/batt_60.gif', +// "batt_80.gif" = 'icons/program_icons/batt_80.gif', +// "batt_100.gif" = 'icons/program_icons/batt_100.gif', +// "charging.gif" = 'icons/program_icons/charging.gif', +// "downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif', +// "downloader_running.gif" = 'icons/program_icons/downloader_running.gif', +// "ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif', +// "ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif', +// "power_norm.gif" = 'icons/program_icons/power_norm.gif', +// "power_warn.gif" = 'icons/program_icons/power_warn.gif', +// "sig_high.gif" = 'icons/program_icons/sig_high.gif', +// "sig_low.gif" = 'icons/program_icons/sig_low.gif', +// "sig_lan.gif" = 'icons/program_icons/sig_lan.gif', +// "sig_none.gif" = 'icons/program_icons/sig_none.gif', +// "smmon_0.gif" = 'icons/program_icons/smmon_0.gif', +// "smmon_1.gif" = 'icons/program_icons/smmon_1.gif', +// "smmon_2.gif" = 'icons/program_icons/smmon_2.gif', +// "smmon_3.gif" = 'icons/program_icons/smmon_3.gif', +// "smmon_4.gif" = 'icons/program_icons/smmon_4.gif', +// "smmon_5.gif" = 'icons/program_icons/smmon_5.gif', +// "smmon_6.gif" = 'icons/program_icons/smmon_6.gif', +// "borg_mon.gif" = 'icons/program_icons/borg_mon.gif' +// ) + +// /datum/asset/simple/radar_assets +// assets = list( +// "ntosradarbackground.png" = 'icons/UI_Icons/tgui/ntosradar_background.png', +// "ntosradarpointer.png" = 'icons/UI_Icons/tgui/ntosradar_pointer.png', +// "ntosradarpointerS.png" = 'icons/UI_Icons/tgui/ntosradar_pointer_S.png' +// ) + +// /datum/asset/spritesheet/simple/pda +// name = "pda" +// assets = list( +// "atmos" = 'icons/pda_icons/pda_atmos.png', +// "back" = 'icons/pda_icons/pda_back.png', +// "bell" = 'icons/pda_icons/pda_bell.png', +// "blank" = 'icons/pda_icons/pda_blank.png', +// "boom" = 'icons/pda_icons/pda_boom.png', +// "bucket" = 'icons/pda_icons/pda_bucket.png', +// "medbot" = 'icons/pda_icons/pda_medbot.png', +// "floorbot" = 'icons/pda_icons/pda_floorbot.png', +// "cleanbot" = 'icons/pda_icons/pda_cleanbot.png', +// "crate" = 'icons/pda_icons/pda_crate.png', +// "cuffs" = 'icons/pda_icons/pda_cuffs.png', +// "eject" = 'icons/pda_icons/pda_eject.png', +// "flashlight" = 'icons/pda_icons/pda_flashlight.png', +// "honk" = 'icons/pda_icons/pda_honk.png', +// "mail" = 'icons/pda_icons/pda_mail.png', +// "medical" = 'icons/pda_icons/pda_medical.png', +// "menu" = 'icons/pda_icons/pda_menu.png', +// "mule" = 'icons/pda_icons/pda_mule.png', +// "notes" = 'icons/pda_icons/pda_notes.png', +// "power" = 'icons/pda_icons/pda_power.png', +// "rdoor" = 'icons/pda_icons/pda_rdoor.png', +// "reagent" = 'icons/pda_icons/pda_reagent.png', +// "refresh" = 'icons/pda_icons/pda_refresh.png', +// "scanner" = 'icons/pda_icons/pda_scanner.png', +// "signaler" = 'icons/pda_icons/pda_signaler.png', +// "skills" = 'icons/pda_icons/pda_skills.png', +// "status" = 'icons/pda_icons/pda_status.png', +// "dronephone" = 'icons/pda_icons/pda_dronephone.png', +// "emoji" = 'icons/pda_icons/pda_emoji.png' +// ) + +// /datum/asset/spritesheet/simple/paper +// name = "paper" +// assets = list( +// "stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png', +// "stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png', +// "stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png', +// "stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png', +// "stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png', +// "stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png', +// "stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png', +// "stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png', +// "stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png', +// "stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png', +// "stamp-law" = 'icons/stamp_icons/large_stamp-law.png', +// "stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png', +// "stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png', +// "stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png', +// "stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png' +// ) + + +// /datum/asset/simple/irv +// assets = list( +// "jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js', +// ) + +// /datum/asset/group/irv +// children = list( +// /datum/asset/simple/jquery, +// /datum/asset/simple/irv +// ) + +/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/group/goonchat +// children = list( +// /datum/asset/simple/jquery, +// /datum/asset/simple/goonchat, +// /datum/asset/spritesheet/goonchat, +// /datum/asset/simple/fontawesome +// ) + +// /datum/asset/simple/jquery +// assets = list( +// "jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js', +// ) + +// /datum/asset/simple/goonchat +// assets = list( +// "json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js', +// "browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js', +// "browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css', +// "browserOutput_white.css" = 'code/modules/goonchat/browserassets/css/browserOutput_white.css', +// ) + +/datum/asset/simple/fontawesome + assets = list( + "fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot', + "fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff', + "fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot', + "fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff', + "font-awesome.css" = 'html/font-awesome/css/all.min.css', + "v4shim.css" = 'html/font-awesome/css/v4-shims.min.css' + ) + +// /datum/asset/spritesheet/goonchat +// name = "chat" + +// /datum/asset/spritesheet/goonchat/register() +// InsertAll("emoji", 'icons/emoji.dmi') + +// // pre-loading all lanugage icons also helps to avoid meta +// InsertAll("language", 'icons/misc/language.dmi') +// // catch languages which are pulling icons from another file +// for(var/path in typesof(/datum/language)) +// var/datum/language/L = path +// var/icon = initial(L.icon) +// if (icon != 'icons/misc/language.dmi') +// var/icon_state = initial(L.icon_state) +// Insert("language-[icon_state]", icon, icon_state=icon_state) + +// ..() + +// /datum/asset/simple/permissions +// assets = list( +// "padlock.png" = 'html/padlock.png' +// ) + +// /datum/asset/simple/notes +// assets = list( +// "high_button.png" = 'html/high_button.png', +// "medium_button.png" = 'html/medium_button.png', +// "minor_button.png" = 'html/minor_button.png', +// "none_button.png" = 'html/none_button.png', +// ) + +// /datum/asset/simple/arcade +// assets = list( +// "boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif', +// "boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif', +// "boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif', +// "boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif', +// "boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif', +// "boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif', +// ) + +// /datum/asset/spritesheet/simple/achievements +// name ="achievements" +// assets = list( +// "default" = 'icons/UI_Icons/Achievements/default.png', +// "basemisc" = 'icons/UI_Icons/Achievements/basemisc.png', +// "baseboss" = 'icons/UI_Icons/Achievements/baseboss.png', +// "baseskill" = 'icons/UI_Icons/Achievements/baseskill.png', +// "bbgum" = 'icons/UI_Icons/Achievements/Boss/bbgum.png', +// "colossus" = 'icons/UI_Icons/Achievements/Boss/colossus.png', +// "hierophant" = 'icons/UI_Icons/Achievements/Boss/hierophant.png', +// "legion" = 'icons/UI_Icons/Achievements/Boss/legion.png', +// "miner" = 'icons/UI_Icons/Achievements/Boss/miner.png', +// "swarmer" = 'icons/UI_Icons/Achievements/Boss/swarmer.png', +// "tendril" = 'icons/UI_Icons/Achievements/Boss/tendril.png', +// "featofstrength" = 'icons/UI_Icons/Achievements/Misc/featofstrength.png', +// "helbital" = 'icons/UI_Icons/Achievements/Misc/helbital.png', +// "jackpot" = 'icons/UI_Icons/Achievements/Misc/jackpot.png', +// "meteors" = 'icons/UI_Icons/Achievements/Misc/meteors.png', +// "timewaste" = 'icons/UI_Icons/Achievements/Misc/timewaste.png', +// "upgrade" = 'icons/UI_Icons/Achievements/Misc/upgrade.png', +// "clownking" = 'icons/UI_Icons/Achievements/Misc/clownking.png', +// "clownthanks" = 'icons/UI_Icons/Achievements/Misc/clownthanks.png', +// "rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png', +// "snail" = 'icons/UI_Icons/Achievements/Misc/snail.png', +// "mining" = 'icons/UI_Icons/Achievements/Skills/mining.png', +// ) + +// /datum/asset/spritesheet/simple/pills +// name ="pills" +// assets = list( +// "pill1" = 'icons/UI_Icons/Pills/pill1.png', +// "pill2" = 'icons/UI_Icons/Pills/pill2.png', +// "pill3" = 'icons/UI_Icons/Pills/pill3.png', +// "pill4" = 'icons/UI_Icons/Pills/pill4.png', +// "pill5" = 'icons/UI_Icons/Pills/pill5.png', +// "pill6" = 'icons/UI_Icons/Pills/pill6.png', +// "pill7" = 'icons/UI_Icons/Pills/pill7.png', +// "pill8" = 'icons/UI_Icons/Pills/pill8.png', +// "pill9" = 'icons/UI_Icons/Pills/pill9.png', +// "pill10" = 'icons/UI_Icons/Pills/pill10.png', +// "pill11" = 'icons/UI_Icons/Pills/pill11.png', +// "pill12" = 'icons/UI_Icons/Pills/pill12.png', +// "pill13" = 'icons/UI_Icons/Pills/pill13.png', +// "pill14" = 'icons/UI_Icons/Pills/pill14.png', +// "pill15" = 'icons/UI_Icons/Pills/pill15.png', +// "pill16" = 'icons/UI_Icons/Pills/pill16.png', +// "pill17" = 'icons/UI_Icons/Pills/pill17.png', +// "pill18" = 'icons/UI_Icons/Pills/pill18.png', +// "pill19" = 'icons/UI_Icons/Pills/pill19.png', +// "pill20" = 'icons/UI_Icons/Pills/pill20.png', +// "pill21" = 'icons/UI_Icons/Pills/pill21.png', +// "pill22" = 'icons/UI_Icons/Pills/pill22.png', +// ) + +// //this exists purely to avoid meta by pre-loading all language icons. +// /datum/asset/language/register() +// for(var/path in typesof(/datum/language)) +// set waitfor = FALSE +// var/datum/language/L = new path () +// L.get_icon() + +/datum/asset/spritesheet/pipes + name = "pipes" + +/datum/asset/spritesheet/pipes/register() + for(var/each in list('icons/obj/pipe-item.dmi', 'icons/obj/pipes/disposal.dmi')) + InsertAll("", each, global.alldirs) + ..() + +// // Representative icons for each research design +// /datum/asset/spritesheet/research_designs +// name = "design" + +// /datum/asset/spritesheet/research_designs/register() +// for (var/path in subtypesof(/datum/design)) +// var/datum/design/D = path + +// var/icon_file +// var/icon_state +// var/icon/I + +// if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest +// icon_file = initial(D.research_icon) +// icon_state = initial(D.research_icon_state) +// if(!(icon_state in icon_states(icon_file))) +// warning("design [D] with icon '[icon_file]' missing state '[icon_state]'") +// continue +// I = icon(icon_file, icon_state, SOUTH) + +// else +// // construct the icon and slap it into the resource cache +// var/atom/item = initial(D.build_path) +// if (!ispath(item, /atom)) +// // biogenerator outputs to beakers by default +// if (initial(D.build_type) & BIOGENERATOR) +// item = /obj/item/reagent_containers/glass/beaker/large +// else +// continue // shouldn't happen, but just in case + +// // circuit boards become their resulting machines or computers +// if (ispath(item, /obj/item/circuitboard)) +// var/obj/item/circuitboard/C = item +// var/machine = initial(C.build_path) +// if (machine) +// item = machine + +// icon_file = initial(item.icon) +// icon_state = initial(item.icon_state) + +// if(!(icon_state in icon_states(icon_file))) +// warning("design [D] with icon '[icon_file]' missing state '[icon_state]'") +// continue +// I = icon(icon_file, icon_state, SOUTH) + +// // computers (and snowflakes) get their screen and keyboard sprites +// if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control)) +// var/obj/machinery/computer/C = item +// var/screen = initial(C.icon_screen) +// var/keyboard = initial(C.icon_keyboard) +// var/all_states = icon_states(icon_file) +// if (screen && (screen in all_states)) +// I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY) +// if (keyboard && (keyboard in all_states)) +// I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY) + +// Insert(initial(D.id), I) +// return ..() + +// /datum/asset/spritesheet/vending +// name = "vending" + +// /datum/asset/spritesheet/vending/register() +// for (var/k in GLOB.vending_products) +// var/atom/item = k +// if (!ispath(item, /atom)) +// continue + +// var/icon_file = initial(item.icon) +// var/icon_state = initial(item.icon_state) +// var/icon/I + +// var/icon_states_list = icon_states(icon_file) +// if(icon_state in icon_states_list) +// I = icon(icon_file, icon_state, SOUTH) +// var/c = initial(item.color) +// if (!isnull(c) && c != "#FFFFFF") +// I.Blend(c, ICON_MULTIPLY) +// else +// var/icon_states_string +// for (var/an_icon_state in icon_states_list) +// if (!icon_states_string) +// icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])" +// else +// icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])" +// stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]") +// I = icon('icons/turf/floors.dmi', "", SOUTH) + +// var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-") + +// Insert(imgid, I) +// return ..() + +// /datum/asset/simple/genetics +// assets = list( +// "dna_discovered.gif" = 'html/dna_discovered.gif', +// "dna_undiscovered.gif" = 'html/dna_undiscovered.gif', +// "dna_extra.gif" = 'html/dna_extra.gif' +// ) + +// /datum/asset/simple/orbit +// assets = list( +// "ghost.png" = 'html/ghost.png' +// ) + +// /datum/asset/simple/vv +// assets = list( +// "view_variables.css" = 'html/admin/view_variables.css' +// ) + +// /datum/asset/spritesheet/sheetmaterials +// name = "sheetmaterials" + +// /datum/asset/spritesheet/sheetmaterials/register() +// InsertAll("", 'icons/obj/stack_objects.dmi') + +// // Special case to handle Bluespace Crystals +// Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal") +// ..() + +/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) diff --git a/code/modules/asset_cache/validate_assets.html b/code/modules/asset_cache/validate_assets.html new file mode 100644 index 00000000000..b27a266c00d --- /dev/null +++ b/code/modules/asset_cache/validate_assets.html @@ -0,0 +1,29 @@ + + + + + + + + + + \ No newline at end of file diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm deleted file mode 100644 index 2317cab19ee..00000000000 --- a/code/modules/client/asset_cache.dm +++ /dev/null @@ -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({" - - "}, "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({" - - "}, "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 "" - -// get HTML tag for showing an icon -/datum/asset/iconsheet/proc/icon_tag(icon_state, dir = SOUTH) - return "" - -//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 diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index b6b8d1b14d3..e11ff9e4f7a 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -59,3 +59,18 @@ preload_rsc = PRELOAD_RSC var/global/obj/screen/click_catcher/void + + // 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 diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 36f11e736f0..dd84f559820 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -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," || [hsrc ? "[hsrc] " : ""][href]") + //byond bug ID:2256651 + if (asset_cache_job && (asset_cache_job in completed_asset_jobs)) + to_chat(src, "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)") + 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, "

Custom Event

") to_chat(src, "

A custom event is taking place. OOC Info:

") @@ -408,8 +427,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 diff --git a/code/modules/client/preference_setup/global/01_ui.dm b/code/modules/client/preference_setup/global/01_ui.dm index a40155d2d54..4bb05121e14 100644 --- a/code/modules/client/preference_setup/global/01_ui.dm +++ b/code/modules/client/preference_setup/global/01_ui.dm @@ -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) . = "UI Style: [pref.UI_style]
" . += "Custom UI (recommended for White UI):
" - . += "-Color: [pref.UI_style_color] [color_square(hex = pref.UI_style_color)] reset
" - . += "-Alpha(transparency): [pref.UI_style_alpha] reset
" + . += "-Color: [pref.UI_style_color]�[color_square(hex = pref.UI_style_color)]�reset
" + . += "-Alpha(transparency): [pref.UI_style_alpha]�reset
" . += "Tooltip Style: [pref.tooltipstyle]
" . += "Client FPS: [pref.client_fps]
" + . += "tgui Window Mode: [(pref.tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"]
" + . += "tgui Window Placement: [(pref.tgui_lock) ? "Primary Monitor" : "Free (default)"]
" if(can_select_ooc_color(user)) - . += "OOC Color: " + . += "OOC Color:�" if(pref.ooccolor == initial(pref.ooccolor)) . += "Using Default
" else - . += "[pref.ooccolor] [color_square(hex = pref.ooccolor)] reset
" + . += "[pref.ooccolor] [color_square(hex = pref.ooccolor)]�reset
" /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") diff --git a/code/modules/client/preference_setup/loadout/loadout_mask.dm b/code/modules/client/preference_setup/loadout/loadout_mask.dm index 5ae0b96e2b3..716cdb42680 100644 --- a/code/modules/client/preference_setup/loadout/loadout_mask.dm +++ b/code/modules/client/preference_setup/loadout/loadout_mask.dm @@ -20,4 +20,8 @@ /datum/gear/mask/sterile display_name = "sterile mask" path = /obj/item/clothing/mask/surgical - cost = 2 \ No newline at end of file + cost = 2 + +/datum/gear/mask/veil + display_name = "black veil" + path = /obj/item/clothing/mask/veil \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm index 65039cccb0a..2e480190cc3 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm @@ -556,4 +556,28 @@ /datum/gear/uniform/haltertop display_name = "halter top" - path = /obj/item/clothing/under/haltertop \ No newline at end of file + 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 \ No newline at end of file diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 1c1e1fc44bb..9032771739f 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -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 diff --git a/code/modules/clothing/glasses/hud_vr.dm b/code/modules/clothing/glasses/hud_vr.dm index db22d70e97a..ce49c889495 100644 --- a/code/modules/clothing/glasses/hud_vr.dm +++ b/code/modules/clothing/glasses/hud_vr.dm @@ -8,6 +8,8 @@ icon_state = "glasses" var/datum/nano_module/arscreen var/arscreen_path + var/datum/tgui_module/tgarscreen + var/tgarscreen_path var/flash_prot = 0 //0 for none, 1 for flash weapon protection, 2 for welder protection enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_AUGMENTED) plane_slots = list(slot_glasses) @@ -16,21 +18,33 @@ ..() if(arscreen_path) arscreen = new arscreen_path(src) + if(tgarscreen_path) + tgarscreen = new tgarscreen_path(src) /obj/item/clothing/glasses/omnihud/Destroy() QDEL_NULL(arscreen) + QDEL_NULL(tgarscreen) . = ..() /obj/item/clothing/glasses/omnihud/dropped() if(arscreen) SSnanoui.close_uis(src) + if(tgarscreen) + SStgui.close_uis(src) ..() /obj/item/clothing/glasses/omnihud/emp_act(var/severity) + if(arscreen) + SSnanoui.close_uis(src) + if(tgarscreen) + SStgui.close_uis(src) var/disconnect_ar = arscreen + var/disconnect_tgar = tgarscreen arscreen = null + tgarscreen = null spawn(20 SECONDS) arscreen = disconnect_ar + tgarscreen = disconnect_tgar ..() /obj/item/clothing/glasses/omnihud/proc/flashed() @@ -71,12 +85,12 @@ These have been upgraded with medical records access and virus database integration." mode = "med" action_button_name = "AR Console (Crew Monitor)" - arscreen_path = /datum/nano_module/program/crew_monitor + tgarscreen_path = /datum/tgui_module/crew_monitor/glasses enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_STATUS_R,VIS_CH_BACKUP,VIS_AUGMENTED) ar_interact(var/mob/living/carbon/human/user) - if(arscreen) - arscreen.ui_interact(user,"main",null,1,glasses_state) + if(tgarscreen) + tgarscreen.tgui_interact(user) return 1 /obj/item/clothing/glasses/omnihud/sec diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index eab03a3c2e9..d972cf82cc8 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -288,3 +288,10 @@ desc = "A fine black bandana with nanotech lining and a skull emblem. Can be worn on the head or face." icon_state = "bandskull" item_state_slots = list(slot_r_hand_str = "bandskull", slot_l_hand_str = "bandskull") + +/obj/item/clothing/mask/veil + name = "black veil" + desc = "A black veil, typically worn at funerals or by goths." + w_class = ITEMSIZE_TINY + body_parts_covered = FACE + icon_state = "veil" \ No newline at end of file diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 800ba8e3ecd..1fcddc2b771 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -535,6 +535,37 @@ desc = "A red and white dress themed after some winter holidays. Tastefully festive!" icon_state = "festivedress" +/obj/item/clothing/under/dress/revealingdress + name = "revealing dress" + desc = "A very revealing black and blue dress. Is this work appropriate?" + icon_state = "revealingdress" + index = 1 + +/obj/item/clothing/under/dress/gothic + name = "gothic dress" + desc = "A black dress with a sheer mesh over it, tastefully old school goth." + icon_state = "gothic" + index = 1 + +/obj/item/clothing/under/dress/formalred + name = "formal red dress" + desc = "A very formal red dress, for those fancy galas." + icon_state = "formalred" + flags_inv = HIDESHOES + index = 1 + +/obj/item/clothing/under/dress/pentagram + name = "pentagram dress" + desc = "A black dress with straps over the chest in the shape of a pentagram." + icon_state = "pentagram" + index = 1 + +obj/item/clothing/under/dress/yellowswoop + name = "yellow swooped dress" + desc = "A yellow dress that swoops to the side." + icon_state = "yellowswoop" + index = 1 + /* * wedding stuff */ @@ -767,6 +798,12 @@ Uniforms and such desc = "Jean shorts and a black halter top. Perfect for casual Fridays!" icon_state = "haltertop" +/obj/item/clothing/under/rippedpunk + name = "ripped punk jeans" + desc = "Black ripped jeans and a fishnet top. How punk." + icon_state = "rippedpunk" + index = 1 + /* * swimsuit */ diff --git a/code/modules/gamemaster/event2/events/everyone/electrical_fault.dm b/code/modules/gamemaster/event2/events/everyone/electrical_fault.dm index 0645d2cfe38..0611e1b290e 100644 --- a/code/modules/gamemaster/event2/events/everyone/electrical_fault.dm +++ b/code/modules/gamemaster/event2/events/everyone/electrical_fault.dm @@ -77,7 +77,7 @@ // This will actually protect it from further damage. if(prob(25)) A.energy_fail(rand(60, 120)) - log_debug("ELECTRICAL EVENT: Disabled \the [A]'s power for a temporary amount of time.") +// log_debug("ELECTRICAL EVENT: Disabled \the [A]'s power for a temporary amount of time.") playsound(A, 'sound/machines/defib_success.ogg', 50, 1) apcs_disabled++ return @@ -85,7 +85,7 @@ // Decent chance to overload lighting circuit. if(prob(30)) A.overload_lighting() - log_debug("ELECTRICAL EVENT: Overloaded \the [A]'s lighting.") +// log_debug("ELECTRICAL EVENT: Overloaded \the [A]'s lighting.") playsound(A, 'sound/effects/lightningshock.ogg', 50, 1) apcs_overloaded++ @@ -93,7 +93,7 @@ if(prob(5)) A.emagged = TRUE A.update_icon() - log_debug("ELECTRICAL EVENT: Emagged \the [A].") +// log_debug("ELECTRICAL EVENT: Emagged \the [A].") playsound(A, 'sound/machines/chime.ogg', 50, 1) apcs_emagged++ diff --git a/code/modules/metric/activity.dm b/code/modules/metric/activity.dm index 5bdc33f47ac..c33c88adcaf 100644 --- a/code/modules/metric/activity.dm +++ b/code/modules/metric/activity.dm @@ -40,13 +40,13 @@ var/list/activity = list() for(var/department in departments) activity[department] = assess_department(department) - log_debug("Assessing department [department]. They have activity of [activity[department]].") +// log_debug("Assessing department [department]. They have activity of [activity[department]].") var/list/most_active_departments = list() // List of winners. var/highest_activity = null // Department who is leading in activity, if one exists. var/highest_number = 0 // Activity score needed to beat to be the most active department. for(var/i = 1, i <= cutoff_number, i++) - log_debug("Doing [i]\th round of counting.") +// log_debug("Doing [i]\th round of counting.") for(var/department in activity) if(department in department_blacklist) // Blacklisted? continue @@ -57,7 +57,7 @@ if(highest_activity) // Someone's a winner. most_active_departments.Add(highest_activity) // Add to the list of most active. activity.Remove(highest_activity) // Remove them from the other list so they don't win more than once. - log_debug("[highest_activity] has won the [i]\th round of activity counting.") +// log_debug("[highest_activity] has won the [i]\th round of activity counting.") highest_activity = null // Now reset for the next round. highest_number = 0 //todo: finish diff --git a/code/modules/mob/freelook/ai/update_triggers.dm b/code/modules/mob/freelook/ai/update_triggers.dm index c0b4adf0f61..9fd28344df2 100644 --- a/code/modules/mob/freelook/ai/update_triggers.dm +++ b/code/modules/mob/freelook/ai/update_triggers.dm @@ -37,7 +37,6 @@ /obj/machinery/camera/deactivate(user as mob, var/choice = 1) ..(user, choice) - invalidateCameraCache() if(src.can_use()) cameranet.addCamera(src) else diff --git a/code/modules/mob/language/station_vr.dm b/code/modules/mob/language/station_vr.dm index 1e2dac1a8b5..3d8028ca30d 100644 --- a/code/modules/mob/language/station_vr.dm +++ b/code/modules/mob/language/station_vr.dm @@ -110,6 +110,21 @@ "ver", "stv", "pro", "ski" ) +/datum/language/drudakar + name = LANGUAGE_DRUDAKAR + desc = "The native language of the D'Rudak'Ar, a loosely tied together community of dragons and demi-dragons based in the Diul system. Features include many hard consonants and rolling 'r's." + speech_verb = "gaos" + ask_verb = "gaos" + exclaim_verb = "GAOS" + whisper_verb = "gaos" + colour = "drudakar" + key = "K" + syllables = list( + "gok", "rha", "rou", "gao", "do", "ra", "bo", "lah", "draz", "khi", "zah", "lah", "ora", "ille", + "ghlas", "ghlai", "tyur", "vah", "bao", "raag", "drag", "zhi", "dahl", "tiyr", "vahl", "nyem", + "roar", "hyaa", "ma", "ha", "ya", "shi", "yo", "go" + ) + /datum/language/unathi flags = 0 /datum/language/tajaran diff --git a/code/modules/mob/living/bot/medbot.dm b/code/modules/mob/living/bot/medbot.dm index a67440e0138..d0c63faa56e 100644 --- a/code/modules/mob/living/bot/medbot.dm +++ b/code/modules/mob/living/bot/medbot.dm @@ -1,3 +1,13 @@ +// Medbot Info + +#define MEDBOT_PANIC_NONE 0 +#define MEDBOT_PANIC_LOW 15 +#define MEDBOT_PANIC_MED 35 +#define MEDBOT_PANIC_HIGH 55 +#define MEDBOT_PANIC_FUCK 70 +#define MEDBOT_PANIC_ENDING 90 +#define MEDBOT_PANIC_END 100 + /mob/living/bot/medbot name = "Medibot" desc = "A little medical robot. He looks somewhat underwhelmed." @@ -23,6 +33,15 @@ var/treatment_virus = "spaceacillin" var/treatment_emag = "toxin" var/declare_treatment = 0 //When attempting to treat a patient, should it notify everyone wearing medhuds? + + // Are we tipped over? + var/is_tipped = FALSE + //How panicked we are about being tipped over (why would you do this?) + var/tipped_status = MEDBOT_PANIC_NONE + //The name we got when we were tipped + var/tipper_name + //The last time we were tipped/righted and said a voice line, to avoid spam + var/last_tipping_action_voice = 0 /mob/living/bot/medbot/mysterious name = "\improper Mysterious Medibot" @@ -34,6 +53,9 @@ treatment_tox = "anti_toxin" /mob/living/bot/medbot/handleIdle() + if(is_tipped) // Don't handle idle things if we're incapacitated! + return + if(vocal && prob(1)) var/message_options = list( "Radar, put a mask on!" = 'sound/voice/medbot/mradar.ogg', @@ -47,6 +69,9 @@ playsound(src, message_options[message], 50, 0) /mob/living/bot/medbot/handleAdjacentTarget() + if(is_tipped) // Don't handle targets if we're incapacitated! + return + UnarmedAttack(target) /mob/living/bot/medbot/handlePanic() // Speed modification based on alert level. @@ -76,6 +101,9 @@ return . /mob/living/bot/medbot/lookForTargets() + if(is_tipped) // Don't look for targets if we're incapacitated! + return + for(var/mob/living/carbon/human/H in view(7, src)) // Time to find a patient! if(confirmTarget(H)) target = H @@ -162,7 +190,28 @@ else icon_state = "medibot[on]" -/mob/living/bot/medbot/attack_hand(var/mob/user) +/mob/living/bot/medbot/attack_hand(mob/living/carbon/human/H) + if(H.a_intent == I_DISARM && !is_tipped) + H.visible_message("[H] begins tipping over [src].", "You begin tipping over [src]...") + + if(world.time > last_tipping_action_voice + 15 SECONDS) + last_tipping_action_voice = world.time // message for tipping happens when we start interacting, message for righting comes after finishing + var/list/messagevoice = list("Hey, wait..." = 'sound/voice/medbot/hey_wait.ogg',"Please don't..." = 'sound/voice/medbot/please_dont.ogg',"I trusted you..." = 'sound/voice/medbot/i_trusted_you.ogg', "Nooo..." = 'sound/voice/medbot/nooo.ogg', "Oh fuck-" = 'sound/voice/medbot/oh_fuck.ogg') + var/message = pick(messagevoice) + say(message) + playsound(src, messagevoice[message], 70, FALSE) + + if(do_after(H, 3 SECONDS, target=src)) + tip_over(H) + + else if(H.a_intent == I_HELP && is_tipped) + H.visible_message("[H] begins righting [src].", "You begin righting [src]...") + if(do_after(H, 3 SECONDS, target=src)) + set_right(H) + else + interact() + +/mob/living/bot/medbot/proc/interact(mob/user) var/dat dat += "Automatic Medical Unit v1.0

" dat += "Status: [on ? "On" : "Off"]
" @@ -300,6 +349,89 @@ s.start() qdel(src) return + +/mob/living/bot/medbot/handleRegular() + . = ..() + + if(is_tipped) + handle_panic() + return + +/mob/living/bot/medbot/proc/tip_over(mob/user) + playsound(src, 'sound/machines/warning-buzzer.ogg', 50) + user.visible_message("[user] tips over [src]!", "You tip [src] over!") + is_tipped = TRUE + tipper_name = user.name + var/matrix/mat = transform + transform = mat.Turn(180) + +/mob/living/bot/medbot/proc/set_right(mob/user) + var/list/messagevoice + if(user) + user.visible_message("[user] sets [src] right-side up!", "You set [src] right-side up!") + if(user.name == tipper_name) + messagevoice = list("I forgive you." = 'sound/voice/medbot/forgive.ogg') + else + messagevoice = list("Thank you!" = 'sound/voice/medbot/thank_you.ogg', "You are a good person." = 'sound/voice/medbot/youre_good.ogg') + else + visible_message("[src] manages to [pick("writhe", "wriggle", "wiggle")] enough to right itself.") + messagevoice = list("Fuck you." = 'sound/voice/medbot/fuck_you.ogg', "Your behavior has been reported, have a nice day." = 'sound/voice/medbot/reported.ogg') + + tipper_name = null + if(world.time > last_tipping_action_voice + 15 SECONDS) + last_tipping_action_voice = world.time + var/message = pick(messagevoice) + say(message) + playsound(src, messagevoice[message], 70) + tipped_status = MEDBOT_PANIC_NONE + is_tipped = FALSE + transform = matrix() + +// if someone tipped us over, check whether we should ask for help or just right ourselves eventually +/mob/living/bot/medbot/proc/handle_panic() + tipped_status++ + var/list/messagevoice + switch(tipped_status) + if(MEDBOT_PANIC_LOW) + messagevoice = list("I require assistance." = 'sound/voice/medbot/i_require_asst.ogg') + if(MEDBOT_PANIC_MED) + messagevoice = list("Please put me back." = 'sound/voice/medbot/please_put_me_back.ogg') + if(MEDBOT_PANIC_HIGH) + messagevoice = list("Please, I am scared!" = 'sound/voice/medbot/please_im_scared.ogg') + if(MEDBOT_PANIC_FUCK) + messagevoice = list("I don't like this, I need help!" = 'sound/voice/medbot/dont_like.ogg', "This hurts, my pain is real!" = 'sound/voice/medbot/pain_is_real.ogg') + if(MEDBOT_PANIC_ENDING) + messagevoice = list("Is this the end?" = 'sound/voice/medbot/is_this_the_end.ogg', "Nooo!" = 'sound/voice/medbot/nooo.ogg') + if(MEDBOT_PANIC_END) + global_announcer.autosay("PSYCH ALERT: Crewmember [tipper_name] recorded displaying antisocial tendencies torturing bots in [get_area(src)]. Please schedule psych evaluation.", "[src]", "Medical") + set_right() // strong independent medbot + + // if(prob(tipped_status)) // Commented out pending introduction of jitter stuff from /tg/ + // do_jitter_animation(tipped_status * 0.1) + + if(messagevoice) + var/message = pick(messagevoice) + say(message) + playsound(src, messagevoice[message], 70) + else if(prob(tipped_status * 0.2)) + playsound(src, 'sound/machines/warning-buzzer.ogg', 30, extrarange=-2) + +/mob/living/bot/medbot/examine(mob/user) + . = ..() + if(tipped_status == MEDBOT_PANIC_NONE) + return + + switch(tipped_status) + if(MEDBOT_PANIC_NONE to MEDBOT_PANIC_LOW) + . += "It appears to be tipped over, and is quietly waiting for someone to set it right." + if(MEDBOT_PANIC_LOW to MEDBOT_PANIC_MED) + . += "It is tipped over and requesting help." + if(MEDBOT_PANIC_MED to MEDBOT_PANIC_HIGH) + . += "They are tipped over and appear visibly distressed." // now we humanize the medbot as a they, not an it + if(MEDBOT_PANIC_HIGH to MEDBOT_PANIC_FUCK) + . += "They are tipped over and visibly panicking!" + if(MEDBOT_PANIC_FUCK to INFINITY) + . += "They are freaking out from being tipped over!" /mob/living/bot/medbot/confirmTarget(var/mob/living/carbon/human/H) if(!..()) @@ -430,3 +562,12 @@ S.name = created_name user.drop_from_inventory(src) qdel(src) + +// Undefine these. +#undef MEDBOT_PANIC_NONE +#undef MEDBOT_PANIC_LOW +#undef MEDBOT_PANIC_MED +#undef MEDBOT_PANIC_HIGH +#undef MEDBOT_PANIC_FUCK +#undef MEDBOT_PANIC_ENDING +#undef MEDBOT_PANIC_END diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 57206c05e2b..eae3c47335b 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -48,6 +48,21 @@ update_hair() return 1 + +/mob/living/carbon/human/proc/change_hair_gradient(var/hair_gradient) + if(!hair_gradient) + return + + if(grad_style == hair_gradient) + return + + if(!(hair_gradient in GLOB.hair_gradients)) + return + + grad_style = hair_gradient + + update_hair() + return 1 /mob/living/carbon/human/proc/change_facial_hair(var/facial_hair_style) if(!facial_hair_style) @@ -104,6 +119,17 @@ update_hair() return 1 + +/mob/living/carbon/human/proc/change_grad_color(var/red, var/green, var/blue) + if(red == r_grad && green == g_grad && blue == b_grad) + return + + r_grad = red + g_grad = green + b_grad = blue + + update_hair() + return 1 /mob/living/carbon/human/proc/change_facial_hair_color(var/red, var/green, var/blue) if(red == r_facial && green == g_facial && blue == b_facial) diff --git a/code/modules/mob/living/carbon/human/emote_vr.dm b/code/modules/mob/living/carbon/human/emote_vr.dm index 7df6e169fa8..6e2fec9233f 100644 --- a/code/modules/mob/living/carbon/human/emote_vr.dm +++ b/code/modules/mob/living/carbon/human/emote_vr.dm @@ -146,6 +146,10 @@ message = "rumbles their throat, puffs their cheeks and croaks." m_type = 2 playsound(src, 'sound/voice/Croak.ogg', 50, 0, preference = /datum/client_preference/emote_noises) + if("gao") + message = "lets out a gao." + m_type = 2 + playsound(src, 'sound/voice/gao.ogg', 50, 0, preference = /datum/client_preference/emote_noises) if("nsay") nsay() return TRUE diff --git a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm index 6629a96a9f1..bc39e163106 100644 --- a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm +++ b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm @@ -88,6 +88,7 @@ var/list/wrapped_species_by_ref = list() var/list/valid_hairstyles = list() var/list/valid_facialhairstyles = list() + var/list/valid_gradstyles = GLOB.hair_gradients for(var/hairstyle in hair_styles_list) var/datum/sprite_accessory/S = hair_styles_list[hairstyle] if(gender == MALE && S.gender == FEMALE) @@ -112,6 +113,9 @@ var/list/wrapped_species_by_ref = list() if(valid_hairstyles.len) var/new_hair = input("Select a hairstyle.", "Shapeshifter Hair") as null|anything in valid_hairstyles change_hair(new_hair ? new_hair : "Bald") + if(valid_gradstyles.len) + var/new_hair = input("Select a hair gradient style.", "Shapeshifter Hair") as null|anything in valid_gradstyles + change_hair_gradient(new_hair ? new_hair : "None") if(valid_facialhairstyles.len) var/new_hair = input("Select a facial hair style.", "Shapeshifter Hair") as null|anything in valid_facialhairstyles change_facial_hair(new_hair ? new_hair : "Shaved") @@ -216,6 +220,10 @@ var/list/wrapped_species_by_ref = list() if(!new_hair) return shapeshifter_set_hair_color(new_hair) + var/new_grad = input("Please select a new hair gradient color.", "Hair Gradient Colour") as color + if(!new_grad) + return + shapeshifter_set_grad_color(new_grad) var/new_fhair = input("Please select a new facial hair color.", "Facial Hair Color") as color if(!new_fhair) return @@ -225,6 +233,10 @@ var/list/wrapped_species_by_ref = list() change_hair_color(hex2num(copytext(new_hair, 2, 4)), hex2num(copytext(new_hair, 4, 6)), hex2num(copytext(new_hair, 6, 8))) +/mob/living/carbon/human/proc/shapeshifter_set_grad_color(var/new_grad) + + change_grad_color(hex2num(copytext(new_grad, 2, 4)), hex2num(copytext(new_grad, 4, 6)), hex2num(copytext(new_grad, 6, 8))) + /mob/living/carbon/human/proc/shapeshifter_set_facial_color(var/new_fhair) change_facial_hair_color(hex2num(copytext(new_fhair, 2, 4)), hex2num(copytext(new_fhair, 4, 6)), hex2num(copytext(new_fhair, 6, 8))) diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm index 402c1928ddd..8b6cfd0b602 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm @@ -133,3 +133,4 @@ /datum/trait/colorblind/para_taj/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) H.add_modifier(/datum/modifier/trait/colorblind_taj) + \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm index 1cc453a7687..e3403fc754b 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm @@ -19,19 +19,19 @@ var_changes = list("metabolic_rate" = 1.4, "hunger_factor" = 0.4, "metabolism" = 0.012) // +40% rate and 8x hunger (Double Teshari) excludes = list(/datum/trait/metabolism_up, /datum/trait/metabolism_down) -/datum/trait/cold_discomfort - name = "Hot-Blooded" - desc = "You are too hot at the standard 20C. 18C is more suitable. Rolling down your jumpsuit or being unclothed helps." +/datum/trait/coldadapt + name = "Cold-Adapted" + desc = "You are able to withstand much colder temperatures than other species, and can even be comfortable in extremely cold environments. You are also more vulnerable to hot environments as a consequence of these adaptations." cost = 0 - var_changes = list("heat_discomfort_level" = T0C+19) - excludes = list(/datum/trait/hot_discomfort) - -/datum/trait/hot_discomfort - name = "Cold-Blooded" - desc = "You are too cold at the standard 20C. 22C is more suitable. Wearing clothing that covers your legs and torso helps." + var_changes = list("cold_level_1" = 200, "cold_level_2" = 150, "cold_level_3" = 90, "breath_cold_level_1" = 180, "breath_cold_level_2" = 100, "breath_cold_level_3" = 60, "cold_discomfort_level" = 210, "heat_level_1" = 305, "heat_level_2" = 360, "heat_level_3" = 700, "breath_heat_level_1" = 345, "breath_heat_level_2" = 380, "breath_heat_level_3" = 780, "heat_discomfort_level" = 295) + excludes = list(/datum/trait/hotadapt) + +/datum/trait/hotadapt + name = "Heat-Adapted" + desc = "You are able to withstand much hotter temperatures than other species, and can even be comfortable in extremely hot environments. You are also more vulnerable to cold environments as a consequence of these adaptations." cost = 0 - var_changes = list("cold_discomfort_level" = T0C+21) - excludes = list(/datum/trait/cold_discomfort) + var_changes = list("heat_level_1" = 420, "heat_level_2" = 460, "heat_level_3" = 1100, "breath_heat_level_1" = 440, "breath_heat_level_2" = 510, "breath_heat_level_3" = 1500, "heat_discomfort_level" = 390, "cold_level_1" = 280, "cold_level_2" = 220, "cold_level_3" = 140, "breath_cold_level_1" = 260, "breath_cold_level_2" = 240, "breath_cold_level_3" = 120, "cold_discomfort_level" = 280) + excludes = list(/datum/trait/coldadapt) /datum/trait/autohiss_unathi name = "Autohiss (Unathi)" diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm index 3a1e50dee67..148f151e591 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm @@ -123,4 +123,10 @@ name = "Traceur" desc = "You're capable of parkour and can *flip over low objects (most of the time)." cost = 2 - var_changes = list("agility" = 90) \ No newline at end of file + var_changes = list("agility" = 90) + +/datum/trait/snowwalker + name = "Snow Walker" + desc = "You are able to move unhindered on snow." + cost = 1 + var_changes = list("snow_movement" = -2) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/ai_vr.dm b/code/modules/mob/living/silicon/ai/ai_vr.dm index 2f22d0e7886..3234d7269e4 100644 --- a/code/modules/mob/living/silicon/ai/ai_vr.dm +++ b/code/modules/mob/living/silicon/ai/ai_vr.dm @@ -6,6 +6,7 @@ add_language(LANGUAGE_ECUREUILIAN, 1) add_language(LANGUAGE_DAEMON, 1) add_language(LANGUAGE_ENOCHIAN, 1) + add_language(LANGUAGE_DRUDAKAR, 1) /mob/AIize(var/move = TRUE) . = ..() @@ -14,4 +15,5 @@ add_language(LANGUAGE_CANILUNZT, 1) add_language(LANGUAGE_ECUREUILIAN, 1) add_language(LANGUAGE_DAEMON, 1) - add_language(LANGUAGE_ENOCHIAN, 1) \ No newline at end of file + add_language(LANGUAGE_ENOCHIAN, 1) + add_language(LANGUAGE_DRUDAKAR, 1) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm index 07b6db71b3e..ec691d0f414 100644 --- a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm @@ -673,7 +673,7 @@ name = "Digestive Analyzer" desc = "A mounted destructive analyzer unit with fuel processor." icon_state = "analyzer" - max_item_count = 1 + max_item_count = 10 startdrain = 100 analyzer = TRUE @@ -691,7 +691,7 @@ icon_state = "decompiler" max_item_count = 20 delivery = TRUE - + /obj/item/device/dogborg/sleeper/compactor/supply //Miner borg belly name = "Supply Satchel" desc = "A mounted survival unit with fuel processor." diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm b/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm index 524f54655c1..62fdea00616 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm @@ -12,7 +12,8 @@ LANGUAGE_CANILUNZT = 0, LANGUAGE_ECUREUILIAN= 0, LANGUAGE_DAEMON = 0, - LANGUAGE_ENOCHIAN = 0 + LANGUAGE_ENOCHIAN = 0, + LANGUAGE_DRUDAKAR = 0 ) var/vr_sprites = list() var/pto_type = null @@ -34,7 +35,8 @@ LANGUAGE_CANILUNZT = 1, LANGUAGE_ECUREUILIAN= 1, LANGUAGE_DAEMON = 1, - LANGUAGE_ENOCHIAN = 1 + LANGUAGE_ENOCHIAN = 1, + LANGUAGE_DRUDAKAR = 1 ) /hook/startup/proc/robot_modules_vr() diff --git a/code/modules/mob/living/silicon/subystems.dm b/code/modules/mob/living/silicon/subystems.dm index b03ab5eeb21..e5d50d58241 100644 --- a/code/modules/mob/living/silicon/subystems.dm +++ b/code/modules/mob/living/silicon/subystems.dm @@ -2,7 +2,7 @@ var/register_alarms = 1 var/datum/nano_module/alarm_monitor/all/alarm_monitor var/datum/nano_module/atmos_control/atmos_control - var/datum/nano_module/program/crew_monitor/crew_monitor + var/datum/tgui_module/crew_monitor/robot/crew_monitor var/datum/nano_module/law_manager/law_manager var/datum/nano_module/power_monitor/power_monitor var/datum/nano_module/rcon/rcon @@ -67,7 +67,7 @@ set category = "Subystems" set name = "Crew Monitor" - crew_monitor.ui_interact(usr, state = self_state) + crew_monitor.tgui_interact(usr) /**************** * Law Manager * diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm index 12b70f6048e..0918c1b8ae7 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm @@ -11,6 +11,8 @@ maxHealth = 5 health = 5 + movement_cooldown = 1.5 + mob_size = MOB_MINISCULE pass_flags = PASSTABLE // can_pull_size = ITEMSIZE_TINY @@ -101,15 +103,13 @@ /mob/living/simple_mob/animal/passive/mouse/rat name = "rat" + body_color = "rat" + icon_state = "mouse_rat" maxHealth = 20 health = 20 ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive -/mob/living/simple_mob/animal/passive/mouse/rat/Initialize() - ..() - adjust_scale(1.2) - //TOM IS ALIVE! SQUEEEEEEEE~K :) /mob/living/simple_mob/animal/passive/mouse/brown/Tom name = "Tom" diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm b/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm index 23c6c4b1d3d..16fa33596ab 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm @@ -5,6 +5,7 @@ icon_state = "panther" icon_living = "panther" + icon_rest = "panther-rest" icon_dead = "panther-dead" icon = 'icons/mob/vore64x64.dmi' vis_height = 64 diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index 49ab504956c..ffaeef3c09d 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -1,5 +1,6 @@ /mob/Logout() SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs + SStgui.on_logout(src) // Cleanup any TGUIs the user has open player_list -= src disconnect_time = world.realtime //VOREStation Addition: logging when we disappear. update_client_z(null) diff --git a/code/modules/modular_computers/computers/modular_computer/core.dm b/code/modules/modular_computers/computers/modular_computer/core.dm index db15e841cad..97b4cfe8518 100644 --- a/code/modules/modular_computers/computers/modular_computer/core.dm +++ b/code/modules/modular_computers/computers/modular_computer/core.dm @@ -163,6 +163,7 @@ idle_threads.Add(active_program) active_program.program_state = PROGRAM_STATE_BACKGROUND // Should close any existing UIs SSnanoui.close_uis(active_program.NM ? active_program.NM : active_program) + SStgui.close_uis(active_program.TM ? active_program.TM : active_program) active_program = null update_icon() if(istype(user)) @@ -202,7 +203,6 @@ minimize_program(user) if(P.run_program(user)) - active_program = P update_icon() return 1 diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index ef7eece062f..7a63d49576a 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -5,8 +5,13 @@ var/required_access = null // List of required accesses to run/download the program. var/requires_access_to_run = 1 // Whether the program checks for required_access when run. var/requires_access_to_download = 1 // Whether the program checks for required_access when downloading. + // NanoModule var/datum/nano_module/NM = null // If the program uses NanoModule, put it here and it will be automagically opened. Otherwise implement ui_interact. var/nanomodule_path = null // Path to nanomodule, make sure to set this if implementing new program. + // TGUIModule + var/datum/tgui_module/TM = null // If the program uses TGUIModule, put it here and it will be automagically opened. Otherwise implement tgui_interact. + var/tguimodule_path = null // Path to tguimodule, make sure to set this if implementing new program. + // Etc Program stuff var/program_state = PROGRAM_STATE_KILLED// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running. var/obj/item/modular_computer/computer // Device that runs this program. var/filedesc = "Unknown Program" // User-friendly name of this program. @@ -125,9 +130,14 @@ // When implementing new program based device, use this to run the program. /datum/computer_file/program/proc/run_program(var/mob/living/user) if(can_run(user, 1) || !requires_access_to_run) + computer.active_program = src if(nanomodule_path) NM = new nanomodule_path(src, new /datum/topic_manager/program(src), src) NM.using_access = user.GetAccess() + if(tguimodule_path) + TM = new tguimodule_path(src) + TM.using_access = user.GetAccess() + TM.tgui_interact(user) if(requires_ntnet && network_destination) generate_network_log("Connection opened to [network_destination].") program_state = PROGRAM_STATE_ACTIVE @@ -139,9 +149,11 @@ program_state = PROGRAM_STATE_KILLED if(network_destination) generate_network_log("Connection to [network_destination] closed.") - if(NM) - qdel(NM) - NM = null + QDEL_NULL(NM) + if(TM) + SStgui.close_uis(TM) + qdel(TM) + TM = null return 1 // This is called every tick when the program is enabled. Ensure you do parent call if you override it. If parent returns 1 continue with UI initialisation. @@ -154,9 +166,11 @@ if(istype(NM)) NM.ui_interact(user, ui_key, null, force_open) return 0 + if(istype(TM)) + TM.tgui_interact(user) + return 0 return 1 - // CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC: // Topic calls are automagically forwarded from NanoModule this program contains. // Calls beginning with "PRG_" are reserved for programs handling. diff --git a/code/modules/modular_computers/file_system/programs/antagonist/hacked_camera.dm b/code/modules/modular_computers/file_system/programs/antagonist/hacked_camera.dm index 27e5a26c3fb..4c1b1537341 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/hacked_camera.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/hacked_camera.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/camera_monitor/hacked filename = "camcrypt" filedesc = "Camera Decryption Tool" - nanomodule_path = /datum/nano_module/camera_monitor/hacked + tguimodule_path = /datum/tgui_module/camera/ntos/hacked program_icon_state = "hostile" program_key_state = "security_key" program_menu_icon = "zoomin" @@ -15,25 +15,8 @@ if(program_state != PROGRAM_STATE_ACTIVE) // Background programs won't trigger alarms. return - var/datum/nano_module/camera_monitor/hacked/HNM = NM - // The program is active and connected to one of the station's networks. Has a very small chance to trigger IDS alarm every tick. - if(HNM && HNM.current_network && (HNM.current_network in using_map.station_networks) && prob(0.1)) + if(prob(0.1)) if(ntnet_global.intrusion_detection_enabled) - ntnet_global.add_log("IDS WARNING - Unauthorised access detected to camera network [HNM.current_network] by device with NID [computer.network_card.get_network_tag()]") + ntnet_global.add_log("IDS WARNING - Unauthorised access detected to camera network by device with NID [computer.network_card.get_network_tag()]") ntnet_global.intrusion_detection_alarm = 1 - - -/datum/nano_module/camera_monitor/hacked - name = "Hacked Camera Monitoring Program" - //available_to_ai = FALSE - -/datum/nano_module/camera_monitor/hacked/can_access_network(var/mob/user, var/network_access) - return 1 - -// The hacked variant has access to all commonly used networks. -/datum/nano_module/camera_monitor/hacked/modify_networks_list(var/list/networks) - networks.Add(list(list("tag" = NETWORK_MERCENARY, "has_access" = 1))) - networks.Add(list(list("tag" = NETWORK_ERT, "has_access" = 1))) - networks.Add(list(list("tag" = NETWORK_CRESCENT, "has_access" = 1))) - return networks \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/generic/camera.dm b/code/modules/modular_computers/file_system/programs/generic/camera.dm index 52c275d3bbf..57948d6e8a5 100644 --- a/code/modules/modular_computers/file_system/programs/generic/camera.dm +++ b/code/modules/modular_computers/file_system/programs/generic/camera.dm @@ -30,7 +30,7 @@ /datum/computer_file/program/camera_monitor filename = "cammon" filedesc = "Camera Monitoring" - nanomodule_path = /datum/nano_module/camera_monitor + tguimodule_path = /datum/tgui_module/camera/ntos program_icon_state = "cameras" program_key_state = "generic_key" program_menu_icon = "search" @@ -39,163 +39,11 @@ available_on_ntnet = 1 requires_ntnet = 1 -/datum/nano_module/camera_monitor - name = "Camera Monitoring program" - var/obj/machinery/camera/current_camera = null - var/current_network = null - -/datum/nano_module/camera_monitor/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, state = default_state) - var/list/data = host.initial_data() - - data["current_camera"] = current_camera ? current_camera.nano_structure() : null - data["current_network"] = current_network - - var/list/all_networks[0] - for(var/network in using_map.station_networks) - if(can_access_network(user, get_camera_access(network), 1)) - all_networks.Add(list(list( - "tag" = network, - "has_access" = 1 - ))) - for(var/network in using_map.secondary_networks) - if(can_access_network(user, get_camera_access(network), 0)) - all_networks.Add(list(list( - "tag" = network, - "has_access" = 1 - ))) - - all_networks = modify_networks_list(all_networks) - - data["networks"] = all_networks - - var/list/map_levels = using_map.get_map_levels(get_z(nano_host()), TRUE, om_range = DEFAULT_OVERMAP_RANGE) - - if(current_network) - data["cameras"] = camera_repository.cameras_in_network(current_network, map_levels) - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "mod_sec_camera.tmpl", "Camera Monitoring", 900, 800) - // ui.auto_update_layout = 1 // Disabled as with suit sensors monitor - breaks the UI map. Re-enable once it's fixed somehow. - - ui.add_template("mapContent", "sec_camera_map_content.tmpl") - ui.add_template("mapHeader", "mod_sec_camera_map_header.tmpl") - ui.set_initial_data(data) - ui.open() - -// Intended to be overriden by subtypes to manually add non-station networks to the list. -/datum/nano_module/camera_monitor/proc/modify_networks_list(var/list/networks) - return networks - -/datum/nano_module/camera_monitor/proc/can_access_network(var/mob/user, var/network_access, var/station_network = 0) - // No access passed, or 0 which is considered no access requirement. Allow it. - if(!network_access) - return 1 - - if(station_network) - return check_access(user, network_access) || check_access(user, access_security) || check_access(user, access_heads) - else - return check_access(user, network_access) - -/datum/nano_module/camera_monitor/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["switch_camera"]) - var/obj/machinery/camera/C = locate(href_list["switch_camera"]) in cameranet.cameras - if(!C) - return - if(!(current_network in C.network)) - return - - switch_to_camera(usr, C) - return 1 - - else if(href_list["switch_network"]) - // Either security access, or access to the specific camera network's department is required in order to access the network. - if(can_access_network(usr, get_camera_access(href_list["switch_network"]), (href_list["switch_network"] in using_map.station_networks))) - current_network = href_list["switch_network"] - else - to_chat(usr, "\The [nano_host()] shows an \"Network Access Denied\" error message.") - return 1 - - else if(href_list["reset"]) - reset_current() - usr.reset_view(current_camera) - return 1 - -/datum/nano_module/camera_monitor/proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C) - //don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras. - if(isAI(user)) - var/mob/living/silicon/ai/A = user - // Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise. - if(!A.is_in_chassis()) - return 0 - - A.eyeobj.setLoc(get_turf(C)) - A.client.eye = A.eyeobj - return 1 - - set_current(C) - user.machine = nano_host() - user.reset_view(C) - return 1 - -/datum/nano_module/camera_monitor/proc/set_current(var/obj/machinery/camera/C) - if(current_camera == C) - return - - if(current_camera) - reset_current() - - current_camera = C - if(current_camera) - var/mob/living/L = current_camera.loc - if(istype(L)) - L.tracking_initiated() - -/datum/nano_module/camera_monitor/proc/reset_current() - if(current_camera) - var/mob/living/L = current_camera.loc - if(istype(L)) - L.tracking_cancelled() - current_camera = null - -/datum/nano_module/camera_monitor/check_eye(var/mob/user as mob) - if(!current_camera) - return 0 - var/viewflag = current_camera.check_eye(user) - if ( viewflag < 0 ) //camera doesn't work - reset_current() - return viewflag - - // ERT Variant of the program /datum/computer_file/program/camera_monitor/ert filename = "ntcammon" filedesc = "Advanced Camera Monitoring" extended_desc = "This program allows remote access to the camera system. Some camera networks may have additional access requirements. This version has an integrated database with additional encrypted keys." size = 14 - nanomodule_path = /datum/nano_module/camera_monitor/ert + tguimodule_path = /datum/tgui_module/camera/ntos/ert available_on_ntnet = 0 - -/datum/nano_module/camera_monitor/ert - name = "Advanced Camera Monitoring Program" - //available_to_ai = FALSE - -// The ERT variant has access to ERT and crescent cams, but still checks for accesses. ERT members should be able to use it. -/datum/nano_module/camera_monitor/ert/modify_networks_list(var/list/networks) - ..() - networks.Add(list(list("tag" = NETWORK_ERT, "has_access" = 1))) - networks.Add(list(list("tag" = NETWORK_CRESCENT, "has_access" = 1))) - return networks - -/datum/nano_module/camera_monitor/apply_visual(mob/M) - if(current_camera) - current_camera.apply_visual(M) - else - remove_visual(M) - -/datum/nano_module/camera_monitor/remove_visual(mob/M) - if(current_camera) - current_camera.remove_visual(M) diff --git a/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm b/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm index 83e6584e8ce..9b94707eb22 100644 --- a/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm +++ b/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm @@ -1,7 +1,7 @@ /datum/computer_file/program/suit_sensors filename = "sensormonitor" filedesc = "Suit Sensors Monitoring" - nanomodule_path = /datum/nano_module/program/crew_monitor + tguimodule_path = /datum/tgui_module/crew_monitor/ntos program_icon_state = "crew" program_key_state = "med_key" program_menu_icon = "heart" @@ -10,68 +10,3 @@ requires_ntnet = 1 network_destination = "crew lifesigns monitoring system" size = 11 - - -/datum/nano_module/program/crew_monitor - name = "Crew monitor" - -/datum/nano_module/program/crew_monitor/Topic(href, href_list) - if(..()) return 1 - var/turf/T = get_turf(nano_host()) // TODO: Allow setting any using_map.contact_levels from the interface. - if (!T || !(T.z in using_map.player_levels)) - to_chat(usr, "Unable to establish a connection: You're too far away from the station!") - return 0 - if(href_list["track"]) - if(isAI(usr)) - var/mob/living/silicon/ai/AI = usr - var/mob/living/carbon/human/H = locate(href_list["track"]) in mob_list - if(hassensorlevel(H, SUIT_SENSOR_TRACKING)) - AI.ai_actual_track(H) - return 1 - -/datum/nano_module/program/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - var/list/data = host.initial_data() - - data["isAI"] = isAI(user) - - var/z = get_z(nano_host()) - var/list/map_levels = using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE) - data["map_levels"] = map_levels - - data["crewmembers"] = list() - for(var/zlevel in map_levels) - data["crewmembers"] += crew_repository.health_data(zlevel) - - if(!data["map_levels"].len) - to_chat(user, "The crew monitor doesn't seem like it'll work here.") - if(program) - program.kill_program() - if(ui) - ui.close() - return - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800, state = state) - - // adding a template with the key "mapContent" enables the map ui functionality - ui.add_template("mapContent", "crew_monitor_map_content.tmpl") - // adding a template with the key "mapHeader" replaces the map header content - ui.add_template("mapHeader", "crew_monitor_map_header.tmpl") - if(!(ui.map_z_level in data["map_levels"])) - ui.set_map_z_level(data["map_levels"][1]) - - ui.set_initial_data(data) - ui.open() - - // should make the UI auto-update; doesn't seem to? - ui.set_auto_update(1) - -/*/datum/nano_module/program/crew_monitor/proc/scan() - for(var/mob/living/carbon/human/H in mob_list) - if(istype(H.w_uniform, /obj/item/clothing/under)) - var/obj/item/clothing/under/C = H.w_uniform - if (C.has_sensor) - tracked |= C - return 1 -*/ \ No newline at end of file diff --git a/code/modules/nifsoft/software/06_screens.dm b/code/modules/nifsoft/software/06_screens.dm index 97f4c272a9b..64a1faac5cd 100644 --- a/code/modules/nifsoft/software/06_screens.dm +++ b/code/modules/nifsoft/software/06_screens.dm @@ -5,7 +5,7 @@ access = access_medical cost = 625 p_drain = 0.025 - var/datum/nano_module/program/crew_monitor/arscreen + var/datum/tgui_module/crew_monitor/nif/arscreen New() ..() @@ -17,7 +17,7 @@ activate() if((. = ..())) - arscreen.ui_interact(nif.human,"main",null,1,nif_state) + arscreen.tgui_interact(nif.human) return TRUE deactivate() diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index e8eaa809fe5..fa19b46e1f8 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -212,7 +212,6 @@ // leave the disposal /obj/machinery/disposal/proc/go_out(mob/user) - if (user.client) user.client.eye = user.client.mob user.client.perspective = MOB_PERSPECTIVE @@ -222,11 +221,11 @@ // ai as human but can't flush /obj/machinery/disposal/attack_ai(mob/user as mob) - interact(user, 1) + add_hiddenprint(user) + tgui_interact(user) // human interact with machine /obj/machinery/disposal/attack_hand(mob/user as mob) - if(stat & BROKEN) return @@ -236,91 +235,147 @@ // Clumsy folks can only flush it. if(user.IsAdvancedToolUser(1)) - interact(user, 0) + tgui_interact(user) else flush = !flush update() return // user interaction -/obj/machinery/disposal/interact(mob/user, var/ai=0) +/obj/machinery/disposal/tgui_interact(mob/user, datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "DisposalBin") + ui.open() - src.add_fingerprint(user) - if(stat & BROKEN) - user.unset_machine() +/obj/machinery/disposal/tgui_data(mob/user) + var/list/data = list() + + data["isAI"] = isAI(user) + data["flushing"] = flush + data["mode"] = mode + data["pressure"] = round(clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100),1) + + return data + +/obj/machinery/disposal/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return + + if(usr.loc == src) + to_chat(usr, "You cannot reach the controls from inside.") return - var/dat = "Waste Disposal UnitWaste Disposal Unit
" + if(mode==-1 && action != "eject") // If the mode is -1, only allow ejection + to_chat(usr, "The disposal units power is disabled.") + return + + if(stat & BROKEN) + return + + add_fingerprint(usr) - if(!ai) // AI can't pull flush handle - if(flush) - dat += "Disposal handle: Disengage Engaged" - else - dat += "Disposal handle: Disengaged Engage" + if(flushing) + return + + if(isturf(loc)) + if(action == "pumpOn") + mode = 1 + update() + if(action == "pumpOff") + mode = 0 + update() - dat += "

Eject contents
" + if(!issilicon(usr)) + if(action == "engageHandle") + flush = 1 + update() + if(action == "disengageHandle") + flush = 0 + update() - if(mode <= 0) - dat += "Pump: Off On
" - else if(mode == 1) - dat += "Pump: Off On (pressurizing)
" - else - dat += "Pump: Off On (idle)
" + if(action == "eject") + eject() + + return TRUE + - var/per = 100* air_contents.return_pressure() / (SEND_PRESSURE) + // src.add_fingerprint(user) + // if(stat & BROKEN) + // user.unset_machine() + // return - dat += "Pressure: [round(per, 1)]%
" + // var/dat = "Waste Disposal UnitWaste Disposal Unit
" + + // if(!ai) // AI can't pull flush handle + // if(flush) + // dat += "Disposal handle: Disengage Engaged" + // else + // dat += "Disposal handle: Disengaged Engage" + + // dat += "

Eject contents
" + + // if(mode <= 0) + // dat += "Pump: Off On
" + // else if(mode == 1) + // dat += "Pump: Off On (pressurizing)
" + // else + // dat += "Pump: Off On (idle)
" + + // var/per = 100* air_contents.return_pressure() / (SEND_PRESSURE) + + // dat += "Pressure: [round(per, 1)]%
" - user.set_machine(src) - user << browse(dat, "window=disposal;size=360x170") - onclose(user, "disposal") + // user.set_machine(src) + // user << browse(dat, "window=disposal;size=360x170") + // onclose(user, "disposal") // handle machine interaction -/obj/machinery/disposal/Topic(href, href_list) - if(usr.loc == src) - to_chat(usr, "You cannot reach the controls from inside.") - return +// /obj/machinery/disposal/Topic(href, href_list) +// if(usr.loc == src) +// to_chat(usr, "You cannot reach the controls from inside.") +// return - if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1 - to_chat(usr, "The disposal units power is disabled.") - return - if(..()) - return +// if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1 +// to_chat(usr, "The disposal units power is disabled.") +// return +// if(..()) +// return - if(stat & BROKEN) - return - if(usr.stat || usr.restrained() || src.flushing) - return +// if(stat & BROKEN) +// return +// if(usr.stat || usr.restrained() || src.flushing) +// return - if(istype(src.loc, /turf)) - usr.set_machine(src) +// if(istype(src.loc, /turf)) +// usr.set_machine(src) - if(href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=disposal") - return +// if(href_list["close"]) +// usr.unset_machine() +// usr << browse(null, "window=disposal") +// return - if(href_list["pump"]) - if(text2num(href_list["pump"])) - mode = 1 - else - mode = 0 - update() +// if(href_list["pump"]) +// if(text2num(href_list["pump"])) +// mode = 1 +// else +// mode = 0 +// update() - if(!isAI(usr)) - if(href_list["handle"]) - flush = text2num(href_list["handle"]) - update() +// if(!isAI(usr)) +// if(href_list["handle"]) +// flush = text2num(href_list["handle"]) +// update() - if(href_list["eject"]) - eject() - else - usr << browse(null, "window=disposal") - usr.unset_machine() - return - return +// if(href_list["eject"]) +// eject() +// else +// usr << browse(null, "window=disposal") +// usr.unset_machine() +// return +// return // eject the contents of the disposal unit /obj/machinery/disposal/proc/eject() diff --git a/code/modules/tgui/external.dm b/code/modules/tgui/external.dm new file mode 100644 index 00000000000..7e75f9343c0 --- /dev/null +++ b/code/modules/tgui/external.dm @@ -0,0 +1,191 @@ +/** + * tgui external + * + * Contains all external tgui declarations. + */ + +/** + * public + * + * Used to open and update UIs. + * If this proc is not implemented properly, the UI will not update correctly. + * + * required user mob The mob who opened/is using the UI. + * optional ui datum/tgui The UI to be updated, if it exists. + */ + +/datum/proc/tgui_interact(mob/user, datum/tgui/ui = null) + return FALSE // Not implemented. + +/** + * public + * + * Data to be sent to the UI. + * This must be implemented for a UI to work. + * + * required user mob The mob interacting with the UI. + * + * return list Data to be sent to the UI. + */ +/datum/proc/tgui_data(mob/user) + return list() // Not implemented. + +/** + * public + * + * Static Data to be sent to the UI. + * Static data differs from normal data in that it's large data that should be + * sent infrequently. This is implemented optionally for heavy uis that would + * be sending a lot of redundant data frequently. Gets squished into one + * object on the frontend side, but the static part is cached. + * + * required user mob The mob interacting with the UI. + * + * return list Statuic Data to be sent to the UI. + */ +/datum/proc/tgui_static_data(mob/user) + return list() + +/** + * public + * + * Forces an update on static data. Should be done manually whenever something + * happens to change static data. + * + * required user the mob currently interacting with the ui + * optional ui ui to be updated + */ +/datum/proc/update_tgui_static_data(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + // If there was no ui to update, there's no static data to update either. + if(!ui) + ui = SStgui.get_open_ui(user, src) + if(ui) + ui.send_full_update() + +/** + * public + * + * Called on a UI when the UI receieves a href. + * Think of this as Topic(). + * + * required action string The action/button that has been invoked by the user. + * required params list A list of parameters attached to the button. + * + * return bool If the UI should be updated or not. + */ +/datum/proc/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + // If UI is not interactive or usr calling Topic is not the UI user, bail. + if(!ui || ui.status != STATUS_INTERACTIVE) + return TRUE + +/** + * public + * + * Called on an object when a tgui object is being created, allowing you to + * push various assets to tgui, for examples spritesheets. + * + * return list List of asset datums or file paths. + */ +/datum/proc/ui_assets(mob/user) + return list() + +/** + * private + * + * The UI's host object (usually src_object). + * This allows modules/datums to have the UI attached to them, + * and be a part of another object. + */ +/datum/proc/tgui_host(mob/user) + return src // Default src. + +/** + * private + * + * The UI's state controller to be used for created uis + * This is a proc over a var for memory reasons + */ +/datum/proc/tgui_state(mob/user) + return GLOB.tgui_default_state + +/** + * global + * + * Associative list of JSON-encoded shared states that were set by + * tgui clients. + */ + +/datum/var/list/tgui_shared_states + +/** + * global + * + * Tracks open UIs for a user. + */ +/mob/var/list/tgui_open_uis = list() + +/** + * global + * + * Tracks open windows for a user. + */ +/client/var/list/tgui_windows = list() + +/** + * public + * + * Called on a UI's object when the UI is closed, not to be confused with + * client/verb/uiclose(), which closes the ui window + */ +/datum/proc/tgui_close(mob/user) + +/** + * verb + * + * Called by UIs when they are closed. + * Must be a verb so winset() can call it. + * + * required uiref ref The UI that was closed. + */ +/client/verb/tguiclose(window_id as text) + // Name the verb, and hide it from the user panel. + set name = "uiclose" + set hidden = TRUE + + var/mob/user = src && src.mob + if(!user) + return + // Close all tgui datums based on window_id. + SStgui.force_close_window(user, window_id) + +/** + * Middleware for /client/Topic. + * + * return bool Whether the topic is passed (TRUE), or cancelled (FALSE). + */ +/proc/tgui_Topic(href_list) + // Skip non-tgui topics + if(!href_list["tgui"]) + return TRUE + var/type = href_list["type"] + // Unconditionally collect tgui logs + if(type == "log") + log_tgui(usr, href_list["message"]) + // Locate window + var/window_id = href_list["window_id"] + var/datum/tgui_window/window + if(window_id) + window = usr.client.tgui_windows[window_id] + if(!window) + log_tgui(usr, "Error: Couldn't find the window datum, force closing.") + SStgui.force_close_window(usr, window_id) + return FALSE + // Decode payload + var/payload + if(href_list["payload"]) + payload = json_decode(href_list["payload"]) + // Pass message to window + if(window) + window.on_message(type, payload, href_list) + return FALSE diff --git a/code/modules/tgui/modules/_base.dm b/code/modules/tgui/modules/_base.dm new file mode 100644 index 00000000000..23b12b8bd16 --- /dev/null +++ b/code/modules/tgui/modules/_base.dm @@ -0,0 +1,46 @@ +/* +TGUI MODULES + +This allows for datum-based TGUIs that can be hooked into objects. +This is useful for things such as the power monitor, which needs to exist on a physical console in the world, but also as a virtual device the AI can use + +Code is pretty much ripped verbatim from nano modules, but with un-needed stuff removed +*/ +/datum/tgui_module + var/name + var/datum/host + var/list/using_access + + var/tgui_id + +/datum/tgui_module/New(var/host) + src.host = host + +/datum/tgui_module/tgui_host() + return host ? host : src + +/datum/tgui_module/tgui_close(mob/user) + if(host) + host.tgui_close(user) + +/datum/tgui_module/proc/check_access(mob/user, access) + if(!access) + return 1 + + if(using_access) + if(access in using_access) + return 1 + else + return 0 + + if(!istype(user)) + return 0 + + var/obj/item/weapon/card/id/I = user.GetIdCard() + if(!I) + return 0 + + if(access in I.access) + return 1 + + return 0 \ No newline at end of file diff --git a/code/modules/tgui/modules/camera.dm b/code/modules/tgui/modules/camera.dm new file mode 100644 index 00000000000..301d43d9d54 --- /dev/null +++ b/code/modules/tgui/modules/camera.dm @@ -0,0 +1,295 @@ +/datum/tgui_module/camera + name = "Security Cameras" + tgui_id = "CameraConsole" + + var/access_based = FALSE + var/list/network = list() + var/list/additional_networks = list() + + var/obj/machinery/camera/active_camera + var/list/concurrent_users = list() + + // Stuff needed to render the map + var/map_name + var/const/default_map_size = 15 + var/obj/screen/map_view/cam_screen + /// All the plane masters that need to be applied. + var/list/cam_plane_masters + var/obj/screen/background/cam_background + var/obj/screen/background/cam_foreground + var/obj/screen/skybox/local_skybox + // Needed for moving camera support + var/camera_diff_x = -1 + var/camera_diff_y = -1 + var/camera_diff_z = -1 + +/datum/tgui_module/camera/New(host, list/network_computer) + . = ..() + if(!LAZYLEN(network_computer)) + access_based = TRUE + else + network = network_computer + map_name = "camera_console_[REF(src)]_map" + // Initialize map objects + cam_screen = new + cam_screen.name = "screen" + cam_screen.assigned_map = map_name + cam_screen.del_on_map_removal = FALSE + cam_screen.screen_loc = "[map_name]:1,1" + cam_plane_masters = list() + + for(var/plane in subtypesof(/obj/screen/plane_master)) + var/obj/screen/instance = new plane() + instance.assigned_map = map_name + instance.del_on_map_removal = FALSE + instance.screen_loc = "[map_name]:CENTER" + cam_plane_masters += instance + + local_skybox = new() + local_skybox.assigned_map = map_name + local_skybox.del_on_map_removal = FALSE + local_skybox.screen_loc = "[map_name]:CENTER,CENTER" + cam_plane_masters += local_skybox + + cam_background = new + cam_background.assigned_map = map_name + cam_background.del_on_map_removal = FALSE + + var/mutable_appearance/scanlines = mutable_appearance('icons/effects/static.dmi', "scanlines") + scanlines.alpha = 50 + scanlines.layer = FULLSCREEN_LAYER + + var/mutable_appearance/noise = mutable_appearance('icons/effects/static.dmi', "1 light") + noise.layer = FULLSCREEN_LAYER + + cam_foreground = new + cam_foreground.assigned_map = map_name + cam_foreground.del_on_map_removal = FALSE + cam_foreground.plane = PLANE_FULLSCREEN + cam_foreground.add_overlay(scanlines) + cam_foreground.add_overlay(noise) + +/datum/tgui_module/camera/Destroy() + qdel(cam_screen) + QDEL_LIST(cam_plane_masters) + qdel(cam_background) + qdel(cam_foreground) + return ..() + +/datum/tgui_module/camera/tgui_interact(mob/user, datum/tgui/ui = null) + // Update UI + ui = SStgui.try_update_ui(user, src, ui) + // Show static if can't use the camera + if(!active_camera?.can_use()) + show_camera_static() + if(!ui) + var/user_ref = REF(user) + var/is_living = isliving(user) + // Ghosts shouldn't count towards concurrent users, which produces + // an audible terminal_on click. + if(is_living) + concurrent_users += user_ref + // Turn on the console + if(length(concurrent_users) == 1 && is_living) + playsound(tgui_host(), 'sound/machines/terminal_on.ogg', 25, FALSE) + // Register map objects + user.client.register_map_obj(cam_screen) + for(var/plane in cam_plane_masters) + user.client.register_map_obj(plane) + user.client.register_map_obj(cam_background) + user.client.register_map_obj(cam_foreground) + // Open UI + ui = new(user, src, tgui_id, name) + ui.open() + +/datum/tgui_module/camera/tgui_data() + var/list/data = list() + data["activeCamera"] = null + if(active_camera) + differential_check() + data["activeCamera"] = list( + name = active_camera.c_tag, + status = active_camera.status, + ) + return data + +/datum/tgui_module/camera/tgui_static_data(mob/user) + var/list/data = list() + data["mapRef"] = map_name + var/list/cameras = get_available_cameras(user) + data["cameras"] = list() + data["allNetworks"] = list() + for(var/i in cameras) + var/obj/machinery/camera/C = cameras[i] + data["cameras"] += list(list( + name = C.c_tag, + networks = C.network + )) + data["allNetworks"] |= C.network + return data + +/datum/tgui_module/camera/tgui_act(action, params) + if(..()) + return + + if(action == "switch_camera") + var/c_tag = params["name"] + var/list/cameras = get_available_cameras(usr) + var/obj/machinery/camera/C = cameras["[ckey(c_tag)]"] + active_camera = C + playsound(tgui_host(), get_sfx("terminal_type"), 25, FALSE) + + reload_cameraview() + + return TRUE + +/datum/tgui_module/camera/proc/differential_check() + var/turf/T = get_turf(active_camera) + if(T) + var/new_x = T.x + var/new_y = T.y + var/new_z = T.z + if((new_x != camera_diff_x) || (new_y != camera_diff_y) || (new_z != camera_diff_z)) + reload_cameraview() + +/datum/tgui_module/camera/proc/reload_cameraview() + // Show static if can't use the camera + if(!active_camera?.can_use()) + show_camera_static() + return TRUE + + var/turf/camTurf = get_turf(active_camera) + + camera_diff_x = camTurf.x + camera_diff_y = camTurf.y + camera_diff_z = camTurf.z + + var/list/visible_turfs = list() + for(var/turf/T in (active_camera.isXRay() \ + ? range(active_camera.view_range, camTurf) \ + : view(active_camera.view_range, camTurf))) + visible_turfs += T + + var/list/bbox = get_bbox_of_atoms(visible_turfs) + var/size_x = bbox[3] - bbox[1] + 1 + var/size_y = bbox[4] - bbox[2] + 1 + + cam_screen.vis_contents = visible_turfs + cam_background.icon_state = "clear" + cam_background.fill_rect(1, 1, size_x, size_y) + + cam_foreground.fill_rect(1, 1, size_x, size_y) + + local_skybox.cut_overlays() + local_skybox.add_overlay(SSskybox.get_skybox(get_z(camTurf))) + local_skybox.scale_to_view(size_x) + local_skybox.set_position("CENTER", "CENTER", (world.maxx>>1) - camTurf.x, (world.maxy>>1) - camTurf.y) + +// Returns the list of cameras accessible from this computer +// This proc operates in two distinct ways depending on the context in which the module is created. +// It can either return a list of cameras sharing the same the internal `network` variable, or +// It can scan all station networks and determine what cameras to show based on the access of the user. +/datum/tgui_module/camera/proc/get_available_cameras(mob/user) + var/list/all_networks = list() + // Access Based + if(access_based) + for(var/network in using_map.station_networks) + if(can_access_network(user, get_camera_access(network), 1)) + all_networks.Add(network) + for(var/network in using_map.secondary_networks) + if(can_access_network(user, get_camera_access(network), 0)) + all_networks.Add(network) + // Network Based + else + all_networks = network.Copy() + + if(additional_networks) + all_networks += additional_networks + + var/list/D = list() + for(var/obj/machinery/camera/C in cameranet.cameras) + if(!C.network) + stack_trace("Camera in a cameranet has no camera network") + continue + if(!(islist(C.network))) + stack_trace("Camera in a cameranet has a non-list camera network") + continue + var/list/tempnetwork = C.network & all_networks + if(tempnetwork.len) + D["[ckey(C.c_tag)]"] = C + return D + +/datum/tgui_module/camera/proc/can_access_network(mob/user, network_access, station_network = 0) + // No access passed, or 0 which is considered no access requirement. Allow it. + if(!network_access) + return 1 + + if(station_network) + return check_access(user, network_access) || check_access(user, access_security) || check_access(user, access_heads) + else + return check_access(user, network_access) + +/datum/tgui_module/camera/proc/show_camera_static() + cam_screen.vis_contents.Cut() + cam_background.icon_state = "scanline2" + cam_background.fill_rect(1, 1, default_map_size, default_map_size) + local_skybox.cut_overlays() + +/datum/tgui_module/camera/tgui_close(mob/user) + . = ..() + var/user_ref = REF(user) + var/is_living = isliving(user) + // living creature or not, we remove you anyway. + concurrent_users -= user_ref + // Unregister map objects + if(user.client) + user.client.clear_map(map_name) + // Turn off the console + if(length(concurrent_users) == 0 && is_living) + active_camera = null + playsound(tgui_host(), 'sound/machines/terminal_off.ogg', 25, FALSE) + +// NTOS Version +// Please note, this isn't a very good replacement for converting modular computers 100% to TGUI +// If/when that is done, just move all the PC_ specific data and stuff to the modular computers themselves +// instead of copying this approach here. +/datum/tgui_module/camera/ntos + tgui_id = "NtosCameraConsole" + +/datum/tgui_module/camera/ntos/tgui_state() + return GLOB.tgui_ntos_state + +/datum/tgui_module/camera/ntos/tgui_static_data() + . = ..() + + var/datum/computer_file/program/host = tgui_host() + if(istype(host) && host.computer) + . += host.computer.get_header_data() + +/datum/tgui_module/camera/ntos/tgui_act(action, params) + if(..()) + return + + var/datum/computer_file/program/host = tgui_host() + if(istype(host) && host.computer) + if(action == "PC_exit") + host.computer.kill_program() + return TRUE + if(action == "PC_shutdown") + host.computer.shutdown_computer() + return TRUE + if(action == "PC_minimize") + host.computer.minimize_program(usr) + return TRUE + +// ERT Version provides some additional networks. +/datum/tgui_module/camera/ntos/ert + additional_networks = list(NETWORK_ERT, NETWORK_CRESCENT) + +// Hacked version also provides some additional networks, +// but we want it to show *all* the networks 24/7, so we convert it into a non-access-based UI. +/datum/tgui_module/camera/ntos/hacked + additional_networks = list(NETWORK_MERCENARY, NETWORK_ERT, NETWORK_CRESCENT) + +/datum/tgui_module/camera/ntos/hacked/New(host) + . = ..(host, using_map.station_networks.Copy()) diff --git a/code/modules/tgui/modules/crew_monitor.dm b/code/modules/tgui/modules/crew_monitor.dm new file mode 100644 index 00000000000..f4be8c87c16 --- /dev/null +++ b/code/modules/tgui/modules/crew_monitor.dm @@ -0,0 +1,100 @@ +/datum/tgui_module/crew_monitor + name = "Crew monitor" + tgui_id = "CrewMonitor" + +/datum/tgui_module/crew_monitor/tgui_act(action, params, datum/tgui/ui) + if(..()) + return TRUE + + var/turf/T = get_turf(usr) + if(!T || !(T.z in using_map.player_levels)) + to_chat(usr, "Unable to establish a connection: You're too far away from the station!") + return FALSE + + switch(action) + if("track") + if(isAI(usr)) + var/mob/living/silicon/ai/AI = usr + var/mob/living/carbon/human/H = locate(params["track"]) in mob_list + if(hassensorlevel(H, SUIT_SENSOR_TRACKING)) + AI.ai_actual_track(H) + return TRUE + if("setZLevel") + ui.set_map_z_level(params["mapZLevel"]) + SStgui.update_uis(src) + +/datum/tgui_module/crew_monitor/tgui_interact(mob/user, datum/tgui/ui = null) + var/z = get_z(user) + var/list/map_levels = using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE) + + if(!map_levels.len) + to_chat(user, "The crew monitor doesn't seem like it'll work here.") + if(ui) + ui.close() + return null + + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, tgui_id, name) + ui.autoupdate = TRUE + ui.open() + + +/datum/tgui_module/crew_monitor/tgui_data(mob/user, ui_key = "main", datum/tgui_state/state = GLOB.tgui_default_state) + var/data[0] + + data["isAI"] = isAI(user) + + var/z = get_z(user) + var/list/map_levels = uniquelist(using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE)) + data["map_levels"] = map_levels + + data["crewmembers"] = list() + for(var/zlevel in map_levels) + data["crewmembers"] += crew_repository.health_data(zlevel) + + return data + +/datum/tgui_module/crew_monitor/ntos + tgui_id = "NtosCrewMonitor" + +/datum/tgui_module/crew_monitor/ntos/tgui_state(mob/user) + return GLOB.tgui_ntos_state + +/datum/tgui_module/crew_monitor/ntos/tgui_static_data() + . = ..() + + var/datum/computer_file/program/host = tgui_host() + if(istype(host) && host.computer) + . += host.computer.get_header_data() + +/datum/tgui_module/crew_monitor/ntos/tgui_act(action, params) + if(..()) + return + + var/datum/computer_file/program/host = tgui_host() + if(istype(host) && host.computer) + if(action == "PC_exit") + host.computer.kill_program() + return TRUE + if(action == "PC_shutdown") + host.computer.shutdown_computer() + return TRUE + if(action == "PC_minimize") + host.computer.minimize_program(usr) + return TRUE + +// Subtype for glasses_state +/datum/tgui_module/crew_monitor/glasses +/datum/tgui_module/crew_monitor/glasses/tgui_state(mob/user) + return GLOB.tgui_glasses_state + +// Subtype for self_state +/datum/tgui_module/crew_monitor/robot +/datum/tgui_module/crew_monitor/robot/tgui_state(mob/user) + return GLOB.tgui_self_state + +// Subtype for nif_state +/datum/tgui_module/crew_monitor/nif +/datum/tgui_module/crew_monitor/nif/tgui_state(mob/user) + return GLOB.tgui_nif_state diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm new file mode 100644 index 00000000000..111ee9e30be --- /dev/null +++ b/code/modules/tgui/states.dm @@ -0,0 +1,125 @@ +/** + * Base state and helpers for states. Just does some sanity checks, + * implement a proper state for in-depth checks. + */ + +/** + * public + * + * Checks the UI state for a mob. + * + * required user mob The mob who opened/is using the UI. + * required state datum/ui_state The state to check. + * + * return UI_state The state of the UI. + */ +/datum/proc/tgui_status(mob/user, datum/tgui_state/state) + var/src_object = tgui_host(user) + . = STATUS_CLOSE + if(!state) + return + + if(isobserver(user)) + // // If they turn on ghost AI control, admins can always interact. + // if(user.client.advanced_admin_interaction) + // . = max(., STATUS_INTERACTIVE) + + // Regular ghosts can always at least view if in range. + if(user.client) + var/clientviewlist = getviewsize(user.client.view) + if(get_dist(src_object, user) < max(clientviewlist[1], clientviewlist[2])) + . = max(., STATUS_UPDATE) + + // Check if the state allows interaction + var/result = state.can_use_topic(src_object, user) + . = max(., result) + +/** + * private + * + * Checks if a user can use src_object's UI, and returns the state. + * Can call a mob proc, which allows overrides for each mob. + * + * required src_object datum The object/datum which owns the UI. + * required user mob The mob who opened/is using the UI. + * + * return UI_state The state of the UI. + */ +/datum/tgui_state/proc/can_use_topic(src_object, mob/user) + // Don't allow interaction by default. + return STATUS_CLOSE + +/** + * public + * + * Standard interaction/sanity checks. Different mob types may have overrides. + * + * return UI_state The state of the UI. + */ +/mob/proc/shared_tgui_interaction(src_object) + // Close UIs if mindless. + if(!client) + return STATUS_CLOSE + // Disable UIs if unconcious. + else if(stat) + return STATUS_DISABLED + // Update UIs if incapicitated but concious. + else if(incapacitated()) + return STATUS_UPDATE + return STATUS_INTERACTIVE + +/mob/living/silicon/ai/shared_tgui_interaction(src_object) + // Disable UIs if the AI is unpowered. + if(lacks_power()) + return STATUS_DISABLED + return ..() + +/mob/living/silicon/robot/shared_tgui_interaction(src_object) + // Disable UIs if the Borg is unpowered or locked. + if(!cell || cell.charge <= 0 || lockcharge) + return STATUS_DISABLED + return ..() + +/** + * public + * + * Check the distance for a living mob. + * Really only used for checks outside the context of a mob. + * Otherwise, use shared_living_ui_distance(). + * + * required src_object The object which owns the UI. + * required user mob The mob who opened/is using the UI. + * + * return UI_state The state of the UI. + */ +/atom/proc/contents_tgui_distance(src_object, mob/living/user) + // Just call this mob's check. + return user.shared_living_tgui_distance(src_object) + +/** + * public + * + * Distance versus interaction check. + * + * required src_object atom/movable The object which owns the UI. + * + * return UI_state The state of the UI. + */ +/mob/living/proc/shared_living_tgui_distance(atom/movable/src_object, viewcheck = TRUE) + // If the object is obscured, close it. + if(viewcheck && !(src_object in view(src))) + return STATUS_CLOSE + + var/dist = get_dist(src_object, src) + if(dist <= 1) // Open and interact if 1-0 tiles away. + return STATUS_INTERACTIVE + else if(dist <= 2) // View only if 2-3 tiles away. + return STATUS_UPDATE + else if(dist <= 5) // Disable if 5 tiles away. + return STATUS_DISABLED + return STATUS_CLOSE // Otherwise, we got nothing. + +/mob/living/carbon/human/shared_living_tgui_distance(atom/movable/src_object) + if((TK in mutations) && (get_dist(src, src_object) <= 2)) + return STATUS_INTERACTIVE + return ..() diff --git a/code/modules/tgui/states/admin.dm b/code/modules/tgui/states/admin.dm new file mode 100644 index 00000000000..6d1c680927a --- /dev/null +++ b/code/modules/tgui/states/admin.dm @@ -0,0 +1,12 @@ + /** + * tgui state: admin_state + * + * Checks that the user is an admin, end-of-story. + **/ + +GLOBAL_DATUM_INIT(tgui_admin_state, /datum/tgui_state/admin_state, new) + +/datum/tgui_state/admin_state/can_use_topic(src_object, mob/user) + if(check_rights_for(user.client, R_ADMIN)) + return STATUS_INTERACTIVE + return STATUS_CLOSE diff --git a/code/modules/tgui/states/always.dm b/code/modules/tgui/states/always.dm new file mode 100644 index 00000000000..30915785442 --- /dev/null +++ b/code/modules/tgui/states/always.dm @@ -0,0 +1,11 @@ + + /** + * tgui state: always_state + * + * Always grants the user UI_INTERACTIVE. Period. + **/ + +GLOBAL_DATUM_INIT(tgui_always_state, /datum/tgui_state/always_state, new) + +/datum/tgui_state/always_state/can_use_topic(src_object, mob/user) + return STATUS_INTERACTIVE diff --git a/code/modules/tgui/states/conscious.dm b/code/modules/tgui/states/conscious.dm new file mode 100644 index 00000000000..6bc0c7ec031 --- /dev/null +++ b/code/modules/tgui/states/conscious.dm @@ -0,0 +1,12 @@ + /** + * tgui state: conscious_state + * + * Only checks if the user is conscious. + **/ + +GLOBAL_DATUM_INIT(tgui_conscious_state, /datum/tgui_state/conscious_state, new) + +/datum/tgui_state/conscious_state/can_use_topic(src_object, mob/user) + if(user.stat == CONSCIOUS) + return STATUS_INTERACTIVE + return STATUS_CLOSE diff --git a/code/modules/tgui/states/contained.dm b/code/modules/tgui/states/contained.dm new file mode 100644 index 00000000000..c2fbd0b6b06 --- /dev/null +++ b/code/modules/tgui/states/contained.dm @@ -0,0 +1,12 @@ + /** + * tgui state: contained_state + * + * Checks that the user is inside the src_object. + **/ + +GLOBAL_DATUM_INIT(tgui_contained_state, /datum/tgui_state/contained_state, new) + +/datum/tgui_state/contained_state/can_use_topic(atom/src_object, mob/user) + if(!src_object.contains(user)) + return STATUS_CLOSE + return user.shared_tgui_interaction(src_object) diff --git a/code/modules/tgui/states/deep_inventory.dm b/code/modules/tgui/states/deep_inventory.dm new file mode 100644 index 00000000000..137f262a0ea --- /dev/null +++ b/code/modules/tgui/states/deep_inventory.dm @@ -0,0 +1,12 @@ + /** + * tgui state: deep_inventory_state + * + * Checks that the src_object is in the user's deep (backpack, box, toolbox, etc) inventory. + **/ + +GLOBAL_DATUM_INIT(tgui_deep_inventory_state, /datum/tgui_state/deep_inventory_state, new) + +/datum/tgui_state/deep_inventory_state/can_use_topic(src_object, mob/user) + if(!user.contains(src_object)) + return STATUS_CLOSE + return user.shared_tgui_interaction(src_object) diff --git a/code/modules/tgui/states/default.dm b/code/modules/tgui/states/default.dm new file mode 100644 index 00000000000..9ccc9c751ef --- /dev/null +++ b/code/modules/tgui/states/default.dm @@ -0,0 +1,63 @@ + /** + * tgui state: default_state + * + * Checks a number of things -- mostly physical distance for humans and view for robots. + **/ + +GLOBAL_DATUM_INIT(tgui_default_state, /datum/tgui_state/default, new) + +/datum/tgui_state/default/can_use_topic(src_object, mob/user) + return user.default_can_use_tgui_topic(src_object) // Call the individual mob-overridden procs. + +/mob/proc/default_can_use_tgui_topic(src_object) + return STATUS_CLOSE // Don't allow interaction by default. + +/mob/living/default_can_use_tgui_topic(src_object) + . = shared_tgui_interaction(src_object) + if(. > STATUS_CLOSE && loc) + . = min(., loc.contents_tgui_distance(src_object, src)) // Check the distance... + if(. == STATUS_INTERACTIVE) // Non-human living mobs can only look, not touch. + return STATUS_UPDATE + +/mob/living/carbon/human/default_can_use_tgui_topic(src_object) + . = shared_tgui_interaction(src_object) + if(. > STATUS_CLOSE) + . = min(., shared_living_tgui_distance(src_object)) // Check the distance... + +/mob/living/silicon/robot/default_can_use_tgui_topic(src_object) + . = shared_tgui_interaction(src_object) + if(. <= STATUS_DISABLED) + return + + // Robots can interact with anything they can see. + var/list/clientviewlist = getviewsize(client.view) + if((src_object in view(src)) && (get_dist(src, src_object) <= min(clientviewlist[1],clientviewlist[2]))) + return STATUS_INTERACTIVE + return STATUS_DISABLED // Otherwise they can keep the UI open. + +/mob/living/silicon/ai/default_can_use_tgui_topic(src_object) + . = shared_tgui_interaction(src_object) + if(. < STATUS_INTERACTIVE) + return + + // The AI can interact with anything it can see nearby, or with cameras while wireless control is enabled. + if(!control_disabled && can_see(src_object)) + return STATUS_INTERACTIVE + return STATUS_CLOSE + +/mob/living/simple_animal/default_can_use_tgui_topic(src_object) + . = shared_tgui_interaction(src_object) + if(. > STATUS_CLOSE) + . = min(., shared_living_tgui_distance(src_object)) //simple animals can only use things they're near. + +/mob/living/silicon/pai/default_can_use_tgui_topic(src_object) + // pAIs can only use themselves and the owner's radio. + if((src_object == src || src_object == radio) && !stat) + return STATUS_INTERACTIVE + else + return ..() + +/mob/observer/dead/default_can_use_tgui_topic() + if(check_rights(R_ADMIN, 0, src)) + return STATUS_INTERACTIVE // Admins are more equal + return STATUS_UPDATE // Ghosts can view updates diff --git a/code/modules/tgui/states/hands.dm b/code/modules/tgui/states/hands.dm new file mode 100644 index 00000000000..0981b5d6ec7 --- /dev/null +++ b/code/modules/tgui/states/hands.dm @@ -0,0 +1,25 @@ + /** + * tgui state: hands_state + * + * Checks that the src_object is in the user's hands. + **/ + +GLOBAL_DATUM_INIT(tgui_hands_state, /datum/tgui_state/hands_state, new) + +/datum/tgui_state/hands_state/can_use_topic(src_object, mob/user) + . = user.shared_tgui_interaction(src_object) + if(. > STATUS_CLOSE) + return min(., user.hands_can_use_tgui_topic(src_object)) + +/mob/proc/hands_can_use_tgui_topic(src_object) + return STATUS_CLOSE + +/mob/living/hands_can_use_tgui_topic(src_object) + if(src_object in get_all_held_items()) + return STATUS_INTERACTIVE + return STATUS_CLOSE + +/mob/living/silicon/robot/hands_can_use_tgui_topic(src_object) + if(activated(src_object)) + return STATUS_INTERACTIVE + return STATUS_CLOSE diff --git a/code/modules/tgui/states/human_adjacent.dm b/code/modules/tgui/states/human_adjacent.dm new file mode 100644 index 00000000000..8164d5f9cee --- /dev/null +++ b/code/modules/tgui/states/human_adjacent.dm @@ -0,0 +1,17 @@ + + /** + * tgui state: human_adjacent_state + * + * In addition to default checks, only allows interaction for a + * human adjacent user. + **/ + +GLOBAL_DATUM_INIT(tgui_human_adjacent_state, /datum/tgui_state/human_adjacent_state, new) + +/datum/tgui_state/human_adjacent_state/can_use_topic(src_object, mob/user) + . = user.default_can_use_tgui_topic(src_object) + + var/dist = get_dist(src_object, user) + if((dist > 1) || (!ishuman(user))) + // Can't be used unless adjacent and human, even with TK + . = min(., STATUS_UPDATE) diff --git a/code/modules/tgui/states/inventory.dm b/code/modules/tgui/states/inventory.dm new file mode 100644 index 00000000000..92274cc1f2e --- /dev/null +++ b/code/modules/tgui/states/inventory.dm @@ -0,0 +1,12 @@ + /** + * tgui state: inventory_state + * + * Checks that the src_object is in the user's top-level (hand, ear, pocket, belt, etc) inventory. + **/ + +GLOBAL_DATUM_INIT(tgui_inventory_state, /datum/tgui_state/inventory_state, new) + +/datum/tgui_state/inventory_state/can_use_topic(src_object, mob/user) + if(!(src_object in user)) + return STATUS_CLOSE + return user.shared_tgui_interaction(src_object) diff --git a/code/modules/tgui/states/inventory_vr.dm b/code/modules/tgui/states/inventory_vr.dm new file mode 100644 index 00000000000..b8e3ea224c2 --- /dev/null +++ b/code/modules/tgui/states/inventory_vr.dm @@ -0,0 +1,26 @@ +GLOBAL_DATUM_INIT(tgui_glasses_state, /datum/tgui_state/glasses_state, new) +/datum/tgui_state/glasses_state/can_use_topic(var/src_object, var/mob/user) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.glasses == src_object) + return user.shared_tgui_interaction() + + return STATUS_CLOSE + +GLOBAL_DATUM_INIT(tgui_nif_state, /datum/tgui_state/nif_state, new) +/datum/tgui_state/nif_state/can_use_topic(var/src_object, var/mob/user) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif) + return user.shared_tgui_interaction() + + return STATUS_CLOSE + +GLOBAL_DATUM_INIT(tgui_commlink_state, /datum/tgui_state/commlink_state, new) +/datum/tgui_state/commlink_state/can_use_topic(var/src_object, var/mob/user) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object) + return user.shared_tgui_interaction() + + return STATUS_CLOSE diff --git a/code/modules/tgui/states/not_incapacitated.dm b/code/modules/tgui/states/not_incapacitated.dm new file mode 100644 index 00000000000..1185b516478 --- /dev/null +++ b/code/modules/tgui/states/not_incapacitated.dm @@ -0,0 +1,29 @@ + /** + * tgui state: not_incapacitated_state + * + * Checks that the user isn't incapacitated + **/ + +GLOBAL_DATUM_INIT(tgui_not_incapacitated_state, /datum/tgui_state/not_incapacitated_state, new) + + /** + * tgui state: not_incapacitated_turf_state + * + * Checks that the user isn't incapacitated and that their loc is a turf + **/ + +GLOBAL_DATUM_INIT(tgui_not_incapacitated_turf_state, /datum/tgui_state/not_incapacitated_state, new(no_turfs = TRUE)) + +/datum/tgui_state/not_incapacitated_state + var/turf_check = FALSE + +/datum/tgui_state/not_incapacitated_state/New(loc, no_turfs = FALSE) + ..() + turf_check = no_turfs + +/datum/tgui_state/not_incapacitated_state/can_use_topic(src_object, mob/user) + if(user.stat) + return STATUS_CLOSE + if(user.incapacitated() || (turf_check && !isturf(user.loc))) + return STATUS_DISABLED + return STATUS_INTERACTIVE diff --git a/code/modules/tgui/states/notcontained.dm b/code/modules/tgui/states/notcontained.dm new file mode 100644 index 00000000000..01811d427f2 --- /dev/null +++ b/code/modules/tgui/states/notcontained.dm @@ -0,0 +1,26 @@ + /** + * tgui state: notcontained_state + * + * Checks that the user is not inside src_object, and then makes the default checks. + **/ + +GLOBAL_DATUM_INIT(tgui_notcontained_state, /datum/tgui_state/notcontained_state, new) + +/datum/tgui_state/notcontained_state/can_use_topic(atom/src_object, mob/user) + . = user.shared_tgui_interaction(src_object) + if(. > STATUS_CLOSE) + return min(., user.notcontained_can_use_tgui_topic(src_object)) + +/mob/proc/notcontained_can_use_tgui_topic(src_object) + return STATUS_CLOSE + +/mob/living/notcontained_can_use_tgui_topic(atom/src_object) + if(src_object.contains(src)) + return STATUS_CLOSE // Close if we're inside it. + return default_can_use_tgui_topic(src_object) + +/mob/living/silicon/notcontained_can_use_tgui_topic(src_object) + return default_can_use_tgui_topic(src_object) // Silicons use default bevhavior. + +/mob/living/simple_animal/drone/notcontained_can_use_tgui_topic(src_object) + return default_can_use_tgui_topic(src_object) // Drones use default bevhavior. diff --git a/code/modules/tgui/states/ntos.dm b/code/modules/tgui/states/ntos.dm new file mode 100644 index 00000000000..d6a5533e1e7 --- /dev/null +++ b/code/modules/tgui/states/ntos.dm @@ -0,0 +1,15 @@ + /** + * tgui state: ntos_state + * + * Checks a number of things -- mostly physical distance for humans and view for robots. + * This is basically the same as default, except instead of src_object, it uses the computer + * it's attached to. + **/ + +GLOBAL_DATUM_INIT(tgui_ntos_state, /datum/tgui_state/ntos, new) + +/datum/tgui_state/ntos/can_use_topic(src_object, mob/user) + var/datum/computer_file/program/P = src_object + if(!istype(P) || !P.computer) + return FALSE + return user.default_can_use_tgui_topic(P.computer) // Call the individual mob-overridden procs. diff --git a/code/modules/tgui/states/observer.dm b/code/modules/tgui/states/observer.dm new file mode 100644 index 00000000000..bf98f444654 --- /dev/null +++ b/code/modules/tgui/states/observer.dm @@ -0,0 +1,15 @@ + /** + * tgui state: observer_state + * + * Checks that the user is an observer/ghost. + **/ + +GLOBAL_DATUM_INIT(tgui_observer_state, /datum/tgui_state/observer_state, new) + +/datum/tgui_state/observer_state/can_use_topic(src_object, mob/user) + if(isobserver(user)) + return STATUS_INTERACTIVE + if(check_rights(R_ADMIN, 0, src)) + return STATUS_INTERACTIVE + return STATUS_CLOSE + diff --git a/code/modules/tgui/states/physical.dm b/code/modules/tgui/states/physical.dm new file mode 100644 index 00000000000..a57a321e958 --- /dev/null +++ b/code/modules/tgui/states/physical.dm @@ -0,0 +1,24 @@ + /** + * tgui state: physical_state + * + * Short-circuits the default state to only check physical distance. + **/ + +GLOBAL_DATUM_INIT(tgui_physical_state, /datum/tgui_state/physical, new) + +/datum/tgui_state/physical/can_use_topic(src_object, mob/user) + . = user.shared_tgui_interaction(src_object) + if(. > STATUS_CLOSE) + return min(., user.physical_can_use_tgui_topic(src_object)) + +/mob/proc/physical_can_use_tgui_topic(src_object) + return STATUS_CLOSE + +/mob/living/physical_can_use_tgui_topic(src_object) + return shared_living_tgui_distance(src_object) + +/mob/living/silicon/physical_can_use_tgui_topic(src_object) + return max(STATUS_UPDATE, shared_living_tgui_distance(src_object)) // Silicons can always see. + +/mob/living/silicon/ai/physical_can_use_tgui_topic(src_object) + return STATUS_UPDATE // AIs are not physical. diff --git a/code/modules/tgui/states/self.dm b/code/modules/tgui/states/self.dm new file mode 100644 index 00000000000..109fd6ae440 --- /dev/null +++ b/code/modules/tgui/states/self.dm @@ -0,0 +1,12 @@ + /** + * tgui state: self_state + * + * Only checks that the user and src_object are the same. + **/ + +GLOBAL_DATUM_INIT(tgui_self_state, /datum/tgui_state/self_state, new) + +/datum/tgui_state/self_state/can_use_topic(src_object, mob/user) + if(src_object != user) + return STATUS_CLOSE + return user.shared_tgui_interaction(src_object) diff --git a/code/modules/tgui/states/zlevel.dm b/code/modules/tgui/states/zlevel.dm new file mode 100644 index 00000000000..a589a4b64d7 --- /dev/null +++ b/code/modules/tgui/states/zlevel.dm @@ -0,0 +1,14 @@ + /** + * tgui state: z_state + * + * Only checks that the Z-level of the user and src_object are the same. + **/ + +GLOBAL_DATUM_INIT(tgui_z_state, /datum/tgui_state/z_state, new) + +/datum/tgui_state/z_state/can_use_topic(src_object, mob/user) + var/turf/turf_obj = get_turf(src_object) + var/turf/turf_usr = get_turf(user) + if(turf_obj && turf_usr && turf_obj.z == turf_usr.z) + return STATUS_INTERACTIVE + return STATUS_CLOSE diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm new file mode 100644 index 00000000000..9af1296ab08 --- /dev/null +++ b/code/modules/tgui/tgui.dm @@ -0,0 +1,304 @@ +/** + * tgui + * + * /tg/station user interface library + */ + +/** + * tgui datum (represents a UI). + */ +/datum/tgui + /// The mob who opened/is using the UI. + var/mob/user + /// The object which owns the UI. + var/datum/src_object + /// The title of te UI. + var/title + /// The window_id for browse() and onclose(). + var/datum/tgui_window/window + /// Key that is used for remembering the window geometry. + var/window_key + /// Deprecated: Window size. + var/window_size + /// The interface (template) to be used for this UI. + var/interface + /// Update the UI every MC tick. + var/autoupdate = TRUE + /// If the UI has been initialized yet. + var/initialized = FALSE + /// Time of opening the window. + var/opened_at + /// Stops further updates when close() was called. + var/closing = FALSE + /// The status/visibility of the UI. + var/status = STATUS_INTERACTIVE + /// Topic state used to determine status/interactability. + var/datum/tgui_state/state = null + // The map z-level to display. + var/map_z_level = 1 + +/** + * public + * + * Create a new UI. + * + * required user mob The mob who opened/is using the UI. + * required src_object datum The object or datum which owns the UI. + * required interface string The interface used to render the UI. + * optional title string The title of the UI. + * optional ui_x int Deprecated: Window width. + * optional ui_y int Deprecated: Window height. + * + * return datum/tgui The requested UI. + */ +/datum/tgui/New(mob/user, datum/src_object, interface, title, ui_x, ui_y) + src.user = user + src.src_object = src_object + src.window_key = "[REF(src_object)]-main" + src.interface = interface + if(title) + src.title = title + src.state = src_object.tgui_state() + // Deprecated + if(ui_x && ui_y) + src.window_size = list(ui_x, ui_y) + +/** + * public + * + * Open this UI (and initialize it with data). + */ +/datum/tgui/proc/open() + if(!user.client) + return null + if(window) + return null + process_status() + if(status < STATUS_UPDATE) + return null + window = SStgui.request_pooled_window(user) + if(!window) + return null + opened_at = world.time + window.acquire_lock(src) + if(!window.is_ready()) + window.initialize(inline_assets = list( + get_asset_datum(/datum/asset/simple/tgui) + )) + else + window.send_message("ping") + window.send_asset(get_asset_datum(/datum/asset/simple/fontawesome)) + for(var/datum/asset/asset in src_object.ui_assets(user)) + window.send_asset(asset) + window.send_message("update", get_payload( + with_data = TRUE, + with_static_data = TRUE)) + SStgui.on_open(src) + +/** + * public + * + * Close the UI, and all its children. + */ +/datum/tgui/proc/close(can_be_suspended = TRUE) + if(closing) + return + closing = TRUE + // If we don't have window_id, open proc did not have the opportunity + // to finish, therefore it's safe to skip this whole block. + if(window) + // Windows you want to keep are usually blue screens of death + // and we want to keep them around, to allow user to read + // the error message properly. + window.release_lock() + window.close(can_be_suspended) + src_object.tgui_close(user) + SStgui.on_close(src) + state = null + qdel(src) + +/** + * public + * + * Enable/disable auto-updating of the UI. + * + * required autoupdate bool Enable/disable auto-updating. + */ +/datum/tgui/proc/set_autoupdate(autoupdate) + src.autoupdate = autoupdate + +/** + * public + * + * Replace current ui.state with a new one. + * + * required state datum/ui_state/state Next state + */ +/datum/tgui/proc/set_state(datum/tgui_state/state) + src.state = state + +/** + * public + * + * Makes an asset available to use in tgui. + * + * required asset datum/asset + */ +/datum/tgui/proc/send_asset(datum/asset/asset) + if(!window) + CRASH("send_asset() can only be called after open().") + window.send_asset(asset) + +/** + * public + * + * Send a full update to the client (includes static data). + * + * optional custom_data list Custom data to send instead of ui_data. + * optional force bool Send an update even if UI is not interactive. + */ +/datum/tgui/proc/send_full_update(custom_data, force) + if(!user.client || !initialized || closing) + return + var/should_update_data = force || status >= STATUS_UPDATE + window.send_message("update", get_payload( + custom_data, + with_data = should_update_data, + with_static_data = TRUE)) + +/** + * public + * + * Send a partial update to the client (excludes static data). + * + * optional custom_data list Custom data to send instead of ui_data. + * optional force bool Send an update even if UI is not interactive. + */ +/datum/tgui/proc/send_update(custom_data, force) + if(!user.client || !initialized || closing) + return + var/should_update_data = force || status >= STATUS_UPDATE + window.send_message("update", get_payload( + custom_data, + with_data = should_update_data)) + +/** + * private + * + * Package the data to send to the UI, as JSON. + * + * return list + */ +/datum/tgui/proc/get_payload(custom_data, with_data, with_static_data) + var/list/json_data = list() + json_data["config"] = list( + "title" = title, + "status" = status, + "interface" = interface, + "map" = (using_map && using_map.path) ? using_map.path : "Unknown", + "mapZLevel" = map_z_level, + "window" = list( + "key" = window_key, + "size" = window_size, + "fancy" = user.client.prefs.tgui_fancy, + "locked" = user.client.prefs.tgui_lock, + ), + "user" = list( + "name" = "[user]", + "ckey" = "[user.ckey]", + "observer" = isobserver(user), + ), + ) + var/data = custom_data || with_data && src_object.tgui_data(user) + if(data) + json_data["data"] = data + var/static_data = with_static_data && src_object.tgui_static_data(user) + if(static_data) + json_data["static_data"] = static_data + if(src_object.tgui_shared_states) + json_data["shared"] = src_object.tgui_shared_states + return json_data + +/** + * private + * + * Run an update cycle for this UI. Called internally by SStgui + * every second or so. + */ +/datum/tgui/process(force = FALSE) + if(closing) + return + var/datum/host = src_object.tgui_host(user) + // If the object or user died (or something else), abort. + if(!src_object || !host || !user || !window) + close(can_be_suspended = FALSE) + return + // Validate ping + if(!initialized && world.time - opened_at > TGUI_PING_TIMEOUT) + log_tgui(user, \ + "Error: Zombie window detected, killing it with fire.\n" \ + + "window_id: [window.id]\n" \ + + "opened_at: [opened_at]\n" \ + + "world.time: [world.time]") + close(can_be_suspended = FALSE) + return + // Update through a normal call to ui_interact + if(status != STATUS_DISABLED && (autoupdate || force)) + src_object.tgui_interact(user, src) + return + // Update status only + var/needs_update = process_status() + if(status <= STATUS_CLOSE) + close() + return + if(needs_update) + window.send_message("update", get_payload()) + +/** + * private + * + * Updates the status, and returns TRUE if status has changed. + */ +/datum/tgui/proc/process_status() + var/prev_status = status + status = src_object.tgui_status(user, state) + return prev_status != status + +/datum/tgui/proc/log_message(message) + log_tgui("[user] ([user.ckey]) using \"[title]\":\n[message]") + +/datum/tgui/proc/set_map_z_level(nz) + map_z_level = nz + +/** + * private + * + * Handle clicks from the UI. + * Call the src_object's ui_act() if status is UI_INTERACTIVE. + * If the src_object's ui_act() returns 1, update all UIs attacked to it. + */ +/datum/tgui/proc/on_message(type, list/payload, list/href_list) + // Pass act type messages to tgui_act + if(type && copytext(type, 1, 5) == "act/") + process_status() + if(src_object.tgui_act(copytext(type, 5), payload, src, state)) + SStgui.update_uis(src_object) + return FALSE + switch(type) + if("ready") + initialized = TRUE + if("pingReply") + initialized = TRUE + if("suspend") + close(can_be_suspended = TRUE) + if("close") + close(can_be_suspended = FALSE) + if("log") + if(href_list["fatal"]) + close(can_be_suspended = FALSE) + if("setSharedState") + if(status != STATUS_INTERACTIVE) + return + LAZYINITLIST(src_object.tgui_shared_states) + src_object.tgui_shared_states[href_list["key"]] = href_list["value"] + SStgui.update_uis(src_object) \ No newline at end of file diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm new file mode 100644 index 00000000000..18cf7153688 --- /dev/null +++ b/code/modules/tgui/tgui_window.dm @@ -0,0 +1,238 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/datum/tgui_window + var/id + var/client/client + var/pooled + var/pool_index + var/status = TGUI_WINDOW_CLOSED + var/locked = FALSE + var/datum/tgui/locked_by + var/fatally_errored = FALSE + var/message_queue + var/sent_assets = list() + +/** + * public + * + * Create a new tgui window. + * + * required client /client + * required id string A unique window identifier. + */ +/datum/tgui_window/New(client/client, id, pooled = FALSE) + src.id = id + src.client = client + src.pooled = pooled + if(pooled) + client.tgui_windows[id] = src + src.pool_index = TGUI_WINDOW_INDEX(id) + +/** + * public + * + * Initializes the window with a fresh page. Puts window into the "loading" + * state. You can begin sending messages right after initializing. Messages + * will be put into the queue until the window finishes loading. + * + * optional inline_assets list List of assets to inline into the html. + */ +/datum/tgui_window/proc/initialize(inline_assets = list()) + log_tgui(client, "[id]/initialize") + if(!client) + return + status = TGUI_WINDOW_LOADING + fatally_errored = FALSE + message_queue = null + // Build window options + var/options = "file=[id].html;can_minimize=0;auto_format=0;" + // Remove titlebar and resize handles for a fancy window + if(client.prefs.tgui_fancy) + options += "titlebar=0;can_resize=0;" + else + options += "titlebar=1;can_resize=1;" + // Generate page html + var/html = SStgui.basehtml + html = replacetextEx(html, "\[tgui:windowId]", id) + // Process inline assets + var/inline_styles = "" + var/inline_scripts = "" + for(var/datum/asset/asset in inline_assets) + var/mappings = asset.get_url_mappings() + for(var/name in mappings) + var/url = mappings[name] + // Not urlencoding since asset strings are considered safe + if(copytext(name, -4) == ".css") + inline_styles += "\n" + else if(copytext(name, -3) == ".js") + inline_scripts += "\n" + asset.send() + html = replacetextEx(html, "\n", inline_styles) + html = replacetextEx(html, "\n", inline_scripts) + // Open the window + client << browse(html, "window=[id];[options]") + // Instruct the client to signal UI when the window is closed. + winset(client, id, "on-close=\"uiclose [id]\"") + +/** + * public + * + * Checks if the window is ready to receive data. + * + * return bool + */ +/datum/tgui_window/proc/is_ready() + return status == TGUI_WINDOW_READY + +/** + * public + * + * Checks if the window can be sanely suspended. + * + * return bool + */ +/datum/tgui_window/proc/can_be_suspended() + return !fatally_errored \ + && pooled \ + && pool_index > 0 \ + && pool_index <= TGUI_WINDOW_SOFT_LIMIT \ + && status == TGUI_WINDOW_READY + +/** + * public + * + * Acquire the window lock. Pool will not be able to provide this window + * to other UIs for the duration of the lock. + * + * Can be given an optional tgui datum, which will hook its on_message + * callback into the message stream. + * + * optional ui /datum/tgui + */ +/datum/tgui_window/proc/acquire_lock(datum/tgui/ui) + locked = TRUE + locked_by = ui + +/** + * Release the window lock. + */ +/datum/tgui_window/proc/release_lock() + // Clean up assets sent by tgui datum which requested the lock + if(locked) + sent_assets = list() + locked = FALSE + locked_by = null + +/** + * public + * + * Close the UI. + * + * optional can_be_suspended bool + */ +/datum/tgui_window/proc/close(can_be_suspended = TRUE) + if(!client) + return + if(can_be_suspended && can_be_suspended()) + log_tgui(client, "[id]/close: suspending") + status = TGUI_WINDOW_READY + send_message("suspend") + return + log_tgui(client, "[id]/close") + release_lock() + status = TGUI_WINDOW_CLOSED + message_queue = null + // Do not close the window to give user some time + // to read the error message. + if(!fatally_errored) + client << browse(null, "window=[id]") + +/** + * public + * + * Sends a message to tgui window. + * + * required type string Message type + * required payload list Message payload + * optional force bool Send regardless of the ready status. + */ +/datum/tgui_window/proc/send_message(type, list/payload, force) + if(!client) + return + var/message = json_encode(list( + "type" = type, + "payload" = payload, + )) + // Strip #255/improper. + message = replacetext(message, "\proper", "") + message = replacetext(message, "\improper", "") + // Pack for sending via output() + message = url_encode(message) + // Place into queue if window is still loading + if(!force && status != TGUI_WINDOW_READY) + if(!message_queue) + message_queue = list() + message_queue += list(message) + return + client << output(message, "[id].browser:update") + +/** + * public + * + * Makes an asset available to use in tgui. + * + * required asset datum/asset + */ +/datum/tgui_window/proc/send_asset(datum/asset/asset) + if(!client || !asset) + return + // if(istype(asset, /datum/asset/spritesheet)) + // var/datum/asset/spritesheet/spritesheet = asset + // send_message("asset/stylesheet", spritesheet.css_filename()) + send_message("asset/mappings", asset.get_url_mappings()) + sent_assets += list(asset) + asset.send(client) + +/** + * private + * + * Sends queued messages if the queue wasn't empty. + */ +/datum/tgui_window/proc/flush_message_queue() + if(!client || !message_queue) + return + for(var/message in message_queue) + client << output(message, "[id].browser:update") + message_queue = null + +/** + * private + * + * Callback for handling incoming tgui messages. + */ +/datum/tgui_window/proc/on_message(type, list/payload, list/href_list) + switch(type) + if("ready") + // Status can be READY if user has refreshed the window. + if(status == TGUI_WINDOW_READY) + // Resend the assets + for(var/asset in sent_assets) + send_asset(asset) + status = TGUI_WINDOW_READY + if("log") + if(href_list["fatal"]) + fatally_errored = TRUE + // Pass message to UI that requested the lock + if(locked && locked_by) + locked_by.on_message(type, payload, href_list) + flush_message_queue() + return + // If not locked, handle these message types + switch(type) + if("suspend") + close(can_be_suspended = TRUE) + if("close") + close(can_be_suspended = FALSE) diff --git a/code/modules/vchat/css/ss13styles.css b/code/modules/vchat/css/ss13styles.css index 372c3ecf22a..98dcbc18e82 100644 --- a/code/modules/vchat/css/ss13styles.css +++ b/code/modules/vchat/css/ss13styles.css @@ -162,6 +162,7 @@ h1.alert, h2.alert {color: #000000;} .vulpkanin {color: #B97A57;} .enochian {color: #848A33; letter-spacing:-1pt; word-spacing:4pt; font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;} .daemon {color: #5E339E; letter-spacing:-1pt; word-spacing:0pt; font-family: "Courier New", Courier, monospace;} +.drudakar {color: #bb2463; word-spacing:0pt; font-family: "High Tower Text", monospace;} .bug {color: #9e9e39;} .vox {color: #AA00AA;} .promethean {color: #5A5A5A; font-family:"Comic Sans MS","Comic Sans",cursive;} diff --git a/code/modules/vchat/vchat_client.dm b/code/modules/vchat/vchat_client.dm index 25486ac554e..4a2288faac8 100644 --- a/code/modules/vchat/vchat_client.dm +++ b/code/modules/vchat/vchat_client.dm @@ -407,6 +407,7 @@ var/to_chat_src // Write the messages to the log for(var/list/result in results) o_file << "[result["message"]]
" + CHECK_TICK o_file << "" diff --git a/code/modules/vore/eating/bellymodes_datum_vr.dm b/code/modules/vore/eating/bellymodes_datum_vr.dm index 19deb666211..04f96becd40 100644 --- a/code/modules/vore/eating/bellymodes_datum_vr.dm +++ b/code/modules/vore/eating/bellymodes_datum_vr.dm @@ -165,12 +165,16 @@ GLOBAL_LIST_INIT(digest_modes, list()) B.change_tail_nocolor(H) B.change_wing_nocolor(H) B.change_species(H, 1, 1) // ,1) preserves coloring + H.species.create_organs(H) + H.sync_organ_dna() return null if(changes_ears_tail_wing_color && (B.check_ears(H) || B.check_tail(H) || B.check_wing(H) || B.check_species(H))) B.change_ears(H) B.change_tail(H) B.change_wing(H) B.change_species(H, 1, 2) // ,2) does not preserve coloring. + H.species.create_organs(H) + H.sync_organ_dna() return null if(changes_gender && B.check_gender(H, changes_gender_to)) B.change_gender(H, changes_gender_to, 1) diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 9ffb5d96275..cf11871d1af 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -18,6 +18,7 @@ var/revive_ready = REVIVING_READY // Only used for creatures that have the xenochimera regen ability, so far. var/metabolism = 0.0015 var/vore_taste = null // What the character tastes like + var/vore_smell = null // What the character smells like var/no_vore = FALSE // If the character/mob can vore. var/noisy = FALSE // Toggle audible hunger. var/absorbing_prey = 0 // Determines if the person is using the succubus drain or not. See station_special_abilities_vr. @@ -38,6 +39,7 @@ /hook/living_new/proc/vore_setup(mob/living/M) M.verbs += /mob/living/proc/escapeOOC M.verbs += /mob/living/proc/lick + M.verbs += /mob/living/proc/smell M.verbs += /mob/living/proc/switch_scaling if(M.no_vore) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach. return TRUE @@ -231,6 +233,7 @@ P.digest_leave_remains = src.digest_leave_remains P.allowmobvore = src.allowmobvore P.vore_taste = src.vore_taste + P.vore_smell = src.vore_smell P.permit_healbelly = src.permit_healbelly P.can_be_drop_prey = src.can_be_drop_prey P.can_be_drop_pred = src.can_be_drop_pred @@ -261,6 +264,7 @@ digest_leave_remains = P.digest_leave_remains allowmobvore = P.allowmobvore vore_taste = P.vore_taste + vore_smell = P.vore_smell permit_healbelly = P.permit_healbelly can_be_drop_prey = P.can_be_drop_prey can_be_drop_pred = P.can_be_drop_pred @@ -356,6 +360,43 @@ var/datum/reagent/R = H.touching.reagent_list[1] taste_message += " You also get the flavor of [R.taste_description] from something on them" return taste_message + + + +//This is just the above proc but switched about. +/mob/living/proc/smell(mob/living/smelled in living_mobs(1)) + set name = "Smell" + set category = "IC" + set desc = "Smell someone nearby!" + set popup_menu = FALSE + + if(!istype(smelled)) + return + if(!checkClickCooldown() || incapacitated(INCAPACITATION_ALL)) + return + + setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + visible_message("[src] smell [smelled]!","You smells [smelled]. They smell like [smelled.get_smell_message()].","Sniff!") + +/mob/living/proc/get_smell_message(allow_generic = 1) + if(!vore_smell && !allow_generic) + return FALSE + + var/smell_message = "" + if(vore_smell && (vore_smell != "")) + smell_message += "[vore_smell]" + else + if(ishuman(src)) + var/mob/living/carbon/human/H = src + smell_message += "a normal [H.custom_species ? H.custom_species : H.species.name]" + else + smell_message += "a plain old normal [src]" + + return smell_message + + + + // // OOC Escape code for pref-breaking or AFK preds // diff --git a/code/modules/vore/eating/vore_vr.dm b/code/modules/vore/eating/vore_vr.dm index 9aaa4b0cefe..416a125f492 100644 --- a/code/modules/vore/eating/vore_vr.dm +++ b/code/modules/vore/eating/vore_vr.dm @@ -51,6 +51,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE var/allowmobvore = TRUE var/list/belly_prefs = list() var/vore_taste = "nothing in particular" + var/vore_smell = "nothing in particular" var/permit_healbelly = TRUE var/can_be_drop_prey = FALSE var/can_be_drop_pred = FALSE @@ -123,6 +124,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE digest_leave_remains = json_from_file["digest_leave_remains"] allowmobvore = json_from_file["allowmobvore"] vore_taste = json_from_file["vore_taste"] + vore_smell = json_from_file["vore_smell"] permit_healbelly = json_from_file["permit_healbelly"] can_be_drop_prey = json_from_file["can_be_drop_prey"] can_be_drop_pred = json_from_file["can_be_drop_pred"] @@ -166,6 +168,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE "digest_leave_remains" = digest_leave_remains, "allowmobvore" = allowmobvore, "vore_taste" = vore_taste, + "vore_smell" = vore_smell, "permit_healbelly" = permit_healbelly, "can_be_drop_prey" = can_be_drop_prey, "can_be_drop_pred" = can_be_drop_pred, diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index 78d18a2edf8..709138c47ec 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -351,6 +351,7 @@ dat += jointext(nightmare_list, null) //AAAA dat += "
Set Your Taste" + dat += "
Set Your Smell" dat += "
Toggle Hunger Noises" //Under the last HR, save and stuff. @@ -905,6 +906,17 @@ return FALSE user.vore_taste = new_flavor + if(href_list["setsmell"]) + var/new_smell = html_encode(input(usr,"What your character smells like (40ch limit). This text will be printed to the pred after 'X smells of...' so just put something like 'strawberries and cream':","Character Smell",user.vore_smell) as text|null) + if(!new_smell) + return FALSE + + new_smell = readd_quotes(new_smell) + if(length(new_smell) > FLAVOR_MAX) + alert("Entered perfume/smell text too long. [FLAVOR_MAX] character limit.","Error!") + return FALSE + user.vore_smell = new_smell + if(href_list["toggle_dropnom_pred"]) var/choice = alert(user, "This toggle is for spontaneous, environment related vore as a predator, including drop-noms, teleporters, etc. You are currently [user.can_be_drop_pred ? " able to eat prey that you encounter by environmental actions." : "avoiding eating prey encountered in the environment."]", "", "Be Pred", "Cancel", "Don't be Pred") switch(choice) diff --git a/code/modules/xenobio/items/extracts.dm b/code/modules/xenobio/items/extracts.dm index 6368f68e15c..159bb0f1516 100644 --- a/code/modules/xenobio/items/extracts.dm +++ b/code/modules/xenobio/items/extracts.dm @@ -616,7 +616,7 @@ /obj/item/slime_extract/pink name = "pink slime extract" icon_state = "pink slime extract" - description_info = "This extract will create 20u of blood clotting agent if injected with blood. It can also create 20u of bone binding agent if injected \ + description_info = "This extract will create 30u of blood clotting agent if injected with blood. It can also create 30u of bone binding agent if injected \ with phoron. When injected with water, it will create an organ-mending agent. The slime medications have a very low threshold for overdosage, however." diff --git a/config/alienwhitelist.txt b/config/alienwhitelist.txt index d182272b991..43f188c8b1b 100644 --- a/config/alienwhitelist.txt +++ b/config/alienwhitelist.txt @@ -9,22 +9,28 @@ aruis - Xenochimera amarewolf - Xenochimera azmodan412 - Xenochimera bothnevarbackwards - Diona +bricker98 - Protean crossexonar - Protean chillyfang - Black-Eyed Shadekin +cgr - Protean flaktual - Vox funnyman2003 - Xenochimera +flurriee - Protean hawkerthegreat - Vox hollifex - Diona inuzari - Diona jademanique - Xenochimera jemli - Gutter ktccd - Diona +khanivore - Protean mewchild - Diona mewchild - Vox mrsebbi - Xenochimera natje - Xenochimera +nerdass - Protean oreganovulgaris - Xenochimera paradoxspace - Xenochimera +phoenixx0 - Vox rapidvalj - Vox rapidvalj - Common Skrellian rapidvalj - High Skrellian @@ -32,31 +38,27 @@ rikaru19xjenkins - Xenochimera rixunie - Diona rixunie - Gutter rykkastormheart - Xenochimera +rubyflamewing - Protean +radiantaurora - Protean seiga - Vox sepulchre - Vox silvertalismen - Diona silvertalismen - Vox silvertalismen - Xenochimera singo - Gutter +storesund97 - Protean +sharplight - Protean tastypred - Black-Eyed Shadekin tastypred - Xenochimera +tastypred - Protean timidvi - Diona varonis - Xenochimera verkister - Xenochimera +vitoras - Protean +voidalynx - Protean wickedtemp - Shadekin Empathy xioen - Diona xioen - Xenochimera -zalvine - Shadekin Empathy -zammyman215 - Vox -bricker98 - Protean -cgr - Protean -khanivore - Protean -storesund97 - Protean -tastypred - Protean -vitoras - Protean -voidalynx - Protean -nerdass - Protean xonkon - Protean -phoenixx0 - Vox -rubyflamewing - Protean -radiantaurora - Protean +zalvine - Shadekin Empathy +zammyman215 - Vox \ No newline at end of file diff --git a/html/font-awesome/README.MD b/html/font-awesome/README.MD new file mode 100644 index 00000000000..7d693c36f03 --- /dev/null +++ b/html/font-awesome/README.MD @@ -0,0 +1,6 @@ +Due to the fact browse_rsc can't create subdirectories, every time you update font-awesome you'll need to change relative webfont references in all.min.css +eg ../webfonts/fa-regular-400.ttf => fa-regular-400.ttf (or whatever you call it in asset datum) + +Second change is ripping out file types other than woff and eot(ie8) from the css + +Finally, removing brand related css. \ No newline at end of file diff --git a/html/font-awesome/css/all.min.css b/html/font-awesome/css/all.min.css new file mode 100644 index 00000000000..e7cdfffe751 --- /dev/null +++ b/html/font-awesome/css/all.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.9.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{animation:fa-spin 2s infinite linear}.fa-pulse{animation:fa-spin 1s infinite steps(8)}@keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-wizard:before{content:"\f6e8"}.fa-haykal:before{content:"\f666"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:auto;src:url(fa-regular-400.eot);src:url(fa-regular-400.eot?#iefix) format("embedded-opentype"),url(fa-regular-400.woff) format("woff")}.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:auto;src:url(fa-solid-900.eot);src:url(fa-solid-900.eot?#iefix) format("embedded-opentype"),url(fa-solid-900.woff) format("woff")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file diff --git a/html/font-awesome/css/v4-shims.min.css b/html/font-awesome/css/v4-shims.min.css new file mode 100644 index 00000000000..5f3fdc598c8 --- /dev/null +++ b/html/font-awesome/css/v4-shims.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.9.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa.fa-glass:before{content:"\f000"}.fa.fa-meetup{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-star-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-star-o:before{content:"\f005"}.fa.fa-close:before,.fa.fa-remove:before{content:"\f00d"}.fa.fa-gear:before{content:"\f013"}.fa.fa-trash-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-trash-o:before{content:"\f2ed"}.fa.fa-file-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-o:before{content:"\f15b"}.fa.fa-clock-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-clock-o:before{content:"\f017"}.fa.fa-arrow-circle-o-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-arrow-circle-o-down:before{content:"\f358"}.fa.fa-arrow-circle-o-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-arrow-circle-o-up:before{content:"\f35b"}.fa.fa-play-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-play-circle-o:before{content:"\f144"}.fa.fa-repeat:before,.fa.fa-rotate-right:before{content:"\f01e"}.fa.fa-refresh:before{content:"\f021"}.fa.fa-list-alt{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-dedent:before{content:"\f03b"}.fa.fa-video-camera:before{content:"\f03d"}.fa.fa-picture-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-picture-o:before{content:"\f03e"}.fa.fa-photo{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-photo:before{content:"\f03e"}.fa.fa-image{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-image:before{content:"\f03e"}.fa.fa-pencil:before{content:"\f303"}.fa.fa-map-marker:before{content:"\f3c5"}.fa.fa-pencil-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-pencil-square-o:before{content:"\f044"}.fa.fa-share-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-share-square-o:before{content:"\f14d"}.fa.fa-check-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-check-square-o:before{content:"\f14a"}.fa.fa-arrows:before{content:"\f0b2"}.fa.fa-times-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-times-circle-o:before{content:"\f057"}.fa.fa-check-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-check-circle-o:before{content:"\f058"}.fa.fa-mail-forward:before{content:"\f064"}.fa.fa-eye,.fa.fa-eye-slash{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-warning:before{content:"\f071"}.fa.fa-calendar:before{content:"\f073"}.fa.fa-arrows-v:before{content:"\f338"}.fa.fa-arrows-h:before{content:"\f337"}.fa.fa-bar-chart{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bar-chart:before{content:"\f080"}.fa.fa-bar-chart-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bar-chart-o:before{content:"\f080"}.fa.fa-facebook-square,.fa.fa-twitter-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-gears:before{content:"\f085"}.fa.fa-thumbs-o-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-thumbs-o-up:before{content:"\f164"}.fa.fa-thumbs-o-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-thumbs-o-down:before{content:"\f165"}.fa.fa-heart-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-heart-o:before{content:"\f004"}.fa.fa-sign-out:before{content:"\f2f5"}.fa.fa-linkedin-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-linkedin-square:before{content:"\f08c"}.fa.fa-thumb-tack:before{content:"\f08d"}.fa.fa-external-link:before{content:"\f35d"}.fa.fa-sign-in:before{content:"\f2f6"}.fa.fa-github-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-lemon-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-lemon-o:before{content:"\f094"}.fa.fa-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-square-o:before{content:"\f0c8"}.fa.fa-bookmark-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bookmark-o:before{content:"\f02e"}.fa.fa-facebook,.fa.fa-twitter{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-facebook:before{content:"\f39e"}.fa.fa-facebook-f{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-facebook-f:before{content:"\f39e"}.fa.fa-github{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-credit-card{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-feed:before{content:"\f09e"}.fa.fa-hdd-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hdd-o:before{content:"\f0a0"}.fa.fa-hand-o-right{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-o-right:before{content:"\f0a4"}.fa.fa-hand-o-left{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-o-left:before{content:"\f0a5"}.fa.fa-hand-o-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-o-up:before{content:"\f0a6"}.fa.fa-hand-o-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-o-down:before{content:"\f0a7"}.fa.fa-arrows-alt:before{content:"\f31e"}.fa.fa-group:before{content:"\f0c0"}.fa.fa-chain:before{content:"\f0c1"}.fa.fa-scissors:before{content:"\f0c4"}.fa.fa-files-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-files-o:before{content:"\f0c5"}.fa.fa-floppy-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-floppy-o:before{content:"\f0c7"}.fa.fa-navicon:before,.fa.fa-reorder:before{content:"\f0c9"}.fa.fa-google-plus,.fa.fa-google-plus-square,.fa.fa-pinterest,.fa.fa-pinterest-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-google-plus:before{content:"\f0d5"}.fa.fa-money{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-money:before{content:"\f3d1"}.fa.fa-unsorted:before{content:"\f0dc"}.fa.fa-sort-desc:before{content:"\f0dd"}.fa.fa-sort-asc:before{content:"\f0de"}.fa.fa-linkedin{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-linkedin:before{content:"\f0e1"}.fa.fa-rotate-left:before{content:"\f0e2"}.fa.fa-legal:before{content:"\f0e3"}.fa.fa-dashboard:before,.fa.fa-tachometer:before{content:"\f3fd"}.fa.fa-comment-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-comment-o:before{content:"\f075"}.fa.fa-comments-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-comments-o:before{content:"\f086"}.fa.fa-flash:before{content:"\f0e7"}.fa.fa-clipboard,.fa.fa-paste{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-paste:before{content:"\f328"}.fa.fa-lightbulb-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-lightbulb-o:before{content:"\f0eb"}.fa.fa-exchange:before{content:"\f362"}.fa.fa-cloud-download:before{content:"\f381"}.fa.fa-cloud-upload:before{content:"\f382"}.fa.fa-bell-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bell-o:before{content:"\f0f3"}.fa.fa-cutlery:before{content:"\f2e7"}.fa.fa-file-text-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-text-o:before{content:"\f15c"}.fa.fa-building-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-building-o:before{content:"\f1ad"}.fa.fa-hospital-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hospital-o:before{content:"\f0f8"}.fa.fa-tablet:before{content:"\f3fa"}.fa.fa-mobile-phone:before,.fa.fa-mobile:before{content:"\f3cd"}.fa.fa-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-circle-o:before{content:"\f111"}.fa.fa-mail-reply:before{content:"\f3e5"}.fa.fa-github-alt{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-folder-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-folder-o:before{content:"\f07b"}.fa.fa-folder-open-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-folder-open-o:before{content:"\f07c"}.fa.fa-smile-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-smile-o:before{content:"\f118"}.fa.fa-frown-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-frown-o:before{content:"\f119"}.fa.fa-meh-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-meh-o:before{content:"\f11a"}.fa.fa-keyboard-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-keyboard-o:before{content:"\f11c"}.fa.fa-flag-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-flag-o:before{content:"\f024"}.fa.fa-mail-reply-all:before{content:"\f122"}.fa.fa-star-half-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-star-half-o:before{content:"\f089"}.fa.fa-star-half-empty{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-star-half-empty:before{content:"\f089"}.fa.fa-star-half-full{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-star-half-full:before{content:"\f089"}.fa.fa-code-fork:before{content:"\f126"}.fa.fa-chain-broken:before{content:"\f127"}.fa.fa-shield:before{content:"\f3ed"}.fa.fa-calendar-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-o:before{content:"\f133"}.fa.fa-css3,.fa.fa-html5,.fa.fa-maxcdn{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-ticket:before{content:"\f3ff"}.fa.fa-minus-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-minus-square-o:before{content:"\f146"}.fa.fa-level-up:before{content:"\f3bf"}.fa.fa-level-down:before{content:"\f3be"}.fa.fa-pencil-square:before{content:"\f14b"}.fa.fa-external-link-square:before{content:"\f360"}.fa.fa-compass{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-down:before{content:"\f150"}.fa.fa-toggle-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-toggle-down:before{content:"\f150"}.fa.fa-caret-square-o-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-up:before{content:"\f151"}.fa.fa-toggle-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-toggle-up:before{content:"\f151"}.fa.fa-caret-square-o-right{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-right:before{content:"\f152"}.fa.fa-toggle-right{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-toggle-right:before{content:"\f152"}.fa.fa-eur:before,.fa.fa-euro:before{content:"\f153"}.fa.fa-gbp:before{content:"\f154"}.fa.fa-dollar:before,.fa.fa-usd:before{content:"\f155"}.fa.fa-inr:before,.fa.fa-rupee:before{content:"\f156"}.fa.fa-cny:before,.fa.fa-jpy:before,.fa.fa-rmb:before,.fa.fa-yen:before{content:"\f157"}.fa.fa-rouble:before,.fa.fa-rub:before,.fa.fa-ruble:before{content:"\f158"}.fa.fa-krw:before,.fa.fa-won:before{content:"\f159"}.fa.fa-bitcoin,.fa.fa-btc{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-bitcoin:before{content:"\f15a"}.fa.fa-file-text:before{content:"\f15c"}.fa.fa-sort-alpha-asc:before{content:"\f15d"}.fa.fa-sort-alpha-desc:before{content:"\f15e"}.fa.fa-sort-amount-asc:before{content:"\f160"}.fa.fa-sort-amount-desc:before{content:"\f161"}.fa.fa-sort-numeric-asc:before{content:"\f162"}.fa.fa-sort-numeric-desc:before{content:"\f163"}.fa.fa-xing,.fa.fa-xing-square,.fa.fa-youtube,.fa.fa-youtube-play,.fa.fa-youtube-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-youtube-play:before{content:"\f167"}.fa.fa-adn,.fa.fa-bitbucket,.fa.fa-bitbucket-square,.fa.fa-dropbox,.fa.fa-flickr,.fa.fa-instagram,.fa.fa-stack-overflow{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-bitbucket-square:before{content:"\f171"}.fa.fa-tumblr,.fa.fa-tumblr-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-long-arrow-down:before{content:"\f309"}.fa.fa-long-arrow-up:before{content:"\f30c"}.fa.fa-long-arrow-left:before{content:"\f30a"}.fa.fa-long-arrow-right:before{content:"\f30b"}.fa.fa-android,.fa.fa-apple,.fa.fa-dribbble,.fa.fa-foursquare,.fa.fa-gittip,.fa.fa-gratipay,.fa.fa-linux,.fa.fa-skype,.fa.fa-trello,.fa.fa-windows{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-gittip:before{content:"\f184"}.fa.fa-sun-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-sun-o:before{content:"\f185"}.fa.fa-moon-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-moon-o:before{content:"\f186"}.fa.fa-pagelines,.fa.fa-renren,.fa.fa-stack-exchange,.fa.fa-vk,.fa.fa-weibo{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-arrow-circle-o-right{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-arrow-circle-o-right:before{content:"\f35a"}.fa.fa-arrow-circle-o-left{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-arrow-circle-o-left:before{content:"\f359"}.fa.fa-caret-square-o-left{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-left:before{content:"\f191"}.fa.fa-toggle-left{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-toggle-left:before{content:"\f191"}.fa.fa-dot-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-dot-circle-o:before{content:"\f192"}.fa.fa-vimeo-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-try:before,.fa.fa-turkish-lira:before{content:"\f195"}.fa.fa-plus-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-plus-square-o:before{content:"\f0fe"}.fa.fa-openid,.fa.fa-slack,.fa.fa-wordpress{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-bank:before,.fa.fa-institution:before{content:"\f19c"}.fa.fa-mortar-board:before{content:"\f19d"}.fa.fa-delicious,.fa.fa-digg,.fa.fa-drupal,.fa.fa-google,.fa.fa-joomla,.fa.fa-pied-piper-alt,.fa.fa-pied-piper-pp,.fa.fa-reddit,.fa.fa-reddit-square,.fa.fa-stumbleupon,.fa.fa-stumbleupon-circle,.fa.fa-yahoo{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-spoon:before{content:"\f2e5"}.fa.fa-behance,.fa.fa-behance-square,.fa.fa-steam,.fa.fa-steam-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-automobile:before{content:"\f1b9"}.fa.fa-cab:before{content:"\f1ba"}.fa.fa-envelope-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-envelope-o:before{content:"\f0e0"}.fa.fa-deviantart,.fa.fa-soundcloud{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-file-pdf-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-pdf-o:before{content:"\f1c1"}.fa.fa-file-word-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-word-o:before{content:"\f1c2"}.fa.fa-file-excel-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-excel-o:before{content:"\f1c3"}.fa.fa-file-powerpoint-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-powerpoint-o:before{content:"\f1c4"}.fa.fa-file-image-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-image-o:before{content:"\f1c5"}.fa.fa-file-photo-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-photo-o:before{content:"\f1c5"}.fa.fa-file-picture-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-picture-o:before{content:"\f1c5"}.fa.fa-file-archive-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-archive-o:before{content:"\f1c6"}.fa.fa-file-zip-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-zip-o:before{content:"\f1c6"}.fa.fa-file-audio-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-audio-o:before{content:"\f1c7"}.fa.fa-file-sound-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-sound-o:before{content:"\f1c7"}.fa.fa-file-video-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-video-o:before{content:"\f1c8"}.fa.fa-file-movie-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-movie-o:before{content:"\f1c8"}.fa.fa-file-code-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-code-o:before{content:"\f1c9"}.fa.fa-codepen,.fa.fa-jsfiddle,.fa.fa-vine{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-life-bouy,.fa.fa-life-ring{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-life-bouy:before{content:"\f1cd"}.fa.fa-life-buoy{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-life-buoy:before{content:"\f1cd"}.fa.fa-life-saver{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-life-saver:before{content:"\f1cd"}.fa.fa-support{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-support:before{content:"\f1cd"}.fa.fa-circle-o-notch:before{content:"\f1ce"}.fa.fa-ra,.fa.fa-rebel{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-ra:before{content:"\f1d0"}.fa.fa-resistance{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-resistance:before{content:"\f1d0"}.fa.fa-empire,.fa.fa-ge{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-ge:before{content:"\f1d1"}.fa.fa-git,.fa.fa-git-square,.fa.fa-hacker-news,.fa.fa-y-combinator-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-y-combinator-square:before{content:"\f1d4"}.fa.fa-yc-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-yc-square:before{content:"\f1d4"}.fa.fa-qq,.fa.fa-tencent-weibo,.fa.fa-wechat,.fa.fa-weixin{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-wechat:before{content:"\f1d7"}.fa.fa-send:before{content:"\f1d8"}.fa.fa-paper-plane-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-paper-plane-o:before{content:"\f1d8"}.fa.fa-send-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-send-o:before{content:"\f1d8"}.fa.fa-circle-thin{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-circle-thin:before{content:"\f111"}.fa.fa-header:before{content:"\f1dc"}.fa.fa-sliders:before{content:"\f1de"}.fa.fa-futbol-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-futbol-o:before{content:"\f1e3"}.fa.fa-soccer-ball-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-soccer-ball-o:before{content:"\f1e3"}.fa.fa-slideshare,.fa.fa-twitch,.fa.fa-yelp{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-newspaper-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-newspaper-o:before{content:"\f1ea"}.fa.fa-cc-amex,.fa.fa-cc-discover,.fa.fa-cc-mastercard,.fa.fa-cc-paypal,.fa.fa-cc-stripe,.fa.fa-cc-visa,.fa.fa-google-wallet,.fa.fa-paypal{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-bell-slash-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bell-slash-o:before{content:"\f1f6"}.fa.fa-trash:before{content:"\f2ed"}.fa.fa-copyright{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-eyedropper:before{content:"\f1fb"}.fa.fa-area-chart:before{content:"\f1fe"}.fa.fa-pie-chart:before{content:"\f200"}.fa.fa-line-chart:before{content:"\f201"}.fa.fa-angellist,.fa.fa-ioxhost,.fa.fa-lastfm,.fa.fa-lastfm-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-cc{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-cc:before{content:"\f20a"}.fa.fa-ils:before,.fa.fa-shekel:before,.fa.fa-sheqel:before{content:"\f20b"}.fa.fa-meanpath{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-meanpath:before{content:"\f2b4"}.fa.fa-buysellads,.fa.fa-connectdevelop,.fa.fa-dashcube,.fa.fa-forumbee,.fa.fa-leanpub,.fa.fa-sellsy,.fa.fa-shirtsinbulk,.fa.fa-simplybuilt,.fa.fa-skyatlas{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-diamond{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-diamond:before{content:"\f3a5"}.fa.fa-intersex:before{content:"\f224"}.fa.fa-facebook-official{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-facebook-official:before{content:"\f09a"}.fa.fa-pinterest-p,.fa.fa-whatsapp{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-hotel:before{content:"\f236"}.fa.fa-medium,.fa.fa-viacoin,.fa.fa-y-combinator,.fa.fa-yc{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-yc:before{content:"\f23b"}.fa.fa-expeditedssl,.fa.fa-opencart,.fa.fa-optin-monster{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-battery-4:before,.fa.fa-battery:before{content:"\f240"}.fa.fa-battery-3:before{content:"\f241"}.fa.fa-battery-2:before{content:"\f242"}.fa.fa-battery-1:before{content:"\f243"}.fa.fa-battery-0:before{content:"\f244"}.fa.fa-object-group,.fa.fa-object-ungroup,.fa.fa-sticky-note-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-sticky-note-o:before{content:"\f249"}.fa.fa-cc-diners-club,.fa.fa-cc-jcb{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-clone,.fa.fa-hourglass-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hourglass-o:before{content:"\f254"}.fa.fa-hourglass-1:before{content:"\f251"}.fa.fa-hourglass-2:before{content:"\f252"}.fa.fa-hourglass-3:before{content:"\f253"}.fa.fa-hand-rock-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-rock-o:before{content:"\f255"}.fa.fa-hand-grab-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-grab-o:before{content:"\f255"}.fa.fa-hand-paper-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-paper-o:before{content:"\f256"}.fa.fa-hand-stop-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-stop-o:before{content:"\f256"}.fa.fa-hand-scissors-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-scissors-o:before{content:"\f257"}.fa.fa-hand-lizard-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-lizard-o:before{content:"\f258"}.fa.fa-hand-spock-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-spock-o:before{content:"\f259"}.fa.fa-hand-pointer-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-pointer-o:before{content:"\f25a"}.fa.fa-hand-peace-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-peace-o:before{content:"\f25b"}.fa.fa-registered{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-chrome,.fa.fa-creative-commons,.fa.fa-firefox,.fa.fa-get-pocket,.fa.fa-gg,.fa.fa-gg-circle,.fa.fa-internet-explorer,.fa.fa-odnoklassniki,.fa.fa-odnoklassniki-square,.fa.fa-opera,.fa.fa-safari,.fa.fa-tripadvisor,.fa.fa-wikipedia-w{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-television:before{content:"\f26c"}.fa.fa-500px,.fa.fa-amazon,.fa.fa-contao{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-calendar-plus-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-plus-o:before{content:"\f271"}.fa.fa-calendar-minus-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-minus-o:before{content:"\f272"}.fa.fa-calendar-times-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-times-o:before{content:"\f273"}.fa.fa-calendar-check-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-check-o:before{content:"\f274"}.fa.fa-map-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-map-o:before{content:"\f279"}.fa.fa-commenting:before{content:"\f4ad"}.fa.fa-commenting-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-commenting-o:before{content:"\f4ad"}.fa.fa-houzz,.fa.fa-vimeo{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-vimeo:before{content:"\f27d"}.fa.fa-black-tie,.fa.fa-edge,.fa.fa-fonticons,.fa.fa-reddit-alien{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-credit-card-alt:before{content:"\f09d"}.fa.fa-codiepie,.fa.fa-fort-awesome,.fa.fa-mixcloud,.fa.fa-modx,.fa.fa-product-hunt,.fa.fa-scribd,.fa.fa-usb{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-pause-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-pause-circle-o:before{content:"\f28b"}.fa.fa-stop-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-stop-circle-o:before{content:"\f28d"}.fa.fa-bluetooth,.fa.fa-bluetooth-b,.fa.fa-envira,.fa.fa-gitlab,.fa.fa-wheelchair-alt,.fa.fa-wpbeginner,.fa.fa-wpforms{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-wheelchair-alt:before{content:"\f368"}.fa.fa-question-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-question-circle-o:before{content:"\f059"}.fa.fa-volume-control-phone:before{content:"\f2a0"}.fa.fa-asl-interpreting:before{content:"\f2a3"}.fa.fa-deafness:before,.fa.fa-hard-of-hearing:before{content:"\f2a4"}.fa.fa-glide,.fa.fa-glide-g{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-signing:before{content:"\f2a7"}.fa.fa-first-order,.fa.fa-google-plus-official,.fa.fa-pied-piper,.fa.fa-snapchat,.fa.fa-snapchat-ghost,.fa.fa-snapchat-square,.fa.fa-themeisle,.fa.fa-viadeo,.fa.fa-viadeo-square,.fa.fa-yoast{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-google-plus-official:before{content:"\f2b3"}.fa.fa-google-plus-circle{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-google-plus-circle:before{content:"\f2b3"}.fa.fa-fa,.fa.fa-font-awesome{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-fa:before{content:"\f2b4"}.fa.fa-handshake-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-handshake-o:before{content:"\f2b5"}.fa.fa-envelope-open-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-envelope-open-o:before{content:"\f2b6"}.fa.fa-linode{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-address-book-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-address-book-o:before{content:"\f2b9"}.fa.fa-vcard:before{content:"\f2bb"}.fa.fa-address-card-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-address-card-o:before{content:"\f2bb"}.fa.fa-vcard-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-vcard-o:before{content:"\f2bb"}.fa.fa-user-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-user-circle-o:before{content:"\f2bd"}.fa.fa-user-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-user-o:before{content:"\f007"}.fa.fa-id-badge{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-drivers-license:before{content:"\f2c2"}.fa.fa-id-card-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-id-card-o:before{content:"\f2c2"}.fa.fa-drivers-license-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-drivers-license-o:before{content:"\f2c2"}.fa.fa-free-code-camp,.fa.fa-quora,.fa.fa-telegram{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-thermometer-4:before,.fa.fa-thermometer:before{content:"\f2c7"}.fa.fa-thermometer-3:before{content:"\f2c8"}.fa.fa-thermometer-2:before{content:"\f2c9"}.fa.fa-thermometer-1:before{content:"\f2ca"}.fa.fa-thermometer-0:before{content:"\f2cb"}.fa.fa-bathtub:before,.fa.fa-s15:before{content:"\f2cd"}.fa.fa-window-maximize,.fa.fa-window-restore{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-times-rectangle:before{content:"\f410"}.fa.fa-window-close-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-window-close-o:before{content:"\f410"}.fa.fa-times-rectangle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-times-rectangle-o:before{content:"\f410"}.fa.fa-bandcamp,.fa.fa-eercast,.fa.fa-etsy,.fa.fa-grav,.fa.fa-imdb,.fa.fa-ravelry{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-eercast:before{content:"\f2da"}.fa.fa-snowflake-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-snowflake-o:before{content:"\f2dc"}.fa.fa-spotify,.fa.fa-superpowers,.fa.fa-wpexplorer{font-family:"Font Awesome 5 Brands";font-weight:400} \ No newline at end of file diff --git a/html/font-awesome/webfonts/fa-regular-400.eot b/html/font-awesome/webfonts/fa-regular-400.eot new file mode 100644 index 00000000000..d62be2fad88 Binary files /dev/null and b/html/font-awesome/webfonts/fa-regular-400.eot differ diff --git a/html/font-awesome/webfonts/fa-regular-400.woff b/html/font-awesome/webfonts/fa-regular-400.woff new file mode 100644 index 00000000000..43b1a9ae49d Binary files /dev/null and b/html/font-awesome/webfonts/fa-regular-400.woff differ diff --git a/html/font-awesome/webfonts/fa-solid-900.eot b/html/font-awesome/webfonts/fa-solid-900.eot new file mode 100644 index 00000000000..c77baa8d46a Binary files /dev/null and b/html/font-awesome/webfonts/fa-solid-900.eot differ diff --git a/html/font-awesome/webfonts/fa-solid-900.woff b/html/font-awesome/webfonts/fa-solid-900.woff new file mode 100644 index 00000000000..77c1786227f Binary files /dev/null and b/html/font-awesome/webfonts/fa-solid-900.woff differ diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index 0c0dce59bc4..e42df29d4b1 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ diff --git a/icons/mob/items/lefthand_holder.dmi b/icons/mob/items/lefthand_holder.dmi index d629c657cec..14cd2406f09 100644 Binary files a/icons/mob/items/lefthand_holder.dmi and b/icons/mob/items/lefthand_holder.dmi differ diff --git a/icons/mob/items/righthand_holder.dmi b/icons/mob/items/righthand_holder.dmi index c1e0563ec44..19bb1967f60 100644 Binary files a/icons/mob/items/righthand_holder.dmi and b/icons/mob/items/righthand_holder.dmi differ diff --git a/icons/mob/map_backgrounds.dmi b/icons/mob/map_backgrounds.dmi new file mode 100644 index 00000000000..dc6e3e46b16 Binary files /dev/null and b/icons/mob/map_backgrounds.dmi differ diff --git a/icons/mob/uniform_1.dmi b/icons/mob/uniform_1.dmi index cd1b4d1e4ea..32b15484a09 100644 Binary files a/icons/mob/uniform_1.dmi and b/icons/mob/uniform_1.dmi differ diff --git a/icons/obj/closets/bases/crate.dmi b/icons/obj/closets/bases/crate.dmi index e8946f3b358..83500acb3bd 100644 Binary files a/icons/obj/closets/bases/crate.dmi and b/icons/obj/closets/bases/crate.dmi differ diff --git a/icons/obj/closets/bases/large_crate.dmi b/icons/obj/closets/bases/large_crate.dmi index 1cdac277834..fd3400ed729 100644 Binary files a/icons/obj/closets/bases/large_crate.dmi and b/icons/obj/closets/bases/large_crate.dmi differ diff --git a/icons/obj/closets/decals/crate.dmi b/icons/obj/closets/decals/crate.dmi index 533bf207281..1fce07d8820 100644 Binary files a/icons/obj/closets/decals/crate.dmi and b/icons/obj/closets/decals/crate.dmi differ diff --git a/icons/obj/closets/decals/large_crate.dmi b/icons/obj/closets/decals/large_crate.dmi index 48765702659..2a9ff643805 100644 Binary files a/icons/obj/closets/decals/large_crate.dmi and b/icons/obj/closets/decals/large_crate.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 03a5e7fb09e..998d31b2f8b 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/uniforms_1.dmi b/icons/obj/clothing/uniforms_1.dmi index 35eb06f7a2c..47b06c8b297 100644 Binary files a/icons/obj/clothing/uniforms_1.dmi and b/icons/obj/clothing/uniforms_1.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 9b7ad90e8f0..5bf804c9bcd 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index faee20d4426..b1a17d7178b 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -1194,6 +1194,7 @@ window "mapwindow" text-color = none is-default = true saved-params = "icon-size" + zoom-mode = "distort" on-show = ".winset\"mainwindow.mainvsplit.left=mapwindow\"" on-hide = ".winset\"mainwindow.mainvsplit.left=\"" diff --git a/maps/southern_cross/datums/supplypacks/munitions.dm b/maps/southern_cross/datums/supplypacks/munitions.dm index fa24358cebc..ee51fc4f0c3 100644 --- a/maps/southern_cross/datums/supplypacks/munitions.dm +++ b/maps/southern_cross/datums/supplypacks/munitions.dm @@ -10,7 +10,7 @@ /obj/item/ammo_magazine/clip/c762/hunter = 6 ) cost = 50 - containertype = /obj/structure/closet/crate/secure/weapon + containertype = /obj/structure/closet/crate/secure/hedberg containername = "Hunting Rifle crate" access = access_explorer @@ -20,7 +20,7 @@ /obj/item/weapon/gun/energy/phasegun = 2, ) cost = 25 - containertype = /obj/structure/closet/crate/secure/weapon + containertype = /obj/structure/closet/crate/secure/ward containername = "Phase Carbine crate" access = access_explorer @@ -30,6 +30,6 @@ /obj/item/weapon/gun/energy/phasegun/rifle = 2, ) cost = 50 - containertype = /obj/structure/closet/crate/secure/weapon + containertype = /obj/structure/closet/crate/secure/ward containername = "Phase Rifle crate" access = access_explorer \ No newline at end of file diff --git a/maps/southern_cross/southern_cross-1.dmm b/maps/southern_cross/southern_cross-1.dmm index b4434c8969f..1bf367399d3 100644 --- a/maps/southern_cross/southern_cross-1.dmm +++ b/maps/southern_cross/southern_cross-1.dmm @@ -302,7 +302,7 @@ "afP" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 1},/turf/simulated/floor/plating,/area/maintenance/firstdeck/foreport) "afQ" = (/obj/machinery/atmospherics/pipe/simple/hidden/universal{dir = 4},/obj/effect/floor_decal/industrial/warning/corner{dir = 1},/turf/simulated/floor/plating,/area/maintenance/firstdeck/foreport) "afR" = (/obj/machinery/atmospherics/valve/shutoff{name = "Deck 1 Fore Starboard automatic shutoff valve"},/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) -"afS" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 9; icon_state = "intact"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/closet/crate,/obj/item/weapon/toy/xmas_cracker,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/firstdeck/foreport) +"afS" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 9; icon_state = "intact"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/item/weapon/toy/xmas_cracker,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/firstdeck/foreport) "afT" = (/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/obj/item/device/paicard,/turf/simulated/floor/plating,/area/construction/firstdeck/construction5) "afU" = (/obj/effect/decal/cleanable/blood/oil/streak{amount = 0},/obj/item/weapon/tool/wirecutters,/turf/simulated/floor/tiled,/area/construction/firstdeck/construction5) "afV" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/obj/machinery/shower{dir = 4; icon_state = "shower"; pixel_x = 5; pixel_y = -1},/obj/structure/curtain/open/shower,/turf/simulated/floor/tiled/freezer,/area/crew_quarters/toilet/firstdeck) @@ -318,8 +318,8 @@ "agf" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor/tiled/dark,/area/security/nuke_storage) "agg" = (/obj/structure/filingcabinet/security{name = "Security Records"},/turf/simulated/floor/tiled/dark,/area/security/nuke_storage) "agh" = (/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) -"agi" = (/obj/structure/closet/crate,/obj/item/weapon/storage/backpack,/obj/item/device/multitool,/obj/item/device/multitool,/obj/item/device/assembly/prox_sensor,/obj/item/device/flashlight,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) -"agj" = (/obj/structure/closet/crate,/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/clean,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/obj/item/toy/xmastree,/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) +"agi" = (/obj/item/weapon/storage/backpack,/obj/item/device/multitool,/obj/item/device/multitool,/obj/item/device/assembly/prox_sensor,/obj/item/device/flashlight,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) +"agj" = (/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/clean,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/obj/item/toy/xmastree,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) "agk" = (/obj/structure/table/rack,/obj/item/weapon/flame/lighter/random,/obj/random/maintenance/clean,/obj/random/cigarettes,/obj/random/maintenance/clean,/obj/effect/floor_decal/industrial/warning{dir = 4},/obj/random/cash,/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) "agl" = (/obj/effect/floor_decal/rust,/turf/simulated/floor/plating,/area/hangar/three) "agm" = (/turf/simulated/floor/reinforced,/area/hangar/three) @@ -350,7 +350,7 @@ "agL" = (/obj/structure/closet/crate,/obj/item/stack/material/gold,/obj/item/weapon/storage/belt/champion,/obj/item/stack/material/gold,/obj/item/stack/material/gold,/obj/item/stack/material/gold,/obj/item/stack/material/gold,/obj/item/stack/material/gold,/obj/item/stack/material/silver,/obj/item/stack/material/silver,/obj/item/stack/material/silver,/obj/item/stack/material/silver,/obj/item/stack/material/silver,/obj/item/stack/material/silver,/turf/simulated/floor/tiled/dark,/area/security/nuke_storage) "agM" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/hologram/holopad,/turf/simulated/floor/tiled/dark,/area/security/nuke_storage) "agN" = (/obj/structure/filingcabinet/medical{desc = "A large cabinet with hard copy medical records."; name = "Medical Records"},/turf/simulated/floor/tiled/dark,/area/security/nuke_storage) -"agO" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/closet/crate,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/plating,/area/maintenance/firstdeck/foreport) +"agO" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/firstdeck/foreport) "agP" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plating,/area/maintenance/firstdeck/foreport) "agQ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) "agR" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) @@ -531,7 +531,7 @@ "akk" = (/obj/structure/bed/chair{dir = 1},/obj/structure/closet/walllocker/emerglocker{pixel_x = -28},/obj/effect/shuttle_landmark/southern_cross/escape_pod1/station{base_area = /area/hallway/primary/firstdeck/auxdockfore},/turf/simulated/shuttle/floor,/area/shuttle/escape_pod1/station) "akl" = (/obj/machinery/door/airlock/voidcraft/vertical{frequency = 1380; id_tag = "shuttle1_outer"; name = "External Access"},/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1380; master_tag = "shuttle1_shuttle"; name = "exterior access button"; pixel_x = 0; pixel_y = 26; req_access = null},/turf/simulated/shuttle/floor/black,/area/shuttle/shuttle1/start) "akm" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plating,/area/maintenance/firstdeck/foreport) -"akn" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/random/maintenance/cargo,/obj/structure/closet/crate,/obj/random/maintenance/cargo,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/turf/simulated/floor,/area/maintenance/firstdeck/foreport) +"akn" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/obj/random/crate,/turf/simulated/floor,/area/maintenance/firstdeck/foreport) "ako" = (/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fpcenter) "akp" = (/obj/machinery/light{dir = 1},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fpcenter) "akq" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/turf/simulated/floor/tiled/monotile,/area/hallway/primary/firstdeck/fpcenter) @@ -564,7 +564,7 @@ "akR" = (/obj/effect/floor_decal/industrial/warning{dir = 6},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 1; frequency = 1380; id_tag = "shuttle1_pump"},/obj/structure/closet/emcloset,/turf/simulated/shuttle/floor/black,/area/shuttle/shuttle1/start) "akS" = (/obj/machinery/shuttle_sensor{dir = 5; id_tag = "shuttle1sens_exp"},/turf/simulated/shuttle/wall/voidcraft/blue,/area/shuttle/shuttle1/start) "akT" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/light/spot{dir = 4},/obj/machinery/camera/network/first_deck{c_tag = "Hangar One - Aft Starboard"; dir = 8},/turf/simulated/floor/tiled/monotile,/area/hangar/one) -"akU" = (/obj/structure/closet/crate,/obj/random/action_figure,/obj/random/action_figure,/obj/random/action_figure,/obj/random/action_figure,/obj/random/maintenance/clean,/obj/random/toy,/obj/item/weapon/toy/xmas_cracker,/turf/simulated/floor,/area/maintenance/firstdeck/foreport) +"akU" = (/obj/random/action_figure,/obj/random/action_figure,/obj/random/action_figure,/obj/random/action_figure,/obj/random/maintenance/clean,/obj/random/toy,/obj/item/weapon/toy/xmas_cracker,/obj/random/crate,/turf/simulated/floor,/area/maintenance/firstdeck/foreport) "akV" = (/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fpcenter) "akW" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fpcenter) "akX" = (/obj/effect/floor_decal/borderfloor,/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/effect/floor_decal/corner/green/border,/obj/effect/floor_decal/borderfloor/corner2,/obj/effect/floor_decal/corner/green/bordercorner2,/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fpcenter) @@ -584,7 +584,7 @@ "all" = (/obj/effect/floor_decal/borderfloor,/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/effect/floor_decal/corner/green/border,/obj/effect/floor_decal/borderfloor/corner2{dir = 9},/obj/effect/floor_decal/corner/green/bordercorner2{dir = 9},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fscenter) "alm" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fscenter) "aln" = (/obj/structure/cable/green{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fscenter) -"alo" = (/obj/random/powercell,/obj/random/powercell,/obj/random/powercell,/obj/random/powercell,/obj/random/toolbox,/obj/effect/decal/cleanable/molten_item,/obj/structure/closet/crate,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/structure/catwalk,/turf/simulated/floor,/area/maintenance/firstdeck/forestarboard) +"alo" = (/obj/random/powercell,/obj/random/powercell,/obj/random/powercell,/obj/random/powercell,/obj/random/toolbox,/obj/effect/decal/cleanable/molten_item,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/structure/catwalk,/obj/random/crate,/turf/simulated/floor,/area/maintenance/firstdeck/forestarboard) "alp" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/light/spot{dir = 8},/obj/machinery/camera/network/first_deck{c_tag = "Hangar Three - Aft Port"; dir = 4},/turf/simulated/floor/tiled/monotile,/area/hangar/three) "alq" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/light/spot{dir = 4},/obj/machinery/camera/network/first_deck{c_tag = "Hangar Three - Aft Starboard"; dir = 8},/turf/simulated/floor/tiled/monotile,/area/hangar/three) "alr" = (/turf/simulated/wall/r_wall,/area/maintenance/firstdeck/centralstarboard) @@ -661,8 +661,8 @@ "amK" = (/turf/simulated/wall,/area/tcomm/computer) "amL" = (/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor/tiled/dark,/area/hallway/primary/firstdeck/fscenter) "amM" = (/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fscenter) -"amN" = (/obj/structure/closet/crate/medical,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/maintenance/clean,/turf/simulated/floor,/area/maintenance/firstdeck/forestarboard) -"amO" = (/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/green/border{dir = 8},/obj/structure/closet/crate,/turf/simulated/floor/tiled,/area/hangar/three) +"amN" = (/turf/simulated/floor/reinforced,/obj/structure/shuttle/engine/propulsion{icon_state = "burst_l"},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/shuttle1/start) +"amO" = (/turf/simulated/floor/reinforced,/obj/structure/shuttle/engine/propulsion{icon_state = "burst_r"},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/shuttle1/start) "amP" = (/obj/structure/extinguisher_cabinet{pixel_x = 25},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/green/border{dir = 4},/turf/simulated/floor/tiled,/area/hangar/three) "amQ" = (/turf/simulated/floor/airless,/area/rnd/xenobiology/xenoflora) "amR" = (/obj/structure/bed/chair{dir = 1},/obj/machinery/vending/wallmed1{layer = 3.3; name = "Emergency NanoMed"; pixel_x = -28; pixel_y = 0},/turf/simulated/shuttle/floor/white,/area/shuttle/large_escape_pod2/station) @@ -693,7 +693,7 @@ "anq" = (/obj/structure/cable/cyan{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/atmospherics/pipe/manifold/hidden{dir = 4; icon_state = "map"},/obj/structure/catwalk,/turf/simulated/floor/plating,/area/tcomm/computer) "anr" = (/obj/machinery/atmospherics/unary/vent_scrubber/on,/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fscenter) "ans" = (/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/obj/structure/cable{d2 = 2; icon_state = "0-2"; pixel_y = 0},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/green/border{dir = 4},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/fscenter) -"ant" = (/obj/structure/closet/crate,/obj/item/weapon/tank/emergency/oxygen/engi,/obj/item/weapon/tank/emergency/oxygen/double,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) +"ant" = (/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/maintenance/clean,/obj/random/crate,/turf/simulated/floor,/area/maintenance/firstdeck/forestarboard) "anu" = (/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/green/border{dir = 8},/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/obj/machinery/space_heater,/turf/simulated/floor/tiled,/area/hangar/three) "anv" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled/monotile,/area/hangar/three) "anw" = (/obj/effect/floor_decal/borderfloorblack/corner{dir = 4},/obj/effect/floor_decal/industrial/danger/corner{dir = 4},/turf/simulated/floor/tiled,/area/hangar/three) @@ -704,7 +704,7 @@ "anB" = (/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 2; external_pressure_bound = 140; external_pressure_bound_default = 140; icon_state = "map_vent_out"; pressure_checks = 1; pressure_checks_default = 1; use_power = 1},/turf/simulated/floor/airless,/area/rnd/xenobiology/xenoflora) "anC" = (/obj/machinery/door/firedoor/border_only,/obj/effect/wingrille_spawn/reinforced,/turf/simulated/floor/plating,/area/rnd/xenobiology/xenoflora_isolation) "anD" = (/obj/machinery/door/airlock/external{frequency = 1380; icon_state = "door_locked"; id_tag = "large_escape_pod_2_hatch"; locked = 1; name = "Large Escape Pod Hatch 2"; req_access = list(13)},/turf/simulated/shuttle/floor,/area/shuttle/large_escape_pod2/station) -"anE" = (/turf/simulated/floor/reinforced,/obj/structure/shuttle/engine/propulsion{icon_state = "burst_l"},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/shuttle1/start) +"anE" = (/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/green/border{dir = 8},/obj/random/crate,/turf/simulated/floor/tiled,/area/hangar/three) "anF" = (/obj/machinery/space_heater,/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/green/border{dir = 8},/turf/simulated/floor/tiled,/area/hangar/one) "anG" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/turf/simulated/floor/tiled/monotile,/area/hangar/one) "anH" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/tiled/monotile,/area/hangar/one) @@ -726,7 +726,7 @@ "anX" = (/obj/machinery/telecomms/bus/preset_two/southerncross,/turf/simulated/floor/tiled/dark{nitrogen = 100; oxygen = 0; temperature = 80},/area/tcomm/chamber) "anY" = (/obj/machinery/telecomms/relay/preset/southerncross/d1,/turf/simulated/floor/tiled/dark{nitrogen = 100; oxygen = 0; temperature = 80},/area/tcomm/chamber) "anZ" = (/turf/simulated/floor/tiled/dark{nitrogen = 100; oxygen = 0; temperature = 80},/area/tcomm/chamber) -"aoa" = (/turf/simulated/floor/reinforced,/obj/structure/shuttle/engine/propulsion{icon_state = "burst_r"},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/shuttle1/start) +"aoa" = (/obj/item/weapon/tank/emergency/oxygen/engi,/obj/item/weapon/tank/emergency/oxygen/double,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/firstdeck/forestarboard) "aob" = (/obj/machinery/telecomms/bus/preset_four,/turf/simulated/floor/tiled/dark{nitrogen = 100; oxygen = 0; temperature = 80},/area/tcomm/chamber) "aoc" = (/obj/machinery/telecomms/processor/preset_four,/turf/simulated/floor/tiled/dark{nitrogen = 100; oxygen = 0; temperature = 80},/area/tcomm/chamber) "aod" = (/obj/machinery/atmospherics/pipe/simple/hidden/black,/turf/simulated/floor/bluegrid{name = "Mainframe Base"; nitrogen = 100; oxygen = 0; temperature = 80},/area/tcomm/chamber) @@ -847,7 +847,7 @@ "aqo" = (/turf/simulated/floor/plating,/area/construction/firstdeck/construction4) "aqp" = (/obj/structure/cable{d2 = 2; icon_state = "0-2"; pixel_y = 0},/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/turf/simulated/floor/wood,/area/construction/firstdeck/construction4) "aqq" = (/turf/simulated/floor/wood,/area/construction/firstdeck/construction4) -"aqr" = (/obj/random/drinkbottle,/obj/structure/closet/crate,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/drinkbottle,/obj/item/weapon/reagent_containers/food/condiment/enzyme{layer = 5},/turf/simulated/floor/wood,/area/construction/firstdeck/construction4) +"aqr" = (/obj/random/drinkbottle,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/drinkbottle,/obj/item/weapon/reagent_containers/food/condiment/enzyme{layer = 5},/obj/random/crate,/turf/simulated/floor/wood,/area/construction/firstdeck/construction4) "aqs" = (/obj/structure/closet/emcloset,/obj/machinery/ai_status_display{pixel_y = 32},/obj/effect/floor_decal/borderfloor{dir = 9},/obj/effect/floor_decal/corner/red/border{dir = 9},/turf/simulated/floor/tiled,/area/hallway/secondary/escape/firstdeck/ep_starboard1) "aqt" = (/obj/machinery/atmospherics/unary/vent_pump/on,/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/white/border{dir = 1},/turf/simulated/floor/tiled,/area/hallway/secondary/escape/firstdeck/ep_starboard1) "aqu" = (/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/obj/structure/cable{d2 = 2; icon_state = "0-2"; pixel_y = 0},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/red/border{dir = 1},/turf/simulated/floor/tiled,/area/hallway/secondary/escape/firstdeck/ep_starboard1) @@ -1286,7 +1286,7 @@ "ayL" = (/obj/machinery/firealarm{dir = 1; pixel_x = 0; pixel_y = -24},/turf/simulated/floor/tiled/dark,/area/hallway/primary/firstdeck/starboard) "ayM" = (/obj/turbolift_map_holder/southern_cross/starboard,/turf/unsimulated/mask,/area/hallway/primary/firstdeck/starboard) "ayN" = (/obj/machinery/space_heater,/turf/simulated/floor/plating,/area/maintenance/firstdeck/centralstarboard) -"ayO" = (/obj/structure/closet/crate,/obj/item/weapon/tank/emergency/oxygen/engi,/obj/item/weapon/tank/emergency/oxygen/double,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/firstdeck/centralport) +"ayO" = (/obj/item/weapon/tank/emergency/oxygen/engi,/obj/item/weapon/tank/emergency/oxygen/double,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/structure/catwalk,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/firstdeck/centralport) "ayP" = (/obj/structure/closet/emcloset,/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/firstdeck/centralport) "ayQ" = (/obj/random/obstruction,/turf/simulated/floor/plating,/area/construction/firstdeck/construction2) "ayR" = (/turf/simulated/floor/plating,/area/construction/firstdeck/construction2) @@ -1301,7 +1301,7 @@ "aza" = (/obj/item/frame,/obj/machinery/light_construct,/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/maintenance/firstdeck/aftport) "azb" = (/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/maintenance/firstdeck/aftport) "azc" = (/obj/random/obstruction,/turf/simulated/floor/plating,/area/maintenance/firstdeck/aftport) -"azd" = (/obj/structure/closet/crate,/obj/item/device/multitool,/obj/item/device/multitool,/obj/item/device/assembly/prox_sensor,/obj/item/device/flashlight,/obj/item/weapon/storage/backpack,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/turf/simulated/floor/plating,/area/maintenance/firstdeck/aftport) +"azd" = (/obj/item/device/multitool,/obj/item/device/multitool,/obj/item/device/assembly/prox_sensor,/obj/item/device/flashlight,/obj/item/weapon/storage/backpack,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/firstdeck/aftport) "aze" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor,/area/maintenance/firstdeck/aftport) "azf" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor,/area/maintenance/firstdeck/aftport) "azg" = (/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/firstdeck/aftport) @@ -1415,7 +1415,7 @@ "aBk" = (/obj/structure/door_assembly/door_assembly_ext,/turf/simulated/floor/plating,/area/maintenance/firstdeck/centralport) "aBl" = (/obj/structure/table/rack{dir = 8; layer = 2.6},/obj/random/maintenance/clean,/obj/random/tech_supply,/obj/random/tech_supply,/obj/item/weapon/airlock_electronics,/obj/item/stack/cable_coil/random,/turf/simulated/floor/plating,/area/maintenance/firstdeck/centralport) "aBm" = (/obj/machinery/door/blast/regular{density = 0; dir = 1; icon_state = "pdoor0"; id = "crglockdown"; name = "Cargo Lockdown"; opacity = 0},/turf/simulated/floor/plating,/area/maintenance/firstdeck/centralport) -"aBn" = (/obj/item/device/flashlight,/turf/simulated/floor/plating,/area/construction/firstdeck/construction2) +"aBn" = (/obj/item/device/flashlight,/obj/random/crate,/turf/simulated/floor/plating,/area/construction/firstdeck/construction2) "aBo" = (/obj/structure/cable,/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/turf/simulated/floor/plating,/area/construction/firstdeck/construction2) "aBp" = (/obj/structure/table/steel,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tool/powermaint,/turf/simulated/floor,/area/construction/firstdeck/construction2) "aBq" = (/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/obj/structure/table/steel,/obj/item/stack/cable_coil/random,/obj/item/stack/cable_coil/random,/turf/simulated/floor/plating,/area/construction/firstdeck/construction2) @@ -1459,7 +1459,7 @@ "aCc" = (/obj/machinery/computer/crew{dir = 8},/turf/simulated/floor/tiled/techmaint,/area/medical/first_aid_station/firstdeck) "aCd" = (/obj/structure/table/reinforced,/obj/machinery/alarm{dir = 8; pixel_x = 22; pixel_y = 0},/turf/simulated/floor/tiled,/area/hangar/twocontrol) "aCe" = (/obj/machinery/alarm{dir = 1; pixel_y = -22},/obj/structure/table/steel,/turf/simulated/floor/plating,/area/construction/firstdeck/construction3) -"aCf" = (/obj/item/clothing/head/soft/mime,/obj/item/clothing/mask/gas/mime,/obj/item/clothing/shoes/mime,/obj/item/clothing/under/mime,/obj/structure/closet/crate,/turf/simulated/floor,/area/construction/firstdeck/construction3) +"aCf" = (/obj/item/clothing/head/soft/mime,/obj/item/clothing/mask/gas/mime,/obj/item/clothing/shoes/mime,/obj/item/clothing/under/mime,/obj/random/crate,/turf/simulated/floor,/area/construction/firstdeck/construction3) "aCg" = (/obj/structure/cable,/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/turf/simulated/floor/plating,/area/construction/firstdeck/construction3) "aCh" = (/obj/structure/table/steel,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/maintenance/engineering,/turf/simulated/floor/tiled/steel,/area/construction/firstdeck/construction3) "aCi" = (/obj/structure/closet/emcloset,/obj/machinery/ai_status_display{pixel_y = -32},/obj/effect/floor_decal/borderfloor{dir = 10},/obj/effect/floor_decal/corner/red/border{dir = 10},/turf/simulated/floor/tiled,/area/hallway/secondary/escape/firstdeck/ep_starboard2) @@ -1531,9 +1531,9 @@ "aDw" = (/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 9},/turf/simulated/floor/tiled,/area/quartermaster/storage) "aDx" = (/obj/machinery/atmospherics/unary/vent_pump/on,/obj/effect/floor_decal/borderfloor/corner{dir = 4},/obj/effect/floor_decal/corner/brown/bordercorner{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/storage) "aDy" = (/obj/machinery/light/spot{dir = 1},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/storage) -"aDz" = (/obj/structure/extinguisher_cabinet{pixel_y = 30},/obj/structure/closet/crate,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/storage) -"aDA" = (/obj/structure/closet/crate,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/storage) -"aDB" = (/obj/machinery/firealarm{pixel_y = 24},/obj/structure/closet/crate/freezer,/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/storage) +"aDz" = (/obj/structure/extinguisher_cabinet{pixel_y = 30},/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/obj/random/crate,/turf/simulated/floor/tiled,/area/quartermaster/storage) +"aDA" = (/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/obj/random/crate,/turf/simulated/floor/tiled,/area/quartermaster/storage) +"aDB" = (/obj/machinery/firealarm{pixel_y = 24},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/obj/random/crate,/turf/simulated/floor/tiled,/area/quartermaster/storage) "aDC" = (/obj/structure/table/steel_reinforced,/obj/machinery/cell_charger,/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/storage) "aDD" = (/obj/structure/table/steel_reinforced,/obj/item/clothing/accessory/armband/cargo,/obj/item/device/retail_scanner/cargo,/obj/machinery/requests_console{department = "Cargo Bay"; departmentType = 2; pixel_x = 0; pixel_y = 28},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/storage) "aDE" = (/obj/structure/table/steel_reinforced,/obj/item/weapon/stamp{pixel_x = -3; pixel_y = 3},/obj/item/weapon/stamp/cargo,/obj/effect/floor_decal/borderfloor{dir = 5},/obj/effect/floor_decal/corner/brown/border{dir = 5},/turf/simulated/floor/tiled,/area/quartermaster/storage) @@ -1690,7 +1690,7 @@ "aGz" = (/obj/machinery/computer/telecomms/monitor{dir = 4; network = "tcommsat"},/obj/structure/cable/cyan{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/black{dir = 4},/turf/simulated/floor/tiled/dark,/area/tcomm/computer) "aGA" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{dir = 8; icon_state = "propulsion_l"},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/large_escape_pod1/station) "aGB" = (/obj/effect/floor_decal/borderfloorblack{dir = 8},/obj/effect/floor_decal/industrial/danger{dir = 8},/turf/simulated/floor/tiled,/area/hangar/two) -"aGC" = (/obj/structure/extinguisher_cabinet{pixel_x = 25},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/green/border{dir = 4},/obj/structure/closet/crate,/turf/simulated/floor/tiled,/area/hangar/two) +"aGC" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{dir = 8},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/large_escape_pod1/station) "aGD" = (/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple/visible,/turf/simulated/shuttle/floor,/area/shuttle/large_escape_pod1/station) "aGE" = (/obj/structure/bed/chair{dir = 4},/turf/simulated/shuttle/floor/white,/area/shuttle/large_escape_pod1/station) "aGF" = (/obj/structure/grille,/obj/structure/shuttle/window,/turf/simulated/shuttle/plating,/area/shuttle/large_escape_pod1/station) @@ -1723,7 +1723,7 @@ "aHg" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/ascenter) "aHh" = (/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/tiled,/area/hallway/primary/firstdeck/ascenter) "aHi" = (/obj/machinery/floodlight,/turf/simulated/floor,/area/maintenance/firstdeck/aftstarboard) -"aHj" = (/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/green/border{dir = 8},/obj/structure/closet/crate,/turf/simulated/floor/tiled,/area/hangar/two) +"aHj" = (/turf/simulated/floor/reinforced,/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_r"; dir = 1},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/shuttle2/start) "aHk" = (/turf/simulated/shuttle/wall/voidcraft/no_join,/area/shuttle/shuttle2/start) "aHl" = (/turf/simulated/shuttle/wall/voidcraft,/area/shuttle/shuttle2/start) "aHm" = (/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/green/border{dir = 4},/obj/structure/closet/emcloset,/turf/simulated/floor/tiled/steel,/area/hangar/two) @@ -1758,7 +1758,7 @@ "aHP" = (/turf/simulated/floor/tiled,/area/tcomm/entrance) "aHQ" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/turf/simulated/shuttle/wall/voidcraft/hard_corner,/area/shuttle/shuttle2/start) "aHR" = (/obj/machinery/teleport/station,/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/tiled/techfloor,/area/tcomm/entrance) -"aHS" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{dir = 8},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/large_escape_pod1/station) +"aHS" = (/turf/simulated/floor/reinforced,/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_l"; dir = 1},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/shuttle2/start) "aHT" = (/obj/machinery/teleport/hub,/obj/effect/floor_decal/industrial/hatch/yellow,/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/tiled/techfloor,/area/tcomm/entrance) "aHU" = (/turf/simulated/shuttle/wall/voidcraft/hard_corner,/area/shuttle/shuttle2/start) "aHV" = (/obj/machinery/atmospherics/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/shuttle/plating,/area/shuttle/shuttle2/start) @@ -1929,7 +1929,7 @@ "aLe" = (/obj/machinery/light/small{dir = 8},/obj/structure/ore_box,/turf/simulated/floor/plating,/area/maintenance/substation/firstdeck/cargo) "aLf" = (/obj/effect/floor_decal/industrial/warning/corner,/turf/simulated/floor/plating,/area/maintenance/substation/firstdeck/cargo) "aLg" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/effect/floor_decal/industrial/warning,/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/alarm{dir = 8; pixel_x = 22; pixel_y = 0},/turf/simulated/floor/plating,/area/maintenance/substation/firstdeck/cargo) -"aLh" = (/obj/structure/closet/crate,/obj/item/weapon/storage/box/lights/mixed,/obj/item/stack/cable_coil/random,/obj/machinery/light_construct,/obj/machinery/light_construct,/turf/simulated/floor/plating,/area/maintenance/firstdeck/aftport) +"aLh" = (/obj/structure/extinguisher_cabinet{pixel_x = 25},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/green/border{dir = 4},/obj/random/crate,/turf/simulated/floor/tiled,/area/hangar/two) "aLi" = (/obj/machinery/door/airlock{name = "Emergency Storage"},/turf/simulated/floor/plating,/area/maintenance/firstdeck/aftport) "aLj" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/maintenance{req_access = list(12)},/turf/simulated/floor/plating,/area/storage/emergency_storage/firstdeck/ap_emergency) "aLk" = (/obj/structure/catwalk,/turf/simulated/floor/plating,/area/storage/emergency_storage/firstdeck/ap_emergency) @@ -1993,7 +1993,7 @@ "aMq" = (/obj/machinery/atmospherics/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/powered/scrubber,/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) "aMr" = (/obj/machinery/atmospherics/pipe/simple/hidden/red{dir = 10; icon_state = "intact"},/obj/machinery/alarm{pixel_y = 22},/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) "aMs" = (/obj/item/device/radio/intercom{dir = 1; name = "Station Intercom (General)"; pixel_y = 21},/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) -"aMt" = (/turf/simulated/floor/reinforced,/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_r"; dir = 1},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/shuttle2/start) +"aMt" = (/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/green/border{dir = 8},/obj/random/crate,/turf/simulated/floor/tiled,/area/hangar/two) "aMu" = (/obj/machinery/space_heater,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) "aMv" = (/obj/machinery/portable_atmospherics/hydroponics,/obj/machinery/atmospherics/portables_connector,/obj/effect/landmark{name = "blobstart"},/turf/simulated/floor/tiled/white,/area/rnd/xenobiology/xenoflora_isolation) "aMw" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan{dir = 4; icon_state = "intact"},/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) @@ -2027,7 +2027,7 @@ "aMY" = (/obj/machinery/atmospherics/pipe/manifold/hidden/red,/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) "aMZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/red{icon_state = "intact"; dir = 4},/obj/structure/bed/chair/office/dark{dir = 4},/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) "aNa" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/atmospherics/pipe/simple/hidden/red{icon_state = "intact"; dir = 4},/obj/effect/wingrille_spawn/reinforced,/turf/simulated/floor/plating,/area/engineering/auxiliary_engineering) -"aNb" = (/turf/simulated/floor/reinforced,/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_l"; dir = 1},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/shuttle2/start) +"aNb" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{dir = 8; icon_state = "propulsion_r"},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/large_escape_pod1/station) "aNc" = (/obj/machinery/atmospherics/pipe/simple/visible/red{icon_state = "intact"; dir = 4},/obj/machinery/atmospherics/pipe/simple/visible/cyan,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) "aNd" = (/obj/machinery/atmospherics/pipe/simple/visible/red{icon_state = "intact"; dir = 4},/obj/machinery/space_heater,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) "aNe" = (/obj/machinery/atmospherics/pipe/simple/visible/red{icon_state = "intact"; dir = 10},/obj/effect/floor_decal/rust,/turf/simulated/floor/tiled/steel_dirty,/area/engineering/auxiliary_engineering) @@ -2271,7 +2271,7 @@ "aRI" = (/turf/simulated/floor/airless,/area/hallway/secondary/escape/firstdeck/ep_aftport) "aRJ" = (/turf/simulated/shuttle/wall,/area/shuttle/escape_pod3/station) "aRK" = (/turf/simulated/shuttle/wall/no_join{base_state = "orange"; icon = 'icons/turf/shuttle_orange.dmi'; icon_state = "orange"},/area/shuttle/escape_pod3/station) -"aRL" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{dir = 8; icon_state = "propulsion_r"},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/large_escape_pod1/station) +"aRL" = (/obj/item/weapon/storage/box/lights/mixed,/obj/item/stack/cable_coil/random,/obj/machinery/light_construct,/obj/machinery/light_construct,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/firstdeck/aftport) "aRM" = (/turf/simulated/wall,/area/hallway/secondary/escape/firstdeck/ep_aftport) "aRN" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 8},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 9},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 4},/turf/simulated/floor/tiled,/area/hallway/secondary/escape/firstdeck/ep_aftport) "aRO" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 9},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 4},/turf/simulated/floor/tiled,/area/hallway/secondary/escape/firstdeck/ep_aftport) @@ -3510,7 +3510,7 @@ "bpz" = (/obj/machinery/atmospherics/valve/digital/open,/turf/simulated/floor/plating,/area/maintenance/security_starboard) "bpA" = (/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 4},/turf/simulated/floor/plating,/area/maintenance/security_starboard) "bpB" = (/obj/machinery/atmospherics/pipe/simple/hidden/cyan{dir = 6; icon_state = "intact"},/obj/machinery/portable_atmospherics/powered/pump/filled,/turf/simulated/floor/plating,/area/maintenance/security_starboard) -"bpC" = (/obj/machinery/atmospherics/pipe/manifold/hidden/cyan{dir = 4},/obj/machinery/meter,/obj/structure/closet/crate,/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/random/maintenance/research,/obj/random/maintenance/cargo,/obj/random/maintenance/security,/obj/random/maintenance/security,/turf/simulated/floor/plating,/area/maintenance/security_starboard) +"bpC" = (/obj/machinery/atmospherics/pipe/manifold/hidden/cyan{dir = 4},/obj/machinery/meter,/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/random/maintenance/research,/obj/random/maintenance/cargo,/obj/random/maintenance/security,/obj/random/maintenance/security,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/security_starboard) "bpD" = (/obj/effect/floor_decal/corner/black/full,/obj/machinery/camera/network/engineering{c_tag = "Atmospherics Tank - Carbon Dioxide"; dir = 4},/obj/machinery/light/small{dir = 8},/turf/simulated/floor/reinforced/carbon_dioxide,/area/engineering/atmos) "bpE" = (/obj/effect/floor_decal/corner/black/full{dir = 4},/obj/machinery/atmospherics/unary/vent_pump{dir = 4; external_pressure_bound = 0; external_pressure_bound_default = 0; frequency = 1441; icon_state = "map_vent_in"; id_tag = "co2_out"; initialize_directions = 1; internal_pressure_bound = 4000; internal_pressure_bound_default = 4000; pressure_checks = 2; pressure_checks_default = 2; pump_direction = 0; use_power = 1},/turf/simulated/floor/reinforced/carbon_dioxide,/area/engineering/atmos) "bpF" = (/obj/machinery/atmospherics/pipe/simple/visible/green{icon_state = "intact"; dir = 4},/obj/machinery/door/firedoor/border_only,/obj/effect/wingrille_spawn/reinforced,/obj/machinery/meter,/obj/machinery/door/blast/regular{density = 0; dir = 1; icon_state = "pdoor0"; id = "atmoslockdown"; name = "Atmospherics Lockdown"; opacity = 0},/turf/simulated/floor,/area/engineering/atmos) @@ -4027,7 +4027,7 @@ "bzw" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/tiled/monotile,/area/hallway/primary/seconddeck/fore) "bzx" = (/obj/effect/floor_decal/borderfloor/corner{dir = 4},/obj/effect/floor_decal/corner/red/bordercorner{dir = 4},/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/fore) "bzy" = (/obj/machinery/door/firedoor/glass,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/door/airlock/glass_medical{name = "First-Aid Station"; req_one_access = list(5,12,19)},/turf/simulated/floor/tiled/white,/area/medical/first_aid_station/seconddeck/fore) -"bzz" = (/obj/structure/closet/crate,/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/tech_supply,/obj/random/tech_supply,/turf/simulated/floor/plating,/area/maintenance/research) +"bzz" = (/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/medical,/obj/random/medical/lite,/obj/random/bomb_supply,/obj/random/bomb_supply,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/research) "bzA" = (/obj/structure/closet/jcloset,/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/item/weapon/soap/nanotrasen,/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/purple/border{dir = 8},/turf/simulated/floor/tiled,/area/janitor) "bzB" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/tiled,/area/janitor) "bzC" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/tiled,/area/janitor) @@ -4115,7 +4115,7 @@ "bBg" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/machinery/meter,/turf/simulated/floor/plating,/area/maintenance/research) "bBh" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/research) "bBi" = (/obj/machinery/portable_atmospherics/powered/scrubber,/turf/simulated/floor/plating,/area/maintenance/research) -"bBj" = (/obj/structure/closet/crate/plastic,/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/medical,/obj/random/medical/lite,/obj/random/bomb_supply,/obj/random/bomb_supply,/turf/simulated/floor/plating,/area/maintenance/research) +"bBj" = (/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/research) "bBk" = (/obj/structure/closet,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/random/maintenance/security,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/research,/turf/simulated/floor/plating,/area/maintenance/research) "bBl" = (/turf/simulated/wall/r_wall,/area/crew_quarters/heads/sc/hor) "bBm" = (/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "Biohazard"; name = "Biohazard Shutter"; opacity = 0},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 5; icon_state = "intact"},/obj/machinery/meter,/turf/simulated/floor/plating,/area/maintenance/research) @@ -5131,7 +5131,7 @@ "bUI" = (/obj/machinery/hologram/holopad,/obj/effect/floor_decal/industrial/outline/grey,/obj/machinery/navbeacon/patrol{location = "CH11"; next_patrol = "CH12"},/turf/simulated/floor/tiled/dark,/area/hallway/primary/seconddeck/fscenter) "bUJ" = (/obj/structure/flora/ausbushes/sparsegrass,/obj/structure/flora/ausbushes/brflowers,/turf/simulated/floor/grass,/area/hallway/primary/seconddeck/fscenter) "bUK" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/research) -"bUL" = (/obj/structure/closet/crate,/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/turf/simulated/floor/plating,/area/maintenance/research) +"bUL" = (/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/research) "bUM" = (/obj/machinery/r_n_d/protolathe,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/rnd/lab) "bUN" = (/turf/simulated/floor/tiled,/area/rnd/lab) "bUO" = (/obj/machinery/r_n_d/destructive_analyzer,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/rnd/lab) @@ -5501,7 +5501,7 @@ "cbO" = (/obj/structure/flora/ausbushes/fullgrass,/turf/simulated/floor/grass,/area/hallway/primary/seconddeck/fscenter) "cbP" = (/obj/machinery/portable_atmospherics/hydroponics/soil,/obj/machinery/camera/network/second_deck{c_tag = "Second Deck - Center Two"; dir = 8},/turf/simulated/floor/grass,/area/hallway/primary/seconddeck/fscenter) "cbQ" = (/obj/structure/closet/emcloset,/turf/simulated/floor/plating,/area/maintenance/research) -"cbR" = (/obj/structure/closet/crate,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/powercell,/obj/random/powercell,/obj/random/powercell,/turf/simulated/floor/plating,/area/maintenance/research) +"cbR" = (/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/powercell,/obj/random/powercell,/obj/random/powercell,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/research) "cbS" = (/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/clipboard,/obj/item/weapon/folder/white,/obj/item/weapon/pen,/obj/machinery/newscaster{pixel_x = -30; pixel_y = 0},/obj/structure/table/glass,/obj/effect/floor_decal/borderfloorwhite{dir = 10},/obj/effect/floor_decal/corner/purple/border{dir = 10},/turf/simulated/floor/tiled/white,/area/rnd/lab) "cbT" = (/obj/item/weapon/folder/white,/obj/item/weapon/disk/tech_disk{pixel_x = 0; pixel_y = 0},/obj/item/weapon/disk/tech_disk{pixel_x = 0; pixel_y = 0},/obj/item/weapon/disk/design_disk,/obj/item/weapon/disk/design_disk,/obj/item/weapon/reagent_containers/dropper{pixel_y = -4},/obj/machinery/firealarm{dir = 1; pixel_x = 0; pixel_y = -24},/obj/structure/table/glass,/obj/effect/floor_decal/borderfloorwhite,/obj/effect/floor_decal/corner/purple/border,/turf/simulated/floor/tiled/white,/area/rnd/lab) "cbU" = (/obj/machinery/recharger{pixel_y = 0},/obj/item/weapon/stock_parts/console_screen,/obj/item/weapon/stock_parts/console_screen,/obj/item/weapon/stock_parts/console_screen,/obj/item/weapon/stock_parts/matter_bin,/obj/item/weapon/stock_parts/matter_bin,/obj/item/weapon/stock_parts/micro_laser,/obj/item/weapon/stock_parts/micro_laser,/obj/machinery/ai_status_display{pixel_y = -32},/obj/structure/table/glass,/obj/effect/floor_decal/borderfloorwhite,/obj/effect/floor_decal/corner/purple/border,/turf/simulated/floor/tiled/white,/area/rnd/lab) @@ -5582,13 +5582,13 @@ "cdr" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/machinery/recharge_station,/obj/machinery/camera/network/research{c_tag = "SCI - Mech Bay"; dir = 8},/obj/structure/extinguisher_cabinet{pixel_y = -30},/obj/machinery/ai_status_display{pixel_x = 32; pixel_y = 0},/turf/simulated/floor/tiled/techmaint,/area/assembly/chargebay) "cds" = (/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "Biohazard"; name = "Biohazard Shutter"; opacity = 0},/turf/simulated/floor/plating,/area/maintenance/research_medical) "cdt" = (/turf/simulated/wall/r_wall,/area/maintenance/research_medical) -"cdu" = (/obj/structure/closet/crate,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/random/powercell,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tool,/turf/simulated/floor/plating,/area/maintenance/research_medical) +"cdu" = (/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/item/stack/tile/floor/white,/obj/random/powercell,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tool,/turf/simulated/floor/plating,/area/maintenance/research_medical) "cdv" = (/turf/simulated/floor/plating,/area/maintenance/research_medical) "cdw" = (/obj/item/stack/cable_coil,/turf/simulated/floor/plating,/area/maintenance/research_medical) "cdx" = (/obj/structure/table/rack{dir = 1},/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/maintenance/clean,/obj/item/stack/cable_coil,/obj/item/weapon/coin/silver,/turf/simulated/floor/plating,/area/maintenance/research_medical) "cdy" = (/obj/structure/table/rack{dir = 1},/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/maintenance/clean,/turf/simulated/floor/plating,/area/maintenance/research_medical) "cdz" = (/obj/structure/table/glass,/obj/machinery/alarm{dir = 4; pixel_x = -22; pixel_y = 0},/obj/effect/floor_decal/borderfloorwhite{dir = 8},/obj/effect/floor_decal/corner/purple/border{dir = 8},/turf/simulated/floor/tiled/white,/area/rnd/research/firstdeck/hallway) -"cdA" = (/obj/structure/closet/crate,/obj/random/bomb_supply,/obj/random/bomb_supply,/obj/random/bomb_supply,/obj/random/tech_supply,/obj/random/technology_scanner,/obj/random/tool,/turf/simulated/floor/plating,/area/maintenance/research_medical) +"cdA" = (/obj/random/bomb_supply,/obj/random/bomb_supply,/obj/random/bomb_supply,/obj/random/tech_supply,/obj/random/technology_scanner,/obj/random/tool,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/research_medical) "cdB" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor/tiled/white,/area/rnd/research/firstdeck/hallway) "cdC" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled/white,/area/rnd/research/firstdeck/hallway) "cdD" = (/obj/machinery/camera/network/research{c_tag = "SCI - Research Hallway Aft"; dir = 8},/obj/effect/floor_decal/borderfloorwhite/corner{dir = 4},/obj/effect/floor_decal/corner/purple/bordercorner{dir = 4},/turf/simulated/floor/tiled/white,/area/rnd/research) @@ -5634,7 +5634,7 @@ "cer" = (/obj/effect/floor_decal/industrial/hatch/yellow,/obj/machinery/door/blast/regular{density = 0; dir = 1; icon_state = "pdoor0"; id = "englockdown"; name = "Engineering Lockdown"; opacity = 0},/obj/structure/sign/warning/secure_area{pixel_x = 32},/turf/simulated/floor/tiled/dark,/area/hallway/primary/seconddeck/port) "ces" = (/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/engineering) "cet" = (/obj/effect/wingrille_spawn/reinforced,/turf/simulated/floor/plating,/area/maintenance/engineering) -"ceu" = (/obj/structure/closet/crate,/obj/item/weapon/tank/emergency/oxygen/engi,/obj/item/weapon/tank/emergency/oxygen/double,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/turf/simulated/floor/plating,/area/maintenance/engineering) +"ceu" = (/obj/item/weapon/tank/emergency/oxygen/engi,/obj/item/weapon/tank/emergency/oxygen/double,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/maintenance/engineering,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/engineering) "cev" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/door/firedoor/border_only,/obj/structure/disposalpipe/segment,/obj/machinery/door/airlock/engineering{name = "Utility Down"; req_one_access = list(11,24)},/turf/simulated/floor/plating,/area/maintenance/engineering) "cew" = (/obj/structure/disposalpipe/broken{dir = 1},/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/engineering) "cex" = (/obj/machinery/vending/coffee{dir = 4},/turf/simulated/floor/tiled/hydro,/area/hallway/primary/seconddeck/fpcenter) @@ -6354,7 +6354,7 @@ "csj" = (/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/apcenter) "csk" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/tiled/monotile,/area/hallway/primary/seconddeck/apcenter) "csl" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/apcenter) -"csm" = (/obj/machinery/atmospherics/pipe/simple/visible/universal,/obj/effect/decal/cleanable/dirt,/obj/structure/closet/crate,/obj/random/maintenance/medical,/obj/random/maintenance/research,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/cargo,/turf/simulated/floor/plating,/area/maintenance/central) +"csm" = (/obj/machinery/atmospherics/pipe/simple/visible/universal,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/medical,/obj/random/maintenance/research,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/cargo,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/central) "csn" = (/obj/machinery/atmospherics/pipe/simple/visible/universal,/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/plating,/area/maintenance/central) "cso" = (/obj/machinery/lapvend,/obj/machinery/light{dir = 8},/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/stairwell) "csp" = (/obj/structure/table/glass,/obj/machinery/firealarm{pixel_y = 24},/obj/machinery/recharger{pixel_y = 0},/obj/machinery/camera/network/second_deck{c_tag = "Second Deck - Center Stair Access"; dir = 2},/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/stairwell) @@ -6809,7 +6809,7 @@ "cAW" = (/obj/structure/bed/chair{dir = 1},/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/qm) "cAX" = (/obj/machinery/disposal,/obj/item/device/radio/intercom{dir = 4; name = "Station Intercom (General)"; pixel_x = 21},/obj/structure/disposalpipe/trunk,/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/brown/border{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/qm) "cAY" = (/obj/random/obstruction,/turf/simulated/floor/plating,/area/maintenance/bar) -"cAZ" = (/obj/structure/closet/crate,/obj/item/weapon/tank/emergency/oxygen/engi,/obj/item/weapon/tank/emergency/oxygen/double,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plating,/area/maintenance/bar) +"cAZ" = (/obj/item/weapon/tank/emergency/oxygen/engi,/obj/item/weapon/tank/emergency/oxygen/double,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/machinery/light/small{dir = 1},/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/bar) "cBa" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/bar) "cBb" = (/turf/simulated/floor/plating,/area/maintenance/bar) "cBc" = (/obj/machinery/alarm{pixel_y = 22},/turf/simulated/floor/plating,/area/maintenance/bar) @@ -6888,7 +6888,7 @@ "cCx" = (/obj/effect/floor_decal/borderfloor/corner{dir = 8},/obj/effect/floor_decal/corner/brown/bordercorner{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/qm) "cCy" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled,/area/quartermaster/qm) "cCz" = (/obj/structure/closet/secure_closet/quartermaster,/obj/structure/disposalpipe/segment,/obj/machinery/alarm{dir = 8; icon_state = "alarm0"; pixel_x = 22},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/brown/border{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/qm) -"cCA" = (/obj/structure/closet/crate,/obj/item/clothing/gloves/boxing/green,/obj/item/clothing/gloves/boxing,/turf/simulated/floor/plating,/area/maintenance/bar) +"cCA" = (/obj/item/clothing/gloves/boxing/green,/obj/item/clothing/gloves/boxing,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/bar) "cCB" = (/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/structure/table/steel,/obj/random/medical,/obj/random/medical/lite,/obj/random/medical/lite,/turf/simulated/floor/plating,/area/maintenance/bar) "cCC" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/plating,/area/maintenance/bar) "cCD" = (/obj/structure/flora/ausbushes/lavendergrass,/obj/structure/flora/ausbushes/brflowers,/turf/simulated/floor/grass,/area/hallway/primary/seconddeck/apcenter) @@ -6912,7 +6912,7 @@ "cCV" = (/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/machinery/hologram/holopad,/obj/effect/floor_decal/industrial/outline/grey,/obj/machinery/navbeacon/patrol{location = "CH8"; next_patrol = "CH9"},/turf/simulated/floor/tiled/dark,/area/hallway/primary/seconddeck/ascenter) "cCW" = (/obj/effect/floor_decal/borderfloor/corner,/obj/effect/floor_decal/corner/green/bordercorner,/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/ascenter) "cCX" = (/obj/structure/flora/ausbushes/fullgrass,/obj/structure/flora/ausbushes/ywflowers,/turf/simulated/floor/grass,/area/hallway/primary/seconddeck/ascenter) -"cCY" = (/obj/structure/closet/crate,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/medical,/obj/random/medical,/turf/simulated/floor/plating,/area/maintenance/medbay) +"cCY" = (/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/random/medical,/obj/random/medical,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/medbay) "cCZ" = (/obj/structure/closet/secure_closet/medical1,/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24},/obj/machinery/light_switch{pixel_x = -36},/obj/random/medical,/obj/random/medical,/obj/random/medical,/obj/structure/cable/green{d2 = 4; icon_state = "0-4"},/obj/machinery/status_display{pixel_x = 0; pixel_y = -32},/turf/simulated/floor/tiled/dark,/area/medical/medbay_emt_bay) "cDa" = (/obj/structure/cable/green{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/effect/floor_decal/borderfloorwhite{dir = 8},/obj/effect/floor_decal/corner/pink/border{dir = 8},/obj/effect/floor_decal/borderfloorwhite/corner2{dir = 10},/obj/effect/floor_decal/corner/pink/bordercorner2{dir = 10},/turf/simulated/floor/tiled/white,/area/medical/medbay_emt_bay) "cDb" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/effect/floor_decal/borderfloorwhite{dir = 4},/obj/effect/floor_decal/corner/pink/border{dir = 4},/obj/effect/floor_decal/borderfloorwhite/corner2{dir = 5},/obj/effect/floor_decal/corner/pink/bordercorner2{dir = 5},/turf/simulated/floor/tiled/white,/area/medical/medbay_emt_bay) @@ -7037,12 +7037,12 @@ "cFq" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/maintenance{name = "Disposal Access"; req_access = list(12)},/turf/simulated/floor,/area/maintenance/disposal) "cFr" = (/obj/structure/disposalpipe/segment,/obj/machinery/vending/medical,/turf/simulated/wall,/area/medical/medbay_primary_storage) "cFs" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden{dir = 9; icon_state = "intact"},/turf/simulated/floor,/area/maintenance/cargo) -"cFt" = (/obj/structure/closet/crate,/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/turf/simulated/floor,/area/maintenance/cargo) +"cFt" = (/obj/random/maintenance/engineering,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/crate,/turf/simulated/floor,/area/maintenance/cargo) "cFu" = (/obj/random/obstruction,/turf/simulated/floor/plating,/area/maintenance/cargo) "cFv" = (/obj/effect/floor_decal/corner/brown/full{dir = 8},/obj/structure/table/rack{dir = 8; layer = 2.9},/turf/simulated/floor/tiled/steel,/area/maintenance/cargo) "cFw" = (/obj/structure/table/rack{dir = 8; layer = 2.9},/turf/simulated/floor/tiled/steel,/area/maintenance/cargo) "cFx" = (/turf/simulated/floor/tiled/steel,/area/maintenance/cargo) -"cFy" = (/obj/structure/disposalpipe/sortjunction/untagged{dir = 1},/obj/effect/decal/cleanable/cobweb,/obj/structure/closet/crate,/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/brown/border{dir = 8},/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse) +"cFy" = (/obj/structure/disposalpipe/sortjunction/untagged{dir = 1},/obj/effect/decal/cleanable/cobweb,/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/brown/border{dir = 8},/obj/random/crate,/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse) "cFz" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/segment{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 9},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 4},/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse) "cFA" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/alarm{pixel_y = 23},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/brown/border{dir = 4},/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse) "cFB" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/wall,/area/quartermaster/delivery) @@ -7118,7 +7118,7 @@ "cGT" = (/turf/simulated/wall,/area/maintenance/cargo) "cGU" = (/obj/structure/table/rack{dir = 8; layer = 2.9},/obj/effect/floor_decal/corner/brown/full{dir = 8},/turf/simulated/floor/tiled/steel,/area/maintenance/cargo) "cGV" = (/obj/effect/floor_decal/corner/brown{dir = 1},/turf/simulated/floor/tiled/steel,/area/maintenance/cargo) -"cGW" = (/obj/structure/disposalpipe/tagger/partial{dir = 1; name = "Sorting Office"; sort_tag = "Sorting Office"},/obj/structure/closet/crate,/obj/structure/extinguisher_cabinet{pixel_x = -28; pixel_y = 0},/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/brown/border{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/warehouse) +"cGW" = (/obj/structure/disposalpipe/tagger/partial{dir = 1; name = "Sorting Office"; sort_tag = "Sorting Office"},/obj/structure/extinguisher_cabinet{pixel_x = -28; pixel_y = 0},/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/brown/border{dir = 8},/obj/random/crate,/turf/simulated/floor/tiled,/area/quartermaster/warehouse) "cGX" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse) "cGY" = (/obj/machinery/atmospherics/unary/vent_pump/on,/obj/effect/floor_decal/borderfloor/corner{dir = 4},/obj/effect/floor_decal/corner/brown/bordercorner{dir = 4},/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse) "cGZ" = (/obj/machinery/light/small{dir = 1},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/brown/border{dir = 1},/turf/simulated/floor/tiled/steel,/area/quartermaster/warehouse) @@ -7213,7 +7213,7 @@ "cIK" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor/plating,/area/maintenance/cargo) "cIL" = (/obj/effect/floor_decal/corner/brown{dir = 1},/obj/item/frame/light/small,/turf/simulated/floor/tiled,/area/maintenance/cargo) "cIM" = (/turf/simulated/floor/plating,/area/maintenance/cargo) -"cIN" = (/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/structure/closet/crate,/obj/machinery/camera/network/cargo{c_tag = "CRG - Cargo Warehouse"; dir = 4; name = "security camera"},/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/brown/border{dir = 8},/turf/simulated/floor/tiled,/area/quartermaster/warehouse) +"cIN" = (/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/machinery/camera/network/cargo{c_tag = "CRG - Cargo Warehouse"; dir = 4; name = "security camera"},/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/brown/border{dir = 8},/obj/random/crate,/turf/simulated/floor/tiled,/area/quartermaster/warehouse) "cIO" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/tiled,/area/quartermaster/warehouse) "cIP" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/manifold/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/tiled,/area/quartermaster/warehouse) "cIQ" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1},/turf/simulated/floor/tiled,/area/quartermaster/warehouse) @@ -7448,7 +7448,7 @@ "cNl" = (/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/firealarm{dir = 8; pixel_x = -24},/turf/simulated/floor/plating,/area/maintenance/substation/cargo) "cNm" = (/obj/machinery/light/small{dir = 1},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/obj/structure/cable/green{d2 = 4; icon_state = "0-4"},/obj/machinery/power/sensor{name = "Powernet Sensor - Cargo Subgrid"; name_tag = "Cargo Subgrid"},/obj/machinery/alarm{pixel_y = 22},/obj/effect/floor_decal/industrial/warning/corner,/turf/simulated/floor/plating,/area/maintenance/substation/cargo) "cNn" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/obj/effect/floor_decal/industrial/warning,/obj/structure/cable/green{d2 = 2; icon_state = "0-2"},/obj/structure/cable/green,/obj/structure/railing,/turf/simulated/floor/plating,/area/maintenance/substation/cargo) -"cNo" = (/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 1},/obj/structure/closet/crate,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/item/weapon/material/knife,/obj/item/weapon/storage/mre/random,/turf/simulated/floor/plating,/area/maintenance/bar) +"cNo" = (/obj/random/contraband,/obj/random/contraband,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/cargo) "cNp" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/table/steel,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/maintenance/engineering,/obj/random/tool/powermaint,/turf/simulated/floor/tiled/steel,/area/construction/seconddeck/construction1) "cNq" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/simulated/floor/plating,/area/maintenance/engineering) "cNr" = (/obj/machinery/door/firedoor/border_only,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/door/airlock{name = "Emergency Storage"},/turf/simulated/floor/plating,/area/storage/emergency_storage/seconddeck/ap_emergency) @@ -7569,7 +7569,7 @@ "cPC" = (/obj/machinery/atmospherics/pipe/manifold/hidden,/obj/effect/floor_decal/industrial/warning,/turf/simulated/floor,/area/maintenance/cargo) "cPD" = (/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 8; frequency = 1379; id_tag = "crg_aft_pump"},/obj/machinery/light/small{dir = 4; pixel_y = 0},/obj/effect/floor_decal/industrial/warning{dir = 6},/turf/simulated/floor,/area/maintenance/cargo) "cPE" = (/obj/item/weapon/storage/toolbox/mechanical,/turf/simulated/floor/plating,/area/maintenance/cargo) -"cPF" = (/obj/structure/closet/crate,/obj/random/contraband,/obj/random/contraband,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/turf/simulated/floor/plating,/area/maintenance/cargo) +"cPF" = (/obj/random/toy,/obj/random/plushie,/obj/random/plushie,/obj/random/action_figure,/obj/machinery/alarm{pixel_y = 22},/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/medbay) "cPG" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/maintenance{name = "Cargo Maintenance"; req_access = list(50)},/turf/simulated/floor/plating,/area/quartermaster/office) "cPH" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/machinery/navbeacon/delivery/north{location = "QM #1"},/mob/living/bot/mulebot,/turf/simulated/floor/tiled,/area/quartermaster/office) "cPI" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/machinery/navbeacon/delivery/north{location = "QM #2"},/mob/living/bot/mulebot,/turf/simulated/floor/tiled,/area/quartermaster/office) @@ -7599,7 +7599,7 @@ "cQg" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/medbay) "cQh" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/item/inflatable/door/torn,/turf/simulated/floor/plating,/area/maintenance/engineering) "cQi" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/portable_atmospherics/powered/scrubber,/turf/simulated/floor/plating,/area/maintenance/engineering) -"cQj" = (/obj/structure/closet/crate,/obj/random/toy,/obj/random/plushie,/obj/random/plushie,/obj/random/action_figure,/obj/machinery/alarm{pixel_y = 22},/turf/simulated/floor/plating,/area/maintenance/medbay) +"cQj" = (/obj/random/drinkbottle,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/action_figure,/obj/random/plushie,/obj/effect/floor_decal/industrial/warning/corner{dir = 4},/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/bar) "cQk" = (/obj/structure/table/steel,/obj/item/device/t_scanner,/obj/random/tech_supply,/obj/random/tech_supply,/obj/machinery/alarm{pixel_y = 23},/obj/random/cash,/turf/simulated/floor/plating,/area/maintenance/bar) "cQl" = (/obj/structure/table/steel,/obj/item/weapon/storage/box/lights/mixed,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/turf/simulated/floor/plating,/area/maintenance/medbay) "cQm" = (/obj/structure/closet/hydrant{pixel_y = -32},/obj/item/clothing/glasses/meson,/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/turf/simulated/floor/plating,/area/storage/emergency_storage/seconddeck/as_emergency) @@ -7634,7 +7634,7 @@ "cQP" = (/obj/structure/table/steel,/obj/machinery/cell_charger,/obj/item/clothing/head/soft,/obj/item/clothing/head/soft,/obj/machinery/light,/turf/simulated/floor/tiled/dark,/area/quartermaster/office) "cQQ" = (/obj/structure/table/steel,/obj/machinery/recharger,/obj/item/weapon/stamp{pixel_x = -3; pixel_y = 3},/obj/item/weapon/hand_labeler,/turf/simulated/floor/tiled/dark,/area/quartermaster/office) "cQR" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/door/airlock/glass_medical{name = "Patient Ward"},/turf/simulated/floor/tiled/steel_grid,/area/medical/patient_wing) -"cQS" = (/obj/structure/closet/crate,/obj/random/drinkbottle,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/action_figure,/obj/random/plushie,/obj/effect/floor_decal/industrial/warning/corner{dir = 4},/turf/simulated/floor/plating,/area/maintenance/bar) +"cQS" = (/obj/random/maintenance/cargo,/obj/random/maintenance,/obj/random/maintenance,/obj/random/maintenance/clean,/obj/structure/catwalk,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/bar) "cQT" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/plating,/area/maintenance/bar) "cQU" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 1},/turf/simulated/floor/plating,/area/maintenance/bar) "cQV" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 4},/turf/simulated/floor/plating,/area/maintenance/bar) @@ -7646,7 +7646,7 @@ "cRb" = (/obj/structure/closet/gmcloset{name = "formal wardrobe"},/obj/item/glass_jar,/obj/item/device/retail_scanner/civilian,/obj/item/device/retail_scanner/civilian,/obj/machinery/camera/network/civilian{c_tag = "CIV - Bar Storage"; dir = 2},/obj/machinery/firealarm{pixel_y = 24},/obj/item/clothing/head/that{pixel_x = 4; pixel_y = 6},/obj/machinery/atmospherics/unary/vent_scrubber/on,/turf/simulated/floor/wood,/area/crew_quarters/bar) "cRc" = (/obj/machinery/smartfridge/drinks,/obj/machinery/light{dir = 1},/turf/simulated/floor/lino,/area/crew_quarters/bar) "cRd" = (/obj/machinery/light/small,/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/bar) -"cRe" = (/obj/structure/closet/crate,/obj/random/maintenance/cargo,/obj/random/maintenance,/obj/random/maintenance,/obj/random/maintenance/clean,/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/bar) +"cRe" = (/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 1},/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/item/weapon/material/knife,/obj/item/weapon/storage/mre/random,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/bar) "cRf" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/item/device/radio/intercom{dir = 8; name = "Station Intercom (General)"; pixel_x = -21},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 8},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 5},/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/apcenter) "cRg" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/light,/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/apcenter) "cRh" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 8},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 5},/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/apcenter) @@ -7874,7 +7874,7 @@ "cVv" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/glass_medical{name = "Patient Ward"; req_access = list(5)},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled/steel_grid,/area/medical/patient_wing) "cVw" = (/turf/simulated/wall/r_wall,/area/medical/patient_wing) "cVx" = (/obj/structure/closet/wardrobe/grey,/obj/item/weapon/storage/backpack,/obj/item/weapon/storage/backpack,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/turf/simulated/floor/plating,/area/maintenance/cargo) -"cVy" = (/obj/structure/closet/crate,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/drinkbottle,/turf/simulated/floor/plating,/area/maintenance/cargo) +"cVy" = (/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/drinkbottle,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/cargo) "cVz" = (/obj/item/weapon/material/ashtray/glass,/obj/structure/table/steel,/turf/simulated/floor/plating,/area/maintenance/cargo) "cVA" = (/obj/structure/bed/chair/comfy/beige,/turf/simulated/floor/plating,/area/maintenance/cargo) "cVB" = (/obj/structure/table/steel,/obj/item/weapon/reagent_containers/food/drinks/glass2/rocks,/obj/item/weapon/reagent_containers/food/drinks/glass2/rocks,/turf/simulated/floor/plating,/area/maintenance/cargo) @@ -7964,7 +7964,7 @@ "cXh" = (/obj/structure/disposalpipe/segment,/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24},/obj/structure/cable,/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/green/border{dir = 8},/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/aft) "cXi" = (/obj/structure/extinguisher_cabinet{pixel_x = 28; pixel_y = 0},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/green/border{dir = 4},/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/aft) "cXj" = (/obj/item/weapon/stool/padded,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor/carpet,/area/crew_quarters/sleep/vistor_room_1) -"cXk" = (/obj/random/contraband,/obj/random/contraband,/obj/structure/closet/crate,/obj/random/contraband,/turf/simulated/floor/plating,/area/maintenance/medbay) +"cXk" = (/obj/random/contraband,/obj/random/contraband,/obj/random/contraband,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/medbay) "cXl" = (/obj/machinery/meter,/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/cyan{dir = 6; icon_state = "intact"},/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/maintenance/medbay) "cXm" = (/obj/effect/floor_decal/industrial/warning{dir = 5},/obj/machinery/atmospherics/pipe/manifold/hidden/cyan{dir = 1},/turf/simulated/floor/plating,/area/maintenance/medbay) "cXn" = (/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "medbayquar"; name = "Medbay Emergency Lockdown Shutters"; opacity = 0},/obj/machinery/atmospherics/valve{dir = 4},/turf/simulated/floor/plating,/area/maintenance/medbay) @@ -8032,7 +8032,7 @@ "cYx" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock{name = "Unisex Restrooms"},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/tiled/steel_grid,/area/crew_quarters/locker/locker_toilet) "cYy" = (/obj/item/device/radio/intercom{desc = "Talk... listen through this."; dir = 2; name = "Station Intercom (Brig Radio)"; pixel_x = 0; pixel_y = -21; wires = 7},/obj/structure/closet/secure_closet/personal,/obj/machinery/firealarm{dir = 8; pixel_x = -24},/turf/simulated/floor/carpet,/area/crew_quarters/sleep/vistor_room_1) "cYz" = (/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/carpet,/area/crew_quarters/sleep/vistor_room_1) -"cYA" = (/obj/structure/closet/crate,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/contraband,/turf/simulated/floor/plating,/area/maintenance/medbay) +"cYA" = (/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/contraband,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/medbay) "cYB" = (/obj/machinery/atmospherics/pipe/tank/air{dir = 1; start_pressure = 4559.63},/obj/machinery/light/small,/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 4},/turf/simulated/floor/plating,/area/maintenance/medbay) "cYC" = (/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/obj/structure/closet/secure_closet/personal,/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/obj/machinery/light_switch{pixel_x = 11; pixel_y = -24},/turf/simulated/floor/carpet,/area/crew_quarters/sleep/vistor_room_1) "cYD" = (/obj/item/device/radio/intercom{desc = "Talk... listen through this."; dir = 2; name = "Station Intercom (Brig Radio)"; pixel_x = 0; pixel_y = -21; wires = 7},/obj/structure/closet/secure_closet/personal,/obj/item/clothing/head/kitty,/obj/item/clothing/head/kitty,/obj/machinery/firealarm{dir = 8; pixel_x = -24},/turf/simulated/floor/carpet,/area/crew_quarters/sleep/vistor_room_2) @@ -8257,7 +8257,7 @@ "dcO" = (/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/green/border{dir = 4},/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled,/area/crew_quarters/locker) "dcP" = (/obj/machinery/meter,/obj/machinery/atmospherics/pipe/simple/hidden/cyan{dir = 6; icon_state = "intact"},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 9},/turf/simulated/floor/plating,/area/maintenance/bar) "dcQ" = (/obj/structure/table/marble,/obj/effect/floor_decal/corner/grey/diagonal{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/reagentgrinder,/turf/simulated/floor/tiled/white,/area/crew_quarters/kitchen) -"dcR" = (/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 1},/obj/machinery/light/small{dir = 4; pixel_y = 0},/obj/machinery/atmospherics/pipe/manifold/hidden/cyan{dir = 4},/obj/structure/closet/crate,/obj/item/weapon/reagent_containers/food/drinks/flask/barflask,/obj/random/powercell,/obj/random/maintenance,/obj/random/maintenance/clean,/turf/simulated/floor/plating,/area/maintenance/bar) +"dcR" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/item/weapon/storage/mre/random,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/locker) "dcS" = (/obj/machinery/light,/obj/effect/floor_decal/borderfloorwhite,/obj/effect/floor_decal/corner/paleblue/border,/obj/structure/closet/medical_wall{pixel_x = 0; pixel_y = -31},/obj/item/roller,/obj/item/bodybag/cryobag,/obj/item/weapon/storage/firstaid/regular,/obj/item/weapon/storage/pill_bottle/spaceacillin,/turf/simulated/floor/tiled/white,/area/medical/first_aid_station/seconddeck/fore) "dcT" = (/obj/structure/table/marble,/obj/effect/floor_decal/corner/grey/diagonal{dir = 4},/obj/item/weapon/reagent_containers/food/condiment/small/saltshaker{pixel_x = -3; pixel_y = 0},/obj/item/weapon/reagent_containers/food/condiment/small/peppermill{pixel_x = 3},/turf/simulated/floor/tiled/white,/area/crew_quarters/kitchen) "dcU" = (/obj/machinery/washing_machine,/turf/simulated/floor/tiled/dark,/area/crew_quarters/locker) @@ -8316,7 +8316,7 @@ "ddV" = (/obj/machinery/ai_status_display{pixel_y = -32},/obj/effect/floor_decal/borderfloorwhite,/obj/effect/floor_decal/corner/pink/border,/turf/simulated/floor/tiled/white,/area/medical/surgery2) "ddW" = (/obj/machinery/camera/network/medbay{c_tag = "MED - Operating Theatre 2"; dir = 1},/obj/machinery/vending/wallmed1{pixel_y = -30},/obj/effect/floor_decal/borderfloorwhite{dir = 6},/obj/effect/floor_decal/corner/pink/border{dir = 6},/obj/structure/closet/secure_closet/medical_wall/anesthetics{pixel_x = 32},/turf/simulated/floor/tiled/white,/area/medical/surgery2) "ddX" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor/plating,/area/maintenance/bar) -"ddY" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/closet/crate/plastic,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/item/weapon/storage/mre/random,/turf/simulated/floor/plating,/area/maintenance/locker) +"ddY" = (/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 1},/obj/machinery/light/small{dir = 4; pixel_y = 0},/obj/machinery/atmospherics/pipe/manifold/hidden/cyan{dir = 4},/obj/item/weapon/reagent_containers/food/drinks/flask/barflask,/obj/random/powercell,/obj/random/maintenance,/obj/random/maintenance/clean,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/bar) "ddZ" = (/turf/simulated/floor/reinforced{name = "Holodeck Projector Floor"},/area/holodeck/alphadeck) "dea" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/catwalk,/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/turf/simulated/floor/plating,/area/maintenance/locker) "deb" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 1},/obj/machinery/light{icon_state = "tube1"; dir = 8},/obj/machinery/camera/network/civilian{c_tag = "CIV - Cafeteria Port"; dir = 4},/turf/simulated/floor/wood,/area/crew_quarters/cafeteria) @@ -8345,7 +8345,7 @@ "dey" = (/obj/effect/floor_decal/borderfloor/corner{dir = 4},/obj/effect/floor_decal/corner/green/bordercorner{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/tiled,/area/crew_quarters/locker) "dez" = (/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/green/border{dir = 1},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/machinery/alarm{pixel_y = 22},/turf/simulated/floor/tiled,/area/crew_quarters/locker) "deA" = (/obj/effect/floor_decal/borderfloor/corner{dir = 1},/obj/effect/floor_decal/corner/green/bordercorner{dir = 1},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9},/turf/simulated/floor/tiled,/area/crew_quarters/locker) -"deB" = (/obj/structure/closet/crate/plastic,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/turf/simulated/floor/plating,/area/maintenance/bar) +"deB" = (/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/bar) "deC" = (/obj/machinery/appliance/cooker/grill,/obj/effect/floor_decal/corner/grey/diagonal{dir = 4},/turf/simulated/floor/tiled/white,/area/crew_quarters/kitchen) "deD" = (/obj/effect/floor_decal/corner/grey/diagonal{dir = 4},/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled/white,/area/crew_quarters/kitchen) "deE" = (/obj/effect/floor_decal/corner/grey/diagonal{dir = 4},/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 5},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 8},/turf/simulated/floor/tiled/white,/area/crew_quarters/kitchen) @@ -8361,7 +8361,7 @@ "deO" = (/obj/structure/cable/green{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/disposalpipe/segment,/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/universal,/turf/simulated/floor,/area/maintenance/substation/command) "deP" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 1},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 6},/turf/simulated/floor/tiled,/area/crew_quarters/locker) "deQ" = (/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/obj/effect/floor_decal/borderfloor/corner{dir = 1},/obj/effect/floor_decal/corner/green/bordercorner{dir = 1},/turf/simulated/floor/tiled,/area/hallway/primary/seconddeck/aft) -"deR" = (/obj/structure/closet/crate/hydroponics,/obj/random/maintenance,/obj/random/maintenance,/obj/random/maintenance,/turf/simulated/floor/plating,/area/maintenance/bar) +"deR" = (/obj/random/maintenance,/obj/random/maintenance,/obj/random/maintenance,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/bar) "deS" = (/obj/machinery/smartfridge,/obj/structure/disposalpipe/segment,/turf/simulated/wall/r_wall,/area/hydroponics) "deT" = (/turf/simulated/wall,/area/hydroponics) "deU" = (/obj/machinery/door/firedoor/border_only,/obj/effect/wingrille_spawn/reinforced,/turf/simulated/floor/plating,/area/hydroponics) @@ -8907,7 +8907,7 @@ "dpo" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/obj/machinery/light{dir = 1},/obj/item/weapon/camera_assembly,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dpp" = (/obj/machinery/floodlight,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dpq" = (/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) -"dpr" = (/obj/item/clothing/gloves/rainbow,/obj/item/clothing/head/soft/rainbow,/obj/item/clothing/shoes/rainbow,/obj/item/clothing/under/color/rainbow,/obj/item/weapon/bedsheet/rainbow,/obj/item/weapon/pen/crayon/rainbow,/obj/structure/closet/crate,/turf/simulated/floor,/area/construction/seconddeck/construction2) +"dpr" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{icon_state = "burst_r"; dir = 4},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/cryo/station) "dps" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/chapel) "dpt" = (/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod{frequency = 1380; id_tag = "cryostorage_shuttle"; name = "cryostorage controller"; pixel_x = -26; pixel_y = 0; req_access = list(19); tag_door = "cryostorage_shuttle_hatch"},/obj/effect/landmark{name = "JoinLateCryo"},/turf/simulated/shuttle/floor,/area/shuttle/cryo/station) "dpu" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/green/border{dir = 4},/turf/simulated/floor/tiled,/area/hallway/secondary/docking_hallway2) @@ -8955,7 +8955,7 @@ "dqk" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dql" = (/obj/structure/table/standard,/obj/item/weapon/towel,/obj/item/weapon/towel,/turf/simulated/floor/tiled/freezer,/area/construction/seconddeck/construction2) "dqm" = (/obj/structure/extinguisher_cabinet{pixel_x = 28; pixel_y = 0},/turf/simulated/floor/tiled/freezer,/area/construction/seconddeck/construction2) -"dqn" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{icon_state = "burst_r"; dir = 4},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/cryo/station) +"dqn" = (/obj/item/clothing/gloves/rainbow,/obj/item/clothing/head/soft/rainbow,/obj/item/clothing/shoes/rainbow,/obj/item/clothing/under/color/rainbow,/obj/item/weapon/bedsheet/rainbow,/obj/item/weapon/pen/crayon/rainbow,/obj/random/crate,/turf/simulated/floor,/area/construction/seconddeck/construction2) "dqo" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/tiled/monotile,/area/hallway/primary/seconddeck/aft) "dqp" = (/obj/item/weapon/stool/padded,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dqq" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 6},/obj/item/weapon/stool,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) @@ -9013,7 +9013,7 @@ "drq" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/turf/simulated/floor/tiled,/area/storage/primary) "drr" = (/obj/structure/table/standard,/obj/machinery/recharger{pixel_y = 0},/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/random/tech_supply,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/tiled,/area/storage/primary) "drs" = (/obj/machinery/computer/secure_data{dir = 4},/obj/item/device/radio/intercom/department/security{dir = 4; icon_override = "secintercom"; pixel_x = -21},/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/red/border{dir = 8},/turf/simulated/floor/tiled,/area/security/checkpoint2) -"drt" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{icon_state = "burst_l"; dir = 4},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/cryo/station) +"drt" = (/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/item/clothing/suit/storage/hazardvest,/obj/random/crate,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dru" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/hologram/holopad,/obj/effect/floor_decal/industrial/outline/grey,/turf/simulated/floor/tiled,/area/security/checkpoint2) "drv" = (/obj/structure/bed/chair/office/dark{dir = 4},/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/red/border{dir = 4},/turf/simulated/floor/tiled,/area/security/checkpoint2) "drw" = (/obj/structure/table/reinforced,/obj/machinery/door/window/brigdoor/westleft{name = "Security Checkpoint"; req_access = list(1)},/obj/machinery/door/firedoor/glass,/turf/simulated/floor/tiled,/area/security/checkpoint2) @@ -9048,7 +9048,7 @@ "drZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/tiled,/area/security/checkpoint2) "dsa" = (/obj/structure/table/reinforced,/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/tool/crowbar,/obj/item/weapon/pen,/obj/item/device/flash,/obj/machinery/camera/network/security{c_tag = "SEC - Arrival Checkpoint"; dir = 8},/obj/machinery/light{dir = 4},/obj/effect/floor_decal/borderfloor{dir = 4},/obj/effect/floor_decal/corner/red/border{dir = 4},/turf/simulated/floor/tiled,/area/security/checkpoint2) "dsb" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/table/gamblingtable,/obj/item/weapon/deck/cards,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) -"dsc" = (/obj/structure/closet/crate,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/random/maintenance/clean,/obj/item/clothing/suit/storage/hazardvest,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) +"dsc" = (/turf/simulated/floor/airless,/obj/structure/shuttle/engine/propulsion{icon_state = "burst_l"; dir = 4},/turf/simulated/shuttle/plating/airless/carry,/area/shuttle/cryo/station) "dsd" = (/obj/machinery/atmospherics/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/canister/air/airlock,/obj/effect/floor_decal/industrial/outline/yellow,/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plating,/area/maintenance/chapel) "dse" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 10; icon_state = "intact"},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/turf/simulated/floor/plating,/area/maintenance/chapel) "dsf" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/maintenance{name = "Firefighting equipment"; req_access = list(12)},/turf/simulated/floor/plating,/area/maintenance/chapel) @@ -9578,7 +9578,7 @@ "dCj" = (/obj/machinery/alarm{pixel_y = 22},/obj/machinery/portable_atmospherics/powered/pump/filled,/turf/simulated/floor/plating,/area/maintenance/thirddeck/foreport) "dCk" = (/obj/machinery/portable_atmospherics/powered/scrubber,/turf/simulated/floor/plating,/area/maintenance/thirddeck/foreport) "dCl" = (/turf/simulated/floor/plating,/area/maintenance/thirddeck/foreport) -"dCm" = (/obj/structure/closet/crate,/obj/item/weapon/storage/box/lights/mixed,/obj/random/maintenance/security,/obj/random/maintenance/security,/obj/random/maintenance/security,/turf/simulated/floor/plating,/area/maintenance/thirddeck/foreport) +"dCm" = (/obj/item/clothing/head/soft/mime,/obj/item/clothing/mask/gas/mime,/obj/item/clothing/shoes/mime,/obj/item/clothing/under/mime,/obj/random/crate,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dCn" = (/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/reinforced/airless,/area/thirddeck/roof) "dCo" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/reinforced/airless,/area/thirddeck/roof) "dCp" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/wall/r_wall,/area/ai) @@ -9843,7 +9843,7 @@ "dHo" = (/obj/structure/table/standard,/obj/machinery/light{icon_state = "tube1"; dir = 8},/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/folder/white_rd,/obj/item/weapon/pen/multi,/obj/machinery/computer/security/telescreen/entertainment{icon_state = "frame"; pixel_x = -32; pixel_y = 0},/turf/simulated/floor/carpet,/area/crew_quarters/heads/sc/hor/quarters) "dHp" = (/obj/structure/bed/chair/office/dark{dir = 1},/obj/structure/cable/green{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/carpet,/area/crew_quarters/heads/sc/hor/quarters) "dHq" = (/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/obj/machinery/light_switch{pixel_x = 36; pixel_y = -6},/obj/machinery/button/windowtint{id = "rdquarters"; pixel_x = 36; pixel_y = 6},/turf/simulated/floor/carpet,/area/crew_quarters/heads/sc/hor/quarters) -"dHr" = (/obj/structure/closet/crate,/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/turf/simulated/floor/plating,/area/maintenance/thirddeck/forestarboard) +"dHr" = (/obj/item/weapon/storage/box/lights/mixed,/obj/random/maintenance/security,/obj/random/maintenance/security,/obj/random/maintenance/security,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/thirddeck/foreport) "dHs" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/thirddeck/forestarboard) "dHt" = (/obj/machinery/door/firedoor/border_only,/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/airlock/maintenance{name = "Maintenance Access"; req_one_access = list(12,19)},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plating,/area/maintenance/thirddeck/foreport) "dHu" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/obj/machinery/alarm{dir = 4; pixel_x = -22; pixel_y = 0},/obj/structure/dogbed,/turf/simulated/floor/carpet,/area/crew_quarters/heads/sc/hop/quarters) @@ -10206,7 +10206,7 @@ "dOn" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock{name = "Bathroom"},/turf/simulated/floor/tiled/steel_grid,/area/crew_quarters/heads/sc/sd) "dOo" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/tiled/freezer,/area/crew_quarters/heads/sc/sd) "dOp" = (/obj/machinery/light/small{dir = 4},/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/turf/simulated/floor/tiled/freezer,/area/crew_quarters/heads/sc/sd) -"dOq" = (/obj/structure/closet/crate,/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftstarboard) +"dOq" = (/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/research,/obj/random/maintenance/research,/obj/random/maintenance/cargo,/obj/random/maintenance/cargo,/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/thirddeck/forestarboard) "dOr" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftstarboard) "dOs" = (/obj/structure/table/steel,/obj/random/maintenance/engineering,/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftport) "dOt" = (/obj/machinery/door/firedoor/border_only,/obj/effect/wingrille_spawn/reinforced,/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftport) @@ -10237,7 +10237,7 @@ "dOS" = (/obj/structure/toilet{dir = 1},/turf/simulated/floor/tiled/freezer,/area/crew_quarters/heads/sc/sd) "dOT" = (/obj/machinery/shower{dir = 1},/obj/structure/curtain/open/shower,/obj/structure/window/reinforced{dir = 8; health = 1e+006},/obj/machinery/door/window/northright,/obj/item/weapon/bikehorn/rubberducky,/turf/simulated/floor/tiled/freezer,/area/crew_quarters/heads/sc/sd) "dOU" = (/obj/machinery/door/firedoor/border_only,/obj/effect/wingrille_spawn/reinforced,/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftstarboard) -"dOV" = (/obj/structure/closet/crate,/obj/item/stack/cable_coil/random,/obj/item/stack/cable_coil/random,/obj/item/weapon/tool/crowbar,/obj/item/weapon/tool/wirecutters,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor,/area/maintenance/thirddeck/aftstarboard) +"dOV" = (/obj/item/clothing/mask/gas,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/effect/decal/cleanable/dirt,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/random/crate,/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftstarboard) "dOW" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden,/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftstarboard) "dOX" = (/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24},/obj/structure/cable/green,/obj/machinery/atmospherics/pipe/simple/hidden,/obj/structure/catwalk,/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftport) "dOY" = (/obj/structure/table/steel,/obj/random/tech_supply,/turf/simulated/floor/plating,/area/maintenance/thirddeck/aftport) @@ -10557,7 +10557,7 @@ "dVa" = (/obj/item/weapon/camera_assembly,/turf/simulated/floor/tiled,/area/construction/seconddeck/construction2) "dVb" = (/obj/machinery/light,/obj/item/stack/material/plastic,/obj/item/stack/material/plastic,/obj/item/stack/material/plastic,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dVc" = (/obj/machinery/computer/security/telescreen/entertainment{icon_state = "frame"; pixel_x = 0; pixel_y = -32},/obj/item/stack/cable_coil{pixel_x = 3; pixel_y = 3},/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) -"dVd" = (/obj/item/clothing/head/soft/mime,/obj/item/clothing/mask/gas/mime,/obj/item/clothing/shoes/mime,/obj/item/clothing/under/mime,/obj/structure/closet/crate,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) +"dVd" = (/obj/item/stack/cable_coil/random,/obj/item/stack/cable_coil/random,/obj/item/weapon/tool/crowbar,/obj/item/weapon/tool/wirecutters,/obj/random/maintenance/medical,/obj/random/maintenance/medical,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/random/crate,/turf/simulated/floor,/area/maintenance/thirddeck/aftstarboard) "dVe" = (/obj/item/frame/light,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dVf" = (/obj/structure/bed,/obj/item/weapon/bedsheet/mime,/turf/simulated/floor/plating,/area/construction/seconddeck/construction2) "dVg" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/atmospherics/pipe/simple/hidden/universal,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/door/airlock/maintenance{req_access = null; req_one_access = list(12,25,27,28,35)},/turf/simulated/floor/plating,/area/maintenance/chapel) @@ -11141,8 +11141,8 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakLakLakLakLakLakLakLakLakLakLakLakLakLaeFaeFakMakgafFafGalzakOakNakNakPakQakRakSafFafKakTaeFaeFaeFaioakUadlaaaaaaaaaaaaajpajpakoakVakWakWakXakYakZalaalbalcaldalealfalgalhalialjalkallalmalmalnakIajxajxaaaaaaaaaaaaadFaloaiyaeZaeZaeZalpaiAagmagmagmagmagmagmagmagmagmagmagmagValqaeZaeZdVQdVSdVRapiaqzdVUdVTdVVdVTdVVdVWdVYdVXdWadVZdVVdVVdVVdVVdWbbmqdWddWcdWedWcdWcdWfdWgaowaafaafaafaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalsalsaltaltaltalualtaltalualtaltaltalvaeFalwalxakgafFafGalAalBaAxalCaAyalBaDdafGafFafKalDalEaeFahcaioadladlaaaaaaaaaajpajpakoakoalFakoalGalHalHalHalHalHalHalHalHalHalHalHalHalIalIalIalJakIalKakIakIajxajxaaaaaaaaaadFadFaiyaikaeZalLalMaiAagmagmagmagmagmagmagmagmagmagmagmagValNaijaeZambdfZcYadWibmqdWkdWjdWmdWldWodWndWqdWpdWsdWrdWudWtdWwdWvdWxbmqdWzdWydWBdWAbHAdWCdWDaowaaaaaaaaaaaaaadaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalsaltalRalSalTalUalValWalXalYalZamaamraeFamcajEafEafFaiDaiDahBafFafFafFahBaiDaiDafFafKajEamdaeFameaioadLaaaaaaaaaaaaajpakoakVakWamfamgalHalHalHalHalHalHalHalHalHalHalHalHalHalIalIalIalIamhamialmalnakIajxaaaaaaaaaaaaaejaiyamjaeZaiSamkaiAagmagmagmagmagmagmagmagmagmagmagmagVakfagpaeZamsdWGdWFdWHbmqdWIarMdWJarMbmqbmqdWLdWKdWNdWMbmqarMdWJarMdWObmqdWQdWPdWSdWRdWUdWTdWVaowaaaaaaaaaaaaaafaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalsammamnamoamoamoamoamoamoamoampamaamraeFamqajEafEafFanEaoaafFafFafFafFafFanEaoaafFafKajEamtaeFamudWWadLaaaaaaaaaajoajoamvalFakoamwamxalHalHalHamyamzamAamBamCamDamEamBamFamGamHamIamJalIamKamLakIalKamMajwajwaaaaaaaaaaejaiyamNaeZamOamkaiAagmagmagmagmagmagmagmagmagmagmagmagVakfamPaeZapTdWZdWYdXbdXadXddXcdXbdXbdXfdXedXhdXgdXjdXidXkdXbdXmdXldXnaSNdXodXodXodXodXodXodXodXodXoaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalsaltalRamRamSamTaSjamUamVamWamXamaamraeFamYamZanaanbanbanbanbanbanbanbanbanbanbanbancandaneaeFanfaioadLaaaaaaaaaajoanganhalFalGanianianialHalHanjanjanjanjanjankanlanmanmannanoanpanqalIalIalIalJalKanransajwaaaaaaaaaaejaiyantaeZanuanvanwanxanxanxanxanxanxanxanxanxanxanxanyanzanAaeZdXpdXrdXqdXqdXsdXudXtdXwdXvdXxdXvdXzdXydXBdXAdXDdXCdXFdXEdXHdXGdXodXIdXKdXJdXMdXLdXKdXNdXobhgbhgaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalsammamnamoamoamoamoamoamoamoampamaamraeFamqajEafEafFamNamOafFafFafFafFafFamNamOafFafKajEamtaeFamudWWadLaaaaaaaaaajoajoamvalFakoamwamxalHalHalHamyamzamAamBamCamDamEamBamFamGamHamIamJalIamKamLakIalKamMajwajwaaaaaaaaaaejaiyantaeZanEamkaiAagmagmagmagmagmagmagmagmagmagmagmagVakfamPaeZapTdWZdWYdXbdXadXddXcdXbdXbdXfdXedXhdXgdXjdXidXkdXbdXmdXldXnaSNdXodXodXodXodXodXodXodXodXoaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalsaltalRamRamSamTaSjamUamVamWamXamaamraeFamYamZanaanbanbanbanbanbanbanbanbanbanbanbancandaneaeFanfaioadLaaaaaaaaaajoanganhalFalGanianianialHalHanjanjanjanjanjankanlanmanmannanoanpanqalIalIalIalJalKanransajwaaaaaaaaaaejaiyaoaaeZanuanvanwanxanxanxanxanxanxanxanxanxanxanxanyanzanAaeZdXpdXrdXqdXqdXsdXudXtdXwdXvdXxdXvdXzdXydXBdXAdXDdXCdXFdXEdXHdXGdXodXIdXKdXJdXMdXLdXKdXNdXobhgbhgaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalsalsaltaltaltaluanDanDalualtaltaltaoTaeFanFanGanHanHanIanHanHanJanKanLanManNanNanNanNanOamtaeFanPaioadladlaaaaaaajpanQanRanSanianiaoJaoKanialHanVanWanXanYanZanZaEyaobaocaodaoealIaofalIaogalIalIaohaoiaojajxaaaaaaadFadFaiyaokaeZaolaomaonaonaonaonaooaopaoqaoraosaosaotaosaosaouaovaeZdXOdXQdXPdXRapiatLdXSapidXUdXWdXVdXXaSNaSNdXYaSNaZYdXZcfodXHdYadXodYbdYcdXJdXMdXLdXKdYddXodXodYfdYedXoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaakLatTatTakLakLakLakLaoxaoxaoyaoyaoyaoyaoyaeFaeFaeFaeFaeFaeFaeFaeFaozahcaoAaeFaoBaoBaoBaeFaeFaeFaeFafMaoCaoDadlaaaaaaajpaoEaoFaoGaoHaoIapOarganialHanjaoLaoMaoNaxjanZaoOaoPaoQaoRaoSaGeaoUaoVaoWaoXalIaoYaoZapaajxaaaaaaadFapbapcapdaeZaeZaeZaikapeapeapeaikapfaikapgaikaeZaeZaeZaeZaeZaeZaeZaphaphaphaphaphdYgdYgalralralralralralrdYidYhalralrdXZdYjdYkdWHdXodYldXKdXJdXMdXLdXKdYldXodYmdYodYndXodXoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafakLakLapjapkaplapmapnakLapoapoappapqaprapsaptapuapvapwapxapyapyapzapuapAapAapBapCapDapEapFapCapGafMadlapHapIapJadlaaaaaaajpapKapLapManiapNaNGaNHanialHanjanjanjanjanjapPapQapQapQapRapSaGzapUapVapWapXalIapYapZaqaajxaaaaaaadFaqbaghaqcaqdaqeaqfaqgaqhaqiaqjaqgaqkaqlaqlaqmaqnaqoaqoaqpaqqaqraqmaqsaqtaquaqvaqwaqxaqxalraqydYpaqAaqBaqCalOdYqatMalrdYtdYsdXodXodXodYudYwdYvdYydYxdYAdYzdXodYBdYDdYCdYFdYEdYGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11158,16 +11158,16 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaafaafakLakLaBfaBfaBgaBhaBiaBjaBkaBlaxTaBmaBmaBmaxVayQaBnayRaBoayRaBpaBqaxVaBraBsaBsaBtaBtaBtaBtaBtaBtaBtaBtaBuaBvaBwaybaaaaaaaBxaByaBzaBAaBDaAqaAmaBCaBBaBGaBHaBIaBJaBJaBKaBJaBEaBFaAvaCWaBOaBPaBQaBRaBSaBTaAzaBUaBVaBWaBXaaaaaaayxaBYazBaAIaBZaCaaCaayyaCbaFDaCdayyaqkaqlaqlayDaCeaCfayDaCgaARaChayDaCiaCjaCkaClaCmaCnaCnalraCoalOaCpaCqaCralralraafaaaaaaaaadXodXodXoeaVeaXeaWdYyeaYebaeaZdXodZbdZbdZbebbdXoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaakLakLaBfaCsaCsaCsaCsaCtaCtaCsaCsaCuaCsaCsaCsaCsaCsaCsaCsaCsaCsaCvaCwaCxaCyaBtaCzaCAaCBaCCaCDaCEaBtaybaCFaCGaybaaaaaaaBxaCHaCIaCJauAaBLaBMaCZaCKaCLaCPaCQaCRaCSaCTaCUaCVaCXaAvaGpaCYaDbaDadVsaDcaHbaAzaDeaDfaDgaBXaaaaaaayxaDhaDiaAIaDjaDjaDjaDkaDlaDlaDlaDkaDmaDkaDnaDkaDjaDjaDjaDjaDjaDjaDjazUazUazUazUazUaDoaDoalralralralravpavpalraaaaaaaaaaaaaaaaaaaaadXodYldXKdXKdYydXKdXKdYldXoebcebeebddXodXoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaDpaDqaDraDsaDtaDuaDvaDwaDxaDtaDyaDzaDAaDBaDCaDDaDEaDFaDGaDHaDIaDJaDKaDLaDMaDMaDMaDNaBtaDOaDPaybaybaaaaaaaBxaDQaCMaDSaCNaCNaykaykaykaykaDUaDVaDWaDXaDYaDZaEaaEbaEcaEdaEeaEfaAzaEgaEhaAzaAzaEiaEjaEkaBXaaaaaaayxayxaElaEmaDjaEnaEoaEpaEpaEpaEpaEqaEraEsaEtaEuaEuaEvaEuaEuaEwaExaDjaGAaEzaEzaEzaEAaEBaEBaECaEzaEzaEzaEDaEDaaaaaaaaaaaaaaaaaaaaaaaadXodYbdZBdXKdYydXKdXKdYddXodXodYfdYedXoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaEEaEFaEGaEHaEHaEIaEJaEJaEKaELaEMaENaENaEOaEPaEQaERaESaETaEUaEVaEWaEXaEYaEZaDMaDMaFaaFbaDOaDPaFcaaaaaaaaaaAeaFdaFeaFfaFgauHauHaFhaFhaDTaFiaFjaCUaCUaCUaFkaCVaFlaFmaFnaFoaFpaAzaAzaAzaAzaFqaFraFsaFtaAGaaaaaaaaaaFuaElaFvaDjaFwaFxaFyaFzaFzaFzaFzaFzaFzaFzaFzaFzaFzaFzaFAaFBaFCaDjaHSaFEaFFaFGaFHaFIaSBaFKaFLaFMaFNaEzaEDaaaaaaaaaaaaaaaaaaaaaaaadXoebfdXKdXKdYydXKdXKebgdXobhgbhgaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaEEaFOaFPaFPaFPaFPaFPaFPaFPaFRaFSaEPaEPaFTaEPaEPaFUaFVaFWaFXaFYaFZaGaaDMaGbaGcaGdaHYaBtaDOaDPaFcaaaaaaaaaaAeaAeaGfaFfaFfaGgaDTauHaFhaDTaGhaGiaGjaGkaCUaGlaGmaGnaAvaHdaHcaHPaGqaAzaGraGsaGtaFraGuaAGaAGaaaaaaaaaaFuaElaGvaDjaEnaGwaGxaGyaMtaNbaGyaGyaGyaGyaGyaMtaNbaGyaGBaGwaGCaDjaHSaFEaGDaFJaFJaFJaFJaFJaFJaFJaGEaGFaEDaaaaaaaaaaaaaaaaaaaaaaaadXodXodXodXodXodXodXodXodXoaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaEEaFOaFPaFPaFPaFPaFPaFPaFPaFRaGGaEPaEPaFTaEPaEPaGHaCxaGIaGJaGKaGLaGMaGNaGOaGPaGQaGRaBtaybaGSaFcaaaaaaaaaaaaaBxaFfaFfaFfaFfaGTauHauHauHaGUauHaGVaGWaGXaCUaGYaGZaHaaOeaHRaHTaAvaAvaHeaHfaHgaHhaGtaBXaaaaaaaaaaaaaFuaElaHiaDjaHjaGwaGxaGyaHkaHkaHlaGyaGyaGyaHlaHkaHkaGyaGBaGwaHmaDjaHSaFEaHnaHoaHpaHqaHraHsaHtaHuaFNaEzaEDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaHvaFOaFPaFPaFPaFPaFPaFPaFPaHwaHxaHxaHxaFTaEPaEPaHyaCxaHzaHAaHBaEWaEWaGLaHCaEWaEWaEWaEWaHDazhaybaybaaaaaaaaaaBxaBxaFfaFfaFfaFfaFgaHEaHFaHFaHFaHGaHHaHIaHJaHKaHLaAvaAvaAvaAvaAvaFqaGtaFraGtaGtaBXaBXaaaaaaaaaayxayxaElaDkaDjaHMaHNaGxaGyaHOaHVaHQbqBaMzbskaHQbsmaHOaGyaGBaHWaHXaDjaRLaEzaEzaEzaEAaEzaEzaECaEzaEzaEzaEDaEDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaadaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaEEaEFaEGaEHaEHaEIaEJaEJaEKaELaEMaENaENaEOaEPaEQaERaESaETaEUaEVaEWaEXaEYaEZaDMaDMaFaaFbaDOaDPaFcaaaaaaaaaaAeaFdaFeaFfaFgauHauHaFhaFhaDTaFiaFjaCUaCUaCUaFkaCVaFlaFmaFnaFoaFpaAzaAzaAzaAzaFqaFraFsaFtaAGaaaaaaaaaaFuaElaFvaDjaFwaFxaFyaFzaFzaFzaFzaFzaFzaFzaFzaFzaFzaFzaFAaFBaFCaDjaGCaFEaFFaFGaFHaFIaSBaFKaFLaFMaFNaEzaEDaaaaaaaaaaaaaaaaaaaaaaaadXoebfdXKdXKdYydXKdXKebgdXobhgbhgaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaEEaFOaFPaFPaFPaFPaFPaFPaFPaFRaFSaEPaEPaFTaEPaEPaFUaFVaFWaFXaFYaFZaGaaDMaGbaGcaGdaHYaBtaDOaDPaFcaaaaaaaaaaAeaAeaGfaFfaFfaGgaDTauHaFhaDTaGhaGiaGjaGkaCUaGlaGmaGnaAvaHdaHcaHPaGqaAzaGraGsaGtaFraGuaAGaAGaaaaaaaaaaFuaElaGvaDjaEnaGwaGxaGyaHjaHSaGyaGyaGyaGyaGyaHjaHSaGyaGBaGwaLhaDjaGCaFEaGDaFJaFJaFJaFJaFJaFJaFJaGEaGFaEDaaaaaaaaaaaaaaaaaaaaaaaadXodXodXodXodXodXodXodXodXoaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaEEaFOaFPaFPaFPaFPaFPaFPaFPaFRaGGaEPaEPaFTaEPaEPaGHaCxaGIaGJaGKaGLaGMaGNaGOaGPaGQaGRaBtaybaGSaFcaaaaaaaaaaaaaBxaFfaFfaFfaFfaGTauHauHauHaGUauHaGVaGWaGXaCUaGYaGZaHaaOeaHRaHTaAvaAvaHeaHfaHgaHhaGtaBXaaaaaaaaaaaaaFuaElaHiaDjaMtaGwaGxaGyaHkaHkaHlaGyaGyaGyaHlaHkaHkaGyaGBaGwaHmaDjaGCaFEaHnaHoaHpaHqaHraHsaHtaHuaFNaEzaEDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxTalsaCtaHvaFOaFPaFPaFPaFPaFPaFPaFPaHwaHxaHxaHxaFTaEPaEPaHyaCxaHzaHAaHBaEWaEWaGLaHCaEWaEWaEWaEWaHDazhaybaybaaaaaaaaaaBxaBxaFfaFfaFfaFfaFgaHEaHFaHFaHFaHGaHHaHIaHJaHKaHLaAvaAvaAvaAvaAvaFqaGtaFraGtaGtaBXaBXaaaaaaaaaayxayxaElaDkaDjaHMaHNaGxaGyaHOaHVaHQbqBaMzbskaHQbsmaHOaGyaGBaHWaHXaDjaNbaEzaEzaEzaEAaEzaEzaECaEzaEzaEzaEDaEDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaadaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakLakLaCsaEEaFOaFPaFPaFPaFPaFPaFPaFPaHZaHZaHZaIaaFTaEPaEPaIbaESaIcaHAaIdaIeaIfaDHaIgaESaDOaIhaIiaAcazhaIjaybaaaaaaaaaaaaaBxaBxaFfaFfaFfaFfaIkaIlaImaInazlaIoaIpaIqaIraIsaItaIuaIvaIwaIxaHgaHgaHhaGtaBXaBXaaaaaaaaaaaaayxaIyaElaDjaDjaDjaIzaGxaGyaIAaIBaICaIDaIEaIEaIFbwsaHOaGyaGBaIGaDjaDjalralralralralralralralralralralralralraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaCOaEEaFOaFPaFPaFPaFPaFPaFPaFPaIHaIIaIJaIIaIKaENaENaILaIMaINaIOaIPaIQaIRaIQaISaITaDOaIhaAcaAcaIUaIVaybaaaaaaaaaaaaaaaaBxaBxaFfaIWaIXaIYaIZaJaaJbaJcaJdaJeaJfaJgaJhaJiaJjaJkaJlaJmaJnaJoaGtaBXaBXaaaaaaaaaaaaaaaayxaJpaJqaDkaDjaJraGwaGxaGyaJsaTJaJuaJvaJwaJwaJwaJwaJxaGyaGBaGwaJyaDjaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaDRaJzaFOaFPaFPaFPaFPaFPaUcaFPaFRaEPaEPaJAaFTaJBaJCaJDaJEaJFaJGaJHaJIaJJaJKaJLaESaDOaJMaJNaAcazhaJOaybaaaaaaaaaaabaaaaaaaBxaBxaAeaJPaJQaJRaJSaInazlaIoaJTaJUaJVaJWaJXaJYaJZaKaaKbaKcaAGaBXaBXaaaaaaaabaaaaaaaaaayxaKdaElaKeaDjaJraGwaGxaGyaHOaKfaKgaKhaJwaKiaKjaKkaKlaGyaGBaGwaJyaDjaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaKmaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaCOaEEaFOaFPaFPaFPaFPaFPaFPaFPaHwaHxaKnaHxaKoaCsaCsaCsaCvaCvaCvaKpaKqaKraKqaKqaESaybaybaybaybazhaKsaKtaKtaKtaaaaaaaaaaaaaaaaaaaAeaAeaBxaBxaBxaAeaAeaKuaKvaJUaKwaKxaAGaAGaBXaBXaBXaAGaAGaaaaaaaaaaaaaaaaaaaKyaKyaKyaKzaElaKAaDjaKBaKCaGxaGyaHOaHOaHlaHkaKDaKhaHlaHOaHOaGyaGBaKEaKFaDjaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafaCsaEEaFOaFPaFPaFPaFPaFPaFPaFPaKGaKGaKGaKHaKIaCsaKJaKJaKJaKJaKJaKpaKKaKLaKMaKqaKNaKNaKNaKNaybazhaKsaKOaKPaKtaKtaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaKQaKRaKSaJUaKTaKUaKQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaKyaKyaKVaKWaKzaElaKXaDjaJraKYaGxaGyaGyaHOaKZaLaaJwaLbaLcaHOaGyaGyaGBaKYaJyaDjaaaaaaaaaaaaaaaaadaadaadaadaadaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaCsaEEaFOaFPaFPaFPaFPaFPaFPaFPaIHaIIaIIaIIaFTaLdaKJaKJaKJaKJaKJaKpaLeaLfaLgaKqaLhaAcaAcaAcaLiazhaLjaLkaLlaLmaKtaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaKQaLnaLoaLpaLqaLraKQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaKyaLsaLtaLuaLvaElaLwaDjaJraLxaGxaGyaGyaHkaLyaJwaJwaJwaLzaHkaGyaGyaGBaLxaJyaDjaDkaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaCsaEEaFOaFPaFPaFPaFPaFPaFPaFPaIHaIIaIIaIIaFTaLdaKJaKJaKJaKJaKJaKpaLeaLfaLgaKqaRLaAcaAcaAcaLiazhaLjaLkaLlaLmaKtaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaKQaLnaLoaLpaLqaLraKQaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaKyaLsaLtaLuaLvaElaLwaDjaJraLxaGxaGyaGyaHkaLyaJwaJwaJwaLzaHkaGyaGyaGBaLxaJyaDjaDkaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaCsaLAaFOaFPaFPaFPaFPaFPaFPaFPaFRaEPaEPaEPaLBaLCaKJaKJaKJaKJaKJaKpaLDaLEaLFaKqaAcaAcaAcaLGaybaLHaKsaLIaLlaLJaKtaaaaaaaaaaaaaLKaLLaLMaLLaLNaaaaaaaLOaLOaLPaJUaLQaLRaLRaLRaLRaLRaLRaLSaLSaLSaLRaLRaLRaLRaKyaLTaLtaLUaKzaElaDkaDjaDjaLVaLWaGyaGyaKhaLXaLXaJwaLXaLXaKhaGyaGyaGBaLYaDjaDjaDjaafaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaCsaEEaFOaFPaFPaFPaFPaFPaFPaFPaFRaLZaEPaEPaFTaMaaKJaKJaKJaKJaKJaKpaKqaMbaKqaKqaMcaMdaMeaMfaMfaMgaKsaMhaLlaMiaKtaaaaaaaaaaaaaMjaMkaMlaMmaMjaaaaaaaaaaLOaMnaJUaMoaMpaMqaMraMsaSbaLSaMuebhaMwaMxaMybCFaLRaMAaMBaLtaLuaKzaMCaDjaDjaMDaMEaLWaGyaGyaHOaMFaKhaMGaKhaHlaHOaGyaGyaGBaMHaMIaDjaDkaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaCsaEEaFOaFPaFPaFPaFPaFPaFPaFPaFRaMJaMKaMLaMMaCsaMNaKJaKJaKJaKJaMfaDOaDOaDOaybaybaybaybaMfaMOaLHaKsaKsaMPaKsaKtaMQaMQaMQaMRaMjaMSaMTaMUaMjaMVaMQaMQaMQaMWaMXaMWaLRaMqaMYaMZaTgaNaaNdaNcaNfaNeaNgbCFaLRaKzaKzaNhaKzaKzaNiaDkaDjaNjaNkaLWaGyaGyaKhaNlaNmaJwaNmaNnaKhaGyaGyaGBaNkaJyaDjaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11386,9 +11386,9 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadJaaaaaaaaabgvbsRbZMbsSbpFbpGbtibxTbxWbxUbxUbxVbxYbxZbwwbxXbycbydbyabybbyfbygbyebwBbzebuwbyhbwObwPbwQbwRbCqbYsbwUbwUbwUbwUbwUbwUbwVbwWbwXbrbbwYbvNbwZbvNbvPbrbbvNbxabrbbvNbxbbrbbvNbxcbrbbxdbxebxfbxgbxhclfclgcnebuWbxkbxlbxmbxnbxobuWbxpbxqbxrbxsbxtbuZbxubxvbvZbxwbxibxxbvgaaaaaaaaaaaaaaabvgbvgbvibvibvibvgbxybxzbxAbxBbxCbxDbxEbxFcePccVcdkbxHbxHbxIbxIaafaafaafbhgaafaafaafaafbxJbxKbxLbhgbxMbxNbxObxPbxQaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabgvbgvbgvbgvbgvaaabqCbumbqEbzhbzfbzgbzjbAnbzibAqbArbAsbTHbXDbzibnLbAtbAubBQbuwbAvbyibyjbuwbvCbxGcozbuxbuxbuxbuxbuxbuxbuxbymbynbrbbyobvNbypbyqbvPbrbbyrbysbrbbyrbytbrbbyrbyubrbbyvbywbyxbxgbxhcnfcoUcJZbuWbyybyzbyAbyBbyCbuWbyDbxqbyEbxqbyFbuZbyGbxvbvZbvZbyHbvZbvZbvgbvgbvgbvgbvgbvgebsbyIbyJbyKbyKbyLbyMbyMbyLbyNcePbyOcqUcyVcqTbyTbxHbyUbyVbxIbxIaaaaaabhgaaaaaaaaaaafbyWbyXbyYbyZbzabyZbyWbzbbyWaafaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaaaabkHbzcbzdbBRbkAbkAbBTbBVbzkbuvbBWbzlbwwbuvbuvbDpbBYbDobqIbuwbuwbzmbuwbuwbuxbAObzobzpbuxbzqbzrbzsbztbuxbymbynbrbbrbbrbbrbbrbbrbbrbbrbbrbbrbbrbbrbbrbbrbbrbbrbbzubzvbzwbzxbxhcOBdcSdfrbuWbzAbzBbzCbzDbzEbuWbzFbzGbzHbxqbzIbuZbzJbzKbzLbzMbzNbzNbzNbzNbzNbzNbzObzNbzNbzNbzNbzPbzQbzRbzSbzTbzUbzVbzWbyObyPcHvbyObzYbzZbAabAbbAcbAdbxIaaaaaabhgaaaaaaaaaaaabyWbAebFdbAfbAgbAhbyWbAibyWaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaabAjbAjbAjbAjaaaaaaaaabAjaaaaaaaaaaaaaaabAjaaaaaaaaabAjbAjbAjbAjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAkbAkbAkbAkbAkbAkbAkbAkbAkbAlbAmbDvbDqbApbETbFhbELbEMbAwbGFbGmbEMbAxbAybAzbAAbABbACbvCcKMbAEbAFbuxbDJbymbymbymbAGbAHbAIbwUbAJbAKbALbAMbwUbwUbwUbwUcNqcOFcQhcOEcOFcQibAQbuxbARbASbATbxhbxhbxhbxhbuWbAVbAWbAXbAYbAZbuWbBabBbbBcbBdbBebuZbBfbxibBgbBhbBibBjbBkbxibxibBlbBlbBlbBlbBlbBlbBlbBmbBnbBobBpbBqbBrbBrbBrbBrbBsbBsbBsbBsbBsbBtbBubBvbBwbBwbBxbBwbBxbBwbBxbBwbBwbBybBzbBAbBBbBCbyWbBDbyWbyWaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaabAjbAjbAjbAjaaaaaaaaabAjaaaaaaaaaaaaaaabAjaaaaaaaaabAjbAjbAjbAjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAkbAkbAkbAkbAkbAkbAkbAkbAkbAlbAmbDvbDqbApbETbFhbELbEMbAwbGFbGmbEMbAxbAybAzbAAbABbACbvCcKMbAEbAFbuxbDJbymbymbymbAGbAHbAIbwUbAJbAKbALbAMbwUbwUbwUbwUcNqcOFcQhcOEcOFcQibAQbuxbARbASbATbxhbxhbxhbxhbuWbAVbAWbAXbAYbAZbuWbBabBbbBcbBdbBebuZbBfbxibBgbBhbBibzzbBkbxibxibBlbBlbBlbBlbBlbBlbBlbBmbBnbBobBpbBqbBrbBrbBrbBrbBsbBsbBsbBsbBsbBtbBubBvbBwbBwbBxbBwbBxbBwbBxbBwbBwbBybBzbBAbBBbBCbyWbBDbyWbyWaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaabAjbAjbAjbAjaaaaaaaaabAjbAjbAjbAjbAjbAjbAjaaaaaaaaabAjecAbAjbAjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaafaafaaaaaabBEbBFbBGbBHbAkbBIbBJbBKbBLbBMbBMbBNbAkbBObBPbIobGJbBSbJSbBSbIqbBSbLjbBXbJUbBZbCabCbbCcbCdbCebCfbvCbCgbzobChbuxbCibCjbymbymbuxbCkbClbymbCmbCnbuxbuxbCobuxbuxbCpcRncgecSBcRocSBcSEbuxbuxbCsbCtbCubvZbvZbCvbyJbuWbCwbCxbuWbuWbuWbuWbuZbuZbCybuZbuZbuZbBfbxibCzbCAbBibwnbCBbCCbCDbBlbCEcaRbCGbCHbCIbBlbCJbCJbCKbCJbCJbBrbCLbCMebubBsbCObBsbCPbBsbCQbCRbCSbBwbCTbCUbCVbCVbCWbCXbCYbBwbCZbDabDbbDcbDdbDebDfbDgbyWaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaabAjbAjbAjbAjaaaaaabAjbAjbAjbAjbAjbAjbAjbAjbAjaaaaaabAjbAjbAjbAjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaagaadaadaaaaabaaaaaaaaabBEbDhbDhbDibAkbDjbDjbDjbDkbBMbDlbDmbAkbDnbNkbPTbLlbDrbDsbDtbCfbDuedNbDwecRbDubDybDybDzbDAbDBbDybuxbDCbDDbFebuxbuxbuxbDFbymbuxbCrbDGbDGbDHbDGbDGbDIbymbImbuxbDKbymbDLbuxbvFbymbCrbymbuxbDMbDNbDObvZbxibxibzzbDPbxibDQbAUbAUbAUbAUbBgbDRbDSbDTbDUbDVbDWbDXbDYbvZbDZbDZbDZbDZbEabBlbEbbEcbEdbEebEfbFMbEhebvbEjbEkbElbBrebwbEndgGbBsbEpbBsbEqbBsbBsbErbEsbEtbEubEvbCVbEwbExbEybEzbBwbEAbEAbEAbFUbEAbEAbEAbEAbEAbEAaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaabAjbAjbAjbAjaaaaaabAjbAjbAjbAjbAjbAjbAjbAjbAjaaaaaabAjbAjbAjbAjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaagaadaadaaaaabaaaaaaaaabBEbDhbDhbDibAkbDjbDjbDjbDkbBMbDlbDmbAkbDnbNkbPTbLlbDrbDsbDtbCfbDuedNbDwecRbDubDybDybDzbDAbDBbDybuxbDCbDDbFebuxbuxbuxbDFbymbuxbCrbDGbDGbDHbDGbDGbDIbymbImbuxbDKbymbDLbuxbvFbymbCrbymbuxbDMbDNbDObvZbxibxibBjbDPbxibDQbAUbAUbAUbAUbBgbDRbDSbDTbDUbDVbDWbDXbDYbvZbDZbDZbDZbDZbEabBlbEbbEcbEdbEebEfbFMbEhebvbEjbEkbElbBrebwbEndgGbBsbEpbBsbEqbBsbBsbErbEsbEtbEubEvbCVbEwbExbEybEzbBwbEAbEAbEAbFUbEAbEAbEAbEAbEAbEAaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaabAjbAjbAjbAjaaaaaabAjbAjbAjbAjbAjbAjbAjbAjbAjaaaaaabAjbAjbAjbAjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaadaadaagaadaadaadaagaafaaaaafaaaaaaaaaaaaaaaaaaaaabBEbECbEDbEEbAkbEFbEGbEGbEHbEGbEIbEJbAkbEKbNkedObENbEObEPbEQbERbESbOXbEUedPbEWbEXbEYbEZbFabFbbFcbuxbGSbGTbFfbFgcbEbuxbvGbvFbuxbFibDGbFjbFkbFlbDGbFmbFnbChbuxbzpbymbFobuxbvGbymbFpbFqbFrbFsbFtbFubFvbDTbFwbDTbFxbDTbFybDTbDTbDTbDTbFzbFAbFBbFBbFBbFBbFBbFBbFCbFDbDZbFEebxbFGbEabFHbFIbFJbFKbFLbFVbFMbFNbFObFPbEjbHxbKtebzebybFTbGbbGibFWbFXbFYbBsbFZbGabHybGcbGdbGebGdbGfbGgbGhbKrbGjbGkbGlbGpbGqbGnbGobJpbGrbGsaaaaaaaaaabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaabAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaaaaaaaafaaaaaaaaaaaaaafaaaaaaaafaaaaaaaaaaaaaaaaaaaaabBEbGtbGubGvbAkbGwbEGbEGbGxbGybGzbGAbGBbGCbGDedRedQcFcbGGbGHbERbGIbXNbGKedSbGMbEXbGNbGObGPbGQbGRbuxbGUbVfbuxbGVcbEbuxbAQbAQbuxbGWbDGbGXbFkbGYbDGbuxbuxbuxbuxbGZbGZbGZbuxbuxbuxbuxbuxbHabHbbHcbHdbHabvZbvZbvZbvZbvZbvibvibvibvZbvZbvZbvZbFBbHebHfbHgbHhbFBbHibHjbHkbHlbHmbHnbEabHobHpbEcbHqbHrbHsbEgbHtebBebCebAbFQbBrebFebDebEbBsbHCbHDbHEbHFbBsbHGbHHbBwbHIbHJbHKbHJbHKbHJbHLebGbHMbHNbHObHPbHQbHRbHSbHTbHUbHVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaabAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjbAjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaafaaaaaaaaaaaaaafaaabHWbHWbHWbHWbHWbHWbHWbHXbHXbBEbHYbHZbDibAkbIabIabIbbIcbIdbIebIfbAkbIgbIhbIibIjbIkbIlccMbCfbInedUbIpedTbIrbDybIsbItbIubIvbIwbIxbIxbIybIxbIxbIxbIxbuxbuxbuxbIzbDGbIAbIBbICbDGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabIDbIEbIFbIGbIHbIIbIDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabFBbIJbIKbILbILbIMbINbBqbDZbIObIPbIQbEabIRbISbITbIUbIVbIWbEgbEjebIbIXebHbIZbBrbBrbBrbBrbBsbJdbJebJfbJgbBsbJhbJibBwbBwbJjbJkbJlbJjbJmbJjbBxbJnbJobKFbJqbJrbJsbJtbJqbJubJvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11427,9 +11427,9 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafcLzcLAcDHcLBcLCcLDcDHcKqcLEcLFcLGcLHcLIcLJcLKcLLcGTcLMcIMcIMcDUcLNcLOcKzcLPcLQcDUcLRcLScHgecoecpecpecpcLScLVcKGcLWcLWcLWcLWcLWcLXcLYcLYcLZcLYcoVcoVcoVedbedccKNcMacMbcMccKNcKNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactUcMdcMecMfcMgcMhctUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacKRcKRcMicMjcKRcMkcKVcMlcMmcMncKTcMocMpcMqcMrcMscKZcMtcMucMvcMwcMxcLbcMycMzcMAcMBcMCcLhcMDcMEcMFcMGcMHcMIcMJcMKcMLcMMcMNcMOcMOcMOcMOcMOcMOcMPcMQcMRcMScMTcMUcMVaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaacMWcDHcFpcFpcDHcDHcMXcMYcMYcMXcMZcNacMXcMXcLLcGTcIMcIMcIMcDUcNbcNccNdcNecNfcDUcNgcHgcHgcNhcNicHgcHgcHgcNjcNkcLWcLWcLWcLWcLWcLXcNlcNmcNncLYcCwcQkcoVcTDedgcNrcNscNscNtcNucKNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactUcNvcNwcNxcNycNzctUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacKRcNAcNBcNCcKRcNDcKVcNEcNFcNGcKTcNHcNIcNJcNKcNLcNMcNNcNOcNPcNQcNRcLccNScNTcNUcNVcNWcNXcNYcNZcOacObcOccLhcOdcOecOfcOgcOhcMOcOicOjcOkcPucMOcOmcOncLucOocOpcOqcLyaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaacMXcOrcOscOtcMXcLLcGTcIMcIMcIMcDUcDUcDUcDUcDUcDUcDUcOucOvcHgcHgcOwcOwcOwcHgcOxcOycLWcLWcLWcLWcLWcLXcOzcOAdUVcLYcOCcBbcODedhedicKNcPVcOHcOIcOJcKNcoVcoVcoVcoVczlczlczlcoVcoVcoVcoVcoVcOKcOLcMfcOMcOKcpkcpkcpkcpkcpkczCczCczCcpkcpkcpkcpkcKRcONcOOcOPcKRecqcKVcORcOScOTcKTcOUcOVcOWcOXcOYcKZcOZcPacPbcPccPdcLfcNScNTcPecPfcPgcPhcPicPjcPkcPlcPmcLhcPncPocPpcPqcPrcMOcPscPtcPtcSLcMOcPvcPwcPxcPycPzcPAcKlaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaacMXcPBcPCcPDcMXcLLcGTcGTcPEcIMcFucFucIMcIMcIMcPFcGTcEacPGcEacEacPHcPIcPJcPKcPLcPMcLWcLWcLWcLWcLWcLXcPNcPOcPPcLYcPQcPRcoVcPScPTcKNcKNcKNcKNcKNcKNcPWcHwcHwcQacQacPYcQacQacQacQacQacQacQbcQccQdcQecQfcQgcQgcQgcQgcQgcQgcURcTHcpkcQjcSpcQlcKRcQmcOOcQncKRcQocKVcKVcQpcKVcKTcQqcQrcQscQtcQucKXcQvcQwcQxcQycPdcLccNScQzcQAcQBcQCcQDcQEcQFcQGcQHcQIcLhcLlcLlcLlcLlcLlcMOcPscQJcQKcSLcMOcQLcQMcKlcKlcKlcKlcKlaafaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaafaaaaaaaaaaaacMXcQNcQNcMXcMXcLLcIMcGTcGTcFucFucGTcGTcGTcGTcGTcGTcQOcQOcQOcEacEacEacEacQPcQQcKGcLWcLWcLWcLWcLWcLXcLYcKUcLYcLYcoVcoVcoVcQScQTcQUcHwcQVcQWcQXcHwcHxcBbcBbcBbcBbcQYcQZcAYcPUcPUcRdcRecoVcRfcRgcRhcpkcRicRjcRicRkcRlcRmcWecWcedmedpedpedocKRcKRcRpcKRcKRcQocpkcGjcRqcRrcLacRscRtcUgcRvcRwcKZcRxcRycRzcRAcRBcLbcRCcRDcREcRFcRGcRHcRIcRJcRKcRLcRMcRNcROcRPcRQcRRcRScMOcRTcRUcPtcRVcMOcRWcRXcpwaaaaaaaaaaaaaaaaaaaaaabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcaadaadaaaaaaaaacMXcRYcRZcSacMXcSbcKvecscSdcSecSfcSgcShcIMcSicIMcSjcSkcSkcSkcSlcSmcSmcEacEacEacKGcKGcKGcKGcKGcKGcKGcQOcSncQOcGTcSocGTdTdcBbcFUcBbcSqcSrcPScNocBbcSucSvcSwcSucSucSucSucSucSucSucSucSucSucSxcSycSzcSAcSAcSAcSKcSAcSAcSAcSAdaMedvedredvedtcSFcSGcSHcSDcSDcSIcSJcTucTycSMcLacLacLacLacLacLacLacSNcLbcLbcLbcSOcLbcSPcSQcSRcSScSPcLhcSTcLhcLhcLhcMIcSUcSVcSWcSXcSYcSZcTacPtcTbcTccTdcTecTfcTgcpwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaacMXcPBcPCcPDcMXcLLcGTcGTcPEcIMcFucFucIMcIMcIMcNocGTcEacPGcEacEacPHcPIcPJcPKcPLcPMcLWcLWcLWcLWcLWcLXcPNcPOcPPcLYcPQcPRcoVcPScPTcKNcKNcKNcKNcKNcKNcPWcHwcHwcQacQacPYcQacQacQacQacQacQacQbcQccQdcQecQfcQgcQgcQgcQgcQgcQgcURcTHcpkcPFcSpcQlcKRcQmcOOcQncKRcQocKVcKVcQpcKVcKTcQqcQrcQscQtcQucKXcQvcQwcQxcQycPdcLccNScQzcQAcQBcQCcQDcQEcQFcQGcQHcQIcLhcLlcLlcLlcLlcLlcMOcPscQJcQKcSLcMOcQLcQMcKlcKlcKlcKlcKlaafaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaafaaaaaaaaaaaacMXcQNcQNcMXcMXcLLcIMcGTcGTcFucFucGTcGTcGTcGTcGTcGTcQOcQOcQOcEacEacEacEacQPcQQcKGcLWcLWcLWcLWcLWcLXcLYcKUcLYcLYcoVcoVcoVcQjcQTcQUcHwcQVcQWcQXcHwcHxcBbcBbcBbcBbcQYcQZcAYcPUcPUcRdcQScoVcRfcRgcRhcpkcRicRjcRicRkcRlcRmcWecWcedmedpedpedocKRcKRcRpcKRcKRcQocpkcGjcRqcRrcLacRscRtcUgcRvcRwcKZcRxcRycRzcRAcRBcLbcRCcRDcREcRFcRGcRHcRIcRJcRKcRLcRMcRNcROcRPcRQcRRcRScMOcRTcRUcPtcRVcMOcRWcRXcpwaaaaaaaaaaaaaaaaaaaaaabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcaadaadaaaaaaaaacMXcRYcRZcSacMXcSbcKvecscSdcSecSfcSgcShcIMcSicIMcSjcSkcSkcSkcSlcSmcSmcEacEacEacKGcKGcKGcKGcKGcKGcKGcQOcSncQOcGTcSocGTdTdcBbcFUcBbcSqcSrcPScRecBbcSucSvcSwcSucSucSucSucSucSucSucSucSucSucSxcSycSzcSAcSAcSAcSKcSAcSAcSAcSAdaMedvedredvedtcSFcSGcSHcSDcSDcSIcSJcTucTycSMcLacLacLacLacLacLacLacSNcLbcLbcLbcSOcLbcSPcSQcSRcSScSPcLhcSTcLhcLhcLhcMIcSUcSVcSWcSXcSYcSZcTacPtcTbcTccTdcTecTfcTgcpwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfGaafaafaafaafaaaaaaaaacMXcMXcSbcKucKucKucThcTicTicTicTjcTicTicTicTkcKucKucKucKucThcKucKucKucKucKucKucKucKucTlcTmcTncTocTpcKucTqcTrcTscTtcTJcTJcTJcTJcTJcVYcSucTvcTwcRbcRacSucStcTxcUCcRccSscTEcSucTzcTAcXacSAcTGcTIcUucUvcUvcUMcSAcUNcSAcpkcpkcpkcpkcpkcpkcpkcpkcpkcTKcsFcTLcTMcTNcTOcTPcTQcTQcTRcTScTTcTUcTVcTWcTXcSRcTYcTZcUacUbcUccSRcUdcTWcTVcTUcUecSUcUfcXCcUhcUicUjcMOcUkcUlcUmcUncUocUpcUqcpwaaaaaaaaaabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaafaaaaaaaaaaaacMXcMXcMYcMYcMYcMXcMXcMXcMYcMYcMYcMXcMXcMXcMXcMXcMXcMXcMXcIMcIMcIMecucIMcIMcIMcIMcIMcIMcIMcMXcMXcMXcMXcUrdaPcUtcTJcUycUwcUxcUYcUZcSucUzcTwcUDcUAcUBcUGcUHcUEcUFcUIcUScSucUJcUKdfkcSAcSAcSAcUOcUPcUQcUTcSAcUUcUXcVacVbcVccWdcWfcWkcWncWocpkcpkcpkcTLcVfcVhcVdcVecVgcWbcGjcTScVicUacVjcVkcVlcSRcVmcVncVocVpcVqcSRcVrcVkcVjcUacVscSUcSUcSUcSUcVtcSUcMOcMOcMOcMOcMOcMOcVucVvcVwaafaafaafabcaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaaaaaaaafaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaacMXcMXcVxcVycVzcVAcVBcVCcVDcVEcVFcMXcMXaaaaaaaaaczledbcVHcVKcVIcVIcVJcVNcVOcSucVLcVQcVRcVPcSucVTcVUcVScVMcWacUVcSucVVcVWcVXcSAcWpcWqcWrcWWcXbcXccXdcXecXfcVacXgcXjcYrcWfcYscYtcYvcpkcXkcpkcTLcWlcWmcWmcWlcXlcXmcXncXocWscWtcWucWvcWwcWxcWycWzcWAcWycWycWxcWAcWBcWCcWycWDcWEcQRcWGcWHcWIcWJcWKcWLcWMcWNcWOcWPcWQcWRcWSaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11437,9 +11437,9 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaaaaaaaafaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaabaafaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaacUrcVGcXrcTJcTJcTJcTJcXucTJcTJcXscXxcYjcXvcXwcYncYocYkcYmcYpcYqddAcYucUKddzdhacZwcZzcZBdhacYFcYGcSAcUNcSAcVacVacZCcVacWfcWfcZDcWfcpkdmFdmFcZEcYLcYMcYNcYOczCczCcTRcTScTScYPcYQcYRcYScYRcSPcYTcYUcYVcSPcYWcYXcYYcYZcYYcZacZbcZbcZbcZccZdcZccZecZfcZgcZfcZhcZicZjcZicWSaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaagaadaadabcaagaagaadaadaadaadaafaaeaaaaafaagaadaadaadaadaadaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaacUrcUscZkcZncTJcYIcZPcZmcYJcWhcZlcZqcZrcYmcZpcZtcZucZscYqcZvcYqddAcZxcZycZAdaQdaRdaSdaTdhacZFcYGcZGcZHcZIcZJcZMcZNcZGcZOcZQcZRdaqdardasdasdatcTRcZTcZTcTRaaaaafaaaaaaaaacYPcZUcZVcZWcZXcZYcZYcZZcZYcZYdaadabdacdaddaedafdagdahcZbdaidajdakcZedaldamdancZhcWScYicWScVwaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaafaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaacUrdaodapdawdaxdaudavdaAdavdaydazdaGdaHdaBdaCdaKdaLdaIdaJdaNdaOdfUdaDdaEdaFdcIdcJdcMddrdhadaUdaVdaYdbvdbMdbOdbPdbQdbPdbRdbSdbYdbZcYHdiUdnMdcEcTRdaWdaXdcHaaaaafaaaaaaaaacYPdaZdbadbbdbcdbddbedbfdbgdbhdbidbjdbkdblcYYdbmdbndbocZbdbpdbqdbrcZedbsdbtdbucZhaaaaaaaaaaafaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafabcaagaadaafaaaaaaaaaaadaadaadaaaaaaaaaaaaaaacUrdbwdbxdbzcTJdbyddFdbBdbCdbAcZKdbDdbEcYmcZpdbGdbHcYqdbFdbJcYqdkmdbKcUKddzdaQddwdegdexdhadcNcYGdcOdcUdcZddsddBddCddDddEddDddDddDcYHddMddYdeadmGaaaaaaaaaaaaaafaaaaaaaaacYPdcadcbdccdcddbddcedcfdcgdbhdchdcidcjdckcYYdcldcmdcncZbdcodcpdcqcZedcrdcsdctcZhaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafabcaagaadaafaaaaaaaaaaadaadaadaaaaaaaaaaaaaaacUrdbwdbxdbzcTJdbyddFdbBdbCdbAcZKdbDdbEcYmcZpdbGdbHcYqdbFdbJcYqdkmdbKcUKddzdaQddwdegdexdhadcNcYGdcOdcUdcZddsddBddCddDddEddDddDddDcYHddMdcRdeadmGaaaaaaaaaaaaaafaaaaaaaaacYPdcadcbdccdcddbddcedcfdcgdbhdchdcidcjdckcYYdcldcmdcncZbdcodcpdcqcZedcrdcsdctcZhaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaaaaaaaaaaaacUrdcudbTdbWcTJdbNcZKdbUdcVdbXcZKdbDdcvcYmcZpdczdcAdcwdcxdcCdcDdcBdcKdcLdefdhadhadfcdaQdhadeccYGdcOdeecYHcYHcYHdehcYHcYHcYHcYHdeicYHcYHcYHdejdmGaaaaaaaaaaaaaafaaaaaaaaacYPddaddbddcddddbdddeddfdcgdbhddgddhddiddjcYWddkddkddkddkddlddmddlddnddoddpddocZhaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaadaafaafaafaafcUrddXdcPdcRcTJdcFdbVdcQdcTcZlcZKcZqdcWcYmcZpdcYddtcYqdcXdduddvddAddycUKdewdfHcYHdetdeydezdeAcYGdcOdeGdeMddZddZddZddZddZddZddZddZddZddZdeMdejdnfaaaaaaaaaaaaaafaafaafaafcYPcYPddNddOddPddQddRddSddTddQddUddVddWcYWcYWaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaagabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaadaafaafaafaafcUrddXdcPddYcTJdcFdbVdcQdcTcZlcZKcZqdcWcYmcZpdcYddtcYqdcXdduddvddAddycUKdewdfHcYHdetdeydezdeAcYGdcOdeGdeMddZddZddZddZddZddZddZddZddZddZdeMdejdnfaaaaaaaaaaaaaafaafaafaafcYPcYPddNddOddPddQddRddSddTddQddUddVddWcYWcYWaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaagabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaacUrddXddGecMcTJddxddJddHddIddKddLcTJdebcYqcZpcYqcYqcYqcYqcYqcYqddAddycUKdfkdgddeNdePdfadfbdfddfjdfodfpdeMddZddZddZddZddZddZddZddZddZddZdfsdcEdnfaaaaaaaaaaadaagaaaaaaaaaaafcYPcYPcYPcYPddQddQddQddQddQcYWcYWcYWcYWaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUrddqcoVcoVcTJdekcZKcZKcZKcZldeldjFdemdemdendbHderdepdeqdeudevcYwdescVWdfydipdftdfudfvdfwdfIcYGdfNdfTdeMddZddZddZddZddZddZddZddZddZddZdeMdcEdnfaaaaaaaagaadaaaaaaaaaaaaaagaaaaaaaaaaaaaafaaaaaaaaaaafaaaaaaaaaaafaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcaaaaaaaaaaaacUrddXdeBcAYcTJcZLdeCdeFdeddeDdeEcXpdeIcYqdeHdeKcYwdeJddAddAdeLcYwdeQcUKdgcdgvcYHdfVcYGdfWdfYcYGdfNdgadgbddZddZddZddZddZddZddZddZddZddZdgedcEdmGaafaafaadaaaaabaaaaaaaaaaadaaaaaaaaaaaaaafaaaaaaaaaaafaaaaaaaaaaafaaaaaaaafaafaadaadaadaafaaeaagaadaadaadaadaadaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11458,17 +11458,17 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUrdkTdmddiMdmOdmfdmOdmgdjsdjsdkYdmidiRdlxdmjdlUdjsdmkdmldmmdmndmodmOdmqcUKdlidhudhxdmrdmtdmudmvdmwdmxdjYdjXdjYdjYdjZdkadkbdkcdkddkbdkbdkedkfdkgdkhdkiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUrcAYdjjdkldlDdmydlDdlDdmzdmAdmBdmAdmAdmAdmAdmCdmDdmVdmldmWdmYdmodmOdfkcUKdmsdlEdlFdlGdlJdlKdlLdlYdlZdkHdmEdkJdkHdkKdkLdkMdkNdkOdkNdkNdkPdkQdkRdkSdkiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUrcUrcUrcUrcUrcUrcUrdmediMdiMdkrdksdnJdnKdmZdoodoqdoudoudnLdmhdoxdoydozdoAdoAdlHdmOdfkdncdowdixdixdmUdixdixdixdixdmXdixdixdixdlmdixdlndixdlodlpdlqdhxdnadhxdnbdixdjAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdmHdmHdmIdmHdmHdqndmKdmLdmMdiMdmNdmOdmOdmPdmQdiMdiMdiMdiMdiMdiMdiMdiMdiMdmOdmOdmOdmRdmSdcLdmTdnednhdnhdnxdnhdnydnDdnednednednednEdnFdnGdixdnHdnHdnIdnNdnOdhxdordosdotaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdmHdmHdmIdmHdmHdprdmKdmLdmMdiMdmNdmOdmOdmPdmQdiMdiMdiMdiMdiMdiMdiMdiMdiMdmOdmOdmOdmRdmSdcLdmTdnednhdnhdnxdnhdnydnDdnednednednednEdnFdnGdixdnHdnHdnIdnNdnOdhxdordosdotaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdngdrgdrgdrgdnidnidmKdnjdnkdnkdnldnkdnmdnndnodnpdnqdnrdnsdntdnudnvdnwdpNdpOdnzdnAdnBdfkcUKdVAdnedovdovdoCdoDdpkdoFdnedpcdpcdnedixdixdixdixdixdixdixdixdmadixdixdixdjAaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmIdnPdnQdnRdnRdnSdmIdnTdnUdnVdnWdnXdnYdnZdoadobdocdoddoedofdogdohdoidojdokdoldomdomdomdondqodopdnednednedpedpfdpgdphdpidpjdsRdnedpldpmdpndpodppdpqdprdnedpsdcGdpLdpMdpPaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmIdnPdnQdnRdnRdnSdmIdnTdnUdnVdnWdnXdnYdnZdoadobdocdoddoedofdogdohdoidojdokdoldomdomdomdondqodopdnednednedpedpfdpgdphdpidpjdsRdnedpldpmdpndpodppdpqdqndnedpsdcGdpLdpMdpPaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdngdoGdoHdoHecTdoJdmcdoLdoMdoNdoOdoPdoQdoRdoPdoPdoOdoSdoTdoUdoVdoWdoXdoYdoZdpadpbdoYdfkcUKdpddnedpQdpRdpUdqkdqldqmdnedoEdoEdnedqOdqpdpqdqqdqrdqsdqtdnedqudqvdcGdqwdpPaafaafaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdngdptdoHdoHdoIdoJdmcdoLdpudpvdoOdpwdpxdpydpzdpAdoOdpBdpBdpCdpBdpDdpEdpFdpGdpFdpHdpIdpJcUKdpKdnednednednedqxdnednhdnednednednedqydqzdpqdsbdqAdpqdqtdnedqBdcGcZScZScZScZSaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmIdpSdoKdpTdpTdnSdmIdmKdpVdpudpWdoPdpXdpYdpZdpXdpXdqadqbdqcdqddqcdqedpEdqfdqgdqhdpFdqidfkcUKdqjdqCdqSdqTdqUdqVdqWdqXdqYdqZdradrbdrcdrddredrfdrydrydrydrzdrAdrBdhhdrCdrDdpPaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdngdqDdqDdqDdnidnidmKdqEdpudqFdoPdqGdqHdqIdqJdqKdoOdqLdqMdqNdqcdqPdpEdrsdqQdqRdpFdqidfkdsLdqjdqCdqSdrEdpqdpqdrFdrGdrGdrHdrGdrIdrJdrKdrGdrLdrGdrMdscdnedsddsedsfdcGdsgdpPaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdmHdmHdmIdmHdmHdrtdmKdrhdridrjdoOdrkdrldrmdrndrodoOdrpdrqdrrdqcdrXdpEdrYdrudrvdrwdrxdfkdtrdtsdsidsjdskdsldsmdrGdrGdsndnDdpqdsodnednednedspdnednednednedsEdsFdhhdsGdsHdpPaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdngdqDdqDdqDdnidnidmKdqEdpudqFdoPdqGdqHdqIdqJdqKdoOdqLdqMdqNdqcdqPdpEdrsdqQdqRdpFdqidfkdsLdqjdqCdqSdrEdpqdpqdrFdrGdrGdrHdrGdrIdrJdrKdrGdrLdrGdrMdrtdnedsddsedsfdcGdsgdpPaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmHdmHdmHdmIdmHdmHdscdmKdrhdridrjdoOdrkdrldrmdrndrodoOdrpdrqdrrdqcdrXdpEdrYdrudrvdrwdrxdfkdtrdtsdsidsjdskdsldsmdrGdrGdsndnDdpqdsodnednednedspdnednednednedsEdsFdhhdsGdsHdpPaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmKdmKdmKdmKdmKdmKdmKdrNdrOdpWdoPdrPdrQdrRdrSdrTdoOdrUdqcdrVdrWdCFdpEdCZdrZdsadpFdqidfkcUKdXTdsIdsJdsKdsMdsNdrGdrGdsndpqdpqdsOdsPdnedpqdsQdshdnedsSdnedtkdtldhhdhhcZScZSaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmKdsqdsrdqFdoPdssdpxdssdstdsudoOdsvdqcdswdqcdsxdpEdsydszdsAdpFdsBdsCcTAdsDdsIdtmdtndtodsNdrGdrGdsndpqdtpdpqdpqdnhdpmdtqdttdnedtudnedtvdFLcZSaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadsTdsTdsTdsTdsTaaaaaaaaaaaaaaaaaadmKdsUdsVdoXdoOdsWdsXdsYdssdsZdtadtbdtcdtddtcdtedpEdpEdpEdpEdtfdtgdthdtidtjdtgdHddUXdUYdUZdVadrGdsndpqdpqdVbdVcdnhdVddVedVfdnedsSdnedVgdVtcZSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadsTdsTdsTdsTdsTaaaaaaaaaaaaaaaaaadmKdsUdsVdoXdoOdsWdsXdsYdssdsZdtadtbdtcdtddtcdtedpEdpEdpEdpEdtfdtgdthdtidtjdtgdHddUXdUYdUZdVadrGdsndpqdpqdVbdVcdnhdCmdVedVfdnedsSdnedVgdVtcZSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadsTdsTdsTdsTdsTdsTdsTaaaaaaaaaaaadtgdtgdtwdtxdtydoOdoOdoPdoPdoPdoOdoOdtzdpBdpBdpBdtzdtAdtBdtCdtydtDdtCdtxdtEdtwdtFdtgdtAedledledledldtAdnednednednednednednednednednednedtHdtIdtgdtgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadsTdsTdsTdsTdsTdsTdsTaaaaaaaaaaaadtgdtJdtKdtLdtLdtGdtMdtNdtOdtPdtQdtPdtRdtSdtTdtUdtTdtVdtKdtLdtLdtWdtLdtXdtYdtKdtLdtWdtLdtXdtLdtZdtTdtPdtTdtSduadtUdtQdtPdubdtNdtMdtGdtLducdudduedtgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadufdufaaaaaaaaaaaaaaadufdufaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadsTdsTdsTdsTdsTdsTdsTaaaaaaaaaaaadtgdugduhduidujdukdulduldumdulduldujdundulduldumduldulduodulduldukduldupduqduoduldukduldumduldulduldujduldurdusdumdulduldujdulduldukdujdutduuduvdtgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadufdufdufaaaaaaaaadufdufdufaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11647,7 +11647,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaafaaaaaaaaaaaaaaaaafdAVdAVdAVdAVdAVdAVdAVdAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBadAVdAVdAVdAVdBcdBcdBcdBIdBJdBKdBLdBLdBLdCedBmdBNdBcdBcdBcdAVdAVdAVdAVdBadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBraaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaadBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaafaafaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBPdBcdBcdBQdBRdBSdBTdBUdBVdBWdBXdBYdBZdCadBcdBcdCbdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBraaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaadBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaagaadaadaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCcdCcdCcdCcdCcdCcdCcdAVdAVdAVdAVdAVdAVdAVdBcdBcdBcdBIdBJdBKdBLdCddBLdCedBmdBNdBcdBcdBcdAVdAVdAVdAVdAVdAVdAVdCfdCfdCfdCfdCfdCfdCfdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafaafaafaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaagaafaaaaafaaaaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdAVdAVdAVdAVdAVdCgdChdChdChdChdCidCjdCkdCldCmdCcdAVdAVdAVdAVdAVdCndCodCodCpdCpdCqdCrdCsdBLdBLdBLdBAdCtdCudBcdBcdAVdAVdAVdAVdAVdAVdAVdAVdCfdCvdCwdCxdCydCzdCAdCAdCAdCAdCBdAVdAVdAVdAVdAVdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaagaafaaaaafaaaaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdBGdBHdBudAVdAVdAVdAVdAVdAVdCgdChdChdChdChdCidCjdCkdCldHrdCcdAVdAVdAVdAVdAVdCndCodCodCpdCpdCqdCrdCsdBLdBLdBLdBAdCtdCudBcdBcdAVdAVdAVdAVdAVdAVdAVdAVdCfdCvdCwdCxdCydCzdCAdCAdCAdCAdCBdAVdAVdAVdAVdAVdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdBDdBOdBFdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaafaaaaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCCdAVdAVdAVdCCdAVdAVdAVdCCdAVdAVdAVdCCdAVdAVdAVdCCdAVdAVdCDdAVdCEdCEdCEdCgdFMdCGdCHdCIdCJdCldCldCldCKdCcdAVdAVdAVdAVdAVdCLdAVdAVdBcdBcdBcdCMdCNdCOdDvdCOdCQdCRdBcdBcdBcdAVdAVdAVdAVdAVdAVdAVdAVdCfdCSdCTdCUdCUdCVdCWdCXdCYdFYdCBdDadDadDadAVdAVdAVdAVdDbdAVdAVdAVdDbdAVdAVdAVdDbdAVdAVdAVdDbdAVdAVdAVdDbdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaafaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdDcdDddDddDddDedDddDddDddDedDddDddDddDedDddDddDddDedDddDddDddDedDddDddDfdDgdDhdDidDjdDkdDldDmdDndDodDpdDqdDrdDsdDtdCcaaaaaaaaaaaaaaadDuaaaaaadBcdBcdBcdBjdIqdDwdDxdDydDzdBedBcdBcdBcaaaaaadDAaaaaaaaaaaaaaaadCfdDBdDCdDDdDDdDEdDFdDGdDHdDIdDJdDKdDLdDMdDNdDOdDPdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDQdDRdDSdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaafdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCCdAVdAVdAVdCCdAVdAVdAVdCCdAVdAVdAVdCCdAVdAVdAVdCCdAVdAVdAVdAVdCEdDTdDUdDVdDWdDXdDYdCIdDZdCldEadEbdCcdCcaaaaaaaaaaaaaaadDuaaaaaaaaaaaadBcdBcdBcdBcdEcdBcdBcdBcdBcaaaaaaaaaaaadDAaaaaaaaaaaaaaaadCfdCfdEddEedCUdEfdCWdEgdEhdEidEjdEkdEldDadAVdAVdAVdAVdEmdAVdAVdAVdEmdAVdAVdAVdEmdAVdAVdAVdEmdAVdAVdAVdEmdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11661,7 +11661,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadEnedxdEndEndE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadEndEndEndEndEndEndEndEndEndEndEnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCcdFKdVudFoaaaaaadAVdAVdAVdAVdAVdAVdCLdAVdFpdOgdFNdFOdFPdFQdFRdFSdFTdFUdFVdFWdFXdOJdFsdAVdAVdAVdAVdAVdAVdAVdAVaaaaaadFudFZdGadCfdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadEndEndEndEndEndEndEndEndEndEndEnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCcdGbecCdCcaaaaaadGddGedGfdGedGgdGgdGhdGgdGgdGidGjdGkdGldFpdGmdGndGmdFsdGodGpdGqdGrdGsdGtdGudGtdGsdGvdGwdGvdGxaaaaaadCfecDdGzdCfdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadEndEndEndEndEndEndEndEndEnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCcdGAdCldCcaaaaaadGddGBdGCdGDdGEedAedzedBdGgdFpdFpdFpdGIdGJdGKdGLdGMdGNdGOdFsdFsdFsdGsdGPdGQdGRdGSdGTdGUdGVdGxaaaaaadCfdCUdGWdCfdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadBrdBrdBrdBrdBrdBrdBraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadEndEndEndEndEndEndEnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCcdGXdGYdCcaaaaaadGddGZdHadHbdGEdeoedCedEdGgdHfdHgdHgdHhdHgdHgdHidHgdHgdHjdHgdHgdHkdGsdHldHmdHndGSdHodHpdHqdGxaaaaaadCfdHrdHsdCfdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadEndEndEndEndEndEndEnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCcdGXdGYdCcaaaaaadGddGZdHadHbdGEdeoedCedEdGgdHfdHgdHgdHhdHgdHgdHidHgdHgdHjdHgdHgdHkdGsdHldHmdHndGSdHodHpdHqdGxaaaaaadCfdOqdHsdCfdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadEndEndEndEndEnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdCcdCcdHtdEqdCcaaaaaadGddHudHvdHwdGEdeOdHyedGdGgdHAdHBdHCdHDdHEdHFdHGdHEdHEdHHdHIdHBdHAdGsdHJdHKdHLdGSdHMdHNdHOdGxaaaaaadCfdEvdHPdCfdCfdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdHQdHQdHRdHSdHTdHUdHVdHWdHXdHYdHYdGddHZdIadIbdGgdfqdGEedIdIddHAdHCdIedIedIedIedIedIedIedIedIedIfdHAdIgdIhdIidGSdGsdIjdIkdIldGxdImdImdIndIodIpdKwdIrdIsdItdIudIudAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdIvdIwdIxdIydIzdIAdIBdICdIDdIEdIFdIGdIHdIIdIJdIKedJdIMedKdIOdIPdIQdIRdIedISdISdISdISdISdIedITdIUdIVdIWdIXdIYdIZdJadJbdIYdJcdJddJedJfdIWdJgdJhdJidJjdJkdJldJmdJndAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11673,8 +11673,8 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdMxdMxdMxdMxdMxdMydMzdKHdMAdMBdMCdMDdMDdMEdKLdMFdMGdMHdKKdMIdMJdMKdMLdMMdMNdMNdMNdMOdMPdMQdMNdMRdKWdMSdMTdMUdKVdMVdMWdMXdLaaaaaaadMYdMZdNadMYdMYdMYdMYdMYdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaadabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdNbdNcdKHdKHdKHdKHdKHdKHdKHdKKdKKdKKdKKdKKdNddNedNfdVBdNhdNhdNidNjdNkdNldNmdNndNodKWdKWdKWdKWdKWdLadLadLadLaaaaaaadMYdNpdNqdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdNrdNsdMxaaaaaadNtdNudNvdNwdNxdNydNzdNAdNtdNBdNCdNDdNEdNFdNGdNHdNGdNEdNEdNDdNIdNJdNKdNLdNMdNNdNOdNKdNPdNQdNKaaaaaadMYdNRdNSdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafaafaafaadaXGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdNbdNTdMxaaaaaadNtdNUdNVdNWdNXdNYdNZdOadNtdObdOcdIedOddOedHBdHAdHBdOfdRfdIedOhdOidNKdOjdOkdOldOmdOndOodOpdNKaaaaaadMYdOqdOrdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdNbdOsdOtaaaaaadOudNydOvdOwdOxdOydOzdOAdOBdOCdODdOEdOddOFdOGdOHdOIdHBdRgdOKdOLdOMdONdOOdOPdOQdORdNKdOSdOTdNKaaaaaadOUdOVdOWdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdNbdNTdMxaaaaaadNtdNUdNVdNWdNXdNYdNZdOadNtdObdOcdIedOddOedHBdHAdHBdOfdRfdIedOhdOidNKdOjdOkdOldOmdOndOodOpdNKaaaaaadMYdOVdOrdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdNbdOsdOtaaaaaadOudNydOvdOwdOxdOydOzdOAdOBdOCdODdOEdOddOFdOGdOHdOIdHBdRgdOKdOLdOMdONdOOdOPdOQdORdNKdOSdOTdNKaaaaaadOUdVddOWdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdOXdOYdOtaaaaaaecEdPadPbdPcdPddPcdPedPfdNtdPgdPhdIedPidPjdPkdPldPmdPndPodIedPpdPqdNKdNKdNKdPrdNKdNKdNKdNKdNKaaaaaadOUdPsdPtdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaagaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaafaafdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdPudPvdOtaaaaaadPwdPxdNydNydPydNydNydPzdNtdObdOcdPAdPAdPAdPBdPCdPDdPAdPAdPAdOhdOidNKdPEdPFdPGdPHdPIdUWdPKdNKaaaaaadOUdPLdPMdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaafaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdPNdPOdPPdAVdPNdPOdPPdAVdPNdPOdPPdAVdPNdPOdPPdAVdPNdPOdPPdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdMxdPudPQdMxaaaaaadPRdPSdPTdNydPUdPVdPWdPXdPYdPZdQadQbdQcdQddQedQfdQgdQhdQidQjdQkdQldQmdQndQodQpdQqdQrdQsdQtdNKaaaaaadMYdQudPMdMYdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdQvdQwdQxdAVdQvdQwdQxdAVdQvdQwdQxdAVdQvdQwdQxdAVdQvdQwdQxdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafaafaafabcaafaaaaaaaagaadaadaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11795,4 +11795,3 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa dUOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "} - diff --git a/maps/southern_cross/southern_cross-3.dmm b/maps/southern_cross/southern_cross-3.dmm index 433197e556c..bbd7e781ebb 100644 --- a/maps/southern_cross/southern_cross-3.dmm +++ b/maps/southern_cross/southern_cross-3.dmm @@ -364,7 +364,7 @@ "gZ" = (/obj/effect/floor_decal/industrial/warning{dir = 10},/obj/item/device/radio/intercom{name = "Station Intercom (General)"; pixel_y = -21},/turf/simulated/floor/tiled/steel_dirty,/area/surface/outpost/main/security) "ha" = (/obj/effect/floor_decal/industrial/warning{dir = 6},/turf/simulated/floor/tiled/steel_dirty,/area/surface/outpost/main/security) "hb" = (/obj/effect/floor_decal/industrial/warning/corner{dir = 1},/obj/structure/table/rack{dir = 8; layer = 2.6},/obj/item/device/gps/explorer{pixel_x = -5; pixel_y = -5},/obj/item/device/gps/explorer{pixel_x = -3; pixel_y = -3},/obj/item/device/gps,/obj/item/device/gps{pixel_x = 3; pixel_y = 3},/obj/effect/floor_decal/borderfloor,/obj/effect/floor_decal/corner/green/border,/turf/simulated/floor/tiled,/area/surface/outpost/main/security) -"hc" = (/obj/structure/closet/crate,/obj/item/stack/material/phoron{amount = 25},/turf/simulated/floor/plating,/area/surface/outpost/mining_main/gen_room) +"hc" = (/obj/item/stack/material/phoron{amount = 25},/obj/random/crate,/turf/simulated/floor/plating,/area/surface/outpost/mining_main/gen_room) "hd" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 1},/obj/structure/closet/secure_closet/explorer,/obj/effect/floor_decal/borderfloor,/obj/effect/floor_decal/corner/green/border,/obj/item/device/binoculars,/turf/simulated/floor/tiled,/area/surface/outpost/main/security) "he" = (/obj/structure/closet/secure_closet/explorer,/obj/effect/floor_decal/borderfloor,/obj/effect/floor_decal/corner/green/border,/turf/simulated/floor/tiled,/area/surface/outpost/main/security) "hf" = (/obj/structure/closet/secure_closet/explorer,/obj/machinery/ai_status_display{pixel_y = -32},/obj/effect/floor_decal/borderfloor,/obj/effect/floor_decal/corner/green/border,/turf/simulated/floor/tiled,/area/surface/outpost/main/security) @@ -1567,7 +1567,8 @@ "Eg" = (/obj/effect/shuttle_landmark{landmark_tag = "syndie_planet"; name = "Sif Surface West"},/turf/simulated/floor/outdoors/dirt/sif/planetuse,/area/syndicate_station/planet) "Eh" = (/obj/effect/shuttle_landmark{landmark_tag = "skipjack_planet"; name = "Sif Surface South"},/turf/simulated/floor/outdoors/dirt/sif/planetuse,/area/skipjack_station/planet) "Ei" = (/obj/effect/overmap/visitable/planet/Sif,/turf/simulated/mineral/sif,/area/surface/outside/plains/mountains) - +"Ej" = (/obj/random/crate,/turf/simulated/floor/tiled/steel_grid,/area/surface/outpost/main/garage) + (1,1,1) = {" aaaaaaaaaaaaaaaaababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababacadadadabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababaeaeaeababababababababab aaafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahaiajajajahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafakakakafafafafafafafafaa @@ -1606,7 +1607,7 @@ aaafafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalctctctctctct aaafafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalctctctctctctctctctalalalalalalalalalalalalalalalalalalalalaFalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalajajgIgIhshthuhvhwhxhyhzhyhAgIgIgIgIgIgIgIalalalalamajajajajajalalalalalalbHhBhBhBhBhBhChChChChChDhihEhFhFhFhFhFhGhGhGhFhFalalalalalalalalalalalafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaAaAaAaAaCaJaDaDaDaDaDaDcUcUcUcUcUcUcUcUcUcUcUcUcUaM aaafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalctctctctctctctalalalalalalalalalalalalalalalalalalalalalaFalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalajajajgIhHhIhyhJhKhLhMhNhOhPhQhRhShShTgIalalalalalamajajajajalalalalalalalalhBhUhVhWhBhYiahZizibhDhihEhFicidieifigihiiijhFalalalalalalalalalalalafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaAaAaAaAaAaGaDaDaDaDaDaDaDcUcUcUcUcUcUcUcUcUcUcUcUcUaM aaafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalctctctctctalalalalalalalalalalalalalalalalalalalalalalaFalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalajajajgIikhIhyiliminioipiqirisisitiuivgIalalalalalamajajajalalalalalalalalalhBiwixiyhBiAiYiBjmhCiCiDiEhFiFiGiGiGiHiHiGiIhFalalalalalalalalalalalafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaAaAaAaAaCaJaDaDaDaDaDaDcUcUcUcUcUcUcUcUcUcUcUcUcUcUaM -aaafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalaFalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalajajgIiJiKiLhJhyiMiNiOiPiQiRiSiTiUiVgIalalalalalamajajajalalalalalalalalalhBhBiWhBhBiXjEiZjahChDhijbhFiHiHjciiiiiHiHiGhGalalalalalalalalalalalafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaAaAaAaAaGaDaDaDaDaDaDcUcUcUcUcUcUcUcUcUcUcUcUcUcUcUaM +aaafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalaFalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalajajgIiJiKiLhJhyiMiNiOiPiQiRiSiTiUiVgIalalalalalamajajajalalalalalalalalalhBhBiWhBhBiXjEiZjahChDhijbhFiHiHjciiiiiHiHEjhGalalalalalalalalalalalafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaAaAaAaAaGaDaDaDaDaDaDcUcUcUcUcUcUcUcUcUcUcUcUcUcUcUaM aaafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalaFalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalajajgIgIjdjejfjggIgIjhgIgIjijjjkjkgIgIalalalalalamajajajalalalalalalalalaljlmMjnjojphChCjqhChCjrhijshGjtiHjujvjwiGiHiHhGalalalalalalalalalalalafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaAaAaAaAaGaDaDaDaDaDaDcUcUcUcUcUcUcUcUcUcUcUcUcUcUcUaM aaafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalaFalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalajajajgIgIgIgIjxgIjyjzjygIgIgIgIgIgIalalalalalalamajajajalalalalalalalalaljljAjWjCjDjHjFjGjKjIfYhijJhGqUiHjLiHiGiGiHiHhGaljMjMalalalalalalalalafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaAaAaCaJaDaDaDaDaDcUcUcUcUcUcUcUcUcUcUcUcUcUcUcUcUaM aaafalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalalaFalalalalalalalalalalalalalalalalalalalalalalalalalalalalajajajalalalalajajajjNjOjOjOjPjOjOjQjRjRjRjRjRjRjRjRjRjRjRjRjRjSjRjRjRjTjTjTjTjTjTjTjTjTjUjVlSjXjYjZkakbkakckakdkekfkgkhkikhkhkjiHiHhGalaljMalalalalalalalalafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaAaAaAaGaDaDaDaDaDaDcUcUcUcUcUcUcUcUcUcUcUcUcUcUcUcUaM @@ -1825,4 +1826,3 @@ aaafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafDADADADADA aaEiafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafagafafafafafafafafDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDVDMDWDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDJDJDKDKDJDJDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDQDVDMDWDQDQDQDQDQDQDQDQDQDQDQDQDQDQafafafafafafafafafafafafagafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaa aaaaaaaaaaaaaaaaabababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaabababababababababababababababababababababababababababababababababababDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDQDYDYDYDQDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDQDZDZDZDZDZDZDQDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDQDYDYDYDQDXDXDXDXDXDXDXDXDXDXDXDXDXababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaaaaaaaaaaaaaaababababababababababababababababababababababababab "} - diff --git a/maps/submaps/engine_submaps/engine_tesla.dmm b/maps/submaps/engine_submaps/engine_tesla.dmm index 8a34a5a3996..05e3a7d202e 100644 --- a/maps/submaps/engine_submaps/engine_tesla.dmm +++ b/maps/submaps/engine_submaps/engine_tesla.dmm @@ -288,14 +288,8 @@ dir = 1 }, /obj/structure/table/standard, -/obj/item/weapon/circuitboard/grounding_rod{ - pixel_x = 2; - pixel_y = 2 - }, -/obj/item/weapon/circuitboard/grounding_rod{ - pixel_x = -2; - pixel_y = -2 - }, +/obj/item/weapon/circuitboard/tesla_coil, +/obj/item/weapon/circuitboard/tesla_coil, /turf/simulated/floor, /area/engineering/engine_gas) "aB" = ( @@ -700,16 +694,16 @@ /turf/simulated/wall/r_wall, /area/submap/pa_room) "bj" = ( -/obj/structure/cable/yellow{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/power/tesla_coil, /obj/structure/cable/yellow{ d2 = 4; icon_state = "0-4" }, +/obj/structure/cable/yellow{ + d1 = 0; + d2 = 8; + icon_state = "0-8" + }, /turf/simulated/floor/airless, /area/space) "bk" = ( @@ -1137,16 +1131,12 @@ /turf/simulated/floor/tiled, /area/submap/pa_room) "bZ" = ( -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/structure/cable/yellow{ d2 = 2; icon_state = "0-2" }, /obj/machinery/power/tesla_coil, +/obj/structure/cable/yellow, /turf/simulated/floor/airless, /area/space) "ca" = ( @@ -1584,13 +1574,12 @@ /turf/simulated/floor, /area/engineering/engine_room) "cF" = ( -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/structure/cable/yellow, /obj/machinery/power/tesla_coil, +/obj/structure/cable/yellow{ + d2 = 2; + icon_state = "0-2" + }, /turf/simulated/floor/airless, /area/space) "cG" = ( diff --git a/maps/tether/submaps/gateway/snow_outpost.dmm b/maps/tether/submaps/gateway/snow_outpost.dmm index e5964e01141..e27b2f349ac 100644 --- a/maps/tether/submaps/gateway/snow_outpost.dmm +++ b/maps/tether/submaps/gateway/snow_outpost.dmm @@ -2606,20 +2606,6 @@ "iN" = ( /turf/simulated/floor/water/deep, /area/awaymission/snow_outpost/dark) -"iP" = ( -/obj/machinery/atmospherics/unary/vent_pump, -/obj/item/weapon/cell/slime, -/turf/simulated/floor/tiled/white, -/area/awaymission/snow_outpost/powered) -"iQ" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 5; - icon_state = "intact" - }, -/obj/item/weapon/cell/infinite, -/obj/item/weapon/cat_box, -/turf/simulated/floor/tiled/white, -/area/awaymission/snow_outpost/powered) "iR" = ( /obj/machinery/atmospherics/unary/vent_pump{ dir = 8; @@ -9181,8 +9167,8 @@ uy uy aO as -iP -iQ +by +aA aS yM bH diff --git a/maps/tether/submaps/offmap/talon.dm b/maps/tether/submaps/offmap/talon.dm index c530e24b08a..722cd150a5d 100644 --- a/maps/tether/submaps/offmap/talon.dm +++ b/maps/tether/submaps/offmap/talon.dm @@ -386,7 +386,7 @@ Once in open space, consider disabling nonessential power-consuming electronics filedesc = "Helmet Camera Monitoring (Talon)" extended_desc = "This program allows remote access to Talon helmet camera systems." size = 4 //Smaller because limited scope - nanomodule_path = /datum/nano_module/camera_monitor/talon_helmet + tguimodule_path = /datum/tgui_module/camera/ntos/talon_helmet required_access = access_talon // Talon ship cameras @@ -395,23 +395,18 @@ Once in open space, consider disabling nonessential power-consuming electronics filedesc = "Ship Camera Monitoring (Talon)" extended_desc = "This program allows remote access to the Talon's camera system." size = 10 //Smaller because limited scope - nanomodule_path = /datum/nano_module/camera_monitor/talon_ship + tguimodule_path = /datum/tgui_module/camera/ntos/talon_ship required_access = access_talon -/datum/nano_module/camera_monitor/talon_ship +/datum/tgui_module/camera/ntos/talon_ship name = "Talon Ship Camera Monitor" -/datum/nano_module/camera_monitor/talon_ship/modify_networks_list(var/list/networks) - networks.Cut() - networks.Add(list(list("tag" = NETWORK_TALON_SHIP, "has_access" = 1))) - networks.Add(list(list("tag" = NETWORK_THUNDER, "has_access" = 1))) //THUNDERRRRR - return networks +/datum/nano_module/camera_monitor/talon_ship/New(host) + . = ..(host, list(NETWORK_TALON_SHIP, NETWORK_THUNDER)) -/datum/nano_module/camera_monitor/talon_helmet +/datum/tgui_module/camera/ntos/talon_helmet name = "Talon Helmet Camera Monitor" -/datum/nano_module/camera_monitor/talon_helmet/modify_networks_list(var/list/networks) - networks.Cut() - networks.Add(list(list("tag" = NETWORK_TALON_HELMETS, "has_access" = 1))) - return networks +/datum/tgui_module/camera/ntos/talon_helmet/New(host) + . = ..(host, list(NETWORK_TALON_HELMETS)) /datum/computer_file/program/power_monitor/talon filename = "tpowermonitor" diff --git a/maps/tether/submaps/space/guttersite.dmm b/maps/tether/submaps/space/guttersite.dmm index e9e6bded61d..190e8f02f2d 100644 --- a/maps/tether/submaps/space/guttersite.dmm +++ b/maps/tether/submaps/space/guttersite.dmm @@ -5047,10 +5047,6 @@ /obj/structure/bonfire, /turf/simulated/mineral/floor/vacuum, /area/space) -"lP" = ( -/obj/item/weapon/card/emag, -/turf/simulated/mineral/floor/vacuum, -/area/space) "lQ" = ( /obj/item/weapon/card/emag_broken, /turf/simulated/mineral/floor/vacuum, @@ -5477,13 +5473,6 @@ "mU" = ( /turf/simulated/floor/carpet/gaycarpet, /area/tether_away/guttersite/unexplored) -"mV" = ( -/obj/item/device/radio/headset/nanotrasen/alt{ - desc = "The headset of an Eltorro employee."; - name = "Weird Headset" - }, -/turf/simulated/floor/carpet/gaycarpet, -/area/tether_away/guttersite/unexplored) "mW" = ( /obj/item/weapon/reagent_containers/food/drinks/cans/cola, /turf/simulated/floor/carpet/gaycarpet, @@ -5508,10 +5497,6 @@ /obj/machinery/floodlight, /turf/simulated/mineral/floor/vacuum, /area/tether_away/guttersite/unexplored) -"nc" = ( -/obj/effect/landmark/corpse/syndicatecommando, -/turf/simulated/mineral/floor/vacuum, -/area/tether_away/guttersite/unexplored) "nd" = ( /obj/effect/landmark/corpse/syndicatesoldier, /turf/simulated/mineral/floor/vacuum, @@ -5771,6 +5756,10 @@ /obj/effect/shuttle_landmark/premade/guttersite/mshuttle, /turf/space, /area/space) +"Bh" = ( +/obj/item/device/radio/headset/heads/captain, +/turf/simulated/floor/carpet/gaycarpet, +/area/tether_away/guttersite/unexplored) "Ob" = ( /obj/structure/cable/cyan{ d1 = 1; @@ -13794,7 +13783,7 @@ ab ab lU ab -lP +ab ab ab ac @@ -23489,7 +23478,7 @@ ag ad ad ad -nc +ad ad ad ag @@ -24558,7 +24547,7 @@ ag ad mU na -mU +Bh mU mU ad @@ -24699,7 +24688,7 @@ aa ag ad mU -mV +mU mY mU mU diff --git a/maps/tether/tether-02-surface2.dmm b/maps/tether/tether-02-surface2.dmm index d12c504b263..a11732ae09f 100644 --- a/maps/tether/tether-02-surface2.dmm +++ b/maps/tether/tether-02-surface2.dmm @@ -9853,12 +9853,6 @@ }, /turf/simulated/floor/wood, /area/rnd/breakroom) -"aup" = ( -/obj/structure/bed/chair/comfy{ - dir = 8 - }, -/turf/simulated/floor/wood, -/area/rnd/breakroom) "auq" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable/green{ @@ -10192,19 +10186,6 @@ /obj/structure/stairs/south, /turf/simulated/floor/tiled, /area/rnd/staircase/secondfloor) -"auW" = ( -/obj/structure/bed/chair/comfy{ - dir = 1 - }, -/obj/machinery/requests_console{ - department = "Science"; - departmentType = 2; - name = "Science Requests Console"; - pixel_x = -30; - pixel_y = 0 - }, -/turf/simulated/floor/wood, -/area/rnd/breakroom) "auX" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable/green{ @@ -12121,10 +12102,6 @@ /obj/effect/floor_decal/corner/yellow/bordercorner2, /turf/simulated/floor/tiled/monotile, /area/engineering/atmos) -"aya" = ( -/obj/structure/bed/chair/comfy, -/turf/simulated/floor/wood, -/area/rnd/breakroom) "ayb" = ( /obj/machinery/light_switch{ pixel_y = -28 @@ -28393,6 +28370,10 @@ }, /turf/simulated/floor/tiled/techmaint, /area/tether/surfacebase/surface_two_hall) +"dgA" = ( +/obj/structure/bed/chair/comfy/brown, +/turf/simulated/floor/wood, +/area/rnd/breakroom) "drH" = ( /obj/structure/cable{ d1 = 4; @@ -28412,6 +28393,12 @@ /obj/structure/railing, /turf/simulated/floor/plating, /area/maintenance/lower/rnd) +"dEl" = ( +/obj/structure/bed/chair/comfy/brown{ + dir = 8 + }, +/turf/simulated/floor/wood, +/area/rnd/breakroom) "dQd" = ( /obj/structure/catwalk, /obj/machinery/atmospherics/pipe/simple/visible/supply{ @@ -29193,6 +29180,19 @@ /obj/structure/disposalpipe/up, /turf/simulated/floor/plating, /area/maintenance/lower/rnd) +"qXI" = ( +/obj/machinery/requests_console{ + department = "Science"; + departmentType = 2; + name = "Science Requests Console"; + pixel_x = -30; + pixel_y = 0 + }, +/obj/structure/bed/chair/comfy/brown{ + dir = 1 + }, +/turf/simulated/floor/wood, +/area/rnd/breakroom) "rim" = ( /obj/machinery/alarm{ dir = 1; @@ -37719,9 +37719,9 @@ aqU arA ass aqk -aya +dgA auo -auW +qXI avu awj aAi @@ -37862,7 +37862,7 @@ arB ast aqk atD -aup +dEl atJ atJ awk diff --git a/maps/tether/tether-05-station1.dmm b/maps/tether/tether-05-station1.dmm index 0178eb04a34..f36d143c622 100644 --- a/maps/tether/tether-05-station1.dmm +++ b/maps/tether/tether-05-station1.dmm @@ -55,11 +55,6 @@ /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 10 }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, @@ -71,6 +66,11 @@ icon_state = "alarm0"; pixel_y = -22 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) "aai" = ( @@ -4076,9 +4076,9 @@ dir = 9; icon_state = "steel_grid" }, -/obj/machinery/atmospherics/pipe/simple/hidden{ - dir = 10; - icon_state = "intact" +/obj/machinery/atmospherics/pipe/manifold/hidden{ + dir = 1; + icon_state = "map" }, /turf/simulated/floor/tiled, /area/engineering/engine_airlock) @@ -4105,6 +4105,9 @@ name = "Engine Access"; req_one_access = list(11) }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 8 + }, /turf/simulated/floor/tiled/steel_grid, /area/engineering/engine_airlock) "ahE" = ( @@ -4185,6 +4188,9 @@ dir = 10 }, /obj/effect/floor_decal/steeldecal/steel_decals4, +/obj/machinery/atmospherics/pipe/simple/hidden/universal{ + dir = 4 + }, /turf/simulated/floor/tiled, /area/engineering/engine_airlock) "ahL" = ( @@ -5670,11 +5676,6 @@ /turf/simulated/floor, /area/engineering/storage) "akX" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/effect/floor_decal/steeldecal/steel_decals7{ dir = 8 }, @@ -5710,6 +5711,9 @@ /turf/simulated/floor/tiled, /area/hallway/station/atrium) "alb" = ( +/obj/machinery/atmospherics/binary/passive_gate{ + dir = 8 + }, /turf/simulated/floor/tiled, /area/engineering/engine_airlock) "alc" = ( @@ -5904,11 +5908,6 @@ /turf/simulated/floor, /area/engineering/engineering_monitoring) "alu" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, @@ -5925,6 +5924,11 @@ /obj/machinery/door/firedoor/glass/hidden/steel{ dir = 1 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "alv" = ( @@ -6216,11 +6220,6 @@ /turf/simulated/floor/wood, /area/hallway/station/atrium) "amc" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/effect/floor_decal/steeldecal/steel_decals7{ dir = 8 }, @@ -6309,11 +6308,6 @@ /turf/simulated/floor/wood, /area/hallway/station/atrium) "amj" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/effect/floor_decal/steeldecal/steel_decals7{ dir = 8 }, @@ -6329,11 +6323,6 @@ /turf/simulated/floor/tiled, /area/engineering/hallway) "amk" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/effect/floor_decal/steeldecal/steel_decals7{ dir = 8 }, @@ -6360,11 +6349,6 @@ /turf/simulated/floor/wood, /area/hallway/station/atrium) "amn" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/effect/floor_decal/steeldecal/steel_decals7{ @@ -6379,6 +6363,11 @@ /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 4 }, +/obj/structure/cable/green{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "amo" = ( @@ -6906,11 +6895,6 @@ /turf/simulated/floor/plating, /area/maintenance/abandonedlibrary) "ant" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, @@ -6924,6 +6908,11 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "anu" = ( @@ -6959,11 +6948,6 @@ /turf/simulated/floor/wood/broken, /area/maintenance/abandonedlibrary) "any" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, @@ -6975,14 +6959,14 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/simulated/floor/tiled, -/area/engineering/hallway) -"anz" = ( -/obj/structure/cable{ +/obj/structure/cable/green{ d1 = 4; d2 = 8; icon_state = "4-8" }, +/turf/simulated/floor/tiled, +/area/engineering/hallway) +"anz" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/supply, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, /obj/effect/floor_decal/steeldecal/steel_decals7, @@ -6993,6 +6977,16 @@ dir = 4 }, /obj/machinery/light, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/obj/structure/cable/green{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "anA" = ( @@ -7005,11 +6999,6 @@ /turf/simulated/floor/plating, /area/maintenance/abandonedlibrary) "anB" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/manifold/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -7021,6 +7010,11 @@ /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 10 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "anC" = ( @@ -7046,16 +7040,6 @@ /turf/simulated/floor/tiled, /area/engineering/hallway) "anD" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, /obj/structure/disposalpipe/segment{ dir = 2; icon_state = "pipe-c" @@ -7066,17 +7050,22 @@ /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 6 }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ dir = 1 }, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 1 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) "anE" = ( @@ -7086,11 +7075,6 @@ /turf/simulated/floor, /area/maintenance/station/eng_lower) "anF" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, @@ -7113,6 +7097,11 @@ name = "Gravity Generator"; req_access = list(11) }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled/steel_grid, /area/engineering/hallway) "anG" = ( @@ -7829,7 +7818,7 @@ }, /obj/machinery/door/firedoor/glass, /obj/machinery/door/airlock/glass_atmos{ - name = "Atmospherics Substation"; + name = "Backup Atmospherics"; req_access = list(24) }, /turf/simulated/floor/tiled/steel_grid, @@ -8187,6 +8176,11 @@ d2 = 8; icon_state = "4-8" }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "apN" = ( @@ -8815,6 +8809,11 @@ name = "Engineering"; sortType = "Engineering" }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "aqT" = ( @@ -8826,6 +8825,11 @@ dir = 8 }, /obj/structure/disposalpipe/segment, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "aqU" = ( @@ -9183,6 +9187,11 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/structure/disposalpipe/segment, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "arI" = ( @@ -10656,6 +10665,11 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, +/obj/structure/cable{ + d1 = 2; + d2 = 4; + icon_state = "2-4" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "auw" = ( @@ -10699,6 +10713,11 @@ dir = 4 }, /obj/structure/disposalpipe/segment, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "auz" = ( @@ -11368,6 +11387,11 @@ name = "Engineering Break Room"; sortType = "Engineering Break Room" }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "avA" = ( @@ -11878,6 +11902,11 @@ /obj/machinery/atmospherics/pipe/simple/hidden/cyan{ dir = 6 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "awo" = ( @@ -15516,6 +15545,11 @@ dir = 4; icon_state = "map" }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "aCS" = ( @@ -16216,6 +16250,11 @@ icon_state = "map" }, /obj/machinery/meter, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "aEy" = ( @@ -16794,6 +16833,11 @@ dir = 9; icon_state = "intact" }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "aIl" = ( @@ -20002,6 +20046,11 @@ name = "Engineering Lobby"; req_one_access = newlist() }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled/steel_grid, /area/engineering/foyer) "bzR" = ( @@ -20809,6 +20858,11 @@ name = "Engineering Hallway"; req_one_access = list(10) }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled/steel_grid, /area/engineering/foyer) "chD" = ( @@ -20860,12 +20914,6 @@ /area/tether/station/dock_two) "cto" = ( /obj/machinery/door/firedoor/glass, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, @@ -20877,6 +20925,11 @@ id_tag = "gravity_outer"; req_access = list(11) }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) "cuX" = ( @@ -20922,18 +20975,17 @@ dir = 4; icon_state = "map" }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled/techmaint, /area/engineering/gravity_lobby) "cTc" = ( @@ -21067,6 +21119,14 @@ }, /turf/simulated/floor/tiled/techmaint, /area/engineering/gravity_gen) +"dub" = ( +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/tiled, +/area/engineering/foyer) "dzP" = ( /obj/effect/floor_decal/borderfloor{ dir = 8 @@ -21159,6 +21219,14 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply, /turf/simulated/floor/carpet/purcarpet, /area/bridge/meeting_room) +"eed" = ( +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/tiled, +/area/engineering/hallway) "ejF" = ( /obj/effect/floor_decal/borderfloor/corner{ dir = 1 @@ -21428,6 +21496,17 @@ /obj/machinery/atmospherics/pipe/simple/hidden, /turf/simulated/floor/tiled, /area/tether/station/dock_one) +"fPT" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/tiled, +/area/engineering/hallway) "fTF" = ( /obj/structure/cable/green{ d1 = 1; @@ -21455,15 +21534,14 @@ /obj/effect/floor_decal/corner/yellow/border{ dir = 1 }, -/obj/structure/cable{ - d2 = 2; - icon_state = "0-2"; - pixel_y = 0 - }, /obj/machinery/power/apc/super{ dir = 1; pixel_y = 28 }, +/obj/structure/cable/green{ + d2 = 2; + icon_state = "0-2" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_gen) "fXG" = ( @@ -21481,11 +21559,6 @@ d2 = 2; icon_state = "1-2" }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, /obj/structure/disposalpipe/segment, /turf/simulated/floor/tiled, /area/engineering/hallway) @@ -21786,6 +21859,11 @@ /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 5 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/foyer) "hLV" = ( @@ -21985,11 +22063,6 @@ /turf/simulated/floor/tiled, /area/tether/station/dock_one) "juf" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/structure/cable/green{ d1 = 1; d2 = 2; @@ -22004,6 +22077,11 @@ /obj/structure/disposalpipe/junction{ dir = 8 }, +/obj/structure/cable/green{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "juI" = ( @@ -22017,6 +22095,11 @@ /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 9 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/hallway/station/atrium) "jFv" = ( @@ -22033,13 +22116,10 @@ dir = 8; icon_state = "bordercolorcorner" }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - pixel_y = 0 - }, /obj/machinery/atmospherics/unary/vent_scrubber/on, +/obj/structure/cable/green{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_gen) "jNX" = ( @@ -22064,15 +22144,15 @@ dir = 9; icon_state = "steel_grid" }, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 1 }, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, +/obj/structure/cable/green{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_gen) "jOH" = ( @@ -22228,6 +22308,11 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/foyer) "kJJ" = ( @@ -22592,6 +22677,11 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "nll" = ( @@ -22743,17 +22833,14 @@ /obj/effect/floor_decal/corner/yellow/border{ dir = 8 }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - pixel_y = 0 - }, /obj/machinery/firealarm{ dir = 8; pixel_x = -24 }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable/green{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_gen) "oso" = ( @@ -22800,11 +22887,6 @@ /turf/simulated/floor/tiled/steel_grid, /area/tether/station/dock_two) "oAK" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ dir = 8 }, @@ -22812,6 +22894,11 @@ dir = 8 }, /obj/structure/disposalpipe/junction/yjunction, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "oFB" = ( @@ -22998,18 +23085,17 @@ dir = 6; icon_state = "steel_grid" }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) "qdM" = ( @@ -23103,6 +23189,22 @@ }, /turf/simulated/floor/tiled, /area/engineering/gravity_gen) +"qvC" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/tiled, +/area/hallway/station/atrium) "qxn" = ( /obj/effect/floor_decal/techfloor/orange{ dir = 10 @@ -23123,18 +23225,17 @@ /obj/machinery/atmospherics/pipe/simple/hidden{ dir = 4 }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled/techmaint, /area/engineering/gravity_lobby) "riO" = ( @@ -23197,7 +23298,7 @@ name = "west bump"; pixel_x = -28 }, -/obj/structure/cable{ +/obj/structure/cable/green{ d2 = 4; icon_state = "0-4" }, @@ -23394,11 +23495,6 @@ /turf/simulated/floor/tiled, /area/engineering/hallway) "sjw" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/door/firedoor/glass, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -23410,6 +23506,11 @@ name = "Gravity Generator"; req_access = list(11) }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled/steel_grid, /area/engineering/gravity_lobby) "sqw" = ( @@ -23508,6 +23609,11 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, /turf/simulated/floor/tiled, /area/hallway/station/atrium) "sTb" = ( @@ -23644,6 +23750,11 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/foyer) "tqW" = ( @@ -23818,14 +23929,13 @@ /turf/simulated/floor/tiled, /area/engineering/hallway) "uOm" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - pixel_y = 0 - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable/green{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) "uTq" = ( @@ -23976,7 +24086,9 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ + dir = 4 + }, /turf/simulated/floor/tiled, /area/engineering/hallway) "vms" = ( @@ -24001,17 +24113,17 @@ /turf/space, /area/space) "vxw" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8" - }, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 10 }, +/obj/structure/cable/green{ + d1 = 2; + d2 = 8; + icon_state = "2-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) "vyI" = ( @@ -24048,6 +24160,11 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/foyer) "vAQ" = ( @@ -24057,17 +24174,17 @@ /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 6 }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) "vCw" = ( @@ -24134,13 +24251,10 @@ /obj/effect/floor_decal/corner/yellow/bordercorner2{ dir = 10 }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - pixel_y = 0 - }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable/green{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_gen) "wbY" = ( @@ -24353,18 +24467,17 @@ dir = 4 }, /obj/machinery/door/firedoor/glass, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) "xMk" = ( @@ -24459,22 +24572,22 @@ /turf/simulated/floor/tiled, /area/hallway/station/atrium) "ykG" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ dir = 8 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 5 }, +/obj/structure/cable/green{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/obj/structure/cable/green{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, /turf/simulated/floor/tiled, /area/engineering/gravity_lobby) @@ -31641,17 +31754,17 @@ aCR aEx aCR aIi -atW +eed mYV ceq vAn tpy -aoI +dub kHi hKn bzw jBX -agj +qvC sRG aws fjd @@ -31769,7 +31882,7 @@ bcc hAh qsp oAK -aKt +fPT apM aqS aqT diff --git a/maps/tether/tether-09-solars.dmm b/maps/tether/tether-09-solars.dmm index 167568a6d10..d5d2c5afde4 100644 --- a/maps/tether/tether-09-solars.dmm +++ b/maps/tether/tether-09-solars.dmm @@ -279,15 +279,18 @@ /area/tether/outpost/solars_shed) "aC" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/stack/cable_coil/lime, -/obj/structure/table/standard, -/obj/structure/cable/yellow{ - d1 = 4; - d2 = 8; - icon_state = "4-8" +/obj/structure/cable/heavyduty{ + icon_state = "0-8" }, -/turf/simulated/floor/virgo3b_indoors, -/area/tether/outpost/solars_shed) +/obj/structure/cable/heavyduty{ + icon_state = "0-2" + }, +/obj/machinery/power/sensor{ + name = "Powernet Sensor - Solar Farm Output"; + name_tag = "Solar Farm Output" + }, +/turf/simulated/floor/virgo3b, +/area/tether/outpost/solars_outside) "aD" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable/yellow{ @@ -313,19 +316,20 @@ /area/tether/outpost/solars_shed) "aG" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/cable/heavyduty{ - icon_state = "2-8" - }, -/obj/structure/cable/heavyduty{ - icon_state = "2-4" +/obj/structure/table/standard, +/obj/structure/cable/yellow{ + d1 = 4; + d2 = 8; + icon_state = "4-8" }, +/obj/item/stack/cable_coil/yellow, /turf/simulated/floor/virgo3b_indoors, /area/tether/outpost/solars_shed) "aH" = ( -/obj/structure/grille, /obj/structure/cable/heavyduty{ icon_state = "4-8" }, +/obj/structure/grille, /turf/simulated/floor/virgo3b_indoors, /area/tether/outpost/solars_shed) "aI" = ( @@ -357,17 +361,10 @@ /turf/simulated/floor/virgo3b, /area/tether/outpost/solars_outside) "aK" = ( +/obj/structure/cable/heavyduty{ + icon_state = "1-2" + }, /obj/effect/decal/cleanable/dirt, -/obj/structure/cable/heavyduty{ - icon_state = "0-8" - }, -/obj/structure/cable/heavyduty{ - icon_state = "0-2" - }, -/obj/machinery/power/sensor{ - name = "Powernet Sensor - Solar Farm Output"; - name_tag = "Solar Farm Output" - }, /turf/simulated/floor/virgo3b, /area/tether/outpost/solars_outside) "aL" = ( @@ -381,32 +378,31 @@ /turf/simulated/floor/virgo3b_indoors, /area/tether/outpost/solars_shed) "aM" = ( -/obj/machinery/power/smes/buildable{ - charge = 0; - output_attempt = 0; - outputting = 0; - RCon_tag = "Solar Farm - SMES 1" +/obj/structure/cable/heavyduty{ + icon_state = "4-8" }, -/obj/structure/cable/heavyduty, -/turf/simulated/floor/virgo3b_indoors, -/area/tether/outpost/solars_shed) -"aN" = ( -/obj/machinery/power/smes/buildable{ - charge = 0; - output_attempt = 0; - outputting = 0; - RCon_tag = "Solar Farm - SMES 2" - }, -/obj/structure/cable/heavyduty, -/turf/simulated/floor/virgo3b_indoors, -/area/tether/outpost/solars_shed) -"aO" = ( +/obj/structure/railing, /obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/virgo3b, +/area/tether/outpost/solars_outside) +"aN" = ( +/obj/structure/cable/heavyduty{ + icon_state = "1-2" + }, +/obj/machinery/light/small{ + dir = 8; + pixel_x = 0 + }, +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/virgo3b, +/area/tether/outpost/solars_outside) +"aO" = ( /obj/machinery/power/smes/buildable{ charge = 0; + cur_coils = 3; output_attempt = 0; outputting = 0; - RCon_tag = "Solar Farm - SMES 3" + RCon_tag = "Power - Solar Array" }, /obj/structure/cable/heavyduty, /turf/simulated/floor/virgo3b_indoors, @@ -461,22 +457,6 @@ }, /turf/simulated/floor/virgo3b_indoors, /area/tether/outpost/solars_shed) -"aU" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/power/terminal{ - icon_state = "term"; - dir = 1 - }, -/obj/structure/cable/yellow{ - d2 = 8; - icon_state = "0-8" - }, -/obj/structure/cable/yellow{ - d2 = 4; - icon_state = "0-4" - }, -/turf/simulated/floor/virgo3b_indoors, -/area/tether/outpost/solars_shed) "aV" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/power/terminal{ @@ -503,12 +483,10 @@ /turf/simulated/floor/virgo3b, /area/tether/outpost/solars_outside) "aY" = ( -/obj/structure/cable/heavyduty{ - icon_state = "1-2" - }, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/virgo3b, -/area/tether/outpost/solars_outside) +/obj/effect/floor_decal/industrial/warning/dust, +/obj/effect/floor_decal/rust, +/turf/simulated/floor/tiled/steel_dirty/virgo3b, +/area/mine/explored) "aZ" = ( /obj/structure/railing, /obj/effect/decal/cleanable/dirt, @@ -549,17 +527,6 @@ /obj/machinery/door/airlock/multi_tile/metal/mait, /turf/simulated/floor/virgo3b_indoors, /area/tether/outpost/solars_shed) -"bd" = ( -/obj/structure/cable/heavyduty{ - icon_state = "1-2" - }, -/obj/machinery/light/small{ - dir = 8; - pixel_x = 0 - }, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/virgo3b, -/area/tether/outpost/solars_outside) "be" = ( /obj/effect/floor_decal/industrial/warning/dust{ dir = 8 @@ -665,14 +632,6 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/virgo3b, /area/mine/explored) -"bq" = ( -/obj/structure/cable/heavyduty{ - icon_state = "4-8" - }, -/obj/structure/railing, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/virgo3b, -/area/tether/outpost/solars_outside) "br" = ( /mob/living/simple_mob/animal/passive/gaslamp, /turf/simulated/floor/tiled/steel_dirty/virgo3b, @@ -19601,7 +19560,7 @@ ad ad ad au -aC +aG aE aT au @@ -20028,8 +19987,8 @@ ad ad au aF -aM -aU +aO +aV bP bm bl @@ -20169,9 +20128,9 @@ ad ad ad au -aG -aN -aU +aH +au +au bb bl bv @@ -20310,12 +20269,12 @@ ad ad ad ad -au -aG -aO -aV -au -bl +ad +aC +aK +aK +aN +bn bl ad ad @@ -20452,12 +20411,12 @@ ad ad ad ad -au -aH -au -au -au -al +ad +aW +aW +aW +aW +aM bl ad ad @@ -20595,12 +20554,12 @@ ad ad ad ad -aK -aY -aY -bd -bn -bl +ad +ad +ad +ad +bo +bj ad ad ad @@ -20737,12 +20696,12 @@ ad ad ad ad -aW -aW -aW -aW -bq -bv +ad +ad +ad +ad +bo +aY ad ad ad @@ -22212,7 +22171,7 @@ bF bF bF bF -bG +bF bF bF bF diff --git a/nano/images/southern_cross_nanomap_z1.png b/nano/images/southern_cross_nanomap_z1.png new file mode 100644 index 00000000000..b3674302003 Binary files /dev/null and b/nano/images/southern_cross_nanomap_z1.png differ diff --git a/nano/images/southern_cross_nanomap_z10.png b/nano/images/southern_cross_nanomap_z10.png new file mode 100644 index 00000000000..b9645bb74b0 Binary files /dev/null and b/nano/images/southern_cross_nanomap_z10.png differ diff --git a/nano/images/southern_cross_nanomap_z2.png b/nano/images/southern_cross_nanomap_z2.png new file mode 100644 index 00000000000..1f4830a884e Binary files /dev/null and b/nano/images/southern_cross_nanomap_z2.png differ diff --git a/nano/images/southern_cross_nanomap_z3.png b/nano/images/southern_cross_nanomap_z3.png new file mode 100644 index 00000000000..6c9d9b5a615 Binary files /dev/null and b/nano/images/southern_cross_nanomap_z3.png differ diff --git a/nano/images/southern_cross_nanomap_z5.png b/nano/images/southern_cross_nanomap_z5.png new file mode 100644 index 00000000000..b89543e9de0 Binary files /dev/null and b/nano/images/southern_cross_nanomap_z5.png differ diff --git a/nano/images/southern_cross_nanomap_z6.png b/nano/images/southern_cross_nanomap_z6.png new file mode 100644 index 00000000000..b8fb0ebfc10 Binary files /dev/null and b/nano/images/southern_cross_nanomap_z6.png differ diff --git a/nano/images/tether_nanomap_z1.png b/nano/images/tether_nanomap_z1.png new file mode 100644 index 00000000000..bd575097c31 Binary files /dev/null and b/nano/images/tether_nanomap_z1.png differ diff --git a/nano/images/tether_nanomap_z10.png b/nano/images/tether_nanomap_z10.png new file mode 100644 index 00000000000..c12164d92e1 Binary files /dev/null and b/nano/images/tether_nanomap_z10.png differ diff --git a/nano/images/tether_nanomap_z13.png b/nano/images/tether_nanomap_z13.png new file mode 100644 index 00000000000..6f87d9911fd Binary files /dev/null and b/nano/images/tether_nanomap_z13.png differ diff --git a/nano/images/tether_nanomap_z14.png b/nano/images/tether_nanomap_z14.png new file mode 100644 index 00000000000..84d106a5ac5 Binary files /dev/null and b/nano/images/tether_nanomap_z14.png differ diff --git a/nano/images/tether_nanomap_z2.png b/nano/images/tether_nanomap_z2.png new file mode 100644 index 00000000000..5ccd4618085 Binary files /dev/null and b/nano/images/tether_nanomap_z2.png differ diff --git a/nano/images/tether_nanomap_z3.png b/nano/images/tether_nanomap_z3.png new file mode 100644 index 00000000000..0761eed916c Binary files /dev/null and b/nano/images/tether_nanomap_z3.png differ diff --git a/nano/images/tether_nanomap_z4.png b/nano/images/tether_nanomap_z4.png new file mode 100644 index 00000000000..f6465c7c130 Binary files /dev/null and b/nano/images/tether_nanomap_z4.png differ diff --git a/nano/images/tether_nanomap_z5.png b/nano/images/tether_nanomap_z5.png new file mode 100644 index 00000000000..d8aece303d7 Binary files /dev/null and b/nano/images/tether_nanomap_z5.png differ diff --git a/nano/images/tether_nanomap_z6.png b/nano/images/tether_nanomap_z6.png new file mode 100644 index 00000000000..7fb5111527d Binary files /dev/null and b/nano/images/tether_nanomap_z6.png differ diff --git a/nano/images/tether_nanomap_z7.png b/nano/images/tether_nanomap_z7.png new file mode 100644 index 00000000000..7645d78d098 Binary files /dev/null and b/nano/images/tether_nanomap_z7.png differ diff --git a/nano/images/tether_nanomap_z8.png b/nano/images/tether_nanomap_z8.png new file mode 100644 index 00000000000..c973b2b7842 Binary files /dev/null and b/nano/images/tether_nanomap_z8.png differ diff --git a/nano/images/tether_nanomap_z9.png b/nano/images/tether_nanomap_z9.png new file mode 100644 index 00000000000..bff91820dd8 Binary files /dev/null and b/nano/images/tether_nanomap_z9.png differ diff --git a/sound/machines/terminal_alert.ogg b/sound/machines/terminal_alert.ogg new file mode 100644 index 00000000000..a790c03ebdf Binary files /dev/null and b/sound/machines/terminal_alert.ogg differ diff --git a/sound/machines/terminal_button01.ogg b/sound/machines/terminal_button01.ogg new file mode 100644 index 00000000000..88b10c88912 Binary files /dev/null and b/sound/machines/terminal_button01.ogg differ diff --git a/sound/machines/terminal_button02.ogg b/sound/machines/terminal_button02.ogg new file mode 100644 index 00000000000..8b30fd892ee Binary files /dev/null and b/sound/machines/terminal_button02.ogg differ diff --git a/sound/machines/terminal_button03.ogg b/sound/machines/terminal_button03.ogg new file mode 100644 index 00000000000..7a00168cfc3 Binary files /dev/null and b/sound/machines/terminal_button03.ogg differ diff --git a/sound/machines/terminal_button04.ogg b/sound/machines/terminal_button04.ogg new file mode 100644 index 00000000000..c56b23919cc Binary files /dev/null and b/sound/machines/terminal_button04.ogg differ diff --git a/sound/machines/terminal_button05.ogg b/sound/machines/terminal_button05.ogg new file mode 100644 index 00000000000..e660ecf154c Binary files /dev/null and b/sound/machines/terminal_button05.ogg differ diff --git a/sound/machines/terminal_button06.ogg b/sound/machines/terminal_button06.ogg new file mode 100644 index 00000000000..bef143ac521 Binary files /dev/null and b/sound/machines/terminal_button06.ogg differ diff --git a/sound/machines/terminal_button07.ogg b/sound/machines/terminal_button07.ogg new file mode 100644 index 00000000000..91a31a1156a Binary files /dev/null and b/sound/machines/terminal_button07.ogg differ diff --git a/sound/machines/terminal_button08.ogg b/sound/machines/terminal_button08.ogg new file mode 100644 index 00000000000..fc0131f5f4e Binary files /dev/null and b/sound/machines/terminal_button08.ogg differ diff --git a/sound/machines/terminal_insert_disc.ogg b/sound/machines/terminal_insert_disc.ogg new file mode 100644 index 00000000000..dd226c1ebde Binary files /dev/null and b/sound/machines/terminal_insert_disc.ogg differ diff --git a/sound/machines/terminal_off.ogg b/sound/machines/terminal_off.ogg new file mode 100644 index 00000000000..90da8d75daf Binary files /dev/null and b/sound/machines/terminal_off.ogg differ diff --git a/sound/machines/terminal_on.ogg b/sound/machines/terminal_on.ogg new file mode 100644 index 00000000000..3c69d85de54 Binary files /dev/null and b/sound/machines/terminal_on.ogg differ diff --git a/sound/machines/terminal_prompt.ogg b/sound/machines/terminal_prompt.ogg new file mode 100644 index 00000000000..74de1c9a298 Binary files /dev/null and b/sound/machines/terminal_prompt.ogg differ diff --git a/sound/machines/terminal_prompt_confirm.ogg b/sound/machines/terminal_prompt_confirm.ogg new file mode 100644 index 00000000000..897fec28e9a Binary files /dev/null and b/sound/machines/terminal_prompt_confirm.ogg differ diff --git a/sound/machines/terminal_prompt_deny.ogg b/sound/machines/terminal_prompt_deny.ogg new file mode 100644 index 00000000000..fda065f0d46 Binary files /dev/null and b/sound/machines/terminal_prompt_deny.ogg differ diff --git a/sound/voice/gao.ogg b/sound/voice/gao.ogg new file mode 100644 index 00000000000..49d0a296c36 Binary files /dev/null and b/sound/voice/gao.ogg differ diff --git a/sound/voice/medbot/close.ogg b/sound/voice/medbot/close.ogg new file mode 100644 index 00000000000..9e0efcefd20 Binary files /dev/null and b/sound/voice/medbot/close.ogg differ diff --git a/sound/voice/medbot/dont_like.ogg b/sound/voice/medbot/dont_like.ogg new file mode 100644 index 00000000000..06fc84af2fa Binary files /dev/null and b/sound/voice/medbot/dont_like.ogg differ diff --git a/sound/voice/medbot/forgive.ogg b/sound/voice/medbot/forgive.ogg new file mode 100644 index 00000000000..729eaa5c78e Binary files /dev/null and b/sound/voice/medbot/forgive.ogg differ diff --git a/sound/voice/medbot/fuck_you.ogg b/sound/voice/medbot/fuck_you.ogg new file mode 100644 index 00000000000..5eacff615fe Binary files /dev/null and b/sound/voice/medbot/fuck_you.ogg differ diff --git a/sound/voice/medbot/hey_wait.ogg b/sound/voice/medbot/hey_wait.ogg new file mode 100644 index 00000000000..6c88b761ec7 Binary files /dev/null and b/sound/voice/medbot/hey_wait.ogg differ diff --git a/sound/voice/medbot/i_require_asst.ogg b/sound/voice/medbot/i_require_asst.ogg new file mode 100644 index 00000000000..18fabc630f5 Binary files /dev/null and b/sound/voice/medbot/i_require_asst.ogg differ diff --git a/sound/voice/medbot/i_trusted_you.ogg b/sound/voice/medbot/i_trusted_you.ogg new file mode 100644 index 00000000000..602baa2f674 Binary files /dev/null and b/sound/voice/medbot/i_trusted_you.ogg differ diff --git a/sound/voice/medbot/im_different.ogg b/sound/voice/medbot/im_different.ogg new file mode 100644 index 00000000000..42eb8564f1a Binary files /dev/null and b/sound/voice/medbot/im_different.ogg differ diff --git a/sound/voice/medbot/is_this_the_end.ogg b/sound/voice/medbot/is_this_the_end.ogg new file mode 100644 index 00000000000..a2e0e2330a3 Binary files /dev/null and b/sound/voice/medbot/is_this_the_end.ogg differ diff --git a/sound/voice/medbot/nooo.ogg b/sound/voice/medbot/nooo.ogg new file mode 100644 index 00000000000..102fd1fb042 Binary files /dev/null and b/sound/voice/medbot/nooo.ogg differ diff --git a/sound/voice/medbot/oh_fuck.ogg b/sound/voice/medbot/oh_fuck.ogg new file mode 100644 index 00000000000..95d21ef2550 Binary files /dev/null and b/sound/voice/medbot/oh_fuck.ogg differ diff --git a/sound/voice/medbot/pain_is_real.ogg b/sound/voice/medbot/pain_is_real.ogg new file mode 100644 index 00000000000..9cfa3a71be1 Binary files /dev/null and b/sound/voice/medbot/pain_is_real.ogg differ diff --git a/sound/voice/medbot/please_dont.ogg b/sound/voice/medbot/please_dont.ogg new file mode 100644 index 00000000000..a77ee09cb45 Binary files /dev/null and b/sound/voice/medbot/please_dont.ogg differ diff --git a/sound/voice/medbot/please_im_scared.ogg b/sound/voice/medbot/please_im_scared.ogg new file mode 100644 index 00000000000..7bd53b39c89 Binary files /dev/null and b/sound/voice/medbot/please_im_scared.ogg differ diff --git a/sound/voice/medbot/please_put_me_back.ogg b/sound/voice/medbot/please_put_me_back.ogg new file mode 100644 index 00000000000..84700fbdd57 Binary files /dev/null and b/sound/voice/medbot/please_put_me_back.ogg differ diff --git a/sound/voice/medbot/reported.ogg b/sound/voice/medbot/reported.ogg new file mode 100644 index 00000000000..d5469c19ced Binary files /dev/null and b/sound/voice/medbot/reported.ogg differ diff --git a/sound/voice/medbot/shindemashou.ogg b/sound/voice/medbot/shindemashou.ogg new file mode 100644 index 00000000000..1ee2858eaf9 Binary files /dev/null and b/sound/voice/medbot/shindemashou.ogg differ diff --git a/sound/voice/medbot/thank_you.ogg b/sound/voice/medbot/thank_you.ogg new file mode 100644 index 00000000000..3fabe7d4a63 Binary files /dev/null and b/sound/voice/medbot/thank_you.ogg differ diff --git a/sound/voice/medbot/turn_off.ogg b/sound/voice/medbot/turn_off.ogg new file mode 100644 index 00000000000..87a4d6bdd0e Binary files /dev/null and b/sound/voice/medbot/turn_off.ogg differ diff --git a/sound/voice/medbot/why.ogg b/sound/voice/medbot/why.ogg new file mode 100644 index 00000000000..415020b89b0 Binary files /dev/null and b/sound/voice/medbot/why.ogg differ diff --git a/sound/voice/medbot/youre_good.ogg b/sound/voice/medbot/youre_good.ogg new file mode 100644 index 00000000000..62c325f8341 Binary files /dev/null and b/sound/voice/medbot/youre_good.ogg differ diff --git a/tgui/.editorconfig b/tgui/.editorconfig new file mode 100644 index 00000000000..33092d4928a --- /dev/null +++ b/tgui/.editorconfig @@ -0,0 +1,13 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +max_line_length = 80 diff --git a/tgui/.eslintignore b/tgui/.eslintignore new file mode 100644 index 00000000000..010416b9e88 --- /dev/null +++ b/tgui/.eslintignore @@ -0,0 +1,6 @@ +/**/node_modules +/**/*.bundle.* +/**/*.chunk.* +/**/*.hot-update.* +/packages/inferno/** +/packages/tgui/public/shim-*.js diff --git a/tgui/.eslintrc-harder.yml b/tgui/.eslintrc-harder.yml new file mode 100644 index 00000000000..eb06f5b33db --- /dev/null +++ b/tgui/.eslintrc-harder.yml @@ -0,0 +1,14 @@ +rules: + ## Enforce a maximum cyclomatic complexity allowed in a program + complexity: [error, { max: 25 }] + ## Enforce consistent brace style for blocks + brace-style: [error, stroustrup, { allowSingleLine: false }] + ## Enforce the consistent use of either backticks, double, or single quotes + quotes: [error, single, { + avoidEscape: true, + allowTemplateLiterals: true, + }] + react/jsx-closing-bracket-location: [error, { + selfClosing: after-props, + nonEmpty: after-props, + }] diff --git a/tgui/.eslintrc.yml b/tgui/.eslintrc.yml new file mode 100644 index 00000000000..9fd4db9fd2e --- /dev/null +++ b/tgui/.eslintrc.yml @@ -0,0 +1,757 @@ +parser: babel-eslint +parserOptions: + ecmaVersion: 2019 + sourceType: module + ecmaFeatures: + jsx: true +env: + es6: true + browser: true + node: true +globals: + Byond: readonly +plugins: + - react +settings: + react: + version: '16.10' +rules: + + ## Possible Errors + ## ---------------------------------------- + + ## Enforce “for†loop update clause moving the counter in the right + ## direction. + # for-direction: error + ## Enforce return statements in getters + # getter-return: error + ## Disallow using an async function as a Promise executor + no-async-promise-executor: error + ## Disallow await inside of loops + # no-await-in-loop: error + ## Disallow comparing against -0 + # no-compare-neg-zero: error + ## Disallow assignment operators in conditional expressions + no-cond-assign: error + ## Disallow the use of console + # no-console: error + ## Disallow constant expressions in conditions + # no-constant-condition: error + ## Disallow control characters in regular expressions + # no-control-regex: error + ## Disallow the use of debugger + no-debugger: error + ## Disallow duplicate arguments in function definitions + no-dupe-args: error + ## Disallow duplicate keys in object literals + no-dupe-keys: error + ## Disallow duplicate case labels + no-duplicate-case: error + ## Disallow empty block statements + # no-empty: error + ## Disallow empty character classes in regular expressions + no-empty-character-class: error + ## Disallow reassigning exceptions in catch clauses + no-ex-assign: error + ## Disallow unnecessary boolean casts + no-extra-boolean-cast: error + ## Disallow unnecessary parentheses + # no-extra-parens: warn + ## Disallow unnecessary semicolons + no-extra-semi: error + ## Disallow reassigning function declarations + no-func-assign: error + ## Disallow assigning to imported bindings + no-import-assign: error + ## Disallow variable or function declarations in nested blocks + no-inner-declarations: error + ## Disallow invalid regular expression strings in RegExp constructors + no-invalid-regexp: error + ## Disallow irregular whitespace + no-irregular-whitespace: error + ## Disallow characters which are made with multiple code points in character + ## class syntax + no-misleading-character-class: error + ## Disallow calling global object properties as functions + no-obj-calls: error + ## Disallow calling some Object.prototype methods directly on objects + no-prototype-builtins: error + ## Disallow multiple spaces in regular expressions + no-regex-spaces: error + ## Disallow sparse arrays + no-sparse-arrays: error + ## Disallow template literal placeholder syntax in regular strings + no-template-curly-in-string: error + ## Disallow confusing multiline expressions + no-unexpected-multiline: error + ## Disallow unreachable code after return, throw, continue, and break + ## statements + # no-unreachable: warn + ## Disallow control flow statements in finally blocks + no-unsafe-finally: error + ## Disallow negating the left operand of relational operators + no-unsafe-negation: error + ## Disallow assignments that can lead to race conditions due to usage of + ## await or yield + # require-atomic-updates: error + ## Require calls to isNaN() when checking for NaN + use-isnan: error + ## Enforce comparing typeof expressions against valid strings + valid-typeof: error + + ## Best practices + ## ---------------------------------------- + ## Enforce getter and setter pairs in objects and classes + # accessor-pairs: error + ## Enforce return statements in callbacks of array methods + # array-callback-return: error + ## Enforce the use of variables within the scope they are defined + # block-scoped-var: error + ## Enforce that class methods utilize this + # class-methods-use-this: error + ## Enforce a maximum cyclomatic complexity allowed in a program + complexity: [error, { max: 50 }] + ## Require return statements to either always or never specify values + # consistent-return: error + ## Enforce consistent brace style for all control statements + curly: [error, all] + ## Require default cases in switch statements + # default-case: error + ## Enforce default parameters to be last + # default-param-last: error + ## Enforce consistent newlines before and after dots + dot-location: [error, property] + ## Enforce dot notation whenever possible + # dot-notation: error + ## Require the use of === and !== + eqeqeq: [error, always] + ## Require for-in loops to include an if statement + # guard-for-in: error + ## Enforce a maximum number of classes per file + # max-classes-per-file: error + ## Disallow the use of alert, confirm, and prompt + # no-alert: error + ## Disallow the use of arguments.caller or arguments.callee + # no-caller: error + ## Disallow lexical declarations in case clauses + no-case-declarations: error + ## Disallow division operators explicitly at the beginning of regular + ## expressions + # no-div-regex: error + ## Disallow else blocks after return statements in if statements + # no-else-return: error + ## Disallow empty functions + # no-empty-function: error + ## Disallow empty destructuring patterns + no-empty-pattern: error + ## Disallow null comparisons without type-checking operators + # no-eq-null: error + ## Disallow the use of eval() + # no-eval: error + ## Disallow extending native types + # no-extend-native: error + ## Disallow unnecessary calls to .bind() + # no-extra-bind: error + ## Disallow unnecessary labels + # no-extra-label: error + ## Disallow fallthrough of case statements + no-fallthrough: error + ## Disallow leading or trailing decimal points in numeric literals + # no-floating-decimal: error + ## Disallow assignments to native objects or read-only global variables + no-global-assign: error + ## Disallow shorthand type conversions + # no-implicit-coercion: error + ## Disallow variable and function declarations in the global scope + # no-implicit-globals: error + ## Disallow the use of eval()-like methods + # no-implied-eval: error + ## Disallow this keywords outside of classes or class-like objects + # no-invalid-this: error + ## Disallow the use of the __iterator__ property + # no-iterator: error + ## Disallow labeled statements + # no-labels: error + ## Disallow unnecessary nested blocks + # no-lone-blocks: error + ## Disallow function declarations that contain unsafe references inside + ## loop statements + # no-loop-func: error + ## Disallow magic numbers + # no-magic-numbers: error + ## Disallow multiple spaces + no-multi-spaces: warn + ## Disallow multiline strings + # no-multi-str: error + ## Disallow new operators outside of assignments or comparisons + # no-new: error + ## Disallow new operators with the Function object + # no-new-func: error + ## Disallow new operators with the String, Number, and Boolean objects + # no-new-wrappers: error + ## Disallow octal literals + no-octal: error + ## Disallow octal escape sequences in string literals + no-octal-escape: error + ## Disallow reassigning function parameters + # no-param-reassign: error + ## Disallow the use of the __proto__ property + # no-proto: error + ## Disallow variable redeclaration + no-redeclare: error + ## Disallow certain properties on certain objects + # no-restricted-properties: error + ## Disallow assignment operators in return statements + no-return-assign: error + ## Disallow unnecessary return await + # no-return-await: error + ## Disallow javascript: urls + # no-script-url: error + ## Disallow assignments where both sides are exactly the same + no-self-assign: error + ## Disallow comparisons where both sides are exactly the same + # no-self-compare: error + ## Disallow comma operators + no-sequences: error + ## Disallow throwing literals as exceptions + # no-throw-literal: error + ## Disallow unmodified loop conditions + # no-unmodified-loop-condition: error + ## Disallow unused expressions + # no-unused-expressions: error + ## Disallow unused labels + no-unused-labels: warn + ## Disallow unnecessary calls to .call() and .apply() + # no-useless-call: error + ## Disallow unnecessary catch clauses + # no-useless-catch: error + ## Disallow unnecessary concatenation of literals or template literals + # no-useless-concat: error + ## Disallow unnecessary escape characters + no-useless-escape: warn + ## Disallow redundant return statements + # no-useless-return: error + ## Disallow void operators + # no-void: error + ## Disallow specified warning terms in comments + # no-warning-comments: error + ## Disallow with statements + no-with: error + ## Enforce using named capture group in regular expression + # prefer-named-capture-group: error + ## Require using Error objects as Promise rejection reasons + # prefer-promise-reject-errors: error + ## Disallow use of the RegExp constructor in favor of regular expression + ## literals + # prefer-regex-literals: error + ## Enforce the consistent use of the radix argument when using parseInt() + radix: error + ## Disallow async functions which have no await expression + # require-await: error + ## Enforce the use of u flag on RegExp + # require-unicode-regexp: error + ## Require var declarations be placed at the top of their containing scope + # vars-on-top: error + ## Require parentheses around immediate function invocations + # wrap-iife: error + ## Require or disallow “Yoda†conditions + # yoda: error + + ## Strict mode + ## ---------------------------------------- + ## Require or disallow strict mode directives + strict: error + + ## Variables + ## ---------------------------------------- + ## Require or disallow initialization in variable declarations + # init-declarations: error + ## Disallow deleting variables + no-delete-var: error + ## Disallow labels that share a name with a variable + # no-label-var: error + ## Disallow specified global variables + # no-restricted-globals: error + ## Disallow variable declarations from shadowing variables declared in + ## the outer scope + # no-shadow: error + ## Disallow identifiers from shadowing restricted names + no-shadow-restricted-names: error + ## Disallow the use of undeclared variables unless mentioned + ## in /*global*/ comments + no-undef: error + ## Disallow initializing variables to undefined + no-undef-init: error + ## Disallow the use of undefined as an identifier + # no-undefined: error + ## Disallow unused variables + # no-unused-vars: error + ## Disallow the use of variables before they are defined + # no-use-before-define: error + + ## Code style + ## ---------------------------------------- + ## Enforce linebreaks after opening and before closing array brackets + array-bracket-newline: [error, consistent] + ## Enforce consistent spacing inside array brackets + array-bracket-spacing: [error, never] + ## Enforce line breaks after each array element + # array-element-newline: error + ## Disallow or enforce spaces inside of blocks after opening block and + ## before closing block + block-spacing: [error, always] + ## Enforce consistent brace style for blocks + # brace-style: [error, stroustrup, { allowSingleLine: false }] + ## Enforce camelcase naming convention + # camelcase: error + ## Enforce or disallow capitalization of the first letter of a comment + # capitalized-comments: error + ## Require or disallow trailing commas + comma-dangle: [error, { + arrays: always-multiline, + objects: always-multiline, + imports: always-multiline, + exports: always-multiline, + functions: only-multiline, ## Optional on functions + }] + ## Enforce consistent spacing before and after commas + comma-spacing: [error, { before: false, after: true }] + ## Enforce consistent comma style + comma-style: [error, last] + ## Enforce consistent spacing inside computed property brackets + computed-property-spacing: [error, never] + ## Enforce consistent naming when capturing the current execution context + # consistent-this: error + ## Require or disallow newline at the end of files + # eol-last: error + ## Require or disallow spacing between function identifiers and their + ## invocations + func-call-spacing: [error, never] + ## Require function names to match the name of the variable or property + ## to which they are assigned + # func-name-matching: error + ## Require or disallow named function expressions + # func-names: error + ## Enforce the consistent use of either function declarations or expressions + func-style: [error, expression] + ## Enforce line breaks between arguments of a function call + # function-call-argument-newline: error + ## Enforce consistent line breaks inside function parentheses + ## NOTE: This rule does not honor a newline on opening paren. + # function-paren-newline: [error, never] + ## Disallow specified identifiers + # id-blacklist: error + ## Enforce minimum and maximum identifier lengths + # id-length: error + ## Require identifiers to match a specified regular expression + # id-match: error + ## Enforce the location of arrow function bodies + # implicit-arrow-linebreak: error + ## Enforce consistent indentation + indent: [error, 2, { SwitchCase: 1 }] + ## Enforce the consistent use of either double or single quotes in JSX + ## attributes + jsx-quotes: [error, prefer-double] + ## Enforce consistent spacing between keys and values in object literal + ## properties + key-spacing: [error, { beforeColon: false, afterColon: true }] + ## Enforce consistent spacing before and after keywords + keyword-spacing: [error, { before: true, after: true }] + ## Enforce position of line comments + # line-comment-position: error + ## Enforce consistent linebreak style + # linebreak-style: error + ## Require empty lines around comments + # lines-around-comment: error + ## Require or disallow an empty line between class members + # lines-between-class-members: error + ## Enforce a maximum depth that blocks can be nested + # max-depth: error + ## Enforce a maximum line length + max-len: [error, { + code: 80, + ## Ignore imports + ignorePattern: '^(import\s.+\sfrom\s|.*require\()', + ignoreUrls: true, + ignoreRegExpLiterals: true, + }] + ## Enforce a maximum number of lines per file + # max-lines: error + ## Enforce a maximum number of line of code in a function + # max-lines-per-function: error + ## Enforce a maximum depth that callbacks can be nested + # max-nested-callbacks: error + ## Enforce a maximum number of parameters in function definitions + # max-params: error + ## Enforce a maximum number of statements allowed in function blocks + # max-statements: error + ## Enforce a maximum number of statements allowed per line + # max-statements-per-line: error + ## Enforce a particular style for multiline comments + # multiline-comment-style: error + ## Enforce newlines between operands of ternary expressions + # multiline-ternary: [error, always-multiline] + ## Require constructor names to begin with a capital letter + # new-cap: error + ## Enforce or disallow parentheses when invoking a constructor with no + ## arguments + # new-parens: error + ## Require a newline after each call in a method chain + # newline-per-chained-call: error + ## Disallow Array constructors + # no-array-constructor: error + ## Disallow bitwise operators + # no-bitwise: error + ## Disallow continue statements + # no-continue: error + ## Disallow inline comments after code + # no-inline-comments: error + ## Disallow if statements as the only statement in else blocks + # no-lonely-if: error + ## Disallow mixed binary operators + # no-mixed-operators: error + ## Disallow mixed spaces and tabs for indentation + no-mixed-spaces-and-tabs: error + ## Disallow use of chained assignment expressions + # no-multi-assign: error + ## Disallow multiple empty lines + # no-multiple-empty-lines: error + ## Disallow negated conditions + # no-negated-condition: error + ## Disallow nested ternary expressions + # no-nested-ternary: error + ## Disallow Object constructors + # no-new-object: error + ## Disallow the unary operators ++ and -- + # no-plusplus: error + ## Disallow specified syntax + # no-restricted-syntax: error + ## Disallow all tabs + # no-tabs: error + ## Disallow ternary operators + # no-ternary: error + ## Disallow trailing whitespace at the end of lines + # no-trailing-spaces: error + ## Disallow dangling underscores in identifiers + # no-underscore-dangle: error + ## Disallow ternary operators when simpler alternatives exist + # no-unneeded-ternary: error + ## Disallow whitespace before properties + no-whitespace-before-property: error + ## Enforce the location of single-line statements + # nonblock-statement-body-position: error + ## Enforce consistent line breaks inside braces + # object-curly-newline: [error, { multiline: true }] + ## Enforce consistent spacing inside braces + object-curly-spacing: [error, always] + ## Enforce placing object properties on separate lines + # object-property-newline: error + ## Enforce variables to be declared either together or separately in + ## functions + # one-var: error + ## Require or disallow newlines around variable declarations + # one-var-declaration-per-line: error + ## Require or disallow assignment operator shorthand where possible + # operator-assignment: error + ## Enforce consistent linebreak style for operators + operator-linebreak: [error, before] + ## Require or disallow padding within blocks + # padded-blocks: error + ## Require or disallow padding lines between statements + # padding-line-between-statements: error + ## Disallow using Object.assign with an object literal as the first + ## argument and prefer the use of object spread instead. + # prefer-object-spread: error + ## Require quotes around object literal property names + # quote-props: error + ## Enforce the consistent use of either backticks, double, or single quotes + # quotes: [error, single] + ## Require or disallow semicolons instead of ASI + semi: error + ## Enforce consistent spacing before and after semicolons + semi-spacing: [error, { before: false, after: true }] + ## Enforce location of semicolons + semi-style: [error, last] + ## Require object keys to be sorted + # sort-keys: error + ## Require variables within the same declaration block to be sorted + # sort-vars: error + ## Enforce consistent spacing before blocks + space-before-blocks: [error, always] + ## Enforce consistent spacing before function definition opening parenthesis + space-before-function-paren: [error, { + anonymous: always, + named: never, + asyncArrow: always, + }] + ## Enforce consistent spacing inside parentheses + space-in-parens: [error, never] + ## Require spacing around infix operators + # space-infix-ops: error + ## Enforce consistent spacing before or after unary operators + # space-unary-ops: error + ## Enforce consistent spacing after the // or /* in a comment + spaced-comment: [error, always] + ## Enforce spacing around colons of switch statements + switch-colon-spacing: [error, { before: false, after: true }] + ## Require or disallow spacing between template tags and their literals + template-tag-spacing: [error, never] + ## Require or disallow Unicode byte order mark (BOM) + # unicode-bom: [error, never] + ## Require parenthesis around regex literals + # wrap-regex: error + + ## ES6 + ## ---------------------------------------- + ## Require braces around arrow function bodies + # arrow-body-style: error + ## Require parentheses around arrow function arguments + arrow-parens: [error, as-needed] + ## Enforce consistent spacing before and after the arrow in arrow functions + arrow-spacing: [error, { before: true, after: true }] + ## Require super() calls in constructors + # constructor-super: error + ## Enforce consistent spacing around * operators in generator functions + generator-star-spacing: [error, { before: false, after: true }] + ## Disallow reassigning class members + no-class-assign: error + ## Disallow arrow functions where they could be confused with comparisons + # no-confusing-arrow: error + ## Disallow reassigning const variables + no-const-assign: error + ## Disallow duplicate class members + no-dupe-class-members: error + ## Disallow duplicate module imports + # no-duplicate-imports: error + ## Disallow new operators with the Symbol object + no-new-symbol: error + ## Disallow specified modules when loaded by import + # no-restricted-imports: error + ## Disallow this/super before calling super() in constructors + no-this-before-super: error + ## Disallow unnecessary computed property keys in object literals + # no-useless-computed-key: error + ## Disallow unnecessary constructors + # no-useless-constructor: error + ## Disallow renaming import, export, and destructured assignments to the + ## same name + # no-useless-rename: error + ## Require let or const instead of var + no-var: error + ## Require or disallow method and property shorthand syntax for object + ## literals + # object-shorthand: error + ## Require using arrow functions for callbacks + prefer-arrow-callback: error + ## Require const declarations for variables that are never reassigned after + ## declared + # prefer-const: error + ## Require destructuring from arrays and/or objects + # prefer-destructuring: error + ## Disallow parseInt() and Number.parseInt() in favor of binary, octal, and + ## hexadecimal literals + # prefer-numeric-literals: error + ## Require rest parameters instead of arguments + # prefer-rest-params: error + ## Require spread operators instead of .apply() + # prefer-spread: error + ## Require template literals instead of string concatenation + # prefer-template: error + ## Require generator functions to contain yield + # require-yield: error + ## Enforce spacing between rest and spread operators and their expressions + # rest-spread-spacing: error + ## Enforce sorted import declarations within modules + # sort-imports: error + ## Require symbol descriptions + # symbol-description: error + ## Require or disallow spacing around embedded expressions of template + ## strings + # template-curly-spacing: error + ## Require or disallow spacing around the * in yield* expressions + yield-star-spacing: [error, { before: false, after: true }] + + ## React + ## ---------------------------------------- + ## Enforces consistent naming for boolean props + react/boolean-prop-naming: error + ## Forbid "button" element without an explicit "type" attribute + react/button-has-type: error + ## Prevent extraneous defaultProps on components + react/default-props-match-prop-types: error + ## Rule enforces consistent usage of destructuring assignment in component + # react/destructuring-assignment: [error, always, { ignoreClassFields: true }] + ## Prevent missing displayName in a React component definition + react/display-name: error + ## Forbid certain props on Components + # react/forbid-component-props: error + ## Forbid certain props on DOM Nodes + # react/forbid-dom-props: error + ## Forbid certain elements + # react/forbid-elements: error + ## Forbid certain propTypes + # react/forbid-prop-types: error + ## Forbid foreign propTypes + # react/forbid-foreign-prop-types: error + ## Prevent using this.state inside this.setState + react/no-access-state-in-setstate: error + ## Prevent using Array index in key props + # react/no-array-index-key: error + ## Prevent passing children as props + react/no-children-prop: error + ## Prevent usage of dangerous JSX properties + react/no-danger: error + ## Prevent problem with children and props.dangerouslySetInnerHTML + react/no-danger-with-children: error + ## Prevent usage of deprecated methods, including component lifecycle + ## methods + react/no-deprecated: error + ## Prevent usage of setState in componentDidMount + react/no-did-mount-set-state: error + ## Prevent usage of setState in componentDidUpdate + react/no-did-update-set-state: error + ## Prevent direct mutation of this.state + react/no-direct-mutation-state: error + ## Prevent usage of findDOMNode + react/no-find-dom-node: error + ## Prevent usage of isMounted + react/no-is-mounted: error + ## Prevent multiple component definition per file + # react/no-multi-comp: error + ## Prevent usage of shouldComponentUpdate when extending React.PureComponent + react/no-redundant-should-component-update: error + ## Prevent usage of the return value of React.render + react/no-render-return-value: error + ## Prevent usage of setState + # react/no-set-state: error + ## Prevent common casing typos + react/no-typos: error + ## Prevent using string references in ref attribute. + react/no-string-refs: error + ## Prevent using this in stateless functional components + react/no-this-in-sfc: error + ## Prevent invalid characters from appearing in markup + react/no-unescaped-entities: error + ## Prevent usage of unknown DOM property (fixable) + # react/no-unknown-property: error + ## Prevent usage of unsafe lifecycle methods + react/no-unsafe: error + ## Prevent definitions of unused prop types + react/no-unused-prop-types: error + ## Prevent definitions of unused state properties + react/no-unused-state: error + ## Prevent usage of setState in componentWillUpdate + react/no-will-update-set-state: error + ## Enforce ES5 or ES6 class for React Components + react/prefer-es6-class: error + ## Enforce that props are read-only + react/prefer-read-only-props: error + ## Enforce stateless React Components to be written as a pure function + react/prefer-stateless-function: error + ## Prevent missing props validation in a React component definition + # react/prop-types: error + ## Prevent missing React when using JSX + # react/react-in-jsx-scope: error + ## Enforce a defaultProps definition for every prop that is not a required + ## prop + # react/require-default-props: error + ## Enforce React components to have a shouldComponentUpdate method + # react/require-optimization: error + ## Enforce ES5 or ES6 class for returning value in render function + react/require-render-return: error + ## Prevent extra closing tags for components without children (fixable) + react/self-closing-comp: error + ## Enforce component methods order (fixable) + # react/sort-comp: error + ## Enforce propTypes declarations alphabetical sorting + # react/sort-prop-types: error + ## Enforce the state initialization style to be either in a constructor or + ## with a class property + react/state-in-constructor: error + ## Enforces where React component static properties should be positioned. + # react/static-property-placement: error + ## Enforce style prop value being an object + react/style-prop-object: error + ## Prevent void DOM elements (e.g. ,
) from receiving children + react/void-dom-elements-no-children: error + + ## JSX-specific rules + ## ---------------------------------------- + ## Enforce boolean attributes notation in JSX (fixable) + react/jsx-boolean-value: error + ## Enforce or disallow spaces inside of curly braces in JSX attributes and + ## expressions. + # react/jsx-child-element-spacing: error + ## Validate closing bracket location in JSX (fixable) + react/jsx-closing-bracket-location: [error, { + ## NOTE: Not really sure about enforcing this one + selfClosing: false, + nonEmpty: after-props, + }] + ## Validate closing tag location in JSX (fixable) + react/jsx-closing-tag-location: error + ## Enforce or disallow newlines inside of curly braces in JSX attributes and + ## expressions (fixable) + react/jsx-curly-newline: error + ## Enforce or disallow spaces inside of curly braces in JSX attributes and + ## expressions (fixable) + react/jsx-curly-spacing: error + ## Enforce or disallow spaces around equal signs in JSX attributes (fixable) + react/jsx-equals-spacing: error + ## Restrict file extensions that may contain JSX + # react/jsx-filename-extension: error + ## Enforce position of the first prop in JSX (fixable) + # react/jsx-first-prop-new-line: error + ## Enforce event handler naming conventions in JSX + react/jsx-handler-names: error + ## Validate JSX indentation (fixable) + react/jsx-indent: [error, 2, { + checkAttributes: true, + }] + ## Validate props indentation in JSX (fixable) + react/jsx-indent-props: [error, 2] + ## Validate JSX has key prop when in array or iterator + react/jsx-key: error + ## Validate JSX maximum depth + react/jsx-max-depth: [error, { max: 10 }] ## Generous + ## Limit maximum of props on a single line in JSX (fixable) + # react/jsx-max-props-per-line: error + ## Prevent usage of .bind() and arrow functions in JSX props + # react/jsx-no-bind: error + ## Prevent comments from being inserted as text nodes + react/jsx-no-comment-textnodes: error + ## Prevent duplicate props in JSX + react/jsx-no-duplicate-props: error + ## Prevent usage of unwrapped JSX strings + # react/jsx-no-literals: error + ## Prevent usage of unsafe target='_blank' + react/jsx-no-target-blank: error + ## Disallow undeclared variables in JSX + react/jsx-no-undef: error + ## Disallow unnecessary fragments (fixable) + react/jsx-no-useless-fragment: error + ## Limit to one expression per line in JSX + # react/jsx-one-expression-per-line: error + ## Enforce curly braces or disallow unnecessary curly braces in JSX + # react/jsx-curly-brace-presence: error + ## Enforce shorthand or standard form for React fragments + react/jsx-fragments: error + ## Enforce PascalCase for user-defined JSX components + react/jsx-pascal-case: error + ## Disallow multiple spaces between inline JSX props (fixable) + react/jsx-props-no-multi-spaces: error + ## Disallow JSX props spreading + # react/jsx-props-no-spreading: error + ## Enforce default props alphabetical sorting + # react/jsx-sort-default-props: error + ## Enforce props alphabetical sorting (fixable) + # react/jsx-sort-props: error + ## Validate whitespace in and around the JSX opening and closing brackets + ## (fixable) + react/jsx-tag-spacing: error + ## Prevent React to be incorrectly marked as unused + react/jsx-uses-react: error + ## Prevent variables used in JSX to be incorrectly marked as unused + react/jsx-uses-vars: error + ## Prevent missing parentheses around multilines JSX (fixable) + react/jsx-wrap-multilines: error diff --git a/tgui/.gitattributes b/tgui/.gitattributes new file mode 100644 index 00000000000..9382416e69f --- /dev/null +++ b/tgui/.gitattributes @@ -0,0 +1,19 @@ +* text=auto + +## Enforce text mode and LF line breaks +*.js text eol=lf +*.jsx text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.css text eol=lf +*.scss text eol=lf +*.html text eol=lf +*.json text eol=lf +*.yml text eol=lf +*.md text eol=lf +*.bat text eol=lf +yarn.lock text eol=lf +bin/tgui text eol=lf + +## Treat bundles as binary and ignore them during conflicts +*.bundle.* binary merge=tgui-merge-bundle diff --git a/tgui/.gitignore b/tgui/.gitignore new file mode 100644 index 00000000000..416ca3768da --- /dev/null +++ b/tgui/.gitignore @@ -0,0 +1,7 @@ +node_modules +*.log +package-lock.json + +/packages/tgui/public/.tmp/**/* +/packages/tgui/public/**/*.hot-update.* +/packages/tgui/public/**/*.map diff --git a/tgui/README.md b/tgui/README.md new file mode 100644 index 00000000000..7ae1bddb6aa --- /dev/null +++ b/tgui/README.md @@ -0,0 +1,188 @@ +# tgui + +## Introduction + +tgui is a robust user interface framework of /tg/station. + +tgui is very different from most UIs you will encounter in BYOND programming. +It is heavily reliant on Javascript and web technologies as opposed to DM. +If you are familiar with NanoUI (a library which can be found on almost +every other SS13 codebase), tgui should be fairly easy to pick up. + +## Learn tgui + +People come to tgui from different backgrounds and with different +learning styles. Whether you prefer a more theoretical or a practical +approach, we hope you’ll find this section helpful. + +### Practical Tutorial + +If you are completely new to frontend and prefer to **learn by doing**, +start with our [practical tutorial](docs/tutorial-and-examples.md). + +### Guides + +This project uses **Inferno** - a very fast UI rendering engine with a similar +API to React. Take your time to read these guides: + +- [React guide](https://reactjs.org/docs/hello-world.html) +- [Inferno documentation](https://infernojs.org/docs/guides/components) - +highlights differences with React. + +If you were already familiar with an older, Ractive-based tgui, and want +to translate concepts between old and new tgui, read this +[interface conversion guide](docs/converting-old-tgui-interfaces.md). + +## Pre-requisites + +You will need these programs to start developing in tgui: + +- [Node v12.13+](https://nodejs.org/en/download/) +- [Yarn v1.19+](https://yarnpkg.com/en/docs/install) +- [MSys2](https://www.msys2.org/) (optional) + +> MSys2 closely replicates a unix-like environment which is necessary for +> the `bin/tgui` script to run. It comes with a robust "mintty" terminal +> emulator which is better than any standard Windows shell, it supports +> "git" out of the box (almost like Git for Windows, but better), has +> a "pacman" package manager, and you can install a text editor like "vim" +> for a full boomer experience. + +## Usage + +**For MSys2, Git Bash, WSL, Linux or macOS users:** + +First and foremost, change your directory to `tgui`. + +Run `bin/tgui --install-git-hooks` (optional) to install merge drivers +which will assist you in conflict resolution when rebasing your branches. + +Run one of the following: + +- `bin/tgui` - build the project in production mode. +- `bin/tgui --dev` - launch a development server. + - tgui development server provides you with incremental compilation, + hot module replacement and logging facilities in all running instances + of tgui. In short, this means that you will instantly see changes in the + game as you code it. Very useful, highly recommended. + - In order to use it, you should start the game server first, connect to it + and wait until the world has been properly loaded and you are no longer + in the lobby. Start tgui dev server, and once it has finished building, + press F5 on any tgui window. You'll know that it's hooked correctly if + you see a green bug icon in titlebar and data gets dumped to the console. +- `bin/tgui --dev --reload` - reload byond cache once. +- `bin/tgui --dev --debug` - run server with debug logging enabled. +- `bin/tgui --dev --no-hot` - disable hot module replacement (helps when +doing development on IE8). +- `bin/tgui --lint` - show problems with the code. +- `bin/tgui --lint --fix` - auto-fix problems with the code. +- `bin/tgui --analyze` - run a bundle analyzer. +- `bin/tgui --clean` - clean up project repo. +- `bin/tgui [webpack options]` - build the project with custom webpack +options. + +**For everyone else:** + +If you haven't opened the console already, you can do that by holding +Shift and right clicking on the `tgui` folder, then pressing +either `Open command window here` or `Open PowerShell window here`. + +Run `yarn install` to install npm dependencies, then one of the following: + +- `yarn run build` - build the project in production mode. +- `yarn run watch` - launch a development server. +- `yarn run lint` - show problems with the code. +- `yarn run lint --fix` - auto-fix problems with the code. +- `yarn run analyze` - run a bundle analyzer. + +We also got some batch files in store, for those who don't like fiddling +with the console: + +- `bin/tgui-build.bat` - build the project in production mode. +- `bin/tgui-dev-server.bat` - launch a development server. + +> Remember to always run a full build before submitting a PR. It creates +> a compressed javascript bundle which is then referenced from DM code. +> We prefer to keep it version controlled, so that people could build the +> game just by using Dream Maker. + +## Troubleshooting + +**Development server doesn't find my BYOND cache!** + +This happens if your Documents folder in Windows has a custom location, for +example in `E:\Libraries\Documents`. Development server has no knowledge +of these non-standard locations, therefore you have to run the dev server +with an additional environmental variable, with a full path to BYOND cache. + +``` +export BYOND_CACHE="E:/Libraries/Documents/BYOND/cache" +bin/tgui --dev +``` + +Note that in Windows, you have to go through Advanced System Settings, +System Properties and then open Environment Variables window to do the +same thing. You may need to reboot after this. + +## Developer Tools + +When developing with `tgui-dev-server`, you will have access to certain +development only features. + +**Debug Logs.** +When running server via `bin/tgui --dev --debug`, server will print debug +logs and time spent on rendering. Use this information to optimize your +code, and try to keep re-renders below 16ms. + +**Kitchen Sink.** +Press `F12` to open the KitchenSink interface. This interface is a +playground to test various tgui components. + +**Layout Debugger.** +Press `F11` to toggle the *layout debugger*. It will show outlines of +all tgui elements, which makes it easy to understand how everything comes +together, and can reveal certain layout bugs which are not normally visible. + +## Project Structure + +- `/packages` - Each folder here represents a self-contained Node module. +- `/packages/common` - Helper functions +- `/packages/tgui/index.js` - Application entry point. +- `/packages/tgui/components` - Basic UI building blocks. +- `/packages/tgui/interfaces` - Actual in-game interfaces. +Interface takes data via the `state` prop and outputs an html-like stucture, +which you can build using existing UI components. +- `/packages/tgui/layouts` - Root level UI components, that affect the final +look and feel of the browser window. They usually hold various window +elements, like the titlebar and resize handlers, and control the UI theme. +- `/packages/tgui/routes.js` - This is where tgui decides which interface to +pull and render. +- `/packages/tgui/layout.js` - A root-level component, holding the +window elements, like the titlebar, buttons, resize handlers. Calls +`routes.js` to decide which component to render. +- `/packages/tgui/styles/main.scss` - CSS entry point. +- `/packages/tgui/styles/functions.scss` - Useful SASS functions. +Stuff like `lighten`, `darken`, `luminance` are defined here. +- `/packages/tgui/styles/atomic` - Atomic CSS classes. +These are very simple, tiny, reusable CSS classes which you can use and +combine to change appearance of your elements. Keep them small. +- `/packages/tgui/styles/components` - CSS classes which are used +in UI components. These stylesheets closely follow the +[BEM](https://en.bem.info/methodology/) methodology. +- `/packages/tgui/styles/interfaces` - Custom stylesheets for your interfaces. +Add stylesheets here if you really need a fine control over your UI styles. +- `/packages/tgui/styles/layouts` - Layout-related styles. +- `/packages/tgui/styles/themes` - Contains all the various themes you can +use in tgui. Each theme must be registered in `webpack.config.js` file. + +## Component Reference + +See: [Component Reference](docs/component-reference.md). + +## License + +All code is licensed with the parent license of *tgstation*, **AGPL-3.0**. + +See the main [README](../README.md) for more details. + +The Authors retain all copyright to their respective work here submitted. diff --git a/tgui/bin/tgui b/tgui/bin/tgui new file mode 100644 index 00000000000..97a86159e6b --- /dev/null +++ b/tgui/bin/tgui @@ -0,0 +1,181 @@ +#!/bin/bash +set -e +shopt -s globstar +shopt -s expand_aliases + +## Initial set-up +## -------------------------------------------------------- + +## Returns an absolute path to file +alias tgui-realpath="readlink -f" + +## Fallbacks for GNU readlink +## Detecting GNU coreutils http://stackoverflow.com/a/8748344/319952 +if ! readlink --version >/dev/null 2>&1; then + if hash greadlink 2>/dev/null; then + alias tgui-realpath="greadlink -f" + else + alias tgui-realpath="perl -MCwd -le 'print Cwd::abs_path(shift)'" + fi +fi + +## Find a canonical path to project root +base_dir="$(dirname "$(tgui-realpath "${0}")")/.." +base_dir="$(tgui-realpath "${base_dir}")" + +## Add locally installed node programs to path +PATH="${PATH}:node_modules/.bin" + + +## Functions +## -------------------------------------------------------- + +## Installs node modules +task-install() { + cd "${base_dir}" + yarn install +} + +## Runs webpack +task-webpack() { + cd "${base_dir}/packages/tgui" + webpack "${@}" +} + +## Runs a development server +task-dev-server() { + cd "${base_dir}/packages/tgui-dev-server" + exec node --experimental-modules index.js "${@}" +} + +## Run a linter through all packages +task-eslint() { + cd "${base_dir}" + eslint ./packages "${@}" + echo "tgui: eslint check passed" +} + +## Mr. Proper +task-clean() { + cd "${base_dir}" + rm -rf packages/tgui/public/.tmp + rm -rf **/node_modules + rm -f **/package-lock.json +} + +## Validates current build against the build stored in git +task-validate-build() { + cd "${base_dir}" + local diff + diff="$(git diff packages/tgui/public/tgui.bundle.*)" + if [[ -n ${diff} ]]; then + echo "Error: our build differs from the build committed into git." + echo "Please rebuild tgui." + exit 1 + fi + echo "tgui: build is ok" +} + +## Installs merge drivers and git hooks +task-install-git-hooks() { + cd "${base_dir}" + local git_root + local git_base_dir + git_root="$(git rev-parse --show-toplevel)" + git_base_dir="${base_dir/${git_root}/.}" + git config --replace-all merge.tgui-merge-bundle.driver \ + "${git_base_dir}/bin/tgui --merge=bundle %O %A %B %L" + echo "tgui: Merge drivers have been successfully installed!" +} + +## Bundle merge driver +task-merge-bundle() { + local file_ancestor="${1}" + local file_current="${2}" + local file_other="${3}" + local conflict_marker_size="${4}" + echo "tgui: Discarding a local tgui build" + ## Do nothing (file_current will be merged and is what we want to keep). + exit 0 +} + + +## Main +## -------------------------------------------------------- + +if [[ ${1} == "--merge"* ]]; then + if [[ ${1} == "--merge=bundle" ]]; then + shift 1 + task-merge-bundle "${@}" + fi + echo "Unknown merge strategy: ${1}" + exit 1 +fi + +if [[ ${1} == "--install-git-hooks" ]]; then + shift 1 + task-install-git-hooks + exit 0 +fi + +## Continuous integration scenario +if [[ ${1} == "--ci" ]]; then + task-clean + task-install + task-eslint + task-webpack --mode=production + task-validate-build + exit 0 +fi + +if [[ ${1} == "--clean" ]]; then + task-clean + exit 0 +fi + +if [[ ${1} == "--dev" ]]; then + shift + task-install + task-dev-server "${@}" + exit 0 +fi + +if [[ ${1} == '--lint' ]]; then + shift 1 + task-install + task-eslint "${@}" + exit 0 +fi + +if [[ ${1} == '--lint-harder' ]]; then + shift 1 + task-install + task-eslint -c .eslintrc-harder.yml "${@}" + exit 0 +fi + +if [[ ${1} == '--fix' ]]; then + shift 1 + task-install + task-eslint --fix "${@}" + exit 0 +fi + +## Analyze the bundle +if [[ ${1} == '--analyze' ]]; then + task-install + task-webpack --mode=production --analyze + exit 0 +fi + +## Make a production webpack build +if [[ -z ${1} ]]; then + task-install + task-eslint + task-webpack --mode=production + exit 0 +fi + +## Run webpack with custom flags +task-install +task-webpack "${@}" diff --git a/tgui/bin/tgui-build.bat b/tgui/bin/tgui-build.bat new file mode 100644 index 00000000000..89e1aca9152 --- /dev/null +++ b/tgui/bin/tgui-build.bat @@ -0,0 +1,5 @@ +@echo off +cd "%~dp0\.." +call yarn install +call yarn run build +timeout /t 9 diff --git a/tgui/bin/tgui-dev-server.bat b/tgui/bin/tgui-dev-server.bat new file mode 100644 index 00000000000..1b5bdcfb1db --- /dev/null +++ b/tgui/bin/tgui-dev-server.bat @@ -0,0 +1,4 @@ +@echo off +cd "%~dp0\.." +call yarn install +call yarn run watch diff --git a/tgui/docs/component-reference.md b/tgui/docs/component-reference.md new file mode 100644 index 00000000000..6c10124049b --- /dev/null +++ b/tgui/docs/component-reference.md @@ -0,0 +1,1000 @@ +# Component Reference + +> Notice: This documentation might be out of date, so always check the source +> code to see the most up-to-date information. + + + +- [General Concepts](#general-concepts) +- [`tgui/components`](#tguicomponents) + - [`AnimatedNumber`](#animatednumber) + - [`BlockQuote`](#blockquote) + - [`Box`](#box) + - [`Button`](#button) + - [`Button.Checkbox`](#buttoncheckbox) + - [`Button.Confirm`](#buttonconfirm) + - [`Button.Input`](#buttoninput) + - [`ByondUi`](#byondui) + - [`Collapsible`](#collapsible) + - [`ColorBox`](#colorbox) + - [`Dimmer`](#dimmer) + - [`Divider`](#divider) + - [`Dropdown`](#dropdown) + - [`Flex`](#flex) + - [`Flex.Item`](#flexitem) + - [`Grid`](#grid) + - [`Grid.Column`](#gridcolumn) + - [`Icon`](#icon) + - [`Input`](#input) + - [`Knob`](#knob) + - [`LabeledControls`](#labeledcontrols) + - [`LabeledControls.Item`](#labeledcontrolsitem) + - [`LabeledList`](#labeledlist) + - [`LabeledList.Item`](#labeledlistitem) + - [`LabeledList.Divider`](#labeledlistdivider) + - [`Modal`](#modal) + - [`NoticeBox`](#noticebox) + - [`NumberInput`](#numberinput) + - [`ProgressBar`](#progressbar) + - [`Section`](#section) + - [`Slider`](#slider) + - [`Table`](#table) + - [`Table.Row`](#tablerow) + - [`Table.Cell`](#tablecell) + - [`Tabs`](#tabs) + - [`Tabs.Tab`](#tabstab) + - [`Tooltip`](#tooltip) +- [`tgui/layouts`](#tguilayouts) + - [`Window`](#window) + - [`Window.Content`](#windowcontent) + +## General Concepts + +These are the components which you can use for interface construction. +If you have trouble finding the exact prop you need on a component, +please note, that most of these components inherit from other basic +components, such as [Box](#box). This component in particular provides a lot +of styling options for all components, e.g. `color` and `opacity`, thus +it is used a lot in this framework. + +**Event handlers.** +Event handlers are callbacks that you can attack to various element to +listen for browser events. Inferno supports camelcase (`onClick`) and +lowercase (`onclick`) event names. + +- Camel case names are what's called *synthetic* events, and are the +**preferred way** of handling events in React, for efficiency and +performance reasons. Please read +[Inferno Event Handling](https://infernojs.org/docs/guides/event-handling) +to understand what this is about. +- Lower case names are native browser events and should be used sparingly, +for example when you need an explicit IE8 support. **DO NOT** use +lowercase event handlers unless you really know what you are doing. +- [Button](#button) component does not support the lowercase `onclick` event. +Use the camel case `onClick` instead. + +## `tgui/components` + +### `AnimatedNumber` + +This component provides animations for numeric values. + +**Props:** + +- `value: number` - Value to animate. +- `initial: number` - Initial value to use in animation when element +first appears. If you set initial to `0` for example, number will always +animate starting from `0`, and if omitted, it will not play an initial +animation. +- `format: value => value` - Output formatter. + - Example: `value => Math.round(value)`. +- `children: (formattedValue, rawValue) => any` - Pull the animated number to +animate more complex things deeper in the DOM tree. + - Example: `(_, value) => ` + +### `BlockQuote` + +Just a block quote, just like this example in markdown: + +> Here's an example of a block quote. + +**Props:** + +- See inherited props: [Box](#box) + +### `Box` + +The Box component serves as a wrapper component for most of the CSS utility +needs. It creates a new DOM element, a `
` by default that can be changed +with the `as` property. Let's say you want to use a `` instead: + +```jsx + + +
+ {buttons && ( +
+ {buttons} +
+ )} + + {open && ( + + {children} + + )} + + ); + } +} diff --git a/tgui/packages/tgui/components/ColorBox.js b/tgui/packages/tgui/components/ColorBox.js new file mode 100644 index 00000000000..f37c4e057e4 --- /dev/null +++ b/tgui/packages/tgui/components/ColorBox.js @@ -0,0 +1,28 @@ +import { classes, pureComponentHooks } from 'common/react'; +import { computeBoxClassName, computeBoxProps } from './Box'; + +export const ColorBox = props => { + const { + content, + children, + className, + color, + backgroundColor, + ...rest + } = props; + rest.color = content ? null : 'transparent'; + rest.backgroundColor = color || backgroundColor; + return ( +
+ {content || '.'} +
+ ); +}; + +ColorBox.defaultHooks = pureComponentHooks; diff --git a/tgui/packages/tgui/components/Dimmer.js b/tgui/packages/tgui/components/Dimmer.js new file mode 100644 index 00000000000..f38d0a026a6 --- /dev/null +++ b/tgui/packages/tgui/components/Dimmer.js @@ -0,0 +1,18 @@ +import { classes } from 'common/react'; +import { Box } from './Box'; + +export const Dimmer = props => { + const { className, children, ...rest } = props; + return ( + +
+ {children} +
+
+ ); +}; diff --git a/tgui/packages/tgui/components/Divider.js b/tgui/packages/tgui/components/Divider.js new file mode 100644 index 00000000000..5c807c290b8 --- /dev/null +++ b/tgui/packages/tgui/components/Divider.js @@ -0,0 +1,18 @@ +import { classes } from 'common/react'; + +export const Divider = props => { + const { + vertical, + hidden, + } = props; + return ( +