diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 6559f28f26..6bd32c762c 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -48,6 +48,9 @@ Pipelines + Other Objects -> Pipe network pipe_color = null init_dir() +/obj/machinery/atmospherics/examine_icon() + return icon(icon=initial(icon),icon_state=initial(icon_state)) + // This is used to set up what directions pipes will connect to. Should be called inside New() and whenever a dir changes. /obj/machinery/atmospherics/proc/init_dir() return diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm index b4c1e30fba..2c53c47583 100644 --- a/code/ATMOSPHERICS/components/unary/cold_sink.dm +++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm @@ -21,15 +21,9 @@ var/set_temperature = T20C // Thermostat var/cooling = 0 -/obj/machinery/atmospherics/unary/freezer/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/stack/cable_coil(src, 2) - RefreshParts() +/obj/machinery/atmospherics/unary/freezer/Initialize() + . = ..() + default_apply_parts() /obj/machinery/atmospherics/unary/freezer/atmos_init() if(node) diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm index 3537082ada..c91ef281f3 100644 --- a/code/ATMOSPHERICS/components/unary/heat_source.dm +++ b/code/ATMOSPHERICS/components/unary/heat_source.dm @@ -21,15 +21,9 @@ var/set_temperature = T20C //thermostat var/heating = 0 //mainly for icon updates -/obj/machinery/atmospherics/unary/heater/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/stack/cable_coil(src, 5) - - RefreshParts() +/obj/machinery/atmospherics/unary/heater/Initialize() + . = ..() + default_apply_parts() /obj/machinery/atmospherics/unary/heater/atmos_init() if(node) diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 079715550e..4db75508b3 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -378,3 +378,8 @@ var/global/list/##LIST_NAME = list();\ // Used by radios to indicate that they have sent a message via something other than subspace #define RADIO_CONNECTION_FAIL 0 #define RADIO_CONNECTION_NON_SUBSPACE 1 + +#define JOB_CARBON 0x1 +#define JOB_SILICON_ROBOT 0x2 +#define JOB_SILICON_AI 0x4 +#define JOB_SILICON 0x6 // 2|4, probably don't set jobs to this, but good for checking diff --git a/code/__defines/preferences.dm b/code/__defines/preferences.dm index 0bb289d2e1..880d9318d8 100644 --- a/code/__defines/preferences.dm +++ b/code/__defines/preferences.dm @@ -1,6 +1,15 @@ +// Modes for examine text output #define EXAMINE_MODE_DEFAULT 0 #define EXAMINE_MODE_INCLUDE_USAGE 1 #define EXAMINE_MODE_SWITCH_TO_PANEL 2 // Should be one higher than the above -#define EXAMINE_MODE_MAX 3 \ No newline at end of file +#define EXAMINE_MODE_MAX 3 + +// Modes for parsing multilingual speech +#define MULTILINGUAL_DEFAULT 0 +#define MULTILINGUAL_SPACE 1 +#define MULTILINGUAL_DOUBLE_DELIMITER 2 +#define MULTILINGUAL_OFF 3 + +#define MULTILINGUAL_MODE_MAX 4 \ No newline at end of file diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index 03724307c6..5a1806805b 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -54,7 +54,7 @@ #define LANGUAGE_AKHANI "Akhani" #define LANGUAGE_ALAI "Alai" #define LANGUAGE_ZADDAT "Vedahq" -#define LANGUAGE_PROMETHEAN "Promethean" +#define LANGUAGE_PROMETHEAN "Promethean Biolinguistics" #define LANGUAGE_BLOB "Blob" #define LANGUAGE_GIBBERISH "Babel" diff --git a/code/__defines/tgs.config.dm b/code/__defines/tgs.config.dm new file mode 100644 index 0000000000..1ae6593419 --- /dev/null +++ b/code/__defines/tgs.config.dm @@ -0,0 +1,12 @@ +#define TGS_EXTERNAL_CONFIGURATION +#define TGS_V3_API +#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name) +#define TGS_READ_GLOBAL(Name) GLOB.##Name +#define TGS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value +#define TGS_WORLD_ANNOUNCE(message) to_chat(world, "[html_encode(##message)]") +#define TGS_INFO_LOG(message) log_to_dd("TGS Info: [##message]") +#define TGS_WARNING_LOG(message) log_to_dd("TGS Warn: [##message]") +#define TGS_ERROR_LOG(message) log_to_dd("TGS Error: [##message]") +#define TGS_NOTIFY_ADMINS(event) message_admins(##event) +#define TGS_CLIENT_COUNT GLOB.clients.len +#define TGS_PROTECT_DATUM(Path) GENERAL_PROTECT_DATUM(##Path) diff --git a/code/__defines/tgs.dm b/code/__defines/tgs.dm new file mode 100644 index 0000000000..4e152ad3cf --- /dev/null +++ b/code/__defines/tgs.dm @@ -0,0 +1,273 @@ +//tgstation-server DMAPI + +#define TGS_DMAPI_VERSION "5.0.0" + +//All functions and datums outside this document are subject to change with any version and should not be relied on + +//CONFIGURATION + +//create this define if you want to do configuration outside of this file +#ifndef TGS_EXTERNAL_CONFIGURATION + +//Comment this out once you've filled in the below +#error TGS API unconfigured + +//Uncomment this if you wish to allow the game to interact with TGS 3 +//This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()() +//#define TGS_V3_API + +//Required interfaces (fill in with your codebase equivalent): + +//create a global variable named `Name` and set it to `Value` +#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) + +//Read the value in the global variable `Name` +#define TGS_READ_GLOBAL(Name) + +//Set the value in the global variable `Name` to `Value` +#define TGS_WRITE_GLOBAL(Name, Value) + +//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities +#define TGS_PROTECT_DATUM(Path) + +//Display an announcement `message` from the server to all players +#define TGS_WORLD_ANNOUNCE(message) + +//Notify current in-game administrators of a string `event` +#define TGS_NOTIFY_ADMINS(event) + +//Write an info `message` to a server log +#define TGS_INFO_LOG(message) + +//Write an warning `message` to a server log +#define TGS_WARNING_LOG(message) + +//Write an error `message` to a server log +#define TGS_ERROR_LOG(message) + +//Get the number of connected /clients +#define TGS_CLIENT_COUNT + +#endif + +//EVENT CODES + +#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //Before a reboot mode change, extras parameters are the current and new reboot mode enums +#define TGS_EVENT_PORT_SWAP -2 //Before a port change is about to happen, extra parameters is new port +#define TGS_EVENT_INSTANCE_RENAMED -3 //Before the instance is renamed, extra prameter is the new name + +//See the descriptions for the parameters of these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs +#define TGS_EVENT_REPO_RESET_ORIGIN 0 +#define TGS_EVENT_REPO_CHECKOUT 1 +#define TGS_EVENT_REPO_FETCH 2 +#define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3 +#define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4 +#define TGS_EVENT_BYOND_INSTALL_START 5 +#define TGS_EVENT_BYOND_INSTALL_FAIL 6 +#define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7 +#define TGS_EVENT_COMPILE_START 8 +#define TGS_EVENT_COMPILE_CANCELLED 9 +#define TGS_EVENT_COMPILE_FAILURE 10 +#define TGS_EVENT_COMPILE_COMPLETE 11 // Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the TGS_EVENT_DEPLOYMENT_COMPLETE instead +#define TGS_EVENT_INSTANCE_AUTO_UPDATE_START 12 +#define TGS_EVENT_DEPLOYMENT_COMPLETE 13 + +//OTHER ENUMS + +#define TGS_REBOOT_MODE_NORMAL 0 +#define TGS_REBOOT_MODE_SHUTDOWN 1 +#define TGS_REBOOT_MODE_RESTART 2 + +#define TGS_SECURITY_TRUSTED 0 +#define TGS_SECURITY_SAFE 1 +#define TGS_SECURITY_ULTRASAFE 2 + +//REQUIRED HOOKS + +//Call this somewhere in /world/New() that is always run +//IMPORTANT: This function may sleep! Other TGS functions will not succeed until it completes +//event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels +//minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated +/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE) + return + +//Call this when your initializations are complete and your game is ready to play before any player interactions happen +//This may use world.sleep_offline to make this happen so ensure no changes are made to it while this call is running +//Most importantly, before this point, note that any static files or directories may be in use by another server. Your code should account for this +//This function should not be called before ..() in /world/New() +/world/proc/TgsInitializationComplete() + return + +//Put this at the start of /world/Topic() +#define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return + +//Call this at the beginning of world/Reboot(reason) +/world/proc/TgsReboot() + return + +//DATUM DEFINITIONS +//unless otherwise specified all datums defined here should be considered read-only, warranty void if written + +//represents git revision information about the current world build +/datum/tgs_revision_information + var/commit //full sha of compiled commit + var/origin_commit //full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch + +//represents a version of tgstation-server +/datum/tgs_version + var/suite //The suite/major version, can be >=3 + + //this group of variables can be null to represent a wild card + var/minor //The minor version + var/patch //The patch version + var/deprecated_patch //The legacy version + + var/raw_parameter //The unparsed parameter + var/deprefixed_parameter //The version only bit of raw_parameter + +//if the tgs_version is a wildcard version +/datum/tgs_version/proc/Wildcard() + return + +//if the tgs_version equals some other_version +/datum/tgs_version/proc/Equals(datum/tgs_version/other_version) + return + +//represents a merge of a GitHub pull request +/datum/tgs_revision_information/test_merge + var/number //pull request number + var/title //pull request title + var/body //pull request body + var/author //pull request github author + var/url //link to pull request html + var/pull_request_commit //commit of the pull request when it was merged + var/time_merged //timestamp of when the merge commit for the pull request was created + var/comment //optional comment left by the one who initiated the test merge + +//represents a connected chat channel +/datum/tgs_chat_channel + var/id //internal channel representation + var/friendly_name //user friendly channel name + var/connection_name //the name of the configured chat connection + var/is_admin_channel //if the server operator has marked this channel for game admins only + var/is_private_channel //if this is a private chat channel + var/custom_tag //user defined string associated with channel + +//represents a chat user +/datum/tgs_chat_user + var/id //Internal user representation, requires channel to be unique + var/friendly_name //The user's public name + var/mention //The text to use to ping this user in a message + var/datum/tgs_chat_channel/channel //The /datum/tgs_chat_channel this user was from + +//user definable callback for handling events +//extra parameters may be specified depending on the event +/datum/tgs_event_handler/proc/HandleEvent(event_code, ...) + set waitfor = FALSE + return + +//user definable chat command +/datum/tgs_chat_command + var/name = "" //the string to trigger this command on a chat bot. e.g. TGS3_BOT: do_this_command + var/help_text = "" //help text for this command + var/admin_only = FALSE //set to TRUE if this command should only be usable by registered chat admins + +//override to implement command +//sender: The tgs_chat_user who send to command +//params: The trimmed string following the command name +//The return value will be stringified and sent to the appropriate chat +/datum/tgs_chat_command/proc/Run(datum/tgs_chat_user/sender, params) + CRASH("[type] has no implementation for Run()") + +//FUNCTIONS + +//Returns the respective supported /datum/tgs_version of the API +/world/proc/TgsMaximumAPIVersion() + return + +/world/proc/TgsMinimumAPIVersion() + return + +//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise +//No function below this succeeds if it returns FALSE or if TgsNew() has yet to be called +/world/proc/TgsAvailable() + return + +//Gets the current /datum/tgs_version of the server tools running the server +/world/proc/TgsVersion() + return + +//Gets the current /datum/tgs_version of the DMAPI being used +/world/proc/TgsApiVersion() + return + +//Gets the name of the TGS instance running the game +/world/proc/TgsInstanceName() + return + +//Get the current `/datum/tgs_revision_information` +/world/proc/TgsRevision() + return + +//Get the current BYOND security level +/world/proc/TgsSecurityLevel() + return + +//Gets a list of active `/datum/tgs_revision_information/test_merge`s +/world/proc/TgsTestMerges() + return + +//Forces a hard reboot of BYOND by ending the process +//unlike del(world) clients will try to reconnect +//If the service has not requested a shutdown, the next server will take over +/world/proc/TgsEndProcess() + return + +//Gets a list of connected tgs_chat_channel +/world/proc/TgsChatChannelInfo() + return + +//Sends a message to connected game chats +//message: The message to send +//channels: optional channels to limit the broadcast to +/world/proc/TgsChatBroadcast(message, list/channels) + return + +//Send a message to non-admin connected chats +//message: The message to send +//admin_only: If TRUE, message will instead be sent to only admin connected chats +/world/proc/TgsTargetedChatBroadcast(message, admin_only) + return + +//Send a private message to a specific user +//message: The message to send +//user: The /datum/tgs_chat_user to send to +/world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user) + return + +/* +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index 5abedfe9ac..a199c88622 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -107,7 +107,7 @@ AngleToHue(hue) Converts an angle to a hue in the valid range. RotateHue(hsv, angle) Takes an HSV or HSVA value and rotates the hue forward through red, green, and blue by an angle from 0 to 360. - (Rotating red by 60° produces yellow.) The result is another HSV or HSVA color with the same saturation and value + (Rotating red by 60deg produces yellow.) The result is another HSV or HSVA color with the same saturation and value as the original, but a different hue. GrayScale(rgb) Takes an RGB or RGBA color and converts it to grayscale. Returns an RGB or RGBA string. @@ -679,7 +679,7 @@ proc/ColorTone(rgb, tone) var/curstate = A.icon_state || defstate if(!((noIcon = (!curicon)))) - var/curstates = icon_states(curicon) + var/curstates = cached_icon_states(curicon) if(!(curstate in curstates)) if("" in curstates) curstate = "" @@ -689,19 +689,16 @@ proc/ColorTone(rgb, tone) var/curdir var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have - //These should use the parent's direction (most likely) - if(!A.dir || A.dir == SOUTH) - curdir = defdir - else - curdir = A.dir + // Use the requested dir or the atom's current dir + curdir = defdir || A.dir - //Try to remove/optimize this section ASAP, CPU hog. + //Try to remove/optimize this section ASAP, CPU hog. //Slightly mitigated by implementing caching using cached_icon_states //Determines if there's directionals. if(!noIcon && curdir != SOUTH) var/exist = FALSE var/static/list/checkdirs = list(NORTH, EAST, WEST) for(var/i in checkdirs) //Not using GLOB for a reason. - if(length(icon_states(icon(curicon, curstate, i)))) + if(length(cached_icon_states(icon(curicon, curstate, i)))) exist = TRUE break if(!exist) @@ -739,8 +736,8 @@ proc/ColorTone(rgb, tone) continue var/current_layer = current.layer if(current_layer < 0) - if(current_layer <= -1000) - return flat + //if(current_layer <= -1000) + //return flat current_layer = process_set + A.layer + current_layer / 1000 for(var/p in 1 to layers.len) @@ -768,7 +765,7 @@ proc/ColorTone(rgb, tone) curblend = BLEND_OVERLAY add = icon(I.icon, I.icon_state, base_icon_dir) else // 'I' is an appearance object. - add = getFlatIcon(image(I), curdir, curicon, curstate, curblend, FALSE, no_anim) + add = getFlatIcon(image(I), I.dir||curdir, curicon, curstate, curblend, FALSE, no_anim) if(!add) continue // Find the new dimensions of the flat icon to fit the added overlay @@ -899,6 +896,37 @@ proc/ColorTone(rgb, tone) composite.Blend(icon(I.icon, I.icon_state, I.dir, 1), ICON_OVERLAY) return composite +GLOBAL_LIST_EMPTY(icon_state_lists) +/proc/cached_icon_states(var/icon/I) + if(!I) + return list() + var/key = I + var/returnlist = GLOB.icon_state_lists[key] + if(!returnlist) + returnlist = icon_states(I) + if(isfile(I)) // It's something that will stick around + GLOB.icon_state_lists[key] = returnlist + return returnlist + +/proc/expire_states_cache(var/key) + if(GLOB.icon_state_lists[key]) + GLOB.icon_state_lists -= key + return TRUE + return FALSE + +GLOBAL_LIST_EMPTY(cached_examine_icons) +/proc/set_cached_examine_icon(var/atom/A, var/icon/I, var/expiry = 12000) + GLOB.cached_examine_icons[weakref(A)] = I + if(expiry) + addtimer(CALLBACK(GLOBAL_PROC, .proc/uncache_examine_icon, weakref(A)), expiry, TIMER_UNIQUE) + +/proc/get_cached_examine_icon(var/atom/A) + var/weakref/WR = weakref(A) + return GLOB.cached_examine_icons[WR] + +/proc/uncache_examine_icon(var/weakref/WR) + GLOB.cached_examine_icons -= WR + proc/adjust_brightness(var/color, var/value) if (!color) return "#FFFFFF" if (!value) return color diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 73ae811193..d4400da8df 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -94,7 +94,7 @@ proc/age2agedescription(age) else return "unknown" /proc/RoundHealth(health) - var/list/icon_states = icon_states(ingame_hud_med) + var/list/icon_states = cached_icon_states(ingame_hud_med) for(var/icon_state in icon_states) if(health >= text2num(icon_state)) return icon_state diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm index 761bd6cae8..6e63dabb45 100644 --- a/code/_helpers/time.dm +++ b/code/_helpers/time.dm @@ -18,6 +18,7 @@ #define DS2TICKS(DS) ((DS)/world.tick_lag) // Convert deciseconds to ticks #define TICKS2DS(T) ((T) TICKS) // Convert ticks to deciseconds +#define DS2NEARESTTICK(DS) TICKS2DS(-round(-(DS2TICKS(DS)))) /proc/get_game_time() var/global/time_offset = 0 @@ -35,25 +36,25 @@ return wtime + (time_offset + wusage) * world.tick_lag -var/roundstart_hour +GLOBAL_VAR_INIT(roundstart_hour, pick(2,7,12,17)) var/station_date = "" var/next_station_date_change = 1 DAY -#define duration2stationtime(time) time2text(station_time_in_ticks + time, "hh:mm") -#define worldtime2stationtime(time) time2text(roundstart_hour HOURS + time, "hh:mm") -#define round_duration_in_ticks (round_start_time ? world.time - round_start_time : 0) -#define station_time_in_ticks (roundstart_hour HOURS + round_duration_in_ticks) +#define duration2stationtime(time) time2text(station_time_in_ds + time, "hh:mm") +#define worldtime2stationtime(time) time2text(GLOB.roundstart_hour HOURS + time, "hh:mm") +#define round_duration_in_ds (GLOB.round_start_time ? world.time - GLOB.round_start_time : 0) +#define station_time_in_ds (GLOB.roundstart_hour HOURS + round_duration_in_ds) /proc/stationtime2text() - return time2text(station_time_in_ticks, "hh:mm") + return time2text(station_time_in_ds + GLOB.timezoneOffset, "hh:mm") /proc/stationdate2text() var/update_time = FALSE - if(station_time_in_ticks > next_station_date_change) + if(station_time_in_ds > next_station_date_change) next_station_date_change += 1 DAY update_time = TRUE if(!station_date || update_time) - var/extra_days = round(station_time_in_ticks / (1 DAY)) DAYS + var/extra_days = round(station_time_in_ds / (1 DAY)) DAYS var/timeofday = world.timeofday + extra_days station_date = num2text((text2num(time2text(timeofday, "YYYY"))+300)) + "-" + time2text(timeofday, "MM-DD") //VOREStation Edit return station_date @@ -64,6 +65,13 @@ var/next_station_date_change = 1 DAY var/time_portion = time2text(world.timeofday, "hh:mm:ss") return "[date_portion]T[time_portion]" +/proc/get_timezone_offset() + var/midnight_gmt_here = text2num(time2text(0,"hh")) * 36000 + if(midnight_gmt_here > 12 HOURS) + return 24 HOURS - midnight_gmt_here + else + return midnight_gmt_here + /proc/gameTimestamp(format = "hh:mm:ss", wtime=null) if(!wtime) wtime = world.time @@ -83,19 +91,19 @@ proc/isDay(var/month, var/day) var/next_duration_update = 0 var/last_round_duration = 0 -var/round_start_time = 0 +GLOBAL_VAR_INIT(round_start_time, 0) /hook/roundstart/proc/start_timer() - round_start_time = world.time + GLOB.round_start_time = world.time return 1 /proc/roundduration2text() - if(!round_start_time) + if(!GLOB.round_start_time) return "00:00" if(last_round_duration && world.time < next_duration_update) return last_round_duration - var/mills = round_duration_in_ticks // 1/10 of a second, not real milliseconds but whatever + var/mills = round_duration_in_ds // 1/10 of a second, not real milliseconds but whatever //var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something var/mins = round((mills % 36000) / 600) var/hours = round(mills / 36000) @@ -107,10 +115,6 @@ var/round_start_time = 0 next_duration_update = world.time + 1 MINUTES return last_round_duration -/hook/startup/proc/set_roundstart_hour() - roundstart_hour = pick(2,7,12,17) - return 1 - /var/midnight_rollovers = 0 /var/rollovercheck_last_timeofday = 0 /proc/update_midnight_rollover() diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 799cc5d113..b431ac1298 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -31,6 +31,14 @@ if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked build_click(src, client.buildmode, params, A) return + + if(multicam_on) + var/turf/T = get_turf(A) + if(T) + for(var/obj/screen/movable/pic_in_pic/ai/P in T.vis_locs) + if(P.ai == src) + P.Click(params) + break if(stat) return diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 23269f5bab..89e0baa087 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -257,6 +257,9 @@ if(Adjacent(user)) user.start_pulling(src) +/turf/CtrlClick(var/mob/user) + user.stop_pulling() + /* Alt click Unused except for AI diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index f2df817366..fa14c1ca48 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -75,6 +75,8 @@ #define ui_ai_pda_log "SOUTH:6,WEST+11:16" #define ui_ai_take_picture "SOUTH:6,WEST+12:16" #define ui_ai_view_images "SOUTH:6,WEST+13:16" +#define ui_ai_multicam "SOUTH+1:6,WEST+12:16" +#define ui_ai_add_multicam "SOUTH+1:6,WEST+13:16" //Gun buttons #define ui_gun1 "EAST-2:26,SOUTH+2:7" diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm index 37d9616ea5..afe8df0c62 100644 --- a/code/_onclick/hud/ai.dm +++ b/code/_onclick/hud/ai.dm @@ -1,3 +1,25 @@ +/obj/screen/ai/multicam + name = "Multicamera Mode" + icon = 'icons/mob/screen_ai.dmi' + icon_state = "multicam" + +/obj/screen/ai/multicam/Click() + if(..()) + return + var/mob/living/silicon/ai/AI = usr + AI.toggle_multicam() + +/obj/screen/ai/add_multicam + name = "New Camera" + icon = 'icons/mob/screen_ai.dmi' + icon_state = "new_cam" + +/obj/screen/ai/add_multicam/Click() + if(..()) + return + var/mob/living/silicon/ai/AI = usr + AI.drop_new_multicam() + /datum/hud/proc/ai_hud() adding = list() other = list() @@ -130,6 +152,16 @@ using.layer = SCREEN_LAYER adding += using +//Multicamera mode + using = new /obj/screen/ai/multicam() + using.screen_loc = ui_ai_multicam + adding += using + +//Add multicamera camera + using = new /obj/screen/ai/add_multicam() + using.screen_loc = ui_ai_add_multicam + adding += using + mymob.client.screen = list() mymob.client.screen += adding + other mymob.client.screen += mymob.client.void diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 1258e4ce94..adbee61eb8 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -28,6 +28,7 @@ inv_box.icon = ui_style inv_box.color = ui_color inv_box.alpha = ui_alpha + inv_box.hud = src var/list/slot_data = hud_data.gear[gear_slot] inv_box.name = gear_slot @@ -192,6 +193,7 @@ using.screen_loc = ui_swaphand1 using.color = ui_color using.alpha = ui_alpha + using.hud = src src.adding += using using = new /obj/screen/inventory() @@ -201,6 +203,7 @@ using.screen_loc = ui_swaphand2 using.color = ui_color using.alpha = ui_alpha + using.hud = src src.adding += using if(hud_data.has_resist) diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index 3602a52481..40e5977c83 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -11,6 +11,8 @@ /obj/screen/movable var/snap2grid = FALSE var/moved = FALSE + var/x_off = -16 + var/y_off = -16 //Snap Screen Object //Tied to the grid, snaps to the nearest turf @@ -40,8 +42,8 @@ screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]" else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off) - var/pix_X = text2num(screen_loc_X[2]) - 16 - var/pix_Y = text2num(screen_loc_Y[2]) - 16 + var/pix_X = text2num(screen_loc_X[2]) + x_off + var/pix_Y = text2num(screen_loc_Y[2]) + y_off screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]" /obj/screen/movable/proc/encode_screen_X(X) diff --git a/code/_onclick/hud/picture_in_picture.dm b/code/_onclick/hud/picture_in_picture.dm new file mode 100644 index 0000000000..14b6a862c2 --- /dev/null +++ b/code/_onclick/hud/picture_in_picture.dm @@ -0,0 +1,175 @@ +/obj/screen/movable/pic_in_pic + name = "Picture-in-picture" + screen_loc = "CENTER" + plane = PLANE_WORLD + icon = null + var/atom/center + var/width = 0 + var/height = 0 + var/list/shown_to = list() + var/list/viewing_turfs = list() + var/obj/screen/component_button/button_x + var/obj/screen/component_button/button_expand + var/obj/screen/component_button/button_shrink + + var/list/background_mas = list() + var/const/max_dimensions = 10 + +/obj/screen/movable/pic_in_pic/Initialize() + . = ..() + make_backgrounds() + +/obj/screen/movable/pic_in_pic/Destroy() + for(var/C in shown_to) + unshow_to(C) + QDEL_NULL(button_x) + QDEL_NULL(button_shrink) + QDEL_NULL(button_expand) + return ..() + +/obj/screen/movable/pic_in_pic/component_click(obj/screen/component_button/component, params) + if(component == button_x) + qdel(src) + else if(component == button_expand) + set_view_size(width+1, height+1) + else if(component == button_shrink) + set_view_size(width-1, height-1) + +/obj/screen/movable/pic_in_pic/proc/make_backgrounds() + var/mutable_appearance/base = new /mutable_appearance() + base.icon = 'icons/misc/pic_in_pic.dmi' + base.layer = DISPOSAL_LAYER + base.plane = PLATING_PLANE + base.appearance_flags = PIXEL_SCALE + + for(var/direction in cardinal) + var/mutable_appearance/dir = new /mutable_appearance(base) + dir.dir = direction + dir.icon_state = "background_[direction]" + background_mas += dir + +/obj/screen/movable/pic_in_pic/proc/add_buttons() + var/static/mutable_appearance/move_tab + if(!move_tab) + move_tab = new /mutable_appearance() + //all these properties are always the same, and since adding something to the overlay + //list makes a copy, there is no reason to make a new one each call + move_tab.icon = 'icons/misc/pic_in_pic.dmi' + move_tab.icon_state = "move" + move_tab.plane = PLANE_PLAYER_HUD + var/matrix/M = matrix() + M.Translate(0, (height + 0.25) * world.icon_size) + move_tab.transform = M + overlays += move_tab + + if(!button_x) + button_x = new /obj/screen/component_button(null, src) + var/mutable_appearance/MA = new /mutable_appearance() + MA.name = "close" + MA.icon = 'icons/misc/pic_in_pic.dmi' + MA.icon_state = "x" + MA.plane = PLANE_PLAYER_HUD + button_x.appearance = MA + M = matrix() + M.Translate((max(4, width) - 0.75) * world.icon_size, (height + 0.25) * world.icon_size) + button_x.transform = M + vis_contents += button_x + + if(!button_expand) + button_expand = new /obj/screen/component_button(null, src) + var/mutable_appearance/MA = new /mutable_appearance() + MA.name = "expand" + MA.icon = 'icons/misc/pic_in_pic.dmi' + MA.icon_state = "expand" + MA.plane = PLANE_PLAYER_HUD + button_expand.appearance = MA + M = matrix() + M.Translate(world.icon_size, (height + 0.25) * world.icon_size) + button_expand.transform = M + vis_contents += button_expand + + if(!button_shrink) + button_shrink = new /obj/screen/component_button(null, src) + var/mutable_appearance/MA = new /mutable_appearance() + MA.name = "shrink" + MA.icon = 'icons/misc/pic_in_pic.dmi' + MA.icon_state = "shrink" + MA.plane = PLANE_PLAYER_HUD + button_shrink.appearance = MA + M = matrix() + M.Translate(2 * world.icon_size, (height + 0.25) * world.icon_size) + button_shrink.transform = M + vis_contents += button_shrink + +/obj/screen/movable/pic_in_pic/proc/add_background() + if((width > 0) && (height > 0)) + for(var/mutable_appearance/dir in background_mas) + var/matrix/M = matrix() + var/x_scale = 1 + var/y_scale = 1 + + var/x_off = 0 + var/y_off = 0 + + if(dir.dir & (NORTH|SOUTH)) + x_scale = width + x_off = (width-1)/2 * world.icon_size + if(dir.dir & NORTH) + y_off = ((height-1) * world.icon_size) + 3 + else + y_off = -3 + + if(dir.dir & (EAST|WEST)) + y_scale = height + y_off = (height-1)/2 * world.icon_size + if(dir.dir & EAST) + x_off = ((width-1) * world.icon_size) + 3 + else + x_off = -3 + + M.Scale(x_scale, y_scale) + M.Translate(x_off, y_off) + dir.transform = M + overlays += dir + +/obj/screen/movable/pic_in_pic/proc/set_view_size(width, height, do_refresh = TRUE) + width = CLAMP(width, 0, max_dimensions) + height = CLAMP(height, 0, max_dimensions) + src.width = width + src.height = height + + y_off = -height * world.icon_size - 16 + + overlays.Cut() + add_background() + add_buttons() + if(do_refresh) + refresh_view() + +/obj/screen/movable/pic_in_pic/proc/set_view_center(atom/target, do_refresh = TRUE) + center = target + if(do_refresh) + refresh_view() + +/obj/screen/movable/pic_in_pic/proc/refresh_view() + vis_contents -= viewing_turfs + if(!width || !height) + return + var/turf/T = get_turf(center) + if(!T) + return + var/turf/lowerleft = locate(max(1, T.x - round(width/2)), max(1, T.y - round(height/2)), T.z) + var/turf/upperright = locate(min(world.maxx, lowerleft.x + width - 1), min(world.maxy, lowerleft.y + height - 1), lowerleft.z) + viewing_turfs = block(lowerleft, upperright) + vis_contents += viewing_turfs + + +/obj/screen/movable/pic_in_pic/proc/show_to(client/C) + if(C) + shown_to[C] = 1 + C.screen += src + +/obj/screen/movable/pic_in_pic/proc/unshow_to(client/C) + if(C) + shown_to -= C + C.screen -= src \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index e82d3ea5f6..ab6985bdbd 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -19,6 +19,9 @@ /obj/screen/Destroy() master = null return ..() + +/obj/screen/proc/component_click(obj/screen/component_button/component, params) + return /obj/screen/text icon = null @@ -31,7 +34,36 @@ /obj/screen/inventory var/slot_id //The indentifier for the slot. It has nothing to do with ID cards. + var/list/object_overlays = list() // Required for inventory/screen overlays. +/obj/screen/inventory/MouseEntered() + ..() + add_overlays() + +/obj/screen/inventory/MouseExited() + ..() + cut_overlay(object_overlays) + object_overlays.Cut() + +/obj/screen/inventory/proc/add_overlays() + var/mob/user = hud.mymob + + if(hud && user && slot_id) + var/obj/item/holding = user.get_active_hand() + + if(!holding || user.get_equipped_item(slot_id)) + return + + var/image/item_overlay = image(holding) + item_overlay.alpha = 92 + + if(!holding.mob_can_equip(user, slot_id, disable_warning = TRUE)) + item_overlay.color = "#ff0000" + else + item_overlay.color = "#00ff00" + + object_overlays += item_overlay + add_overlay(object_overlays) /obj/screen/close name = "close" @@ -102,78 +134,116 @@ icon_state = "zone_sel" screen_loc = ui_zonesel var/selecting = BP_TORSO + var/static/list/hover_overlays_cache = list() + var/hovering_choice + var/mutable_appearance/selecting_appearance /obj/screen/zone_sel/Click(location, control,params) + if(isobserver(usr)) + return + var/list/PL = params2list(params) var/icon_x = text2num(PL["icon-x"]) var/icon_y = text2num(PL["icon-y"]) - var/old_selecting = selecting //We're only going to update_icon() if there's been a change + var/choice = get_zone_at(icon_x, icon_y) + if(!choice) + return 1 + return set_selected_zone(choice, usr) + +/obj/screen/zone_sel/MouseEntered(location, control, params) + MouseMove(location, control, params) + +/obj/screen/zone_sel/MouseMove(location, control, params) + if(isobserver(usr)) + return + + var/list/PL = params2list(params) + var/icon_x = text2num(PL["icon-x"]) + var/icon_y = text2num(PL["icon-y"]) + var/choice = get_zone_at(icon_x, icon_y) + + if(hovering_choice == choice) + return + vis_contents -= hover_overlays_cache[hovering_choice] + hovering_choice = choice + + var/obj/effect/overlay/zone_sel/overlay_object = hover_overlays_cache[choice] + if(!overlay_object) + overlay_object = new + overlay_object.icon_state = "[choice]" + hover_overlays_cache[choice] = overlay_object + vis_contents += overlay_object + + +/obj/effect/overlay/zone_sel + icon = 'icons/mob/zone_sel.dmi' + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + alpha = 128 + anchored = TRUE + layer = LAYER_HUD_ABOVE + plane = PLANE_PLAYER_HUD_ABOVE + +/obj/screen/zone_sel/MouseExited(location, control, params) + if(!isobserver(usr) && hovering_choice) + vis_contents -= hover_overlays_cache[hovering_choice] + hovering_choice = null + +/obj/screen/zone_sel/proc/get_zone_at(icon_x, icon_y) switch(icon_y) if(1 to 3) //Feet switch(icon_x) if(10 to 15) - selecting = BP_R_FOOT + return BP_R_FOOT if(17 to 22) - selecting = BP_L_FOOT - else - return 1 + return BP_L_FOOT if(4 to 9) //Legs switch(icon_x) if(10 to 15) - selecting = BP_R_LEG + return BP_R_LEG if(17 to 22) - selecting = BP_L_LEG - else - return 1 + return BP_L_LEG if(10 to 13) //Hands and groin switch(icon_x) if(8 to 11) - selecting = BP_R_HAND + return BP_R_HAND if(12 to 20) - selecting = BP_GROIN + return BP_GROIN if(21 to 24) - selecting = BP_L_HAND - else - return 1 + return BP_L_HAND if(14 to 22) //Chest and arms to shoulders switch(icon_x) if(8 to 11) - selecting = BP_R_ARM + return BP_R_ARM if(12 to 20) - selecting = BP_TORSO + return BP_TORSO if(21 to 24) - selecting = BP_L_ARM - else - return 1 + return BP_L_ARM if(23 to 30) //Head, but we need to check for eye or mouth if(icon_x in 12 to 20) - selecting = BP_HEAD switch(icon_y) if(23 to 24) if(icon_x in 15 to 17) - selecting = O_MOUTH + return O_MOUTH if(26) //Eyeline, eyes are on 15 and 17 if(icon_x in 14 to 18) - selecting = O_EYES + return O_EYES if(25 to 27) if(icon_x in 15 to 17) - selecting = O_EYES + return O_EYES + return BP_HEAD - if(old_selecting != selecting) - update_icon() - return 1 - -/obj/screen/zone_sel/proc/set_selected_zone(bodypart) - var/old_selecting = selecting - selecting = bodypart - if(old_selecting != selecting) +/obj/screen/zone_sel/proc/set_selected_zone(choice, mob/user) + if(isobserver(user)) + return + if(choice != selecting) + selecting = choice update_icon() /obj/screen/zone_sel/update_icon() - overlays.Cut() - overlays += image('icons/mob/zone_sel.dmi', "[selecting]") - + cut_overlay(selecting_appearance) + selecting_appearance = mutable_appearance('icons/mob/zone_sel.dmi', "[selecting]") + add_overlay(selecting_appearance) /obj/screen/Click(location, control, params) if(!usr) return 1 @@ -535,3 +605,15 @@ var/mob/living/carbon/C = hud.mymob if(C.handcuffed) overlays |= handcuff_overlay + +// PIP stuff +/obj/screen/component_button + var/obj/screen/parent + +/obj/screen/component_button/Initialize(mapload, obj/screen/new_parent) + . = ..() + parent = new_parent + +/obj/screen/component_button/Click(params) + if(parent) + parent.component_click(src, params) diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 88309b5074..485df1de41 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -50,8 +50,8 @@ /obj/machinery/teleport/hub/attack_ghost(mob/user as mob) var/atom/l = loc var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z)) - if(com.locked) - user.loc = get_turf(com.locked) + if(com?.teleport_control.locked) + user.loc = get_turf(com.teleport_control.locked) /obj/effect/portal/attack_ghost(mob/user as mob) if(target) diff --git a/code/controllers/autotransfer.dm b/code/controllers/autotransfer.dm index e64f8de229..8008ef3df9 100644 --- a/code/controllers/autotransfer.dm +++ b/code/controllers/autotransfer.dm @@ -17,14 +17,14 @@ datum/controller/transfer_controller/Destroy() datum/controller/transfer_controller/process() currenttick = currenttick + 1 //VOREStation Edit START - if (round_duration_in_ticks >= shift_last_vote - 2 MINUTES) - shift_last_vote = 999999999999 //Setting to a stupidly high number since it'll be not used again. - to_world("Warning: This upcoming round-extend vote will be your ONLY extend vote. Wrap up your scenes in the next 4 fuckin hours if the round is extended.") //YAWN EDIT NIGGA VOREStation Edit - if (round_duration_in_ticks >= shift_hard_end - 1 MINUTE) + if (round_duration_in_ds >= shift_last_vote - 2 MINUTES) + shift_last_vote = 99999999 //Setting to a stupidly high number since it'll be not used again. + to_world("Warning: You have one hour left in the shift. Wrap up your scenes in the next 60 minutes before the transfer is called.") //VOREStation Edit + if (round_duration_in_ds >= shift_hard_end - 1 MINUTE) init_shift_change(null, 1) shift_hard_end = timerbuffer + config.vote_autotransfer_interval //If shuttle somehow gets recalled, let's force it to call again next time a vote would occur. timerbuffer = timerbuffer + config.vote_autotransfer_interval //Just to make sure a vote doesn't occur immediately afterwords. - else if (round_duration_in_ticks >= timerbuffer - 1 MINUTE) + else if (round_duration_in_ds >= timerbuffer - 1 MINUTE) SSvote.autotransfer() //VOREStation Edit END timerbuffer = timerbuffer + config.vote_autotransfer_interval diff --git a/code/controllers/configuration_vr.dm b/code/controllers/configuration_vr.dm index ad839a5730..a91c04e517 100644 --- a/code/controllers/configuration_vr.dm +++ b/code/controllers/configuration_vr.dm @@ -11,6 +11,7 @@ var/static/pto_cap = 100 //Hours var/static/require_flavor = FALSE var/static/ipqualityscore_apikey //API key for ipqualityscore.com + var/static/use_playtime_restriction_for_jobs = FALSE /hook/startup/proc/read_vs_config() var/list/Lines = file2list("config/config.txt") @@ -61,4 +62,6 @@ config.require_flavor = TRUE if ("ipqualityscore_apikey") config.ipqualityscore_apikey = value + if ("use_playtime_restriction_for_jobs") + config.use_playtime_restriction_for_jobs = TRUE return 1 diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 2212291b9e..811e8497f6 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -156,12 +156,15 @@ GLOBAL_REAL(Master, /datum/controller/master) = new // Please don't stuff random bullshit here, // Make a subsystem, give it the SS_NO_FIRE flag, and do your work in it's Initialize() -/datum/controller/master/Initialize(delay, init_sss) +/datum/controller/master/Initialize(delay, init_sss, tgs_prime) set waitfor = 0 if(delay) sleep(delay) + if(tgs_prime) + world.TgsInitializationComplete() + if(init_sss) init_subtypes(/datum/controller/subsystem, subsystems) diff --git a/code/controllers/subsystems/game_master.dm b/code/controllers/subsystems/game_master.dm index d5326bfba6..ce7e8176c3 100644 --- a/code/controllers/subsystems/game_master.dm +++ b/code/controllers/subsystems/game_master.dm @@ -109,7 +109,7 @@ SUBSYSTEM_DEF(game_master) return FALSE // Last minute antagging is bad for humans to do, so the GM will respect the start and end of the round. - var/mills = round_duration_in_ticks + var/mills = round_duration_in_ds var/mins = round((mills % 36000) / 600) var/hours = round(mills / 36000) diff --git a/code/controllers/subsystems/nightshift.dm b/code/controllers/subsystems/nightshift.dm index 9e89a05cee..3f0d9bfda8 100644 --- a/code/controllers/subsystems/nightshift.dm +++ b/code/controllers/subsystems/nightshift.dm @@ -20,7 +20,7 @@ SUBSYSTEM_DEF(nightshift) return ..() /datum/controller/subsystem/nightshift/fire(resumed = FALSE) - if(round_duration_in_ticks < nightshift_first_check) + if(round_duration_in_ds < nightshift_first_check) return check_nightshift() diff --git a/code/controllers/subsystems/persist_vr.dm b/code/controllers/subsystems/persist_vr.dm index 41811a2a6a..ca0feb37f6 100644 --- a/code/controllers/subsystems/persist_vr.dm +++ b/code/controllers/subsystems/persist_vr.dm @@ -47,23 +47,33 @@ SUBSYSTEM_DEF(persist) // Update client whatever var/client/C = M.client - var/wait_in_hours = (wait / (1 HOUR)) * J.timeoff_factor + var/wait_in_hours = wait / (1 HOUR) + var/pto_factored = wait_in_hours * J.timeoff_factor LAZYINITLIST(C.department_hours) + LAZYINITLIST(C.play_hours) var/dept_hours = C.department_hours - if(isnum(C.department_hours[department_earning])) - dept_hours[department_earning] += wait_in_hours + var/play_hours = C.play_hours + if(isnum(dept_hours[department_earning])) + dept_hours[department_earning] += pto_factored else - dept_hours[department_earning] = wait_in_hours + dept_hours[department_earning] = pto_factored - //Cap it + // If they're earning PTO they must be in a useful job so are earning playtime in that department + if(J.timeoff_factor > 0) + if(isnum(play_hours[department_earning])) + play_hours[department_earning] += wait_in_hours + else + play_hours[department_earning] = wait_in_hours + + // Cap it dept_hours[department_earning] = min(config.pto_cap, dept_hours[department_earning]) - // Okay we figured it out, lets update database! var/sql_ckey = sql_sanitize_text(C.ckey) var/sql_dpt = sql_sanitize_text(department_earning) var/sql_bal = text2num("[C.department_hours[department_earning]]") - var/DBQuery/query = dbcon.NewQuery("INSERT INTO vr_player_hours (ckey, department, hours) VALUES ('[sql_ckey]', '[sql_dpt]', [sql_bal]) ON DUPLICATE KEY UPDATE hours = VALUES(hours)") + var/sql_total = text2num("[C.play_hours[department_earning]]") + var/DBQuery/query = dbcon.NewQuery("INSERT INTO vr_player_hours (ckey, department, hours, total_hours) VALUES ('[sql_ckey]', '[sql_dpt]', [sql_bal], [sql_total]) ON DUPLICATE KEY UPDATE hours = VALUES(hours), total_hours = VALUES(total_hours)") query.Execute() if (MC_TICK_CHECK) diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index 397f32078c..f213c6bf30 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -394,21 +394,26 @@ var/global/datum/controller/subsystem/ticker/ticker /datum/controller/subsystem/ticker/proc/create_characters() for(var/mob/new_player/player in player_list) - if(player && player.ready && player.mind) - if(player.mind.assigned_role=="AI") + if(player && player.ready && player.mind?.assigned_role) + var/datum/job/J = SSjob.get_job(player.mind.assigned_role) + + // Snowflakey AI treatment + if(J.mob_type & JOB_SILICON_AI) player.close_spawn_windows() - player.AIize() - else if(!player.mind.assigned_role) + player.AIize(move = TRUE) continue - else - //VOREStation Edit Start - var/mob/living/carbon/human/new_char = player.create_character() - if(new_char) - qdel(player) - if(istype(new_char) && !(new_char.mind.assigned_role=="Cyborg")) - data_core.manifest_inject(new_char) - //VOREStation Edit End + + // Ask their new_player mob to spawn them + if(!player.spawn_checks_vr(player.mind.assigned_role)) continue //VOREStation Add + var/mob/living/carbon/human/new_char = player.create_character() + + // Created their playable character, delete their /mob/new_player + if(new_char) + qdel(player) + // If they're a carbon, they can get manifested + if(J.mob_type & JOB_CARBON) + data_core.manifest_inject(new_char) /datum/controller/subsystem/ticker/proc/collect_minds() for(var/mob/living/player in player_list) diff --git a/code/datums/orbit.dm b/code/datums/orbit.dm index 5d457ff4ac..0176d7f23d 100644 --- a/code/datums/orbit.dm +++ b/code/datums/orbit.dm @@ -4,10 +4,12 @@ var/lock = TRUE var/turf/lastloc var/lastprocess + var/matrix/init_transform -/datum/orbit/New(_orbiter, _orbiting, _lock) +/datum/orbit/New(var/atom/movable/_orbiter, var/atom/_orbiting, _lock) orbiter = _orbiter orbiting = _orbiting + init_transform = _orbiter.transform SSorbit.processing += src if (!orbiting.orbiters) orbiting.orbiters = list() @@ -24,6 +26,7 @@ SSorbit.processing -= src if (orbiter) orbiter.orbiting = null + orbiter.transform = init_transform orbiter = null if (orbiting) if (orbiting.orbiters) @@ -84,7 +87,6 @@ new/datum/orbit(src, A, lockinorbit) if (!orbiting) //something failed, and our orbit datum deleted itself return - var/matrix/initial_transform = matrix(transform) //Head first! if (pre_rotation) @@ -101,9 +103,6 @@ SpinAnimation(rotation_speed, -1, clockwise, rotation_segments) - //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit - transform = initial_transform - /atom/movable/proc/stop_orbit() SpinAnimation(0,0) qdel(orbiting) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 962c91a621..e00a4a99df 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -4,6 +4,7 @@ var/list/restricted_jobs = list() // Jobs that cannot be this antagonist (depending on config) var/list/protected_jobs = list() // As above. var/list/roundstart_restricted = list() //Jobs that can be this antag, but not at roundstart + var/avoid_silicons = FALSE // If we won't hand this antag role to silicons (AI, borg, etc) // Strings. var/welcome_text = "Cry havoc and let slip the dogs of war!" diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm index c8f2928ced..10f7a75b15 100644 --- a/code/game/antagonist/antagonist_helpers.dm +++ b/code/game/antagonist/antagonist_helpers.dm @@ -10,6 +10,10 @@ return FALSE if(config.protect_roles_from_antagonist && (player.assigned_role in protected_jobs)) return FALSE + if(avoid_silicons) + var/datum/job/J = SSjob.get_job(player.assigned_role) + if(J.mob_type & JOB_SILICON) + return FALSE return TRUE /datum/antagonist/proc/antags_are_dead() diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm index 860e73a052..694c4a3634 100644 --- a/code/game/antagonist/station/changeling.dm +++ b/code/game/antagonist/station/changeling.dm @@ -5,7 +5,7 @@ role_text_plural = "Changelings" bantype = "changeling" feedback_tag = "changeling_objective" - restricted_jobs = list("AI", "Cyborg") + avoid_silicons = TRUE protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Colony Director") welcome_text = "Use say \"#g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them." antag_sound = 'sound/effects/antag_notice/ling_alert.ogg' diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm index dc98622ba7..06aab654b4 100644 --- a/code/game/antagonist/station/cultist.dm +++ b/code/game/antagonist/station/cultist.dm @@ -11,7 +11,8 @@ var/datum/antagonist/cultist/cult role_text = "Cultist" role_text_plural = "Cultists" bantype = "cultist" - restricted_jobs = list("Chaplain","AI", "Cyborg") + restricted_jobs = list("Chaplain") + avoid_silicons = TRUE protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director") roundstart_restricted = list("Internal Affairs Agent", "Head of Security", "Colony Director") role_type = BE_CULTIST diff --git a/code/game/antagonist/station/loyalist.dm b/code/game/antagonist/station/loyalist.dm index 9b2333b491..ec27584426 100644 --- a/code/game/antagonist/station/loyalist.dm +++ b/code/game/antagonist/station/loyalist.dm @@ -29,7 +29,7 @@ var/datum/antagonist/loyalists/loyalists faction_welcome = "Preserve NanoTrasen's interests against the traitorous recidivists amongst the crew. Protect the heads of staff with your life." faction_indicator = "loyal" faction_invisible = 1 - restricted_jobs = list("AI", "Cyborg") + avoid_silicons = TRUE /datum/antagonist/loyalists/New() ..() diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm index ed3c804506..cdd4efb8f3 100644 --- a/code/game/antagonist/station/renegade.dm +++ b/code/game/antagonist/station/renegade.dm @@ -6,7 +6,7 @@ var/datum/antagonist/renegade/renegades role_text = "Renegade" role_text_plural = "Renegades" bantype = "renegade" - restricted_jobs = list("AI", "Cyborg") + avoid_silicons = TRUE welcome_text = "Something's going to go wrong today, you can just feel it. You're paranoid, you've got a gun, and you're going to survive." antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg' antag_text = "You are a minor antagonist! Within the rules, \ diff --git a/code/game/antagonist/station/revolutionary.dm b/code/game/antagonist/station/revolutionary.dm index 17c519b7a0..1db40f396a 100644 --- a/code/game/antagonist/station/revolutionary.dm +++ b/code/game/antagonist/station/revolutionary.dm @@ -29,7 +29,7 @@ var/datum/antagonist/revolutionary/revs faction_indicator = "rev" faction_invisible = 1 - restricted_jobs = list("AI", "Cyborg") + avoid_silicons = TRUE protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Colony Director", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer") roundstart_restricted = list("Internal Affairs Agent", "Colony Director", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer") diff --git a/code/game/antagonist/station/stowaway.dm b/code/game/antagonist/station/stowaway.dm index dc3814b3b1..574fda0bca 100644 --- a/code/game/antagonist/station/stowaway.dm +++ b/code/game/antagonist/station/stowaway.dm @@ -6,7 +6,7 @@ var/datum/antagonist/stowaway/stowaways role_text = "Stowaway" role_text_plural = "Stowaways" bantype = "renegade" - restricted_jobs = list("AI") + avoid_silicons = TRUE // This was previously allowing cyborgs to be stowaways, but given that they would just connect to the AI, it didn't make much sense welcome_text = "People are known to run from many things, or to many things, for many different reasons. You happen to be one of those people." antag_text = "You are a minor antagonist! Within the server rules, do whatever it is \ that you came to the station to do. Espionage, thievery, or just running from the law are all examples. \ diff --git a/code/game/antagonist/station/thug.dm b/code/game/antagonist/station/thug.dm index 61d92e1646..f26d6441a8 100644 --- a/code/game/antagonist/station/thug.dm +++ b/code/game/antagonist/station/thug.dm @@ -6,7 +6,7 @@ var/datum/antagonist/thug/thugs role_text = "Thug" role_text_plural = "Thugs" bantype = "renegade" - restricted_jobs = list("AI", "Cyborg") + avoid_silicons = TRUE welcome_text = "Sometimes, people just need to get messed up. Luckily, that's what you're here to do." antag_text = "You are a minor antagonist! Within the server rules, do whatever it is \ that you came to the station to do, be it violence, theft, or just extreme self-defense. \ diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 5f8ccb3391..123daae654 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -37,8 +37,8 @@ // During dynamic mapload (reader.dm) this assigns the var overrides from the .dmm file // Native BYOND maploading sets those vars before invoking New(), by doing this FIRST we come as close to that behavior as we can. - if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New() - _preloader.load(src) + if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() + GLOB._preloader.load(src) // Pass our arguments to InitAtom so they can be passed to initialize(), but replace 1st with if-we're-during-mapload. var/do_initialize = SSatoms.initialized @@ -184,14 +184,18 @@ var/list/output = list("[bicon(src)] That's [f_name] [suffix]", desc) - if(user.client?.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE) + if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE) output += description_info - if(user.client?.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL) + if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL) user.client.statpanel = "Examine" // Switch to stat panel return output +// Don't make these call bicon or anything, these are what bicon uses. They need to return an icon. +/atom/proc/examine_icon() + return icon(icon=src.icon, icon_state=src.icon_state, dir=SOUTH, frame=1, moving=0) + // called by mobs when e.g. having the atom as their machine, pulledby, loc (AKA mob being inside the atom) or buckled var set. // see code/modules/mob/mob_movement.dm for more. /atom/proc/relaymove() diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index c79a0e94be..b9b8f6db8a 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -56,16 +56,9 @@ var/obj/item/weapon/reagent_containers/glass/beaker = null var/opened = 0 -/obj/machinery/dna_scannernew/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - component_parts += new /obj/item/stack/cable_coil(src) - component_parts += new /obj/item/stack/cable_coil(src) - RefreshParts() +/obj/machinery/dna_scannernew/Initialize() + . = ..() + default_apply_parts() /obj/machinery/dna_scannernew/relaymove(mob/user as mob) if (user.stat) diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm index 578c1a0d8c..9fcb4bd0ea 100644 --- a/code/game/gamemodes/game_mode_latespawn.dm +++ b/code/game/gamemodes/game_mode_latespawn.dm @@ -34,7 +34,7 @@ if(emergency_shuttle.shuttle && (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP || emergency_shuttle.shuttle.moving_status == SHUTTLE_INTRANSIT)) return // Don't do anything if the shuttle's coming. - var/mills = round_duration_in_ticks + var/mills = round_duration_in_ds var/mins = round((mills % 36000) / 600) var/hours = round(mills / 36000) diff --git a/code/game/jobs/job/captain_vr.dm b/code/game/jobs/job/captain_vr.dm index f08a1b4079..746d92cf86 100644 --- a/code/game/jobs/job/captain_vr.dm +++ b/code/game/jobs/job/captain_vr.dm @@ -1,12 +1,14 @@ /datum/job/captain disallow_jobhop = TRUE pto_type = PTO_CIVILIAN + //dept_time_required = 60 //Pending something more complicated /datum/job/hop disallow_jobhop = TRUE pto_type = PTO_CIVILIAN departments = list(DEPARTMENT_COMMAND, DEPARTMENT_CIVILIAN) departments_managed = list(DEPARTMENT_CIVILIAN, DEPARTMENT_CARGO, DEPARTMENT_PLANET) + dept_time_required = 60 alt_titles = list("Crew Resources Officer" = /datum/alt_title/cro, "Deputy Director" = /datum/alt_title/deputy_director) diff --git a/code/game/jobs/job/civilian_vr.dm b/code/game/jobs/job/civilian_vr.dm index 2844108187..433935e55b 100644 --- a/code/game/jobs/job/civilian_vr.dm +++ b/code/game/jobs/job/civilian_vr.dm @@ -12,6 +12,7 @@ /datum/job/qm pto_type = PTO_CARGO + dept_time_required = 20 /datum/job/cargo_tech total_positions = 3 diff --git a/code/game/jobs/job/engineering_vr.dm b/code/game/jobs/job/engineering_vr.dm index 10337d9881..0ed001bd28 100644 --- a/code/game/jobs/job/engineering_vr.dm +++ b/code/game/jobs/job/engineering_vr.dm @@ -1,6 +1,7 @@ /datum/job/chief_engineer disallow_jobhop = TRUE pto_type = PTO_ENGINEERING + dept_time_required = 60 /datum/job/engineer pto_type = PTO_ENGINEERING diff --git a/code/game/jobs/job/exploration_vr.dm b/code/game/jobs/job/exploration_vr.dm index 987041de61..d555c531a2 100644 --- a/code/game/jobs/job/exploration_vr.dm +++ b/code/game/jobs/job/exploration_vr.dm @@ -44,6 +44,7 @@ var/const/SAR =(1<<14) economic_modifier = 8 minimal_player_age = 7 pto_type = PTO_EXPLORATION + dept_time_required = 20 access = list(access_eva, access_maint_tunnels, access_external_airlocks, access_pilot, access_explorer, access_gateway) minimal_access = list(access_eva, access_maint_tunnels, access_external_airlocks, access_pilot, access_explorer, access_gateway) diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 082753d0fc..a1ca756462 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -31,6 +31,7 @@ var/outfit_type // What outfit datum does this job use in its default title? var/offmap_spawn = FALSE // Do we require weird and special spawning and datacore handling? + var/mob_type = JOB_CARBON // Bitflags representing mob type this job spawns // Description of the job's role and minimum responsibilities. var/job_description = "This Job doesn't have a description! Please report it!" diff --git a/code/game/jobs/job/job_vr.dm b/code/game/jobs/job/job_vr.dm index ce982aaab9..3ffd0d05f9 100644 --- a/code/game/jobs/job/job_vr.dm +++ b/code/game/jobs/job/job_vr.dm @@ -14,6 +14,20 @@ //Disallow joining as this job midround from off-duty position via going on-duty var/disallow_jobhop = FALSE + //Time required in the department as other jobs before playing this one (in hours) + var/dept_time_required = 0 + // Check client-specific availability rules. /datum/job/proc/player_has_enough_pto(client/C) return timeoff_factor >= 0 || (C && LAZYACCESS(C.department_hours, pto_type) > 0) + +/datum/job/proc/player_has_enough_playtime(client/C) + return (available_in_playhours(C) == 0) + +/datum/job/proc/available_in_playhours(client/C) + if(C && config.use_playtime_restriction_for_jobs) + if(isnum(C.play_hours[pto_type])) // Has played that department before + return max(0, dept_time_required - C.play_hours[pto_type]) + else // List doesn't have that entry, maybe never played, maybe invalid PTO type (you should fix that...) + return dept_time_required // Could be 0, too, which is fine! They can play that + return 0 \ No newline at end of file diff --git a/code/game/jobs/job/medical_vr.dm b/code/game/jobs/job/medical_vr.dm index 306fe9acaa..1a29d1ec9d 100644 --- a/code/game/jobs/job/medical_vr.dm +++ b/code/game/jobs/job/medical_vr.dm @@ -1,6 +1,7 @@ /datum/job/cmo disallow_jobhop = TRUE pto_type = PTO_MEDICAL + dept_time_required = 60 /datum/job/doctor spawn_positions = 5 diff --git a/code/game/jobs/job/science_vr.dm b/code/game/jobs/job/science_vr.dm index d1bd15c364..637b41f3cb 100644 --- a/code/game/jobs/job/science_vr.dm +++ b/code/game/jobs/job/science_vr.dm @@ -1,6 +1,7 @@ /datum/job/rd disallow_jobhop = TRUE pto_type = PTO_SCIENCE + dept_time_required = 60 access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_teleporter, access_sec_doors, diff --git a/code/game/jobs/job/security_vr.dm b/code/game/jobs/job/security_vr.dm index 9e55d807b0..24b4a33325 100644 --- a/code/game/jobs/job/security_vr.dm +++ b/code/game/jobs/job/security_vr.dm @@ -1,6 +1,7 @@ /datum/job/hos disallow_jobhop = TRUE pto_type = PTO_SECURITY + dept_time_required = 60 access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory, access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, @@ -13,6 +14,7 @@ /datum/job/warden pto_type = PTO_SECURITY + dept_time_required = 20 /datum/job/detective pto_type = PTO_SECURITY diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm index 6f89adcd07..1619569c9d 100644 --- a/code/game/jobs/job/silicon.dm +++ b/code/game/jobs/job/silicon.dm @@ -18,6 +18,7 @@ economic_modifier = 0 has_headset = FALSE assignable = FALSE + mob_type = JOB_SILICON_AI outfit_type = /decl/hierarchy/outfit/job/silicon/ai job_description = "The AI oversees the operation of the station and its crew, but has no real authority over them. \ The AI is required to follow its Laws, and Lawbound Synthetics that are linked to it are expected to follow \ @@ -54,6 +55,7 @@ economic_modifier = 0 has_headset = FALSE assignable = FALSE + mob_type = JOB_SILICON_ROBOT outfit_type = /decl/hierarchy/outfit/job/silicon/cyborg job_description = "A Cyborg is a mobile station synthetic, piloted by a cybernetically preserved brain. It is considered a person, but is still required \ to follow its Laws." diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 34e75f4320..2470fdc114 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -60,8 +60,12 @@ var/global/datum/controller/occupations/job_master return 0 if(!job.player_old_enough(player.client)) return 0 - if(!is_job_whitelisted(player, rank)) //VOREStation Code + //VOREStation Add + if(!job.player_has_enough_playtime(player.client)) return 0 + if(!is_job_whitelisted(player, rank)) + return 0 + //VOREStation Add End var/position_limit = job.total_positions if(!latejoin) @@ -97,6 +101,9 @@ var/global/datum/controller/occupations/job_master Debug("FOC character not old enough, Player: [player]") continue //VOREStation Code Start + if(!job.player_has_enough_playtime(player.client)) + Debug("FOC character not enough playtime, Player: [player]") + continue if(!is_job_whitelisted(player, job.title)) Debug("FOC is_job_whitelisted failed, Player: [player]") continue @@ -133,6 +140,9 @@ var/global/datum/controller/occupations/job_master continue //VOREStation Code Start + if(!job.player_has_enough_playtime(player.client)) + Debug("GRJ player not enough playtime, Player: [player]") + continue if(!is_job_whitelisted(player, job.title)) Debug("GRJ player not whitelisted for this job, Player: [player], Job: [job.title]") continue @@ -283,6 +293,12 @@ var/global/datum/controller/occupations/job_master Debug("DO player not old enough, Player: [player], Job:[job.title]") continue + //VOREStation Add + if(!job.player_has_enough_playtime(player.client)) + Debug("DO player not enough playtime, Player: [player]") + continue + //VOREStation Add End + // If the player wants that job on this level, then try give it to him. if(player.client.prefs.GetJobDepartment(job, level) & job.flag) @@ -373,54 +389,64 @@ var/global/datum/controller/occupations/job_master //Equip custom gear loadout. var/list/custom_equip_slots = list() //If more than one item takes the same slot, all after the first one spawn in storage. var/list/custom_equip_leftovers = list() - if(H.client.prefs.gear && H.client.prefs.gear.len && job.title != "Cyborg" && job.title != "AI") + if(H.client.prefs.gear && H.client.prefs.gear.len && !(job.mob_type & JOB_SILICON)) for(var/thing in H.client.prefs.gear) var/datum/gear/G = gear_datums[thing] - if(G) - var/permitted - if(G.allowed_roles) - for(var/job_name in G.allowed_roles) - if(job.title == job_name) - permitted = 1 + if(!G) //Not a real gear datum (maybe removed, as this is loaded from their savefile) + continue + + var/permitted + // Check if it is restricted to certain roles + if(G.allowed_roles) + for(var/job_name in G.allowed_roles) + if(job.title == job_name) + permitted = 1 + else + permitted = 1 + + // Check if they're whitelisted for this gear (in alien whitelist? seriously?) + if(G.whitelisted && !is_alien_whitelisted(H, GLOB.all_species[G.whitelisted])) + permitted = 0 + + // If they aren't, tell them + if(!permitted) + to_chat(H, "Your current species, job or whitelist status does not permit you to spawn with [thing]!") + continue + + // Implants get special treatment + if(G.slot == "implant") + var/obj/item/weapon/implant/I = G.spawn_item(H) + I.invisibility = 100 + I.implant_loadout(H) + continue + + // Try desperately (and sorta poorly) to equip the item + if(G.slot && !(G.slot in custom_equip_slots)) + var/metadata = H.client.prefs.gear[G.display_name] + if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head) + custom_equip_leftovers += thing + else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot)) + to_chat(H, "Equipping you with \the [thing]!") + custom_equip_slots.Add(G.slot) else - permitted = 1 + custom_equip_leftovers.Add(thing) + else + spawn_in_storage += thing - if(G.whitelisted && !is_alien_whitelisted(H, GLOB.all_species[G.whitelisted])) - - //if(G.whitelisted && (G.whitelisted != H.species.name || !is_alien_whitelisted(H, G.whitelisted))) - permitted = 0 - - if(!permitted) - to_chat(H, "Your current species, job or whitelist status does not permit you to spawn with [thing]!") - continue - - if(G.slot == "implant") - var/obj/item/weapon/implant/I = G.spawn_item(H) - I.invisibility = 100 - I.implant_loadout(H) - continue - - if(G.slot && !(G.slot in custom_equip_slots)) - // This is a miserable way to fix the loadout overwrite bug, but the alternative requires - // adding an arg to a bunch of different procs. Will look into it after this merge. ~ Z - var/metadata = H.client.prefs.gear[G.display_name] - if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head) - custom_equip_leftovers += thing - else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot)) - to_chat(H, "Equipping you with \the [thing]!") - custom_equip_slots.Add(G.slot) - else - custom_equip_leftovers.Add(thing) - else - spawn_in_storage += thing - //Equip job items. + // Set up their account job.setup_account(H) + + // Equip job items. job.equip(H, H.mind ? H.mind.role_alt_title : "") + + // Stick their fingerprints on literally everything job.apply_fingerprints(H) - if(job.title != "Cyborg" && job.title != "AI") + + // Only non-silicons get post-job-equip equipment + if(!(job.mob_type & JOB_SILICON)) H.equip_post_job() - //If some custom items could not be equipped before, try again now. + // If some custom items could not be equipped before, try again now. for(var/thing in custom_equip_leftovers) var/datum/gear/G = gear_datums[thing] if(G.slot in custom_equip_slots) @@ -456,14 +482,16 @@ var/global/datum/controller/occupations/job_master H.mind.assigned_role = rank alt_title = H.mind.role_alt_title - switch(rank) - if("Cyborg") - return H.Robotize() - if("AI") - return H - if("Colony Director") - var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20) - captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z) + // If we're a silicon, we may be done at this point + if(job.mob_type & JOB_SILICON_ROBOT) + return H.Robotize() + if(job.mob_type & JOB_SILICON_AI) + return H + + // TWEET PEEP + if(rank == "Colony Director") + var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20) + captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z) //Deferred item spawning. if(spawn_in_storage && spawn_in_storage.len) @@ -573,7 +601,7 @@ var/global/datum/controller/occupations/job_master if(!J) continue J.total_positions = text2num(value) J.spawn_positions = text2num(value) - if(name == "AI" || name == "Cyborg")//I dont like this here but it will do for now + if(J.mob_type & JOB_SILICON) J.total_positions = 0 return 1 @@ -598,6 +626,11 @@ var/global/datum/controller/occupations/job_master if(!job.player_old_enough(player.client)) level6++ continue + //VOREStation Add + if(!job.player_has_enough_playtime(player.client)) + level6++ + continue + //VOREStation Add End if(player.client.prefs.GetJobDepartment(job, 1) & job.flag) level1++ else if(player.client.prefs.GetJobDepartment(job, 2) & job.flag) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 70fd190afe..c19873fd3d 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -180,21 +180,10 @@ idle_power_usage = 15 active_power_usage = 200 //builtin health analyzer, dialysis machine, injectors. -/obj/machinery/sleeper/New() - ..() +/obj/machinery/sleeper/Initialize() + . = ..() beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src) - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) - component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) - component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) - component_parts += new /obj/item/weapon/reagent_containers/syringe(src) - component_parts += new /obj/item/weapon/reagent_containers/syringe(src) - component_parts += new /obj/item/weapon/reagent_containers/syringe(src) - component_parts += new /obj/item/stack/material/glass/reinforced(src, 2) - - RefreshParts() + default_apply_parts() /obj/machinery/sleeper/Destroy() if(console) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index f5034bcf71..482988caf2 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -15,14 +15,9 @@ light_color = "#00FF00" var/obj/machinery/body_scanconsole/console -/obj/machinery/bodyscanner/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/stack/material/glass/reinforced(src, 2) - RefreshParts() +/obj/machinery/bodyscanner/Initialize() + . = ..() + default_apply_parts() /obj/machinery/bodyscanner/Destroy() if(console) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index facb9e4402..bb1629c109 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -29,15 +29,10 @@ var/filtertext -/obj/machinery/autolathe/New() - ..() +/obj/machinery/autolathe/Initialize() + . = ..() wires = new(src) - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) + default_apply_parts() RefreshParts() /obj/machinery/autolathe/Destroy() diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index 6f62b2e056..220d9fd013 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -15,17 +15,14 @@ var/build_eff = 1 var/eat_eff = 1 -/obj/machinery/biogenerator/New() - ..() +/obj/machinery/biogenerator/Initialize() + . = ..() var/datum/reagents/R = new/datum/reagents(1000) reagents = R R.my_atom = src beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src) - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - RefreshParts() + default_apply_parts() /obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well. update_icon() diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm index d40a89c202..b5a25b24a0 100644 --- a/code/game/machinery/bioprinter.dm +++ b/code/game/machinery/bioprinter.dm @@ -77,14 +77,10 @@ add_overlay("bioprinter_working") //VOREStation Edit End -/obj/machinery/organ_printer/New() - ..() - - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - RefreshParts() - +/obj/machinery/organ_printer/Initialize() + . = ..() + default_apply_parts() + /obj/machinery/organ_printer/examine(var/mob/user) . = ..() var/biomass = get_biomass_volume() @@ -274,7 +270,7 @@ icon_state = "bioprinter" circuit = /obj/item/weapon/circuitboard/bioprinter -/obj/machinery/organ_printer/flesh/full/New() +/obj/machinery/organ_printer/flesh/full/Initialize() . = ..() container = new /obj/item/weapon/reagent_containers/glass/bottle/biomass(src) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 15f9d65bc3..3dbe68fd29 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -29,6 +29,7 @@ var/short_range = 2 var/light_disabled = 0 + var/in_use_lights = 0 // TO BE IMPLEMENTED - LIES. var/alarm_on = 0 var/busy = 0 diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 917fed33eb..2b768fb3e6 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -13,13 +13,9 @@ var/chargelevel = -1 circuit = /obj/item/weapon/circuitboard/cell_charger -/obj/machinery/cell_charger/New() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/stack/cable_coil(src, 5) - RefreshParts() - ..() - return +/obj/machinery/cell_charger/Initialize() + . = ..() + default_apply_parts() /obj/machinery/cell_charger/update_icon() icon_state = "ccharger[charging ? 1 : 0]" diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index ebd740e5e5..e5fec765ca 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -46,17 +46,9 @@ var/list/containers = list() // Beakers for our liquid biomass var/container_limit = 3 // How many beakers can the machine hold? -/obj/machinery/clonepod/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - component_parts += new /obj/item/stack/cable_coil(src, 2) - - RefreshParts() +/obj/machinery/clonepod/Initialize() + . = ..() + default_apply_parts() update_icon() /obj/machinery/clonepod/attack_ai(mob/user as mob) diff --git a/code/game/machinery/computer/shutoff_monitor.dm b/code/game/machinery/computer/shutoff_monitor.dm index e2413c5e21..89cd4127db 100644 --- a/code/game/machinery/computer/shutoff_monitor.dm +++ b/code/game/machinery/computer/shutoff_monitor.dm @@ -2,7 +2,7 @@ name = "automated shutoff valve monitor" desc = "Console used to remotely monitor shutoff valves on the station." icon_keyboard = "power_key" - icon_screen = "power:0" + icon_screen = "power_monitor" light_color = "#a97faa" circuit = /obj/item/weapon/circuitboard/shutoff_monitor var/datum/nano_module/shutoff_monitor/monitor diff --git a/code/game/machinery/computer/timeclock_vr.dm b/code/game/machinery/computer/timeclock_vr.dm index 42e78683ec..85924d79f6 100644 --- a/code/game/machinery/computer/timeclock_vr.dm +++ b/code/game/machinery/computer/timeclock_vr.dm @@ -154,6 +154,7 @@ && !job.whitelist_only \ && !jobban_isbanned(user,job.title) \ && job.player_old_enough(user.client) \ + && job.player_has_enough_playtime(user.client) \ && job.pto_type == department \ && !job.disallow_jobhop \ && job.timeoff_factor > 0 diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 41e3297c2b..4393417e26 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -64,7 +64,7 @@ if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon))) return if (href_list["close"]) - usr << browse(null, "window=airlock") + usr << browse(null, "window=airlock_electronics") return if (href_list["login"]) diff --git a/code/game/machinery/exonet_node.dm b/code/game/machinery/exonet_node.dm index 1813d2dc71..b9b95e103c 100644 --- a/code/game/machinery/exonet_node.dm +++ b/code/game/machinery/exonet_node.dm @@ -21,21 +21,9 @@ // Proc: New() // Parameters: None // Description: Adds components to the machine for deconstruction. -/obj/machinery/exonet_node/map/New() - ..() - - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/subspace/ansible(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/crystal(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src) - component_parts += new /obj/item/stack/cable_coil(src, 2) - RefreshParts() - +/obj/machinery/exonet_node/map/Initialize() + . = ..() + default_apply_parts() desc = "This machine is one of many, many nodes inside [using_map.starsys_name]'s section of the Exonet, connecting the [using_map.station_short] to the rest of the system, at least \ electronically." @@ -187,7 +175,7 @@ // Description: This writes to the logs list, so that people can see what people are doing on the Exonet ingame. Note that this is not an admin logging function. // Communicators are already logged seperately. /obj/machinery/exonet_node/proc/write_log(var/origin_address, var/target_address, var/data_type, var/content) - //var/timestamp = time2text(station_time_in_ticks, "hh:mm:ss") + //var/timestamp = time2text(station_time_in_ds, "hh:mm:ss") var/timestamp = "[stationdate2text()] [stationtime2text()]" var/msg = "[timestamp] | FROM [origin_address] TO [target_address] | TYPE: [data_type] | CONTENT: [content]" logs.Add(msg) diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm index a0ef0503fd..42f7b681b7 100644 --- a/code/game/machinery/jukebox.dm +++ b/code/game/machinery/jukebox.dm @@ -54,8 +54,8 @@ new/datum/track("Russkiy rep Diskoteka", 'sound/music/russianrapdisco.ogg') ) -/obj/machinery/media/jukebox/New() - ..() +/obj/machinery/media/jukebox/Initialize() + . = ..() default_apply_parts() wires = new/datum/wires/jukebox(src) update_icon() @@ -63,7 +63,7 @@ /obj/machinery/media/jukebox/Destroy() qdel(wires) wires = null - ..() + return ..() // On initialization, copy our tracks from the global list /obj/machinery/media/jukebox/Initialize() diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 3871908ff2..b126376ecc 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -121,13 +121,17 @@ Class Procs: if(ispath(circuit)) circuit = new circuit(src) -/obj/machinery/Initialize() +/obj/machinery/Initialize(var/mapload) . = ..() global.machines += src + if(ispath(circuit)) + circuit = new circuit(src) if(!speed_process) START_MACHINE_PROCESSING(src) else START_PROCESSING(SSfastprocess, src) + if(!mapload) + power_change() /obj/machinery/Destroy() if(!speed_process) @@ -452,6 +456,7 @@ Class Procs: return 1 /datum/proc/apply_visual(mob/M) + M.sight = 0 //Just reset their mesons and stuff so they can't use them, by default. return /datum/proc/remove_visual(mob/M) diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index 7c184c27de..25805c694e 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -17,16 +17,8 @@ var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess. /obj/machinery/mass_driver/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/weapon/stock_parts/gear(src) - component_parts += new /obj/item/weapon/stock_parts/gear(src) - component_parts += new /obj/item/weapon/stock_parts/spring(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/stack/cable_coil(src, 5) - RefreshParts() + . = ..() + default_apply_parts() /obj/machinery/mass_driver/attackby(var/obj/item/I, mob/user) if(default_deconstruction_screwdriver(user, I)) diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 883a963fa2..9fd9f74999 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -79,7 +79,7 @@ newMsg.body = msg newMsg.time_stamp = "[stationtime2text()]" newMsg.is_admin_message = adminMessage - newMsg.post_time = round_duration_in_ticks // Should be almost universally unique + newMsg.post_time = round_duration_in_ds // Should be almost universally unique if(message_type) newMsg.message_type = message_type if(photo) diff --git a/code/game/machinery/pda_multicaster.dm b/code/game/machinery/pda_multicaster.dm index 29de5307cf..29416e828e 100644 --- a/code/game/machinery/pda_multicaster.dm +++ b/code/game/machinery/pda_multicaster.dm @@ -23,17 +23,9 @@ "cargo" = new /obj/item/device/pda/multicaster/cargo(src), "civilian" = new /obj/item/device/pda/multicaster/civilian(src)) -/obj/machinery/pda_multicaster/prebuilt/New() - ..() - - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/telecomms/pda_multicaster(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/ansible(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src) - component_parts += new /obj/item/stack/cable_coil(src, 2) - RefreshParts() +/obj/machinery/pda_multicaster/prebuilt/Initialize() + . = ..() + default_apply_parts() /obj/machinery/pda_multicaster/Destroy() for(var/atom/movable/AM in contents) diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 06acd97d0b..2b8b8aa637 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -17,13 +17,9 @@ var/portable = 1 circuit = /obj/item/weapon/circuitboard/recharger -/obj/machinery/recharger/New() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/stack/cable_coil(src, 5) - RefreshParts() - ..() - return +/obj/machinery/recharger/Initialize() + . = ..() + default_apply_parts() /obj/machinery/recharger/examine(mob/user) . = ..() diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 75cc5b55cc..c683a56c0e 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -22,17 +22,9 @@ var/weld_power_use = 2300 // power used per point of brute damage repaired. 2.3 kW ~ about the same power usage of a handheld arc welder var/wire_power_use = 500 // power used per point of burn damage repaired. -/obj/machinery/recharge_station/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/cell/high(src) - component_parts += new /obj/item/stack/cable_coil(src, 5) - RefreshParts() - +/obj/machinery/recharge_station/Initialize() + . = ..() + default_apply_parts() update_icon() /obj/machinery/recharge_station/proc/has_cell_power() diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 165df28298..46acbb4fdc 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -32,13 +32,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept /obj/machinery/telecomms/processor/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/crystal(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser/high(src) - component_parts += new /obj/item/stack/cable_coil(src, 1) + default_apply_parts() /obj/machinery/telecomms/broadcaster/proc/link_radio(var/obj/item/device/radio/R) if(!istype(R)) diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 1d765375be..e89b9aa726 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -266,13 +266,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/receiver/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/subspace/ansible(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - RefreshParts() + default_apply_parts() /obj/machinery/telecomms/receiver/proc/link_radio(var/obj/item/device/radio/R) if(!istype(R)) @@ -355,13 +349,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/hub/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/stack/cable_coil(src, 2) - RefreshParts() + default_apply_parts() /obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) if(is_freq_listening(signal)) @@ -401,13 +389,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/relay/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/stack/cable_coil(src, 2) - RefreshParts() + default_apply_parts() /obj/machinery/telecomms/relay/forceMove(var/newloc) . = ..(newloc) @@ -464,12 +446,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/bus/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/stack/cable_coil(src, 1) - RefreshParts() + default_apply_parts() /obj/machinery/telecomms/bus/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) @@ -525,17 +502,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/processor/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/amplifier(src) - component_parts += new /obj/item/weapon/stock_parts/subspace/analyzer(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/stack/cable_coil(src, 2) - RefreshParts() + default_apply_parts() /obj/machinery/telecomms/processor/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) @@ -596,12 +563,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() /obj/machinery/telecomms/server/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/subspace/sub_filter(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/stack/cable_coil(src, 1) - RefreshParts() + default_apply_parts() /obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index c27de5c31c..1cf1e901fb 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -1,3 +1,6 @@ +////// +////// Teleporter computer +////// /obj/machinery/computer/teleporter name = "teleporter control console" desc = "Used to control a linked teleportation Hub and Station." @@ -5,23 +8,23 @@ icon_screen = "teleport" circuit = /obj/item/weapon/circuitboard/teleporter dir = 4 - var/obj/item/locked = null var/id = null var/one_time_use = 0 //Used for one-time-use teleport cards (such as clown planet coordinates.) //Setting this to 1 will set locked to null after a player enters the portal and will not allow hand-teles to open portals to that location. + var/datum/nano_module/program/teleport_control/teleport_control /obj/machinery/computer/teleporter/New() id = "[rand(1000, 9999)]" ..() underlays.Cut() underlays += image('icons/obj/stationobjs_vr.dmi', icon_state = "telecomp-wires") //VOREStation Edit: different direction for wires to account for dirs - return + teleport_control = new(src) /obj/machinery/computer/teleporter/Initialize() . = ..() - var/obj/machinery/teleport/station/station - var/obj/machinery/teleport/hub/hub - + var/obj/machinery/teleport/station/station = null + var/obj/machinery/teleport/hub/hub = null + // Search surrounding turfs for the station, and then search the station's surrounding turfs for the hub. for(var/direction in cardinal) station = locate(/obj/machinery/teleport/station, get_step(src, direction)) @@ -34,9 +37,15 @@ if(istype(station)) station.com = hub + teleport_control.hub = hub if(istype(hub)) hub.com = src + teleport_control.station = station + +/obj/machinery/computer/teleporter/Destroy() + qdel_null(teleport_control) + return ..() /obj/machinery/computer/teleporter/attackby(I as obj, mob/living/user as mob) if(istype(I, /obj/item/weapon/card/data/)) @@ -74,7 +83,7 @@ else for(var/mob/O in hearers(src, null)) O.show_message("Locked In", 2) - locked = L + teleport_control.locked = L one_time_use = 1 add_fingerprint(usr) @@ -86,57 +95,109 @@ /obj/machinery/teleport/station/attack_ai() attack_hand() -/obj/machinery/computer/teleporter/attack_hand(user as mob) - if(..()) return +/obj/machinery/computer/teleporter/attack_ai(mob/user) + ui_interact(user) - /* Ghosts can't use this one because it's a direct selection */ - if(istype(user, /mob/observer/dead)) return +/obj/machinery/computer/teleporter/attack_hand(mob/user) + add_fingerprint(user) + if(stat & (BROKEN|NOPOWER)) + return + ui_interact(user) - var/list/L = list() - var/list/areaindex = list() +/obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + teleport_control.ui_interact(user, ui_key, ui, force_open) - for(var/obj/item/device/radio/beacon/R in all_beacons) - var/turf/T = get_turf(R) - if(!T) - continue - if(!(T.z in using_map.player_levels)) - continue - var/tmpname = T.loc.name - if(areaindex[tmpname]) - tmpname = "[tmpname] ([++areaindex[tmpname]])" - else - areaindex[tmpname] = 1 - L[tmpname] = R +/obj/machinery/computer/teleporter/interact(mob/user) + teleport_control.ui_interact(user) - for (var/obj/item/weapon/implant/tracking/I in all_tracking_implants) - if(!I.implanted || !ismob(I.loc)) - continue - else - var/mob/M = I.loc - if(M.stat == 2) - if(M.timeofdeath + 6000 < world.time) - continue - var/turf/T = get_turf(M) - if(T) continue - if(T.z == 2) continue - var/tmpname = M.real_name +////// +////// Nano-module for teleporter +////// +/datum/nano_module/program/teleport_control + name = "Teleporter Control" + var/locked_name = "Not Locked" + var/obj/item/locked = null + var/obj/machinery/teleport/station/station = null + var/obj/machinery/teleport/hub/hub = null + +/datum/nano_module/program/teleport_control/Topic(href, href_list) + if(..()) return 1 + + if(href_list["select_target"]) + var/list/L = list() + var/list/areaindex = list() + + for(var/obj/item/device/radio/beacon/R in all_beacons) + var/turf/T = get_turf(R) + if(!T) + continue + if(!(T.z in using_map.player_levels)) + continue + var/tmpname = T.loc.name if(areaindex[tmpname]) tmpname = "[tmpname] ([++areaindex[tmpname]])" else areaindex[tmpname] = 1 - L[tmpname] = I + L[tmpname] = R - var/desc = input("Please select a location to lock in.", "Locking Computer") in L|null - if(!desc) - return - if(get_dist(src, usr) > 1 && !issilicon(usr)) - return + for (var/obj/item/weapon/implant/tracking/I in all_tracking_implants) + if(!I.implanted || !ismob(I.loc)) + continue + else + var/mob/M = I.loc + if(M.stat == 2) + if(M.timeofdeath + 6000 < world.time) + continue + var/turf/T = get_turf(M) + if(T) continue + if(T.z == 2) continue + var/tmpname = M.real_name + if(areaindex[tmpname]) + tmpname = "[tmpname] ([++areaindex[tmpname]])" + else + areaindex[tmpname] = 1 + L[tmpname] = I - locked = L[desc] - for(var/mob/O in hearers(src, null)) - O.show_message("Locked In", 2) - add_fingerprint(usr) - return + var/desc = input("Please select a location to lock in.", "Locking Menu") in L|null + if(!desc) + return 0 + if(get_dist(host, usr) > 1 && !issilicon(usr)) + return 0 + + locked = L[desc] + locked_name = desc + return 1 + + if(href_list["test_fire"]) + station?.testfire() + return 1 + + if(href_list["toggle_on"]) + if(!station) + return 0 + + if(station.engaged) + station.disengage() + else + station.engage() + + return 1 + +/datum/nano_module/program/teleport_control/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["locked_name"] = locked_name ? locked_name : "No Target" + data["station_connected"] = station ? 1 : 0 + data["hub_connected"] = hub ? 1 : 0 + data["calibrated"] = hub ? hub.accurate : 0 + data["teleporter_on"] = station ? station.engaged : 0 + + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) + if(!ui) + ui = new(user, src, ui_key, "teleport_control.tmpl", "Teleport Control Console", 400, 500, state = state) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) /obj/machinery/computer/teleporter/verb/set_id(t as text) set category = "Object" @@ -158,6 +219,9 @@ if(!T || istype(T, /area)) return null return T +////// +////// Root of all the machinery +////// /obj/machinery/teleport name = "teleport" icon = 'icons/obj/stationobjs.dmi' @@ -165,6 +229,9 @@ anchored = 1.0 var/lockeddown = 0 +////// +////// The part you step into +////// /obj/machinery/teleport/hub name = "teleporter hub" desc = "It's the hub of a teleporting machine." @@ -178,22 +245,15 @@ circuit = /obj/item/weapon/circuitboard/teleporter_hub var/obj/machinery/computer/teleporter/com -/obj/machinery/teleport/hub/New() - ..() - underlays.Cut() +/obj/machinery/teleport/hub/Initialize() + . = ..() underlays += image('icons/obj/stationobjs.dmi', icon_state = "tele-wires") + default_apply_parts() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/stack/cable_coil(src, 10) - RefreshParts() +/obj/machinery/teleport/hub/Destroy() + com?.teleport_control.hub = null + com = null + return ..() /obj/machinery/teleport/hub/Bumped(M as mob|obj) spawn() @@ -205,7 +265,7 @@ /obj/machinery/teleport/hub/proc/teleport(atom/movable/M as mob|obj) if(!com) return - if(!com.locked) + if(!com.teleport_control.locked) for(var/mob/O in hearers(src, null)) O.show_message("Failure: Cannot authenticate locked on coordinates. Please reinstate coordinate matrix.") return @@ -221,11 +281,11 @@ if(prob(5) && !accurate) //oh dear a problem, put em in deep space do_teleport(M, locate(rand((2*TRANSITIONEDGE), world.maxx - (2*TRANSITIONEDGE)), rand((2*TRANSITIONEDGE), world.maxy - (2*TRANSITIONEDGE)), 3), 2) else - do_teleport(M, com.locked) //dead-on precision + do_teleport(M, com.teleport_control.locked) //dead-on precision if(com.one_time_use) //Make one-time-use cards only usable one time! com.one_time_use = 0 - com.locked = null + com.teleport_control.locked = null else var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, src) @@ -235,92 +295,10 @@ for(var/mob/B in hearers(src, null)) B.show_message("Test fire completed.") return -/* -/proc/do_teleport(atom/movable/M as mob|obj, atom/destination, precision) - if(istype(M, /obj/effect)) - qdel(M) - return - if(istype(M, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks get teleported --NeoFite - for(var/mob/O in viewers(M, null)) - O.show_message(text("The [] bounces off of the portal!", M.name), 1) - return - if(istype(M, /mob/living)) - var/mob/living/MM = M - if(MM.check_contents_for(/obj/item/weapon/disk/nuclear)) - to_chat(MM, "Something you are carrying seems to be unable to pass through the portal. Better drop it if you want to go through.") - return - var/disky = 0 - for (var/atom/O in M.contents) //I'm pretty sure this accounts for the maximum amount of container in container stacking. --NeoFite - if(istype(O, /obj/item/weapon/storage) || istype(O, /obj/item/weapon/gift)) - for (var/obj/OO in O.contents) - if(istype(OO, /obj/item/weapon/storage) || istype(OO, /obj/item/weapon/gift)) - for (var/obj/OOO in OO.contents) - if(istype(OOO, /obj/item/weapon/disk/nuclear)) - disky = 1 - if(istype(OO, /obj/item/weapon/disk/nuclear)) - disky = 1 - if(istype(O, /obj/item/weapon/disk/nuclear)) - disky = 1 - if(istype(O, /mob/living)) - var/mob/living/MM = O - if(MM.check_contents_for(/obj/item/weapon/disk/nuclear)) - disky = 1 - if(disky) - for(var/mob/P in viewers(M, null)) - P.show_message(text("The [] bounces off of the portal!", M.name), 1) - return - -//Bags of Holding cause bluespace teleportation to go funky. --NeoFite - if(istype(M, /mob/living)) - var/mob/living/MM = M - if(MM.check_contents_for(/obj/item/weapon/storage/backpack/holding)) - to_chat(MM, "The Bluespace interface on your Bag of Holding interferes with the teleport!") - precision = rand(1,100) - if(istype(M, /obj/item/weapon/storage/backpack/holding)) - precision = rand(1,100) - for (var/atom/O in M.contents) //I'm pretty sure this accounts for the maximum amount of container in container stacking. --NeoFite - if(istype(O, /obj/item/weapon/storage) || istype(O, /obj/item/weapon/gift)) - for (var/obj/OO in O.contents) - if(istype(OO, /obj/item/weapon/storage) || istype(OO, /obj/item/weapon/gift)) - for (var/obj/OOO in OO.contents) - if(istype(OOO, /obj/item/weapon/storage/backpack/holding)) - precision = rand(1,100) - if(istype(OO, /obj/item/weapon/storage/backpack/holding)) - precision = rand(1,100) - if(istype(O, /obj/item/weapon/storage/backpack/holding)) - precision = rand(1,100) - if(istype(O, /mob/living)) - var/mob/living/MM = O - if(MM.check_contents_for(/obj/item/weapon/storage/backpack/holding)) - precision = rand(1,100) - - var/turf/destturf = get_turf(destination) - - var/tx = destturf.x + rand(precision * -1, precision) - var/ty = destturf.y + rand(precision * -1, precision) - - var/tmploc - - if(ismob(destination.loc)) //If this is an implant. - tmploc = locate(tx, ty, destturf.z) - else - tmploc = locate(tx, ty, destination.z) - - if(tx == destturf.x && ty == destturf.y && (istype(destination.loc, /obj/structure/closet) || istype(destination.loc, /obj/structure/closet/secure_closet))) - tmploc = destination.loc - - if(tmploc==null) - return - - M.loc = tmploc - sleep(2) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, M) - s.start() - return -*/ +////// +////// The middle part +////// /obj/machinery/teleport/station name = "station" desc = "It's the station thingy of a teleport thingy." //seriously, wtf. @@ -335,29 +313,15 @@ circuit = /obj/item/weapon/circuitboard/teleporter_station var/obj/machinery/teleport/hub/com -/obj/machinery/teleport/station/New() - ..() - overlays.Cut() - overlays += image('icons/obj/stationobjs.dmi', icon_state = "controller-wires") +/obj/machinery/teleport/station/Initialize() + . = ..() + add_overlay("controller-wires") + default_apply_parts() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/stack/cable_coil(src, 10) - RefreshParts() - -/obj/machinery/teleport/station/attackby(var/obj/item/weapon/W) - attack_hand() - -/obj/machinery/teleport/station/attack_ai() - attack_hand() - -/obj/machinery/teleport/station/attack_hand() - if(engaged) - disengage() - else - engage() +/obj/machinery/teleport/station/Destroy() + com?.com?.teleport_control.station = null + com = null + return ..() /obj/machinery/teleport/station/proc/engage() if(stat & (BROKEN|NOPOWER)) @@ -389,27 +353,17 @@ engaged = 0 return -/obj/machinery/teleport/station/verb/testfire() - set name = "Test Fire Teleporter" - set category = "Object" - set src in oview(1) - - if(stat & (BROKEN|NOPOWER) || !istype(usr,/mob/living)) +/obj/machinery/teleport/station/proc/testfire() + if(!com || active) return - if(com && !active) - active = 1 - for(var/mob/O in hearers(src, null)) - O.show_message("Test firing!", 2) - com.teleport() - use_power(5000) - flick(src, "controller-c") //VOREStation Add + active = TRUE + visible_message("Test firing!") + com.teleport() + use_power(5000) + flick(src, "controller-c") //VOREStation Add - spawn(30) - active=0 - - add_fingerprint(usr) - return + VARSET_IN(src, active, FALSE, 3 SECONDS) /obj/machinery/teleport/station/power_change() ..() diff --git a/code/game/machinery/virtual_reality/vr_console.dm b/code/game/machinery/virtual_reality/vr_console.dm index 8a417a98bc..75236c3cd2 100644 --- a/code/game/machinery/virtual_reality/vr_console.dm +++ b/code/game/machinery/virtual_reality/vr_console.dm @@ -23,13 +23,9 @@ active_power_usage = 200 light_color = "#FF0000" -/obj/machinery/vr_sleeper/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/stack/material/glass/reinforced(src, 2) - - RefreshParts() +/obj/machinery/vr_sleeper/Initialize() + . = ..() + default_apply_parts() /obj/machinery/vr_sleeper/Initialize() . = ..() diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 2a6b90cdc6..edb8e56155 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -29,14 +29,10 @@ /obj/item/clothing/head/helmet/space ) -/obj/machinery/washing_machine/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/weapon/stock_parts/gear(src) - component_parts += new /obj/item/weapon/stock_parts/gear(src) - RefreshParts() - +/obj/machinery/washing_machine/Initialize() + . = ..() + default_apply_parts() + /obj/machinery/washing_machine/verb/start() set name = "Start Washing" set category = "Object" diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index 5584590f92..c2288709e5 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -12,15 +12,9 @@ var/charge = 45 var/repair = 0 -/obj/machinery/mech_recharger/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - RefreshParts() +/obj/machinery/mech_recharger/Initialize() + . = ..() + default_apply_parts() /obj/machinery/mech_recharger/Crossed(var/obj/mecha/M) . = ..() diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index a881cdb720..734c5bfa4c 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -26,22 +26,11 @@ var/category = null var/sync_message = "" -/obj/machinery/mecha_part_fabricator/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - RefreshParts() - - files = new /datum/research(src) //Setup the research data holder. - return - /obj/machinery/mecha_part_fabricator/Initialize() - update_categories() . = ..() + default_apply_parts() + files = new /datum/research(src) //Setup the research data holder. + update_categories() /obj/machinery/mecha_part_fabricator/process() ..() diff --git a/code/game/mecha/mech_prosthetics.dm b/code/game/mecha/mech_prosthetics.dm index 5e93378a0c..bb2c5f87ce 100644 --- a/code/game/mecha/mech_prosthetics.dm +++ b/code/game/mecha/mech_prosthetics.dm @@ -29,18 +29,11 @@ var/species = "Human" var/sync_message = "" -/obj/machinery/pros_fabricator/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - RefreshParts() - +/obj/machinery/pros_fabricator/Initialize() + . = ..() + default_apply_parts() + files = new /datum/research(src) //Setup the research data holder. - return /obj/machinery/pros_fabricator/Initialize() . = ..() diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index ba863c8c31..a5516c4c33 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -95,9 +95,9 @@ var/list/cargo = list() var/cargo_capacity = 3 - var/static/image/radial_image_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject"), - var/static/image/radial_image_airtoggle = image(icon= 'icons/mob/radial.dmi', icon_state = "radial_airtank"), - var/static/image/radial_image_lighttoggle = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_light"), + var/static/image/radial_image_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject") + var/static/image/radial_image_airtoggle = image(icon= 'icons/mob/radial.dmi', icon_state = "radial_airtank") + var/static/image/radial_image_lighttoggle = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_light") var/static/image/radial_image_statpanel = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine2") diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index fb82e6515a..f2a15be551 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -49,6 +49,9 @@ if(triggered) return + if(istype(M, /obj/mecha)) + explode(M) + if(istype(M, /mob/living/)) if(!M.hovering) explode(M) @@ -79,7 +82,7 @@ triggered = 1 s.set_up(3, 1, src) s.start() - if(M) + if(istype(M)) M.radiation += 50 randmutb(M) domutcheck(M,null) @@ -96,7 +99,7 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() s.set_up(3, 1, src) s.start() - if(M) + if(istype(M)) M.Stun(30) visible_message("\The [src.name] flashes violently before disintegrating!") spawn(0) @@ -136,7 +139,10 @@ triggered = 1 s.set_up(3, 1, src) s.start() - if(M) + if(istype(M, /obj/mecha)) + var/obj/mecha/E = M + M = E.occupant + if(istype(M)) qdel(M.client) spawn(0) qdel(s) @@ -195,7 +201,7 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() s.set_up(3, 1, src) s.start() - if(M) + if(istype(M)) M.adjust_fire_stacks(5) M.fire_act() visible_message("\The [src.name] bursts into flames!") diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 795355a6e3..deddf50ca5 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -7,7 +7,7 @@ layer = ABOVE_TURF_LAYER anchored = 1 w_class = ITEMSIZE_LARGE - canhear_range = 2 + canhear_range = 7 //VOREStation Edit flags = NOBLOODY var/circuit = /obj/item/weapon/circuitboard/intercom var/number = 0 @@ -195,7 +195,19 @@ icon_state = "intercom_open" else icon_state = initial(icon_state) +//VOREStation Add Start +/obj/item/device/radio/intercom/AICtrlClick(var/mob/user) + ToggleBroadcast() + to_chat(user, "\The [src]'s microphone is now [broadcasting ? "enabled" : "disabled"].") +/obj/item/device/radio/intercom/AIAltClick(var/mob/user) + if(frequency == AI_FREQ) + set_frequency(initial(frequency)) + to_chat(user, "\The [src]'s frequency is now set to Default.") + else + set_frequency(AI_FREQ) + to_chat(user, "\The [src]'s frequency is now set to AI Private.") +//VOREStation Add End /obj/item/device/radio/intercom/locked var/locked_frequency diff --git a/code/game/objects/items/weapons/RCD_vr.dm b/code/game/objects/items/weapons/RCD_vr.dm index 5cfc822efa..f4089e9b9c 100644 --- a/code/game/objects/items/weapons/RCD_vr.dm +++ b/code/game/objects/items/weapons/RCD_vr.dm @@ -9,9 +9,9 @@ var/ammostate var/list/effects = list() - var/static/image/radial_image_airlock = image(icon = 'icons/mob/radial.dmi', icon_state = "airlock"), - var/static/image/radial_image_decon = image(icon= 'icons/mob/radial.dmi', icon_state = "delete"), - var/static/image/radial_image_grillewind = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow"), + var/static/image/radial_image_airlock = image(icon = 'icons/mob/radial.dmi', icon_state = "airlock") + var/static/image/radial_image_decon = image(icon= 'icons/mob/radial.dmi', icon_state = "delete") + var/static/image/radial_image_grillewind = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow") var/static/image/radial_image_floorwall = image(icon = 'icons/mob/radial.dmi', icon_state = "wallfloor") // Ammo for the (non-electric) RCDs. diff --git a/code/game/objects/items/weapons/storage/internal.dm b/code/game/objects/items/weapons/storage/internal.dm index 498f6aa5d3..00d6f79402 100644 --- a/code/game/objects/items/weapons/storage/internal.dm +++ b/code/game/objects/items/weapons/storage/internal.dm @@ -1,90 +1,90 @@ -//A storage item intended to be used by other items to provide storage functionality. -//Types that use this should consider overriding emp_act() and hear_talk(), unless they shield their contents somehow. -/obj/item/weapon/storage/internal - preserve_item = 1 - var/obj/item/master_item - -/obj/item/weapon/storage/internal/New(obj/item/MI) - master_item = MI - loc = master_item - //name = master_item.name //VOREStation Removal - verbs -= /obj/item/verb/verb_pickup //make sure this is never picked up. - ..() - -/obj/item/weapon/storage/internal/Destroy() - master_item = null - . = ..() - -/obj/item/weapon/storage/internal/attack_hand() - return //make sure this is never picked up - -/obj/item/weapon/storage/internal/mob_can_equip() - return 0 //make sure this is never picked up - -//Helper procs to cleanly implement internal storages - storage items that provide inventory slots for other items. -//These procs are completely optional, it is up to the master item to decide when it's storage get's opened by calling open() -//However they are helpful for allowing the master item to pretend it is a storage item itself. -//If you are using these you will probably want to override attackby() as well. -//See /obj/item/clothing/suit/storage for an example. - -//items that use internal storage have the option of calling this to emulate default storage MouseDrop behaviour. -//returns 1 if the master item's parent's MouseDrop() should be called, 0 otherwise. It's strange, but no other way of -//doing it without the ability to call another proc's parent, really. -/obj/item/weapon/storage/internal/proc/handle_mousedrop(mob/user as mob, obj/over_object as obj) - if (ishuman(user) || issmall(user)) //so monkeys can take off their backpacks -- Urist - - if (istype(user.loc,/obj/mecha)) // stops inventory actions in a mech - return 0 - - if(over_object == user && Adjacent(user)) // this must come before the screen objects only block - src.open(user) - return 0 - - if (!( istype(over_object, /obj/screen) )) - return 1 - - //makes sure master_item is equipped before putting it in hand, so that we can't drag it into our hand from miles away. - //there's got to be a better way of doing this... - if (!(master_item.loc == user) || (master_item.loc && master_item.loc.loc == user)) - return 0 - - if (!( user.restrained() ) && !( user.stat )) - switch(over_object.name) - if("r_hand") - user.unEquip(master_item) - user.put_in_r_hand(master_item) - if("l_hand") - user.unEquip(master_item) - user.put_in_l_hand(master_item) - master_item.add_fingerprint(user) - return 0 - return 0 - -//items that use internal storage have the option of calling this to emulate default storage attack_hand behaviour. -//returns 1 if the master item's parent's attack_hand() should be called, 0 otherwise. -//It's strange, but no other way of doing it without the ability to call another proc's parent, really. -/obj/item/weapon/storage/internal/proc/handle_attack_hand(mob/user as mob) - - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.l_store == master_item && !H.get_active_hand()) //Prevents opening if it's in a pocket. - H.put_in_hands(master_item) - H.l_store = null - return 0 - if(H.r_store == master_item && !H.get_active_hand()) - H.put_in_hands(master_item) - H.r_store = null - return 0 - - src.add_fingerprint(user) - if (master_item.loc == user) - src.open(user) - return 0 - - for(var/mob/M in range(1, master_item.loc)) - if (M.s_active == src) - src.close(M) - return 1 - -/obj/item/weapon/storage/internal/Adjacent(var/atom/neighbor) - return master_item.Adjacent(neighbor) +//A storage item intended to be used by other items to provide storage functionality. +//Types that use this should consider overriding emp_act() and hear_talk(), unless they shield their contents somehow. +/obj/item/weapon/storage/internal + preserve_item = 1 + var/obj/item/master_item + +/obj/item/weapon/storage/internal/New(obj/item/MI) + master_item = MI + loc = master_item + //name = master_item.name //VOREStation Removal + verbs -= /obj/item/verb/verb_pickup //make sure this is never picked up. + ..() + +/obj/item/weapon/storage/internal/Destroy() + master_item = null + . = ..() + +/obj/item/weapon/storage/internal/attack_hand() + return //make sure this is never picked up + +/obj/item/weapon/storage/internal/mob_can_equip(M as mob, slot, disable_warning = 0) + return 0 //make sure this is never picked up + +//Helper procs to cleanly implement internal storages - storage items that provide inventory slots for other items. +//These procs are completely optional, it is up to the master item to decide when it's storage get's opened by calling open() +//However they are helpful for allowing the master item to pretend it is a storage item itself. +//If you are using these you will probably want to override attackby() as well. +//See /obj/item/clothing/suit/storage for an example. + +//items that use internal storage have the option of calling this to emulate default storage MouseDrop behaviour. +//returns 1 if the master item's parent's MouseDrop() should be called, 0 otherwise. It's strange, but no other way of +//doing it without the ability to call another proc's parent, really. +/obj/item/weapon/storage/internal/proc/handle_mousedrop(mob/user as mob, obj/over_object as obj) + if (ishuman(user) || issmall(user)) //so monkeys can take off their backpacks -- Urist + + if (istype(user.loc,/obj/mecha)) // stops inventory actions in a mech + return 0 + + if(over_object == user && Adjacent(user)) // this must come before the screen objects only block + src.open(user) + return 0 + + if (!( istype(over_object, /obj/screen) )) + return 1 + + //makes sure master_item is equipped before putting it in hand, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this... + if (!(master_item.loc == user) || (master_item.loc && master_item.loc.loc == user)) + return 0 + + if (!( user.restrained() ) && !( user.stat )) + switch(over_object.name) + if("r_hand") + user.unEquip(master_item) + user.put_in_r_hand(master_item) + if("l_hand") + user.unEquip(master_item) + user.put_in_l_hand(master_item) + master_item.add_fingerprint(user) + return 0 + return 0 + +//items that use internal storage have the option of calling this to emulate default storage attack_hand behaviour. +//returns 1 if the master item's parent's attack_hand() should be called, 0 otherwise. +//It's strange, but no other way of doing it without the ability to call another proc's parent, really. +/obj/item/weapon/storage/internal/proc/handle_attack_hand(mob/user as mob) + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.l_store == master_item && !H.get_active_hand()) //Prevents opening if it's in a pocket. + H.put_in_hands(master_item) + H.l_store = null + return 0 + if(H.r_store == master_item && !H.get_active_hand()) + H.put_in_hands(master_item) + H.r_store = null + return 0 + + src.add_fingerprint(user) + if (master_item.loc == user) + src.open(user) + return 0 + + for(var/mob/M in range(1, master_item.loc)) + if (M.s_active == src) + src.close(M) + return 1 + +/obj/item/weapon/storage/internal/Adjacent(var/atom/neighbor) + return master_item.Adjacent(neighbor) diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm index 95db86460e..a668075068 100644 --- a/code/game/objects/items/weapons/storage/wallets.dm +++ b/code/game/objects/items/weapons/storage/wallets.dm @@ -63,7 +63,7 @@ overlays.Cut() if(front_id) var/tiny_state = "id-generic" - if("id-"+front_id.icon_state in icon_states(icon)) + if("id-"+front_id.icon_state in cached_icon_states(icon)) tiny_state = "id-"+front_id.icon_state var/image/tiny_image = new/image(icon, icon_state = tiny_state) tiny_image.appearance_flags = RESET_COLOR diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index fb33d8f30d..7d0947fbbf 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -147,11 +147,11 @@ Frequency: if(com) break break - if (istype(com, /obj/machinery/computer/teleporter) && com.locked && !com.one_time_use) + if (istype(com, /obj/machinery/computer/teleporter) && com.teleport_control.locked && !com.one_time_use) if(R.icon_state == "tele1") - L["[com.id] (Active)"] = com.locked + L["[com.id] (Active)"] = com.teleport_control.locked else - L["[com.id] (Inactive)"] = com.locked + L["[com.id] (Inactive)"] = com.teleport_control.locked var/list/turfs = list( ) for(var/turf/T in orange(10)) if(T.x>world.maxx-8 || T.x<8) continue //putting them at the edge is dumb diff --git a/code/game/objects/structures/barsign.dm b/code/game/objects/structures/barsign.dm index cd1c448b2f..e54c75eebb 100644 --- a/code/game/objects/structures/barsign.dm +++ b/code/game/objects/structures/barsign.dm @@ -6,7 +6,7 @@ var/cult = 0 /obj/structure/sign/double/barsign/proc/get_valid_states(initial=1) - . = icon_states(icon) + . = cached_icon_states(icon) . -= "on" . -= "narsiebistro" . -= "empty" diff --git a/code/game/objects/structures/cliff.dm b/code/game/objects/structures/cliff.dm index c4caf4b7ab..66fb945988 100644 --- a/code/game/objects/structures/cliff.dm +++ b/code/game/objects/structures/cliff.dm @@ -114,7 +114,7 @@ two tiles on initialization, and which way a cliff is facing may change during m var/subtraction_icon_state = "[icon_state]-subtract" var/cache_string = "[icon_state]_[T.icon]_[T.icon_state]" - if(T && subtraction_icon_state in icon_states(icon)) + if(T && subtraction_icon_state in cached_icon_states(icon)) cut_overlays() // If we've made the same icon before, just recycle it. if(cache_string in GLOB.cliff_icon_cache) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 3df62610c9..2434d33e89 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -47,6 +47,9 @@ else . += "There is a thick layer of silicate covering it." +/obj/structure/window/examine_icon() + return icon(icon=initial(icon),icon_state=initial(icon_state)) + /obj/structure/window/take_damage(var/damage = 0, var/sound_effect = 1) var/initialhealth = health diff --git a/code/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm index 60157c1ee8..aa6f3b0e6f 100644 --- a/code/game/turfs/flooring/flooring.dm +++ b/code/game/turfs/flooring/flooring.dm @@ -26,9 +26,10 @@ var/list/flooring_types var/name = "floor" var/desc var/icon - var/icon_base + var/icon_base // initial base icon_state without edges or corners. - var/has_base_range + var/has_base_range // This will pick between a range of 0 - x. Number icon_states accordingly. + // Note that this will append a 0 - x number automatically to icon_base, but NOT the dmi. Do icon_base = "grass", but name grass0 inside the dmi. etc etc. var/has_damage_range var/has_burn_range var/damage_temperature @@ -42,17 +43,69 @@ var/list/flooring_types var/descriptor = "tiles" var/flags var/can_paint - var/list/footstep_sounds = list() // key=species name, value = list of soundss + var/list/footstep_sounds = list() // key=species name, value = list of sounds, + // For instance, footstep_sounds = list("key" = list(sound.ogg)) /decl/flooring/grass name = "grass" desc = "Do they smoke grass out in space, Bowie? Or do they smoke AstroTurf?" icon = 'icons/turf/flooring/grass.dmi' icon_base = "grass" - has_base_range = 3 + has_base_range = 1 damage_temperature = T0C+80 flags = TURF_HAS_EDGES | TURF_REMOVE_SHOVEL build_type = /obj/item/stack/tile/grass + footstep_sounds = list("human" = list( + 'sound/effects/footstep/grass1.ogg', + 'sound/effects/footstep/grass2.ogg', + 'sound/effects/footstep/grass3.ogg', + 'sound/effects/footstep/grass4.ogg')) + +/decl/flooring/grass/sif // Subtype for Sif's grass. + name = "growth" + desc = "A natural moss that has adapted to the sheer cold climate." + icon = 'icons/turf/outdoors.dmi' + icon_base = "grass_sif" + has_base_range = 1 + +/decl/flooring/water + name = "water" + desc = "Water is wet, gosh, who knew!" + icon = 'icons/turf/outdoors.dmi' + icon_base = "seashallow" + footstep_sounds = list("human" = list( + 'sound/effects/footstep/water1.ogg', + 'sound/effects/footstep/water2.ogg', + 'sound/effects/footstep/water3.ogg', + 'sound/effects/footstep/water4.ogg')) + +/decl/flooring/sand + name = "sand" + desc = "I don't like sand. It's coarse and rough and irritating and it gets everywhere." + icon = 'icons/misc/beach.dmi' + icon_base = "sand" + footstep_sounds = list("human" = list( + 'sound/effects/footstep/HeavySand1.ogg', + 'sound/effects/footstep/HeavySand2.ogg', + 'sound/effects/footstep/HeavySand3.ogg', + 'sound/effects/footstep/HeavySand4.ogg')) + +/decl/flooring/sand/desert // Subtype of sand, desert. + name = "desert" + desc = "I don't like sand. It's coarse and rough and irritating and it gets everywhere." + icon = 'icons/turf/desert.dmi' + icon_base = "desert" + +/decl/flooring/mud + name = "mud" + desc = "STICKY AND WET!" + icon = 'icons/turf/outdoors.dmi' + icon_base = "mud_dark" + footstep_sounds = list("human" = list( + 'sound/effects/footstep/mud1.ogg', + 'sound/effects/footstep/mud2.ogg', + 'sound/effects/footstep/mud3.ogg', + 'sound/effects/footstep/mud4.ogg')) /decl/flooring/asteroid name = "coarse sand" @@ -61,6 +114,26 @@ var/list/flooring_types icon_base = "asteroid" flags = TURF_HAS_EDGES | TURF_REMOVE_SHOVEL build_type = null + footstep_sounds = list("human" = list( + 'sound/effects/footstep/asteroid1.ogg', + 'sound/effects/footstep/asteroid2.ogg', + 'sound/effects/footstep/asteroid3.ogg', + 'sound/effects/footstep/asteroid4.ogg', + 'sound/effects/footstep/asteroid5.ogg')) + +/decl/flooring/dirt + name = "dirt" + desc = "Gritty and unpleasant, just like dirt." + icon = 'icons/turf/outdoors.dmi' + icon_base = "dirt-dark" + flags = TURF_HAS_EDGES | TURF_REMOVE_SHOVEL + build_type = null + footstep_sounds = list("human" = list( + 'sound/effects/footstep/asteroid1.ogg', + 'sound/effects/footstep/asteroid2.ogg', + 'sound/effects/footstep/asteroid3.ogg', + 'sound/effects/footstep/asteroid4.ogg', + 'sound/effects/footstep/asteroid5.ogg')) /decl/flooring/snow name = "snow" @@ -216,7 +289,7 @@ var/list/flooring_types icon_base = "lino" can_paint = 1 build_type = /obj/item/stack/tile/linoleum - flags = TURF_REMOVE_SCREWDRIVER + flags = TURF_REMOVE_SCREWDRIVER | TURF_CAN_BREAK | TURF_CAN_BURN /decl/flooring/tiling/red name = "floor" @@ -239,7 +312,6 @@ var/list/flooring_types name = "floor" icon_base = "asteroidfloor" has_damage_range = null - flags = TURF_REMOVE_CROWBAR build_type = /obj/item/stack/tile/floor/steel /decl/flooring/tiling/white @@ -252,7 +324,6 @@ var/list/flooring_types name = "floor" icon_base = "white" has_damage_range = null - flags = TURF_REMOVE_CROWBAR build_type = /obj/item/stack/tile/floor/yellow /decl/flooring/tiling/dark @@ -260,7 +331,6 @@ var/list/flooring_types desc = "How ominous." icon_base = "dark" has_damage_range = null - flags = TURF_REMOVE_CROWBAR build_type = /obj/item/stack/tile/floor/dark /decl/flooring/tiling/hydro @@ -308,20 +378,26 @@ var/list/flooring_types desc = "Heavily reinforced with steel rods." icon = 'icons/turf/flooring/tiles.dmi' icon_base = "reinforced" - flags = TURF_REMOVE_WRENCH | TURF_ACID_IMMUNE + flags = TURF_REMOVE_WRENCH | TURF_ACID_IMMUNE | TURF_CAN_BURN | TURF_CAN_BREAK build_type = /obj/item/stack/rods build_cost = 2 build_time = 30 apply_thermal_conductivity = 0.025 apply_heat_capacity = 325000 can_paint = 1 + footstep_sounds = list("human" = list( + 'sound/effects/footstep/hull1.ogg', + 'sound/effects/footstep/hull2.ogg', + 'sound/effects/footstep/hull3.ogg', + 'sound/effects/footstep/hull4.ogg', + 'sound/effects/footstep/hull5.ogg')) /decl/flooring/reinforced/circuit name = "processing strata" icon = 'icons/turf/flooring/circuit.dmi' icon_base = "bcircuit" build_type = null - flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_CROWBAR + flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_CAN_BURN | TURF_REMOVE_CROWBAR can_paint = 1 /decl/flooring/reinforced/circuit/green @@ -337,3 +413,13 @@ var/list/flooring_types has_damage_range = 6 flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK can_paint = null + +/decl/flooring/lava // Defining this in case someone DOES step on lava and survive. Somehow. + name = "lava" + desc = "Lava. Y'know. Sets you on fire. AAAAAAAAAAA" + icon = 'icons/turf/outdoors.dmi' + icon_base = "lava" + footstep_sounds = list("human" = list( + 'sound/effects/footstep/lava1.ogg', + 'sound/effects/footstep/lava2.ogg', + 'sound/effects/footstep/lava3.ogg')) \ No newline at end of file diff --git a/code/game/turfs/flooring/flooring_premade.dm b/code/game/turfs/flooring/flooring_premade.dm index 5453c2da40..d3ef65ec6a 100644 --- a/code/game/turfs/flooring/flooring_premade.dm +++ b/code/game/turfs/flooring/flooring_premade.dm @@ -387,8 +387,7 @@ name = "snow" icon = 'icons/turf/snow_new.dmi' icon_state = "snow" - outdoors = TRUE - movement_cost = 8 + initial_flooring = /decl/flooring/snow var/list/crossed_dirs = list() footstep_sounds = list("human" = list( //YW edit: Should provide proper snow stepping! 'sound/effects/footstep/snow1.ogg', diff --git a/code/game/turfs/simulated/floor_icon.dm b/code/game/turfs/simulated/floor_icon.dm index cf5396aa96..e11ad7e998 100644 --- a/code/game/turfs/simulated/floor_icon.dm +++ b/code/game/turfs/simulated/floor_icon.dm @@ -1,4 +1,4 @@ -var/list/flooring_cache = list() +GLOBAL_LIST_EMPTY(flooring_cache) var/image/no_ceiling_image = null @@ -79,10 +79,11 @@ var/image/no_ceiling_image = null icon = 'icons/turf/flooring/plating.dmi' icon_state = "dmg[rand(1,4)]" else if(flooring) + var/rand_key = rand(0,2) if(!isnull(broken) && (flooring.flags & TURF_CAN_BREAK)) - add_overlay(get_flooring_overlay("[flooring.icon_base]-broken-[broken]","broken[broken]")) // VOREStation Edit - Eris overlays + add_overlay(get_flooring_overlay("[flooring.icon_base]-broken-[rand_key]","broken[rand_key]")) if(!isnull(burnt) && (flooring.flags & TURF_CAN_BURN)) - add_overlay(get_flooring_overlay("[flooring.icon_base]-burned-[burnt]","burned[burnt]")) // VOREStation Edit - Eris overlays + add_overlay(get_flooring_overlay("[flooring.icon_base]-burned-[rand_key]","burned[rand_key]")) if(update_neighbors) for(var/turf/simulated/floor/F in range(src, 1)) @@ -96,8 +97,8 @@ var/image/no_ceiling_image = null add_overlay(no_ceiling_image) /turf/simulated/floor/proc/get_flooring_overlay(var/cache_key, var/icon_base, var/icon_dir = 0) - if(!flooring_cache[cache_key]) + if(!GLOB.flooring_cache[cache_key]) var/image/I = image(icon = flooring.icon, icon_state = icon_base, dir = icon_dir) I.layer = layer - flooring_cache[cache_key] = I - return flooring_cache[cache_key] + GLOB.flooring_cache[cache_key] = I + return GLOB.flooring_cache[cache_key] diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index 01ad912b70..902c38c16a 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -13,6 +13,7 @@ movement_cost = 2 can_build_into_floor = TRUE can_dirty = FALSE + initial_flooring = /decl/flooring/lava // Defining this in case someone DOES step on lava and survive. Somehow. /turf/simulated/floor/lava/outdoors outdoors = TRUE diff --git a/code/game/turfs/simulated/outdoors/dirt.dm b/code/game/turfs/simulated/outdoors/dirt.dm index 4d14205072..58e1db4951 100644 --- a/code/game/turfs/simulated/outdoors/dirt.dm +++ b/code/game/turfs/simulated/outdoors/dirt.dm @@ -1,6 +1,7 @@ -/turf/simulated/floor/outdoors/dirt - name = "dirt" - desc = "Quite dirty!" - icon_state = "dirt-dark" - edge_blending_priority = 2 - turf_layers = list(/turf/simulated/floor/outdoors/rocks) \ No newline at end of file +/turf/simulated/floor/outdoors/dirt + name = "dirt" + desc = "Quite dirty!" + icon_state = "dirt-dark" + edge_blending_priority = 2 + turf_layers = list(/turf/simulated/floor/outdoors/rocks) + initial_flooring = /decl/flooring/asteroid \ No newline at end of file diff --git a/code/game/turfs/simulated/outdoors/grass.dm b/code/game/turfs/simulated/outdoors/grass.dm index 553b4858bb..4909b14c20 100644 --- a/code/game/turfs/simulated/outdoors/grass.dm +++ b/code/game/turfs/simulated/outdoors/grass.dm @@ -4,21 +4,22 @@ var/list/grass_types = list( /turf/simulated/floor/outdoors/grass name = "grass" - icon_state = "grass" + icon_state = "grass0" edge_blending_priority = 4 + initial_flooring = /decl/flooring/grass turf_layers = list( /turf/simulated/floor/outdoors/rocks, /turf/simulated/floor/outdoors/dirt ) var/grass_chance = 20 - +/* var/animal_chance = 1 // Weighted spawn list. var/list/animal_types = list( /mob/living/simple_mob/animal/passive/tindalos = 1 ) - +*/ var/list/grass_types = list( /obj/structure/flora/ausbushes/sparsegrass, /obj/structure/flora/ausbushes/fullgrass @@ -34,12 +35,13 @@ var/list/grass_types = list( /turf/simulated/floor/outdoors/grass/sif name = "growth" - icon_state = "grass_sif" + icon_state = "grass_sif0" + initial_flooring = /decl/flooring/grass/sif edge_blending_priority = 4 grass_chance = 5 var/tree_chance = 2 - - animal_chance = 0 //VOREStation Edit +/* + animal_chance = 0.5 animal_types = list( /mob/living/simple_mob/animal/sif/diyaab = 10, @@ -48,7 +50,7 @@ var/list/grass_types = list( /mob/living/simple_mob/animal/sif/shantak/retaliate = 2, /obj/random/mob/multiple/sifmobs = 1 ) - +*/ grass_types = list( /obj/structure/flora/sif/eyes = 1, /obj/structure/flora/sif/tendrils = 10 @@ -63,30 +65,26 @@ var/list/grass_types = list( . = ..() /turf/simulated/floor/outdoors/grass/Initialize() - if(prob(50)) - icon_state = "[initial(icon_state)]2" - //edge_blending_priority++ - if(grass_chance && prob(grass_chance) && !check_density()) var/grass_type = pickweight(grass_types) new grass_type(src) - +/* if(animal_chance && prob(animal_chance) && !check_density()) var/animal_type = pickweight(animal_types) new animal_type(src) - +*/ . = ..() /turf/simulated/floor/outdoors/grass/forest name = "thick grass" - icon_state = "grass-dark" + icon_state = "grass-dark0" grass_chance = 80 //tree_chance = 20 edge_blending_priority = 5 /turf/simulated/floor/outdoors/grass/sif/forest name = "thick growth" - icon_state = "grass_sif_dark" + icon_state = "grass_sif_dark0" edge_blending_priority = 5 tree_chance = 10 grass_chance = 0 diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm index 7bef49cd49..bbc71d536b 100644 --- a/code/game/turfs/simulated/outdoors/outdoors.dm +++ b/code/game/turfs/simulated/outdoors/outdoors.dm @@ -81,6 +81,7 @@ var/list/turf_edge_cache = list() name = "mud" icon_state = "mud_dark" edge_blending_priority = 3 + initial_flooring = /decl/flooring/mud /turf/simulated/floor/outdoors/rocks name = "rocks" diff --git a/code/game/turfs/simulated/wall_icon.dm b/code/game/turfs/simulated/wall_icon.dm index 5bf41c4a5f..dd49744a8f 100644 --- a/code/game/turfs/simulated/wall_icon.dm +++ b/code/game/turfs/simulated/wall_icon.dm @@ -67,7 +67,7 @@ I.color = reinf_material.icon_colour add_overlay(I) else - if("[reinf_material.icon_reinf]0" in icon_states('icons/turf/wall_masks.dmi')) + if("[reinf_material.icon_reinf]0" in cached_icon_states('icons/turf/wall_masks.dmi')) // Directional icon for(var/i = 1 to 4) I = image('icons/turf/wall_masks.dmi', "[reinf_material.icon_reinf][wall_connections[i]]", dir = 1<<(i-1)) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index add0b3b11d..1fc49d58a9 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -46,6 +46,9 @@ dismantle_wall(null,null,1) ..() +/turf/simulated/wall/examine_icon() + return icon(icon=initial(icon), icon_state=initial(icon_state)) + /turf/simulated/wall/process() // Calling parent will kill processing if(!radiate()) diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm index 2068bd2e35..0093f84849 100644 --- a/code/game/turfs/simulated/water.dm +++ b/code/game/turfs/simulated/water.dm @@ -20,6 +20,8 @@ /turf/simulated/floor/water/Initialize() . = ..() + var/decl/flooring/F = get_flooring_data(/decl/flooring/water) + footstep_sounds = F?.footstep_sounds update_icon() handle_fish() diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm index 056facb60c..c5338b3db9 100644 --- a/code/game/turfs/unsimulated/beach.dm +++ b/code/game/turfs/unsimulated/beach.dm @@ -15,6 +15,7 @@ name = "Water" icon_state = "water" initialized = FALSE + movement_cost = 4 // Water should slow you down, just like simulated turf. /turf/unsimulated/beach/water/Initialize() . = ..() @@ -23,20 +24,17 @@ /turf/simulated/floor/beach name = "Beach" icon = 'icons/misc/beach.dmi' - footstep_sounds = list("human" = list( - 'sound/effects/footstep/carpet1.ogg', - 'sound/effects/footstep/carpet2.ogg', - 'sound/effects/footstep/carpet3.ogg', - 'sound/effects/footstep/carpet4.ogg', - 'sound/effects/footstep/carpet5.ogg')) + initial_flooring = /decl/flooring/sand /turf/simulated/floor/beach/sand name = "Sand" icon_state = "sand" + initial_flooring = /decl/flooring/sand /turf/simulated/floor/beach/sand/desert icon = 'icons/turf/desert.dmi' icon_state = "desert" + initial_flooring = /decl/flooring/sand/desert /turf/simulated/floor/beach/sand/desert/Initialize() . = ..() @@ -51,10 +49,24 @@ /turf/simulated/floor/beach/water name = "Water" icon_state = "water" + movement_cost = 4 // Water should slow you down, just like the original simulated turf. + initial_flooring = /decl/flooring/water /turf/simulated/floor/beach/water/ocean icon_state = "seadeep" + movement_cost = 8 // Deep water should be difficult to wade through. + initial_flooring = /decl/flooring/water/beach/deep /turf/simulated/floor/beach/water/Initialize() . = ..() add_overlay(image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1)) + +/decl/flooring/water/beach/deep // We're custom-defining a 'deep' water turf for the beach. + name = "deep water" + desc = "Deep Ocean Water" + icon = 'icons/misc/beach.dmi' + icon_base = "seadeep" + footstep_sounds = list("human" = list( + 'sound/effects/footstep/bubbles3.ogg', // No I don't get why it's named 3/4/5 either. Whatever. + 'sound/effects/footstep/bubbles4.ogg', + 'sound/effects/footstep/bubbles5.ogg')) diff --git a/code/game/world.dm b/code/game/world.dm index a71a3e6cdb..6e76ab93a1 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -15,6 +15,8 @@ if(byond_version < RECOMMENDED_VERSION) to_world_log("Your server's byond version does not meet the recommended requirements for this server. Please update BYOND") + TgsNew() + config.post_load() if(config && config.server_name != null && config.server_suffix && world.port > 0) @@ -25,7 +27,7 @@ // if(config && config.log_runtime) // log = file("data/logs/runtime/[time2text(world.realtime,"YYYY-MM-DD-(hh-mm-ss)")]-runtime.log") - GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000 + GLOB.timezoneOffset = get_timezone_offset() callHook("startup") init_vchat() @@ -62,7 +64,7 @@ master_controller = new /datum/controller/game_controller() - Master.Initialize(10, FALSE) + Master.Initialize(10, FALSE, TRUE) spawn(1) master_controller.setup() @@ -82,6 +84,7 @@ var/world_topic_spam_protect_ip = "0.0.0.0" var/world_topic_spam_protect_time = world.timeofday /world/Topic(T, addr, master, key) + TGS_TOPIC log_topic("\"[T]\", from:[addr], master:[master], key:[key]") if (T == "ping") @@ -409,6 +412,7 @@ var/world_topic_spam_protect_time = world.timeofday if(config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite C << link("byond://[config.server]") + TgsReboot() log_world("World rebooted at [time_stamp()]") ..() diff --git a/code/hub.dm b/code/hub.dm index c085c0500d..d3e49cecb4 100644 --- a/code/hub.dm +++ b/code/hub.dm @@ -3,6 +3,10 @@ hub = "Exadv1.spacestation13" hub_password = "kMZy3U5jJHSiBQjr" name = "Space Station 13" + /*YW EDIT we want to be on the hub + name = "VOREStation" //VOREStation Edit + visibility = 0 //VOREStation Edit + */ /* This is for any host that would like their server to appear on the main SS13 hub. To use it, simply replace the password above, with the password found below, and it should work. If not, let us know on the main tgstation IRC channel of irc.rizon.net #tgstation13 we can help you there. diff --git a/code/modules/admin/verbs/buildmode.dm b/code/modules/admin/verbs/buildmode.dm index 6a0d8ba266..7f9e02b769 100644 --- a/code/modules/admin/verbs/buildmode.dm +++ b/code/modules/admin/verbs/buildmode.dm @@ -161,6 +161,7 @@ Right Mouse Button on enemy mob = Command selected mobs to attack mob
\ Right Mouse Button on allied mob = Command selected mobs to follow mob
\ Right Mouse Button + shift on any mob = Command selected mobs to follow mob regardless of faction
\ + Note: The following also reset the mob's home position:
\ Right Mouse Button on tile = Command selected mobs to move to tile (will cancel if enemies are seen)
\ Right Mouse Button + shift on tile = Command selected mobs to reposition to tile (will not be inturrupted by enemies)
\ Right Mouse Button + alt on obj/turfs = Command selected mobs to attack obj/turf
\ @@ -569,6 +570,7 @@ var/told = 0 for(var/mob/living/unit in holder.selected_mobs) var/datum/ai_holder/AI = unit.ai_holder + AI.home_turf = T if(unit.get_AI_stance() == STANCE_SLEEP) unit.forceMove(T) forced++ diff --git a/code/modules/ai/ai_holder.dm b/code/modules/ai/ai_holder.dm index d4686e1537..3cabb3ffde 100644 --- a/code/modules/ai/ai_holder.dm +++ b/code/modules/ai/ai_holder.dm @@ -27,6 +27,16 @@ QDEL_NULL(ai_holder) return ..() +/mob/living/Login() + if(!stat && ai_holder) + ai_holder.manage_processing(AI_NO_PROCESS) + return ..() + +/mob/living/Logout() + if(!stat && !key && ai_holder) + ai_holder.manage_processing(AI_PROCESSING) + return ..() + /datum/ai_holder var/mob/living/holder = null // The mob this datum is going to control. var/stance = STANCE_IDLE // Determines if the mob should be doing a specific thing, e.g. attacking, following, standing around, etc. @@ -145,11 +155,15 @@ // 'Tactical' processes such as moving a step, meleeing an enemy, firing a projectile, and other fairly cheap actions that need to happen quickly. /datum/ai_holder/proc/handle_tactics() + if(holder.key && !autopilot) + return handle_special_tactic() handle_stance_tactical() // 'Strategical' processes that are more expensive on the CPU and so don't get run as often as the above proc, such as A* pathfinding or robust targeting. /datum/ai_holder/proc/handle_strategicals() + if(holder.key && !autopilot) + return handle_special_strategical() handle_stance_strategical() @@ -160,6 +174,8 @@ // For setting the stance WITHOUT processing it /datum/ai_holder/proc/set_stance(var/new_stance) + if(holder.key && !autopilot) + return if(stance == new_stance) ai_log("set_stance() : Ignoring change stance to same stance request.", AI_LOG_INFO) return @@ -277,11 +293,11 @@ if(STANCE_IDLE) if(speak_chance) // In the long loop since otherwise it wont shut up. handle_idle_speaking() - + if(hostile) ai_log("handle_stance_strategical() : STANCE_IDLE, going to find_target().", AI_LOG_TRACE) find_target() - + if(should_go_home()) ai_log("handle_stance_tactical() : STANCE_IDLE, going to go home.", AI_LOG_TRACE) go_home() diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 5580c7fd98..ed6439d3cd 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -204,12 +204,12 @@ You can set verify to TRUE if you want send() to sleep until the client has the directions = list(SOUTH) var/sprites = list() - for (var/icon_state_name in icon_states(I)) + 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(icon_states(sprite))) // that direction or state doesn't exist + if (!sprite || !length(cached_icon_states(sprite))) // that direction or state doesn't exist continue sprites[sprite_name] = sprite return sprites diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index c90f5ec504..05bb6b17cd 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -27,8 +27,6 @@ var/chatOutputLoadedAt var/adminhelped = 0 - var/examine_text_mode = 0 // Just examine text, include usage (description_info), switch to examine panel. - /////////////// //SOUND STUFF// @@ -56,6 +54,7 @@ var/account_join_date = "(Requires database)" var/account_age = "(Requires database)" var/list/department_hours // VOREStation Edit - Track hours of leave accured for each department. + var/list/play_hours // VOREStation Edit - Tracks total playtime hours for each departments. preload_rsc = PRELOAD_RSC diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 7df78ea617..7425c5b72e 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -325,11 +325,13 @@ // VOREStation Edit Start - Department Hours if(config.time_off) - var/DBQuery/query_hours = dbcon.NewQuery("SELECT department, hours FROM vr_player_hours WHERE ckey = '[sql_ckey]'") + var/DBQuery/query_hours = dbcon.NewQuery("SELECT department, hours, total_hours FROM vr_player_hours WHERE ckey = '[sql_ckey]'") query_hours.Execute() + LAZYINITLIST(department_hours) + LAZYINITLIST(play_hours) while(query_hours.NextRow()) - LAZYINITLIST(department_hours) department_hours[query_hours.item[1]] = text2num(query_hours.item[2]) + play_hours[query_hours.item[1]] = text2num(query_hours.item[3]) // VOREStation Edit End - Department Hours if(sql_id) diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 7c9d179f27..06f0a0c877 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -901,7 +901,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O dat += "[current_species.blurb]" //vorestation edit end dat += "" - if("preview" in icon_states(current_species.icobase)) + if("preview" in cached_icon_states(current_species.icobase)) usr << browse_rsc(icon(current_species.icobase,"preview"), "species_preview_[current_species.name].png") dat += "

" dat += "Language: [current_species.species_language]
" diff --git a/code/modules/client/preference_setup/loadout/loadout_eyes_vr.dm b/code/modules/client/preference_setup/loadout/loadout_eyes_vr.dm index da9ad9021d..42c87335f6 100644 --- a/code/modules/client/preference_setup/loadout/loadout_eyes_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_eyes_vr.dm @@ -13,6 +13,27 @@ display_name = "AR glasses, prescription" path = /obj/item/clothing/glasses/omnihud/prescription +/datum/gear/eyes/arglasses/sec + display_name = "AR-S glasses (Sec)" + path = /obj/item/clothing/glasses/omnihud/sec + allowed_roles = list("Security Officer","Head of Security","Warden","Detective") + +/datum/gear/eyes/arglasses/eng + display_name = "AR-E glasses (Eng)" + path = /obj/item/clothing/glasses/omnihud/eng + allowed_roles = list("Station Engineer","Chief Engineer","Atmospheric Technician") + +/datum/gear/eyes/arglasses/med + display_name = "AR-M glasses (Medical)" + path = /obj/item/clothing/glasses/omnihud/med + allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist", "Field Medic") + +/datum/gear/eyes/arglasses/all + display_name = "AR-B glasses (CD, HoP)" + path = /obj/item/clothing/glasses/omnihud/all + cost = 2 + allowed_roles = list("Colony Director","Head of Personnel") + /datum/gear/eyes/spiffygogs display_name = "slick orange goggles" path = /obj/item/clothing/glasses/fluff/spiffygogs diff --git a/code/modules/client/preference_setup/loadout/loadout_fluffitems_vr.dm b/code/modules/client/preference_setup/loadout/loadout_fluffitems_vr.dm index 452b721e6d..088a13c443 100644 --- a/code/modules/client/preference_setup/loadout/loadout_fluffitems_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_fluffitems_vr.dm @@ -92,7 +92,7 @@ /datum/gear/fluff/aurora path = /obj/item/clothing/accessory/solgov/department/security/aurora display_name = "Aurora's keepsake" - description = "An old solgov sec insignia given to Aurora" + description = "An old solcom sec insignia given to Aurora" ckeywhitelist = list("storesund97") character_name = list("Aurora") @@ -150,27 +150,6 @@ ckeywhitelist = list("bwoincognito") character_name = list("Tasald Corlethian") -/datum/gear/fluff/tasald_cartographer_jumpsuit - path = /obj/item/clothing/under/solgov/utility/sifguard/officer/exploration - display_name = "Tasald's Cartographer's uniform - jumpsuit" - slot = slot_w_uniform - ckeywhitelist = list("bwoincognito") - character_name = list("Tasald Corlethian") - -/datum/gear/fluff/tasald_cartographer_jacket - path = /obj/item/clothing/suit/storage/service/sifguard/command - display_name = "Tasald's Cartographer's uniform - jacket" - slot = slot_wear_suit - ckeywhitelist = list("bwoincognito") - character_name = list("Tasald Corlethian") - -/datum/gear/fluff/tasald_cartographer_beret - path = /obj/item/clothing/head/beret/sol/expedition/command - display_name = "Tasald's Cartographer's uniform - beret" - slot = slot_head - ckeywhitelist = list("bwoincognito") - character_name = list("Tasald Corlethian") - /datum/gear/fluff/octavius_box path = /obj/item/weapon/storage/box/fluff/octavious display_name = "Octavious' Box" diff --git a/code/modules/client/preference_setup/occupation/occupation.dm b/code/modules/client/preference_setup/occupation/occupation.dm index 220af5af8e..d0ff9588d5 100644 --- a/code/modules/client/preference_setup/occupation/occupation.dm +++ b/code/modules/client/preference_setup/occupation/occupation.dm @@ -143,6 +143,12 @@ var/available_in_days = job.available_in_days(user.client) . += "[rank] \[IN [(available_in_days)] DAYS]" continue + //VOREStation Add + if(!job.player_has_enough_playtime(user.client)) + var/available_in_hours = job.available_in_playhours(user.client) + . += "[rank] \[IN [(available_in_hours)] DEPTHOURS]" + continue + //VOREStation Add End if(job.minimum_character_age && user.client && (user.client.prefs.age < job.minimum_character_age)) . += "[rank] \[MINIMUM CHARACTER AGE: [job.minimum_character_age]]" continue diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 14f4b5100e..2c09523d93 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -134,6 +134,10 @@ datum/preferences var/lastnews // Hash of last seen lobby news content. + var/examine_text_mode = 0 // Just examine text, include usage (description_info), switch to examine panel. + var/multilingual_mode = 0 // Default behaviour, delimiter-key-space, delimiter-key-delimiter, off + + /datum/preferences/New(client/C) player_setup = new(src) set_biological_gender(pick(MALE, FEMALE)) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 652f2ac082..efa91fc860 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -81,6 +81,8 @@ else player_setup.load_character(S) S.cd = "/character[default_slot]" + player_setup.save_character(S) + sanitize_preferences() player_setup.load_character(S) return 1 @@ -104,7 +106,9 @@ slot = sanitize_integer(slot, 1, config.character_slots, initial(default_slot)) if(slot != default_slot) default_slot = slot + nif_path = nif_durability = nif_savedata = null //VOREStation Add - Don't copy NIF S["default_slot"] << slot + else S["default_slot"] << default_slot diff --git a/code/modules/client/preferences_spawnpoints.dm b/code/modules/client/preferences_spawnpoints.dm index acf1c771a7..e990ee1793 100644 --- a/code/modules/client/preferences_spawnpoints.dm +++ b/code/modules/client/preferences_spawnpoints.dm @@ -13,6 +13,7 @@ var/list/spawntypes = list() var/list/restrict_job = null var/list/disallow_job = null var/announce_channel = "Common" + var/allowed_mob_types = JOB_SILICON|JOB_CARBON proc/check_job_spawning(job) if(restrict_job && !(job in restrict_job)) @@ -22,9 +23,15 @@ var/list/spawntypes = list() return 0 var/datum/job/J = SSjob.get_job(job) - if(J?.offmap_spawn && !(job in restrict_job)) + if(!J) // Couldn't find, admin shenanigans? Allow it + return 1 + + if(J.offmap_spawn && !(job in restrict_job)) return 0 + if(!(J.mob_type & allowed_mob_types)) + return 0 + return 1 /datum/spawnpoint/proc/get_spawn_position() @@ -57,7 +64,7 @@ var/list/spawntypes = list() /datum/spawnpoint/cryo display_name = "Cryogenic Storage" msg = "has completed cryogenic revival" - disallow_job = list("Cyborg") + allowed_mob_types = JOB_CARBON /datum/spawnpoint/cryo/New() ..() @@ -66,7 +73,7 @@ var/list/spawntypes = list() /datum/spawnpoint/cyborg display_name = "Cyborg Storage" msg = "has been activated from storage" - restrict_job = list("Cyborg") + allowed_mob_types = JOB_SILICON /datum/spawnpoint/cyborg/New() ..() diff --git a/code/modules/client/preferences_toggle_procs.dm b/code/modules/client/preferences_toggle_procs.dm index b8e0ea3d5c..e33f3645d1 100644 --- a/code/modules/client/preferences_toggle_procs.dm +++ b/code/modules/client/preferences_toggle_procs.dm @@ -328,17 +328,34 @@ set category = "Preferences" set desc = "Control the additional behaviour of examining things" - examine_text_mode++ - examine_text_mode %= EXAMINE_MODE_MAX // This cycles through them because if you're already specifically being routed to the examine panel, you probably don't need to have the extra text printed to chat - switch(examine_text_mode) // ... And I only wanted to add one verb + prefs.examine_text_mode++ + prefs.examine_text_mode %= EXAMINE_MODE_MAX // This cycles through them because if you're already specifically being routed to the examine panel, you probably don't need to have the extra text printed to chat + switch(prefs.examine_text_mode) // ... And I only wanted to add one verb if(EXAMINE_MODE_DEFAULT) - to_chat(src, "Examining things will only output the base examine text, and you will not be redirected to the examine panel automatically.") + to_chat(src, "Examining things will only output the base examine text, and you will not be redirected to the examine panel automatically.") if(EXAMINE_MODE_INCLUDE_USAGE) - to_chat(src, "Examining things will also print any extra usage information normally included in the examine panel to the chat.") + to_chat(src, "Examining things will also print any extra usage information normally included in the examine panel to the chat.") if(EXAMINE_MODE_SWITCH_TO_PANEL) - to_chat(src, "Examining things will direct you to the examine panel, where you can view extended information about the thing.") + to_chat(src, "Examining things will direct you to the examine panel, where you can view extended information about the thing.") + +/client/verb/toggle_multilingual_mode() + set name = "Toggle Multilingual Mode" + set category = "Preferences" + set desc = "Control the behaviour of multilingual speech parsing" + + prefs.multilingual_mode++ + prefs.multilingual_mode %= MULTILINGUAL_MODE_MAX // Cycles through the various options + switch(prefs.multilingual_mode) + if(MULTILINGUAL_DEFAULT) + to_chat(src, "Multilingual parsing will only check for the delimiter-key combination (,0galcom-2tradeband).") + if(MULTILINGUAL_SPACE) + to_chat(src, "Multilingual parsing will enforce a space after the delimiter-key combination (,0 galcom -2still galcom). The extra space will be consumed by the pattern-matching.") + if(MULTILINGUAL_DOUBLE_DELIMITER) + to_chat(src, "Multilingual parsing will enforce the a language delimiter after the delimiter-key combination (,0,galcom -2 still galcom). The extra delimiter will be consumed by the pattern-matching.") + if(MULTILINGUAL_OFF) + to_chat(src, "Multilingual parsing is now disabled. Entire messages will be in the language specified at the start of the message.") //Toggles for Staff diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 4b92cdd149..5f61f21582 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -59,7 +59,7 @@ user.recalculate_vis() //BS12: Species-restricted clothing check. -/obj/item/clothing/mob_can_equip(M as mob, slot) +/obj/item/clothing/mob_can_equip(M as mob, slot, disable_warning = 0) //if we can't equip the item anyway, don't bother with species_restricted (cuts down on spam) if (!..()) @@ -808,7 +808,7 @@ //autodetect rollability if(rolled_down < 0) - if(("[worn_state]_d_s" in icon_states(icon)) || ("[worn_state]_s" in icon_states(rolled_down_icon)) || ("[worn_state]_d_s" in icon_states(icon_override))) + if(("[worn_state]_d_s" in cached_icon_states(icon)) || ("[worn_state]_s" in cached_icon_states(rolled_down_icon)) || ("[worn_state]_d_s" in cached_icon_states(icon_override))) rolled_down = 0 if(rolled_down == -1) @@ -845,11 +845,11 @@ under_icon = sprite_sheets[H.species.get_bodytype(H)] else if(item_icons && item_icons[slot_w_uniform_str]) under_icon = item_icons[slot_w_uniform_str] - else if ("[worn_state]_s" in icon_states(rolled_down_icon)) + else if ("[worn_state]_s" in cached_icon_states(rolled_down_icon)) under_icon = rolled_down_icon // The _s is because the icon update procs append it. - if((under_icon == rolled_down_icon && "[worn_state]_s" in icon_states(under_icon)) || ("[worn_state]_d_s" in icon_states(under_icon))) + if((under_icon == rolled_down_icon && "[worn_state]_s" in cached_icon_states(under_icon)) || ("[worn_state]_d_s" in cached_icon_states(under_icon))) if(rolled_down != 1) rolled_down = 0 else @@ -868,13 +868,13 @@ under_icon = sprite_sheets[H.species.get_bodytype(H)] else if(item_icons && item_icons[slot_w_uniform_str]) under_icon = item_icons[slot_w_uniform_str] - else if ("[worn_state]_s" in icon_states(rolled_down_sleeves_icon)) + else if ("[worn_state]_s" in cached_icon_states(rolled_down_sleeves_icon)) under_icon = rolled_down_sleeves_icon else if(index) under_icon = new /icon("[INV_W_UNIFORM_DEF_ICON]_[index].dmi") // The _s is because the icon update procs append it. - if((under_icon == rolled_down_sleeves_icon && "[worn_state]_s" in icon_states(under_icon)) || ("[worn_state]_r_s" in icon_states(under_icon))) + if((under_icon == rolled_down_sleeves_icon && "[worn_state]_s" in cached_icon_states(under_icon)) || ("[worn_state]_r_s" in cached_icon_states(under_icon))) if(rolled_sleeves != 1) rolled_sleeves = 0 else @@ -958,7 +958,7 @@ if(rolled_down) body_parts_covered = initial(body_parts_covered) body_parts_covered &= ~(UPPER_TORSO|ARMS) - if("[worn_state]_s" in icon_states(rolled_down_icon)) + if("[worn_state]_s" in cached_icon_states(rolled_down_icon)) icon_override = rolled_down_icon item_state_slots[slot_w_uniform_str] = "[worn_state]" else @@ -991,7 +991,7 @@ rolled_sleeves = !rolled_sleeves if(rolled_sleeves) body_parts_covered &= ~(ARMS) - if("[worn_state]_s" in icon_states(rolled_down_sleeves_icon)) + if("[worn_state]_s" in cached_icon_states(rolled_down_sleeves_icon)) icon_override = rolled_down_sleeves_icon item_state_slots[slot_w_uniform_str] = "[worn_state]" else diff --git a/code/modules/clothing/clothing_vr.dm b/code/modules/clothing/clothing_vr.dm index 62228ea5a0..0545cb92b7 100644 --- a/code/modules/clothing/clothing_vr.dm +++ b/code/modules/clothing/clothing_vr.dm @@ -135,7 +135,7 @@ var/mob/living/carbon/human/H = user if(isTaurTail(H.tail_style)) var/datum/sprite_accessory/tail/taur/taurtail = H.tail_style - if(taurtail.suit_sprites && (get_worn_icon_state(slot_wear_suit_str) in icon_states(taurtail.suit_sprites))) + if(taurtail.suit_sprites && (get_worn_icon_state(slot_wear_suit_str) in cached_icon_states(taurtail.suit_sprites))) icon_override = taurtail.suit_sprites normalize = FALSE taurized = TRUE diff --git a/code/modules/clothing/gloves/arm_guards.dm b/code/modules/clothing/gloves/arm_guards.dm index 558f855545..791bb0a10b 100644 --- a/code/modules/clothing/gloves/arm_guards.dm +++ b/code/modules/clothing/gloves/arm_guards.dm @@ -7,7 +7,7 @@ w_class = ITEMSIZE_NORMAL drop_sound = 'sound/items/drop/metalshield.ogg' -/obj/item/clothing/gloves/arm_guard/mob_can_equip(var/mob/living/carbon/human/H, slot) +/obj/item/clothing/gloves/arm_guard/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = 0) if(..()) //This will only run if no other problems occured when equiping. if(H.wear_suit) if(H.wear_suit.body_parts_covered & ARMS) diff --git a/code/modules/clothing/gloves/gauntlets.dm b/code/modules/clothing/gloves/gauntlets.dm index 8807fb93ad..eb5d05c909 100644 --- a/code/modules/clothing/gloves/gauntlets.dm +++ b/code/modules/clothing/gloves/gauntlets.dm @@ -14,7 +14,7 @@ punch_force = 5 var/obj/item/clothing/gloves/gloves = null //Undergloves -/obj/item/clothing/gloves/gauntlets/mob_can_equip(mob/user) +/obj/item/clothing/gloves/gauntlets/mob_can_equip(mob/user, slot, disable_warning = 0) var/mob/living/carbon/human/H = user if(H.gloves) gloves = H.gloves diff --git a/code/modules/clothing/head/solgov_vr.dm b/code/modules/clothing/head/solgov_vr.dm index 3861ecebe1..0a9ddd2c41 100644 --- a/code/modules/clothing/head/solgov_vr.dm +++ b/code/modules/clothing/head/solgov_vr.dm @@ -6,8 +6,8 @@ desc = "It's a blue ballcap in Terran Commonwealth Government colors." /obj/item/clothing/head/soft/sol/expedition - name = "\improper Explorer corps cap" - desc = "It's a black ballcap bearing a Terran Commonwealth Explorer Corps crest." + name = "\improper NDF cap" + desc = "It's a black ballcap bearing a Nanotrasen Defense Force crest." /obj/item/clothing/head/soft/sol/fleet name = "fleet cap" @@ -70,12 +70,12 @@ //Dress /obj/item/clothing/head/dress/expedition - name = "explorer's dress cap" - desc = "A peaked grey dress uniform cap belonging to the Terran Commonwealth Explorer Corps." + name = "\improper NDF dress cap" + desc = "A peaked grey dress uniform cap belonging to the Nanotrasen Defense Force." /obj/item/clothing/head/dress/expedition/command - name = "explorer's command dress cap" - desc = "A peaked grey dress uniform cap belonging to the Terran Commonwealth Explorer Corps. This one is trimmed in gold." + name = "\improper NDF command dress cap" + desc = "A peaked grey dress uniform cap belonging to the Nanotrasen Defense Force. This one is trimmed in gold." /obj/item/clothing/head/dress/fleet name = "fleet dress wheel cover" @@ -124,28 +124,28 @@ desc = "A white beret denoting service in the Interstellar Health Service. For medics that are more inclined towards style than safety." /obj/item/clothing/head/beret/sol/expedition - name = "explorer's beret" - desc = "A black beret belonging to the Terran Commonwealth explorer corps. For personnel that are more inclined towards style than safety." + name = "\improper NDF beret" + desc = "A black beret belonging to the Nanotrasen Defense Force. For personnel that are more inclined towards style than safety." /obj/item/clothing/head/beret/sol/expedition/security - name = "explorer's security beret" - desc = "A Terran Commonwealth Explorer Corps beret with a security crest. For personnel that are more inclined towards style than safety." + name = "\improper NDF security beret" + desc = "A Nanotrasen Defense Force beret with a security crest. For personnel that are more inclined towards style than safety." /obj/item/clothing/head/beret/sol/expedition/medical - name = "explorer's medical beret" - desc = "A Terran Commonwealth Explorer Corps beret with a medical crest. For personnel that are more inclined towards style than safety." + name = "\improper NDF medical beret" + desc = "A Nanotrasen Defense Force beret with a medical crest. For personnel that are more inclined towards style than safety." /obj/item/clothing/head/beret/sol/expedition/engineering - name = "explorer's engineering beret" - desc = "A Terran Commonwealth Explorer Corps beret with an engineering crest. For personnel that are more inclined towards style than safety." + name = "\improper NDF engineering beret" + desc = "A Nanotrasen Defense Force beret with an engineering crest. For personnel that are more inclined towards style than safety." /obj/item/clothing/head/beret/sol/expedition/supply - name = "explorer's supply beret" - desc = "A Terran Commonwealth Explorer Corps beret with a supply crest. For personnel that are more inclined towards style than safety." + name = "\improper NDF supply beret" + desc = "A Nanotrasen Defense Force beret with a supply crest. For personnel that are more inclined towards style than safety." /obj/item/clothing/head/beret/sol/expedition/command - name = "explorer's command beret" - desc = "A Terran Commonwealth Explorer Corps beret with a command crest. For personnel that are more inclined towards style than safety." + name = "\improper NDF command beret" + desc = "A Nanotrasen Defense Force beret with a command crest. For personnel that are more inclined towards style than safety." /obj/item/clothing/head/beret/sol/fleet name = "fleet beret" diff --git a/code/modules/clothing/masks/monitor.dm b/code/modules/clothing/masks/monitor.dm index 230f224d09..be337c9067 100644 --- a/code/modules/clothing/masks/monitor.dm +++ b/code/modules/clothing/masks/monitor.dm @@ -33,7 +33,7 @@ canremove = 1 return ..() -/obj/item/clothing/mask/monitor/mob_can_equip(var/mob/living/carbon/human/user, var/slot) +/obj/item/clothing/mask/monitor/mob_can_equip(var/mob/living/carbon/human/user, var/slot, disable_warning = FALSE) if (!..()) return 0 if(istype(user)) diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 57b8a0911a..816c5052fc 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -42,7 +42,7 @@ user.update_inv_shoes() //so our mob-overlays update user.update_action_buttons() -/obj/item/clothing/shoes/magboots/mob_can_equip(mob/user, slot) +/obj/item/clothing/shoes/magboots/mob_can_equip(mob/user, slot, disable_warning = FALSE) var/mob/living/carbon/human/H = user if(H.shoes) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 691f53de5a..3920ddd636 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -520,7 +520,7 @@ |ACCESSORY_SLOT_ARMOR_M) blood_overlay_type = "armor" -/obj/item/clothing/suit/armor/pcarrier/mob_can_equip(var/mob/living/carbon/human/H, slot) +/obj/item/clothing/suit/armor/pcarrier/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = FALSE) if(..()) //This will only run if no other problems occured when equiping. if(H.gloves) if(H.gloves.body_parts_covered & ARMS) diff --git a/code/modules/clothing/suits/solgov_vr.dm b/code/modules/clothing/suits/solgov_vr.dm index 21c6851acf..b23cb35bc9 100644 --- a/code/modules/clothing/suits/solgov_vr.dm +++ b/code/modules/clothing/suits/solgov_vr.dm @@ -2,40 +2,40 @@ //Service /obj/item/clothing/suit/storage/service/sifguard - name = "\improper SolCom jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has silver buttons." + name = "\improper NDF jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has silver buttons." /obj/item/clothing/suit/storage/service/sifguard/medical - name = "\improper SolCom medical jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has silver buttons and blue trim." + name = "\improper NDF medical jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has silver buttons and blue trim." /obj/item/clothing/suit/storage/service/sifguard/medical/command - name = "\improper SolCom medical command jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has gold buttons and blue trim." + name = "\improper NDF medical command jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has gold buttons and blue trim." /obj/item/clothing/suit/storage/service/sifguard/engineering - name = "\improper SolCom engineering jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has silver buttons and orange trim." + name = "\improper NDF engineering jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has silver buttons and orange trim." /obj/item/clothing/suit/storage/service/sifguard/engineering/command - name = "\improper SolCom engineering command jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has gold buttons and orange trim." + name = "\improper NDF engineering command jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has gold buttons and orange trim." /obj/item/clothing/suit/storage/service/sifguard/supply - name = "\improper SolCom supply jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has silver buttons and brown trim." + name = "\improper NDF supply jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has silver buttons and brown trim." /obj/item/clothing/suit/storage/service/sifguard/security - name = "\improper SolCom security jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has silver buttons and red trim." + name = "\improper NDF security jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has silver buttons and red trim." /obj/item/clothing/suit/storage/service/sifguard/security/command - name = "\improper SolCom security command jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has gold buttons and red trim." + name = "\improper NDF security command jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has gold buttons and red trim." /obj/item/clothing/suit/storage/service/sifguard/command - name = "\improper SolCom command jacket" - desc = "A uniform service jacket belonging to the Terran Commonwealth Explorer Corps. It has gold buttons and gold trim." + name = "\improper NDF command jacket" + desc = "A uniform service jacket belonging to the Nanotrasen Defense Force. It has gold buttons and gold trim." /obj/item/clothing/suit/storage/service/marine name = "marine coat" @@ -76,12 +76,12 @@ //Dress /obj/item/clothing/suit/dress/expedition - name = "SolCom dress jacket" - desc = "A silver and grey dress jacket belonging to the Terran Commonwealth Explorer Corps. Fashionable, for the 24th century at least." + name = "\improper NDF dress jacket" + desc = "A silver and grey dress jacket belonging to the Nanotrasen Defense Force. Fashionable, for the 24th century at least." /obj/item/clothing/suit/dress/expedition/command - name = "explorer's command dress jacket" - desc = "A gold and grey dress jacket belonging to the Terran Commonwealth Explorer Corps. The height of fashion." + name = "\improper NDF command dress jacket" + desc = "A gold and grey dress jacket belonging to the Nanotrasen Defense Force. The height of fashion." /obj/item/clothing/suit/storage/toggle/dress/fleet name = "fleet dress jacket" diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index a20b4b4686..a9ace268ac 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -24,7 +24,7 @@ if(!inv_overlay) var/tmp_icon_state = "[overlay_state? "[overlay_state]" : "[icon_state]"]" if(icon_override) - if("[tmp_icon_state]_tie" in icon_states(icon_override)) + if("[tmp_icon_state]_tie" in cached_icon_states(icon_override)) tmp_icon_state = "[tmp_icon_state]_tie" inv_overlay = image(icon = icon_override, icon_state = tmp_icon_state, dir = SOUTH) else @@ -48,7 +48,7 @@ tmp_icon_state = on_rolled["rolled"] if(icon_override) - if("[tmp_icon_state]_mob" in icon_states(icon_override)) + if("[tmp_icon_state]_mob" in cached_icon_states(icon_override)) tmp_icon_state = "[tmp_icon_state]_mob" mob_overlay = image("icon" = icon_override, "icon_state" = "[tmp_icon_state]") else if(wearer && sprite_sheets[wearer.species.get_bodytype(wearer)]) //Teshari can finally into webbing, too! diff --git a/code/modules/clothing/under/accessories/lockets.dm b/code/modules/clothing/under/accessories/lockets.dm index ca859addb5..153df0d584 100644 --- a/code/modules/clothing/under/accessories/lockets.dm +++ b/code/modules/clothing/under/accessories/lockets.dm @@ -13,7 +13,7 @@ if(!base_icon) base_icon = icon_state - if(!("[base_icon]_open" in icon_states(icon))) + if(!("[base_icon]_open" in cached_icon_states(icon))) to_chat(user, "\The [src] doesn't seem to open.") return diff --git a/code/modules/clothing/under/accessories/torch_vr.dm b/code/modules/clothing/under/accessories/torch_vr.dm index caba931c6f..730710fe9b 100644 --- a/code/modules/clothing/under/accessories/torch_vr.dm +++ b/code/modules/clothing/under/accessories/torch_vr.dm @@ -192,3 +192,22 @@ armour attachments /obj/item/clothing/accessory/armor/helmcover/blue/sol name = "peacekeeper helmet cover" desc = "A fabric cover for armored helmets. This one is in TCG peacekeeper colors." + +/********* +ranks - ndf +*********/ +/obj/item/clothing/accessory/solgov/rank/ec/enlisted + name = "ranks (E-1 seaman recruit)" + desc = "Insignia denoting the rank of Seaman Recruit." + +/obj/item/clothing/accessory/solgov/rank/ec/enlisted/e3 + name = "ranks (E-3 seaman)" + desc = "Insignia denoting the rank of Seaman." + +/obj/item/clothing/accessory/solgov/rank/ec/enlisted/e5 + name = "ranks (E-5 petty officer)" + desc = "Insignia denoting the rank of Petty Officer." + +/obj/item/clothing/accessory/solgov/rank/ec/enlisted/e7 + name = "ranks (E-7 chief petty officer)" + desc = "Insignia denoting the rank of Chief Petty Officer." diff --git a/code/modules/clothing/under/solgov_vr.dm b/code/modules/clothing/under/solgov_vr.dm index e663db1344..891439d2d3 100644 --- a/code/modules/clothing/under/solgov_vr.dm +++ b/code/modules/clothing/under/solgov_vr.dm @@ -2,8 +2,8 @@ //PT /obj/item/clothing/under/solgov/pt/sifguard - name = "\improper SolCom pt uniform" - desc = "A baggy shirt bearing the seal of the Terran Commonwealth Explorer Corps and some dorky looking blue shorts." + name = "\improper NDF pt uniform" + desc = "A baggy shirt bearing the seal of the Nanotrasen Defense Force and some dorky looking blue shorts." /obj/item/clothing/under/solgov/pt/fleet name = "fleet pt uniform" @@ -21,12 +21,12 @@ desc = "A comfortable turtleneck and black utility trousers." /obj/item/clothing/under/solgov/utility/sifguard - name = "\improper SolCom uniform" - desc = "The utility uniform of the Terran Commonwealth Explorer Corps, made from biohazard resistant material. This one has silver trim." + name = "\improper NDF uniform" + desc = "The utility uniform of the Nanotrasen Defense Force, made from biohazard resistant material. This one has silver trim." /obj/item/clothing/under/solgov/utility/sifguard/officer - name = "\improper SolCom officer uniform" - desc = "The utility uniform of the Terran Commonwealth Explorer Corps, made from biohazard resistant material. This one has gold trim." + name = "\improper NDF officer uniform" + desc = "The utility uniform of the Nanotrasen Defense Force, made from biohazard resistant material. This one has gold trim." /obj/item/clothing/under/solgov/utility/fleet @@ -77,12 +77,12 @@ desc = "The service uniform of the TCG Marine Corps. Slimming and stylish." /obj/item/clothing/under/solgov/mildress/expeditionary - name = "\improper SolCom dress uniform" - desc = "The dress uniform of the Terran Commonwealth Explorer Corps in silver trim." + name = "\improper NDF dress uniform" + desc = "The dress uniform of the Nanotrasen Defense Force in silver trim." /obj/item/clothing/under/solgov/mildress/expeditionary/command - name = "\improper SolCom command dress uniform" - desc = "The dress uniform of the Terran Commonwealth Explorer Corps in gold trim." + name = "\improper NDF command dress uniform" + desc = "The dress uniform of the Nanotrasen Defense Force in gold trim." /obj/item/clothing/under/solgov/mildress/marine name = "marine dress uniform" diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index b87183c385..5e85c0123c 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -78,7 +78,7 @@ var/list/new_item_icons = list() var/list/new_item_state_slots = list() - var/list/available_states = icon_states(CUSTOM_ITEM_MOB) + var/list/available_states = cached_icon_states(CUSTOM_ITEM_MOB) //If l_hand or r_hand are not present, preserve them using item_icons/item_state_slots //Then use icon_override to make every other slot use the custom sprites by default. diff --git a/code/modules/detectivework/microscope/dnascanner.dm b/code/modules/detectivework/microscope/dnascanner.dm index 94d4acd5cd..0b9782b2c8 100644 --- a/code/modules/detectivework/microscope/dnascanner.dm +++ b/code/modules/detectivework/microscope/dnascanner.dm @@ -16,14 +16,9 @@ var/last_process_worldtime = 0 var/report_num = 0 -/obj/machinery/dnaforensics/New() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - RefreshParts() - ..() +/obj/machinery/dnaforensics/Initialize() + . = ..() + default_apply_parts() /obj/machinery/dnaforensics/attackby(var/obj/item/W, mob/user as mob) diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 02a8ad8acd..ca30941c1c 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -22,7 +22,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT var/last_world_time = 0 /datum/event_container/process() - if(!round_start_time) + if(!GLOB.round_start_time) return //don't do events if the round hasn't even started yet if(!next_event_time) diff --git a/code/modules/examine/examine.dm b/code/modules/examine/examine.dm index 6e2df0b1fa..f49c672bca 100644 --- a/code/modules/examine/examine.dm +++ b/code/modules/examine/examine.dm @@ -5,7 +5,7 @@ This means that this file can be unchecked, along with the other examine files, and can be removed entirely with no effort. */ -#define EXAMINE_PANEL_PADDING " " +#define EXAMINE_PANEL_PADDING " " /atom/ var/description_info = null //Helpful blue text. @@ -56,7 +56,7 @@ description_holders["interactions"] = A.get_description_interaction() description_holders["name"] = "[A.name]" - description_holders["icon"] = "\icon[A]" + description_holders["icon"] = "\icon[A.examine_icon()]" description_holders["desc"] = A.desc /mob/Stat() diff --git a/code/modules/food/drinkingglass/drinkingglass.dm b/code/modules/food/drinkingglass/drinkingglass.dm index 928c24954b..c2c5dc4219 100644 --- a/code/modules/food/drinkingglass/drinkingglass.dm +++ b/code/modules/food/drinkingglass/drinkingglass.dm @@ -74,9 +74,9 @@ update_icon() /obj/item/weapon/reagent_containers/food/drinks/glass2/proc/can_add_extra(obj/item/weapon/glass_extra/GE) - if(!("[base_icon]_[GE.glass_addition]left" in icon_states(icon))) //VOREStation Edit + if(!("[base_icon]_[GE.glass_addition]left" in cached_icon_states(icon))) //VOREStation Edit return 0 - if(!("[base_icon]_[GE.glass_addition]right" in icon_states(icon))) //VOREStation Edit + if(!("[base_icon]_[GE.glass_addition]right" in cached_icon_states(icon))) //VOREStation Edit return 0 return 1 @@ -106,9 +106,9 @@ over_liquid |= "[base_icon][amnt]_fizz" for(var/S in R.glass_special) - if("[base_icon]_[S]" in icon_states(icon)) //VOREStation Edit + if("[base_icon]_[S]" in cached_icon_states(icon)) //VOREStation Edit under_liquid |= "[base_icon]_[S]" - else if("[base_icon][amnt]_[S]" in icon_states(icon)) //VOREStation Edit + else if("[base_icon][amnt]_[S]" in cached_icon_states(icon)) //VOREStation Edit over_liquid |= "[base_icon][amnt]_[S]" for(var/k in under_liquid) diff --git a/code/modules/food/kitchen/microwave.dm b/code/modules/food/kitchen/microwave.dm index b9beeed09b..593a7892fd 100644 --- a/code/modules/food/kitchen/microwave.dm +++ b/code/modules/food/kitchen/microwave.dm @@ -31,13 +31,11 @@ ********************/ /obj/machinery/microwave/Initialize() + . = ..() reagents = new/datum/reagents(100) reagents.my_atom = src - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) + default_apply_parts() if (!available_recipes) available_recipes = new @@ -60,9 +58,7 @@ acceptable_items |= /obj/item/device/soulstone acceptable_items |= /obj/item/weapon/fuel_assembly/supermatter - RefreshParts() soundloop = new(list(src), FALSE) - return ..() /obj/machinery/microwave/Destroy() QDEL_NULL(soundloop) diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 982f44e794..90afa7f416 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -141,7 +141,7 @@ var/image/fruit_base = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-product") fruit_base.color = "[seed.get_trait(TRAIT_PRODUCT_COLOUR)]" plant_icon.overlays |= fruit_base - if("[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf" in icon_states('icons/obj/hydroponics_products.dmi')) + if("[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf" in cached_icon_states('icons/obj/hydroponics_products.dmi')) var/image/fruit_leaves = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf") fruit_leaves.color = "[seed.get_trait(TRAIT_PLANT_COLOUR)]" plant_icon.overlays |= fruit_leaves diff --git a/code/modules/hydroponics/seed_controller.dm b/code/modules/hydroponics/seed_controller.dm index 1ca42f4c60..28315b361a 100644 --- a/code/modules/hydroponics/seed_controller.dm +++ b/code/modules/hydroponics/seed_controller.dm @@ -53,7 +53,7 @@ var/global/datum/controller/plants/plant_controller // Set in New(). /datum/controller/plants/proc/setup() // Build the icon lists. - for(var/icostate in icon_states('icons/obj/hydroponics_growing.dmi')) + for(var/icostate in cached_icon_states('icons/obj/hydroponics_growing.dmi')) var/split = findtext(icostate,"-") if(!split) // invalid icon_state @@ -71,7 +71,7 @@ var/global/datum/controller/plants/plant_controller // Set in New(). if(!(base in GLOB.forbidden_plant_growth_sprites)) accessible_plant_sprites[base] = ikey - for(var/icostate in icon_states('icons/obj/hydroponics_products.dmi')) + for(var/icostate in cached_icon_states('icons/obj/hydroponics_products.dmi')) var/split = findtext(icostate,"-") var/base = copytext(icostate,1,split) if(split) diff --git a/code/modules/integrated_electronics/subtypes/time.dm b/code/modules/integrated_electronics/subtypes/time.dm index df8e686b1f..9633ef7881 100644 --- a/code/modules/integrated_electronics/subtypes/time.dm +++ b/code/modules/integrated_electronics/subtypes/time.dm @@ -86,10 +86,10 @@ power_draw_per_use = 4 /obj/item/integrated_circuit/time/clock/do_work() - set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") ) - set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) ) - set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) ) - set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) ) + set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ds, "hh:mm:ss") ) + set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ds, "hh") ) ) + set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ds, "mm") ) ) + set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ds, "ss") ) ) push_data() activate_pin(2) diff --git a/code/modules/maps/tg/reader.dm b/code/modules/maps/tg/reader.dm index 71adb65bad..b7bf3561f5 100644 --- a/code/modules/maps/tg/reader.dm +++ b/code/modules/maps/tg/reader.dm @@ -2,15 +2,9 @@ //SS13 Optimized Map loader ////////////////////////////////////////////////////////////// -/* //global datum that will preload variables on atoms instanciation GLOBAL_VAR_INIT(use_preloader, FALSE) GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new) -*/ - -//global datum that will preload variables on atoms instanciation -var/global/dmm_suite/preloader/_preloader = new() -var/global/use_preloader = FALSE /dmm_suite // /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g @@ -36,6 +30,12 @@ var/global/use_preloader = FALSE * */ /dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num, no_changeturf as num, orientation as num) + + dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g") + trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g") + trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g") + modelCache = list() + //How I wish for RAII if(!measureOnly) Master.StartLoadingMap() @@ -350,7 +350,7 @@ var/global/use_preloader = FALSE index = members.len if(members[index] != /area/template_noop) var/atom/instance - _preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation + GLOB._preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation var/atype = members[index] for(var/area/A in world) if(A.type == atype) @@ -361,8 +361,8 @@ var/global/use_preloader = FALSE if(crds) instance.contents.Add(crds) - if(use_preloader && instance) - _preloader.load(instance) + if(GLOB.use_preloader && instance) + GLOB._preloader.load(instance) //then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect @@ -398,7 +398,7 @@ var/global/use_preloader = FALSE //Instance an atom at (x,y,z) and gives it the variables in attributes /dmm_suite/proc/instance_atom(path,list/attributes, turf/crds, no_changeturf, orientation=0) - _preloader.setup(attributes, path) + GLOB._preloader.setup(attributes, path) if(crds) if(!no_changeturf && ispath(path, /turf)) @@ -406,8 +406,8 @@ var/global/use_preloader = FALSE else . = create_atom(path, crds)//first preloader pass - if(use_preloader && .)//second preloader pass, for those atoms that don't ..() in New() - _preloader.load(.) + if(GLOB.use_preloader && .)//second preloader pass, for those atoms that don't ..() in New() + GLOB._preloader.load(.) //custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize if(TICK_CHECK) @@ -530,7 +530,7 @@ var/global/use_preloader = FALSE /dmm_suite/preloader/proc/setup(list/the_attributes, path) if(the_attributes.len) - use_preloader = TRUE + GLOB.use_preloader = TRUE attributes = the_attributes target_path = path @@ -540,7 +540,7 @@ var/global/use_preloader = FALSE if(islist(value)) value = deepCopyList(value) what.vars[attribute] = value - use_preloader = FALSE + GLOB.use_preloader = FALSE /area/template_noop name = "Area Passthrough" diff --git a/code/modules/media/mediamanager.dm b/code/modules/media/mediamanager.dm index 96b9ab36cb..5ff00d5eee 100644 --- a/code/modules/media/mediamanager.dm +++ b/code/modules/media/mediamanager.dm @@ -11,7 +11,7 @@ #ifdef DEBUG_MEDIAPLAYER #define MP_DEBUG(x) to_chat(owner,x) -#warning Please comment out #define DEBUG_MEDIAPLAYER before committing. +#warn Please comment out #define DEBUG_MEDIAPLAYER before committing. #else #define MP_DEBUG(x) #endif diff --git a/code/modules/mining/drilling/drill.dm b/code/modules/mining/drilling/drill.dm index 3c38927910..f4e51a0c30 100644 --- a/code/modules/mining/drilling/drill.dm +++ b/code/modules/mining/drilling/drill.dm @@ -52,16 +52,9 @@ var/need_update_field = 0 var/need_player_check = 0 -/obj/machinery/mining/drill/New() - - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/cell/high(src) - - RefreshParts() +/obj/machinery/mining/drill/Initialize() + . = ..() + default_apply_parts() /obj/machinery/mining/drill/process() diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index e1a3e01690..79ef6b1c4c 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -163,6 +163,8 @@ turf/simulated/mineral/floor/light_corner if(random_icon) dir = pick(alldirs) . = INITIALIZE_HINT_LATELOAD + var/decl/flooring/F = get_flooring_data(/decl/flooring/sand) + footstep_sounds = F?.footstep_sounds /turf/simulated/mineral/LateInitialize() if(density && mineral) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index e20d3740c9..349859029f 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -152,6 +152,13 @@ if(new_stat != DEAD) CRASH("It is best if observers stay dead, thank you.") +/mob/observer/dead/examine_icon() + var/icon/I = get_cached_examine_icon(src) + if(!I) + I = getFlatIcon(src, defdir = SOUTH, no_anim = TRUE) + set_cached_examine_icon(src, I, 200 SECONDS) + return I + /* Transfer_mind is there to check if mob is being deleted/not going to have a body. Works together with spawning an observer, noted above. diff --git a/code/modules/mob/freelook/ai/eye.dm b/code/modules/mob/freelook/ai/eye.dm index c79417cb86..5b37804da3 100644 --- a/code/modules/mob/freelook/ai/eye.dm +++ b/code/modules/mob/freelook/ai/eye.dm @@ -10,17 +10,36 @@ /mob/observer/eye/aiEye/New() ..() visualnet = cameranet + +/mob/observer/eye/aiEye/Destroy() + if(owner) + var/mob/living/silicon/ai/ai = owner + ai.all_eyes -= src + owner = null + . = ..() /mob/observer/eye/aiEye/setLoc(var/T, var/cancel_tracking = 1) - if(..()) + if(owner) + T = get_turf(T) + loc = T + var/mob/living/silicon/ai/ai = owner if(cancel_tracking) ai.ai_cancel_tracking() - //Holopad + if(use_static) + ai.camera_visibility(src) + + if(ai.client && !ai.multicam_on) + ai.client.eye = src + + if(ai.master_multicam) + ai.master_multicam.refresh_view() + if(ai.holo) if(ai.hologram_follow) ai.holo.move_hologram(ai) + return 1 // AI MOVEMENT @@ -46,6 +65,7 @@ if(!newloc) newloc = src.loc eyeobj = new /mob/observer/eye/aiEye(newloc) + all_eyes += eyeobj eyeobj.owner = src eyeobj.name = "[src.name] (AI Eye)" // Give it a name if(client) @@ -66,7 +86,12 @@ /atom/proc/move_camera_by_click() if(istype(usr, /mob/living/silicon/ai)) var/mob/living/silicon/ai/AI = usr - if(AI.eyeobj && AI.client.eye == AI.eyeobj) + if(AI.eyeobj) + if(!AI.multicam_on || AI.client.eye != AI.eyeobj) + return + var/area/A = get_area(AI.eyeobj) + if(istype(A, /area/ai_multicam_room)) + return var/turf/T = get_turf(src) if(T) AI.eyeobj.setLoc(T) diff --git a/code/modules/mob/freelook/chunk.dm b/code/modules/mob/freelook/chunk.dm index 41439b4adc..5f59d2e737 100644 --- a/code/modules/mob/freelook/chunk.dm +++ b/code/modules/mob/freelook/chunk.dm @@ -25,12 +25,12 @@ // Add an eye to the chunk, then update if changed. -/datum/chunk/proc/add(mob/observer/eye/eye) - if(!eye.owner) - return +/datum/chunk/proc/add(mob/observer/eye/eye, add_images = TRUE) + if(add_images) + var/client/client = eye.GetViewerClient() + if(client) + client.images += obscured eye.visibleChunks += src - if(eye.owner.client) - eye.owner.client.images += obscured visible++ seenby += eye if(changed && !updating) @@ -38,12 +38,12 @@ // Remove an eye from the chunk, then update if changed. -/datum/chunk/proc/remove(mob/observer/eye/eye) - if(!eye.owner) - return +/datum/chunk/proc/remove(mob/observer/eye/eye, remove_images = TRUE) + if(remove_images) + var/client/client = eye.GetViewerClient() + if(client) + client.images -= obscured eye.visibleChunks -= src - if(eye.owner.client) - eye.owner.client.images -= obscured seenby -= eye if(visible > 0) visible-- @@ -92,10 +92,11 @@ obscured -= t.obfuscations[obfuscation.type] for(var/eye in seenby) var/mob/observer/eye/m = eye - if(!m || !m.owner) + if(!m) continue - if(m.owner.client) - m.owner.client.images -= t.obfuscations[obfuscation.type] + var/client/client = m.GetViewerClient() + if(client) + client.images -= t.obfuscations[obfuscation.type] for(var/turf in visRemoved) var/turf/t = turf @@ -109,11 +110,12 @@ obscured += t.obfuscations[obfuscation.type] for(var/eye in seenby) var/mob/observer/eye/m = eye - if(!m || !m.owner) + if(!m) seenby -= m continue - if(m.owner.client) - m.owner.client.images += t.obfuscations[obfuscation.type] + var/client/client = m.GetViewerClient() + if(client) + client.images += t.obfuscations[obfuscation.type] /datum/chunk/proc/acquireVisibleTurfs(var/list/visible) diff --git a/code/modules/mob/freelook/eye.dm b/code/modules/mob/freelook/eye.dm index 85cfc736c9..89a15c3000 100644 --- a/code/modules/mob/freelook/eye.dm +++ b/code/modules/mob/freelook/eye.dm @@ -23,6 +23,8 @@ var/ghostimage = null var/datum/visualnet/visualnet + var/use_static = TRUE + var/static_visibility_range = 16 /mob/observer/eye/Destroy() if(owner) @@ -67,8 +69,8 @@ visualnet.updateVisibility(owner, 0) owner.loc = loc visualnet.updateVisibility(owner, 0) - - visualnet.visibility(src) + if(use_static) + visualnet.visibility(src, owner.client) return 1 return 0 @@ -85,6 +87,11 @@ return return eyeobj.EyeMove(n, direct) + +/mob/observer/eye/proc/GetViewerClient() + if(owner) + return owner.client + return null /mob/observer/eye/EyeMove(n, direct) var/initial = initial(sprint) diff --git a/code/modules/mob/freelook/visualnet.dm b/code/modules/mob/freelook/visualnet.dm index bbcd0c7d66..44cd9278cc 100644 --- a/code/modules/mob/freelook/visualnet.dm +++ b/code/modules/mob/freelook/visualnet.dm @@ -2,6 +2,8 @@ // // The datum containing all the chunks. +#define CHUNK_SIZE 16 + /datum/visualnet // The chunks of the map, mapping the areas that an object can see. var/list/chunks = list() @@ -36,29 +38,63 @@ // Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set. -/datum/visualnet/proc/visibility(mob/observer/eye/eye) - // 0xf = 15 - var/x1 = max(0, eye.x - 16) & ~0xf - var/y1 = max(0, eye.y - 16) & ~0xf - var/x2 = min(world.maxx, eye.x + 16) & ~0xf - var/y2 = min(world.maxy, eye.y + 16) & ~0xf +/datum/visualnet/proc/visibility(list/moved_eyes, client/C, list/other_eyes) + if(!islist(moved_eyes)) + moved_eyes = moved_eyes ? list(moved_eyes) : list() + if(islist(other_eyes)) + other_eyes = (other_eyes - moved_eyes) + else + other_eyes = list() - var/list/visibleChunks = list() + var/list/chunks_pre_seen = list() + var/list/chunks_post_seen = list() - for(var/x = x1; x <= x2; x += 16) - for(var/y = y1; y <= y2; y += 16) - visibleChunks += getChunk(x, y, eye.z) + for(var/V in moved_eyes) + var/mob/observer/eye/eye = V + if(C) + chunks_pre_seen |= eye.visibleChunks + // 0xf = 15 + var/static_range = eye.static_visibility_range + var/x1 = max(0, eye.x - static_range) & ~(CHUNK_SIZE - 1) + var/y1 = max(0, eye.y - static_range) & ~(CHUNK_SIZE - 1) + var/x2 = min(world.maxx, eye.x + static_range) & ~(CHUNK_SIZE - 1) + var/y2 = min(world.maxy, eye.y + static_range) & ~(CHUNK_SIZE - 1) - var/list/remove = eye.visibleChunks - visibleChunks - var/list/add = visibleChunks - eye.visibleChunks + var/list/visibleChunks = list() - for(var/chunk in remove) - var/datum/chunk/c = chunk - c.remove(eye) + for(var/x = x1; x <= x2; x += CHUNK_SIZE) + for(var/y = y1; y <= y2; y += CHUNK_SIZE) + visibleChunks |= getChunk(x, y, eye.z) - for(var/chunk in add) - var/datum/chunk/c = chunk - c.add(eye) + var/list/remove = eye.visibleChunks - visibleChunks + var/list/add = visibleChunks - eye.visibleChunks + + for(var/chunk in remove) + var/datum/chunk/c = chunk + c.remove(eye, FALSE) + + for(var/chunk in add) + var/datum/chunk/c = chunk + c.add(eye, FALSE) + + if(C) + chunks_post_seen |= eye.visibleChunks + + if(C) + for(var/V in other_eyes) + var/mob/observer/eye/eye = V + chunks_post_seen |= eye.visibleChunks + + var/list/remove = chunks_pre_seen - chunks_post_seen + var/list/add = chunks_post_seen - chunks_pre_seen + + for(var/chunk in remove) + var/datum/chunk/c = chunk + C.images -= c.obscured + + for(var/chunk in add) + var/datum/chunk/c = chunk + C.images += c.obscured // Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index f7ee2d9520..9687bde18f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1596,6 +1596,13 @@ else layer = HIDING_LAYER +/mob/living/carbon/human/examine_icon() + var/icon/I = get_cached_examine_icon(src) + if(!I) + I = getFlatIcon(src, defdir = SOUTH, no_anim = TRUE) + set_cached_examine_icon(src, I, 50 SECONDS) + return I + /mob/living/carbon/human/proc/get_display_species() //Shows species in tooltip if(src.custom_species) //VOREStation Add diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index a0892c9fc9..cd2d368d6d 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -2,40 +2,38 @@ /mob/living/carbon/human/movement_delay(oldloc, direct) - var/tally = 0 + . = 0 + + if (istype(loc, /turf/space)) + return ..() - 1 if(species.slowdown) - tally = species.slowdown - - if (istype(loc, /turf/space)) return -1 // It's hard to be slowed down in space by... anything - - if(embedded_flag) - handle_embedded_objects() //Moving with objects stuck in you can cause bad times. + . += species.slowdown if(force_max_speed) - return HUMAN_LOWEST_SLOWDOWN + return ..() + HUMAN_LOWEST_SLOWDOWN for(var/datum/modifier/M in modifiers) if(!isnull(M.haste) && M.haste == TRUE) - return HUMAN_LOWEST_SLOWDOWN // Returning -1 will actually result in a slowdown for Teshari. + return ..() + HUMAN_LOWEST_SLOWDOWN // Returning -1 will actually result in a slowdown for Teshari. if(!isnull(M.slowdown)) - tally += M.slowdown + . += M.slowdown var/health_deficiency = (getMaxHealth() - health) - if(health_deficiency >= 40) tally += (health_deficiency / 25) + if(health_deficiency >= 40) . += (health_deficiency / 25) if(can_feel_pain()) - if(halloss >= 10) tally += (halloss / 10) //halloss shouldn't slow you down if you can't even feel it + if(halloss >= 10) . += (halloss / 10) //halloss shouldn't slow you down if you can't even feel it var/hungry = (500 - nutrition) / 5 //VOREStation Edit - Fixed 500 here instead of our huge MAX_NUTRITION - if (hungry >= 70) tally += hungry/50 + if (hungry >= 70) . += hungry/50 //VOREstation start if (feral >= 10) //crazy feral animals give less and less of a shit about pain and hunger as they get crazier - tally = max(species.slowdown, species.slowdown+((tally-species.slowdown)/(feral/10))) // As feral scales to damage, this amounts to an effective +1 slowdown cap - if(shock_stage >= 10) tally -= 1.5 //this gets a +3 later, feral critters take reduced penalty + . = max(species.slowdown, species.slowdown+((.-species.slowdown)/(feral/10))) // As feral scales to damage, this amounts to an effective +1 slowdown cap + if(shock_stage >= 10) . -= 1.5 //this gets a +3 later, feral critters take reduced penalty if(reagents.has_reagent("numbenzyme")) - tally += 1.5 //A tad bit of slowdown. + . += 1.5 //A tad bit of slowdown. if(riding_datum) //Bit of slowdown for taur rides if rider is bigger or fatter than mount. var/datum/riding/R = riding_datum var/mob/living/L = R.ridden @@ -43,48 +41,48 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M if(H.size_multiplier > L.size_multiplier) - tally += 1 + . += 1 if(H.weight > L.weight) - tally += 1 + . += 1 //VOREstation end if(istype(buckled, /obj/structure/bed/chair/wheelchair)) for(var/organ_name in list(BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM)) var/obj/item/organ/external/E = get_organ(organ_name) if(!E || E.is_stump()) - tally += 4 + . += 4 else if(E.splinted && E.splinted.loc != E) - tally += 0.5 + . += 0.5 else if(E.status & ORGAN_BROKEN) - tally += 1.5 + . += 1.5 else for(var/organ_name in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)) var/obj/item/organ/external/E = get_organ(organ_name) if(!E || E.is_stump()) - tally += 4 + . += 4 else if(E.splinted && E.splinted.loc != E) - tally += 0.5 + . += 0.5 else if(E.status & ORGAN_BROKEN) - tally += 1.5 + . += 1.5 - if(shock_stage >= 10) tally += 3 + if(shock_stage >= 10) . += 3 - if(aiming && aiming.aiming_at) tally += 5 // Iron sights make you slower, it's a well-known fact. + if(aiming && aiming.aiming_at) . += 5 // Iron sights make you slower, it's a well-known fact. if(FAT in src.mutations) - tally += 1.5 + . += 1.5 if (bodytemperature < species.cold_level_1) - tally += (species.cold_level_1 - bodytemperature) / 10 * 1.75 + . += (species.cold_level_1 - bodytemperature) / 10 * 1.75 - tally += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow + . += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow if(mRun in mutations) - tally = 0 + . = 0 // Turf related slowdown var/turf/T = get_turf(src) - tally += calculate_turf_slowdown(T, direct) + . += calculate_turf_slowdown(T, direct) // Item related slowdown. var/item_tally = calculate_item_encumbrance() @@ -101,19 +99,25 @@ item_tally *= species.item_slowdown_mod - tally += item_tally + . += item_tally if(CE_SLOWDOWN in chem_effects) - if (tally >= 0 ) - tally = (tally + tally/4) //Add a quarter of penalties on top. - tally += chem_effects[CE_SLOWDOWN] + if (. >= 0 ) + . *= 1.25 //Add a quarter of penalties on top. + . += chem_effects[CE_SLOWDOWN] if(CE_SPEEDBOOST in chem_effects) - if (tally >= 0) // cut any penalties in half - tally = tally/2 - tally -= chem_effects[CE_SPEEDBOOST] // give 'em a buff on top. + if (. >= 0) // cut any penalties in half + . *= 0.5 + . -= chem_effects[CE_SPEEDBOOST] // give 'em a buff on top. - return max(HUMAN_LOWEST_SLOWDOWN, tally+config.human_delay) // Minimum return should be the same as force_max_speed + . = max(HUMAN_LOWEST_SLOWDOWN, . + config.human_delay) // Minimum return should be the same as force_max_speed + . += ..() + +/mob/living/carbon/human/Moved() + . = ..() + if(embedded_flag) + handle_embedded_objects() //Moving with objects stuck in you can cause bad times. // This calculates the amount of slowdown to receive from items worn. This does NOT include species modifiers. // It is in a seperate place to avoid an infinite loop situation with dragging mobs dragging each other. diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index e4162219fe..ed41c4c69b 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -322,7 +322,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() base_icon.MapColors(rgb(tone[1],0,0),rgb(0,tone[2],0),rgb(0,0,tone[3])) //Handle husk overlay. - if(husk && ("overlay_husk" in icon_states(species.icobase))) + if(husk && ("overlay_husk" in cached_icon_states(species.icobase))) var/icon/mask = new(base_icon) var/icon/husk_over = new(species.icobase,"overlay_husk") mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 8fc975073e..d74f43bced 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -224,7 +224,15 @@ default behaviour is: for(var/obj/structure/window/win in get_step(AM,t)) now_pushing = 0 return - step(AM, t) + var/turf/T = AM.loc + var/turf/T2 = get_step(AM,t) + if(!T2) // Map edge + now_pushing = 0 + return + var/move_time = movement_delay(loc, t) + move_time = DS2NEARESTTICK(move_time) + if(AM.Move(T2, t, move_time)) + Move(T, t, move_time) if(ishuman(AM) && AM:grabbed_by) for(var/obj/item/weapon/grab/G in AM:grabbed_by) step(G:assailant, get_dir(G:assailant, AM)) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index fa59ebf5c8..61f0be1a95 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -85,6 +85,14 @@ var/list/ai_verbs_default = list( var/datum/ai_icon/selected_sprite // The selected icon set var/custom_sprite = 0 // Whether the selected icon is custom var/carded + + // Multicam Vars + var/multicam_allowed = TRUE + var/multicam_on = FALSE + var/obj/screen/movable/pic_in_pic/ai/master_multicam + var/list/multicam_screens = list() + var/list/all_eyes = list() + var/max_multicams = 6 can_be_antagged = TRUE @@ -478,12 +486,27 @@ var/list/ai_verbs_default = list( return +/mob/living/silicon/ai/proc/camera_visibility(mob/observer/eye/aiEye/moved_eye) + cameranet.visibility(moved_eye, client, all_eyes) + +/mob/living/silicon/ai/forceMove(atom/destination) + . = ..() + if(.) + end_multicam() + /mob/living/silicon/ai/reset_view(atom/A) if(camera) camera.set_light(0) if(istype(A,/obj/machinery/camera)) camera = A - ..() + if(A != GLOB.ai_camera_room_landmark) + end_multicam() + . = ..() + if(.) + if(!A && isturf(loc) && eyeobj) + end_multicam() + client.eye = eyeobj + client.perspective = MOB_PERSPECTIVE if(istype(A,/obj/machinery/camera)) if(camera_light_on) A.set_light(AI_CAMERA_LUMINOSITY) else A.set_light(0) diff --git a/code/modules/mob/living/silicon/ai/ai_vr.dm b/code/modules/mob/living/silicon/ai/ai_vr.dm index 0fe723cad3..2f22d0e788 100644 --- a/code/modules/mob/living/silicon/ai/ai_vr.dm +++ b/code/modules/mob/living/silicon/ai/ai_vr.dm @@ -7,7 +7,7 @@ add_language(LANGUAGE_DAEMON, 1) add_language(LANGUAGE_ENOCHIAN, 1) -/mob/AIize(move = 1) +/mob/AIize(var/move = TRUE) . = ..() add_language(LANGUAGE_BIRDSONG, 1) add_language(LANGUAGE_SAGARU, 1) diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index b1398d3170..e155b8e005 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -94,6 +94,7 @@ spawn(20) to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.") + end_multicam() sleep(50) if (loc.power_equip) if (!istype(T, /turf/space)) diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm index fa06162c31..57856a861f 100644 --- a/code/modules/mob/living/silicon/ai/login.dm +++ b/code/modules/mob/living/silicon/ai/login.dm @@ -1,4 +1,4 @@ -/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up ¬_¬ ~Carn +/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up �_� ~Carn ..() for(var/obj/effect/rune/rune in rune_list) client.images += rune.blood_image @@ -6,5 +6,7 @@ for(var/obj/machinery/ai_status_display/O in machines) //change status O.mode = 1 O.emotion = "Neutral" + if(multicam_on) + end_multicam() src.view_core() return \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm new file mode 100644 index 0000000000..018454608c --- /dev/null +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -0,0 +1,327 @@ +//Picture in picture + +/obj/screen/movable/pic_in_pic/ai + var/mob/living/silicon/ai/ai + var/list/highlighted_mas = list() + var/highlighted = FALSE + var/mob/observer/eye/aiEye/pic_in_pic/aiEye + +/obj/screen/movable/pic_in_pic/ai/Initialize() + . = ..() + aiEye = new /mob/observer/eye/aiEye/pic_in_pic() + aiEye.screen = src + +/obj/screen/movable/pic_in_pic/ai/Destroy() + . = ..() + if(!QDELETED(aiEye)) + QDEL_NULL(aiEye) + else + aiEye = null + set_ai(null) + +/obj/screen/movable/pic_in_pic/ai/Click() + ..() + if(ai) + ai.select_main_multicam_window(src) + +/obj/screen/movable/pic_in_pic/ai/make_backgrounds() + ..() + var/mutable_appearance/base = new /mutable_appearance() + base.icon = 'icons/misc/pic_in_pic.dmi' + base.layer = DISPOSAL_LAYER + base.plane = PLATING_PLANE + base.appearance_flags = PIXEL_SCALE + + for(var/direction in cardinal) + var/mutable_appearance/dir = new /mutable_appearance(base) + dir.dir = direction + dir.icon_state = "background_highlight_[direction]" + highlighted_mas += dir + +/obj/screen/movable/pic_in_pic/ai/add_background() + if((width > 0) && (height > 0)) + if(!highlighted) + return ..() + + for(var/mutable_appearance/dir in highlighted_mas) + var/matrix/M = matrix() + var/x_scale = 1 + var/y_scale = 1 + + var/x_off = 0 + var/y_off = 0 + + if(dir.dir & (NORTH|SOUTH)) + x_scale = width + x_off = (width-1)/2 * world.icon_size + if(dir.dir & NORTH) + y_off = ((height-1) * world.icon_size) + 3 + else + y_off = -3 + + if(dir.dir & (EAST|WEST)) + y_scale = height + y_off = (height-1)/2 * world.icon_size + if(dir.dir & EAST) + x_off = ((width-1) * world.icon_size) + 3 + else + x_off = -3 + + M.Scale(x_scale, y_scale) + M.Translate(x_off, y_off) + dir.transform = M + overlays += dir + +/obj/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE) + if(!aiEye) + qdel(src) + return + + aiEye.static_visibility_range = (round(max(width, height) / 2) + 1) + if(ai) + ai.camera_visibility(aiEye) + ..() + +/obj/screen/movable/pic_in_pic/ai/set_view_center(atom/target, do_refresh = TRUE) + ..() + if(!aiEye) + qdel(src) + return + + aiEye.setLoc(get_turf(target)) + +/obj/screen/movable/pic_in_pic/ai/refresh_view() + ..() + if(!aiEye) + qdel(src) + return + + aiEye.setLoc(get_turf(center)) + +/obj/screen/movable/pic_in_pic/ai/proc/highlight() + if(highlighted) + return + if(!aiEye) + qdel(src) + return + highlighted = TRUE + overlays.Cut() + add_background() + add_buttons() + +/obj/screen/movable/pic_in_pic/ai/proc/unhighlight() + if(!highlighted) + return + if(!aiEye) + qdel(src) + return + highlighted = FALSE + overlays.Cut() + add_background() + add_buttons() + +/obj/screen/movable/pic_in_pic/ai/proc/set_ai(mob/living/silicon/ai/new_ai) + if(!aiEye && !QDELETED(src)) + if(new_ai) + to_chat(new_ai, "

You've run into a unfixable bug with AI eye code. \ +In order to create a new multicam, you will have to select a different camera first before trying to add one, or ask an admin to fix you. \ +Whatever you did that made the last camera window disappear-- don't do that again.

") + qdel(src) + return + if(ai) + ai.multicam_screens -= src + ai.all_eyes -= aiEye + if(ai.master_multicam == src) + ai.master_multicam = null + if(ai.multicam_on) + unshow_to(ai.client) + ai = new_ai + if(new_ai) + new_ai.multicam_screens += src + ai.all_eyes += aiEye + if(new_ai.multicam_on) + show_to(new_ai.client) + +//Turf, area, and landmark for the viewing room + +/turf/unsimulated/ai_visible + name = "" + icon = 'icons/misc/pic_in_pic.dmi' + icon_state = "room_background" + flags = NOJAUNT + plane = SPACE_PLANE + layer = AREA_LAYER + 0.1 + +/turf/unsimulated/ai_visible/Initialize() + . = ..() + +/area/ai_multicam_room + name = "ai_multicam_room" + icon_state = "ai_camera_room" + dynamic_lighting = FALSE + ambience = list() + +GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) + +/obj/effect/landmark/ai_multicam_room + name = "ai camera room" + icon_state = "x" + +/obj/effect/landmark/ai_multicam_room/Initialize() + . = ..() + qdel(GLOB.ai_camera_room_landmark) + GLOB.ai_camera_room_landmark = src + +/obj/effect/landmark/ai_multicam_room/Destroy() + if(GLOB.ai_camera_room_landmark == src) + GLOB.ai_camera_room_landmark = null + return ..() + +//Dummy camera eyes + +/mob/observer/eye/aiEye/pic_in_pic + name = "Secondary AI Eye" + var/obj/screen/movable/pic_in_pic/ai/screen + var/list/cameras_telegraphed = list() + var/telegraph_cameras = TRUE + var/telegraph_range = 7 + +/mob/observer/eye/aiEye/pic_in_pic/GetViewerClient() + if(screen && screen.ai) + return screen.ai.client + +/mob/observer/eye/aiEye/pic_in_pic/setLoc(turf/T) + T = get_turf(T) + forceMove(T) + if(screen && screen.ai) + screen.ai.camera_visibility(src) + else + cameranet.visibility(src) + update_camera_telegraphing() + +/mob/observer/eye/aiEye/pic_in_pic/proc/update_camera_telegraphing() + if(!telegraph_cameras) + return + var/list/obj/machinery/camera/add = list() + var/list/obj/machinery/camera/remove = list() + var/list/obj/machinery/camera/visible = list() + for(var/VV in visibleChunks) + var/datum/chunk/camera/CC = VV + for(var/V in CC.cameras) + var/obj/machinery/camera/C = V + if (!C.can_use() || (get_dist(C, src) > telegraph_range)) + continue + visible |= C + + add = visible - cameras_telegraphed + remove = cameras_telegraphed - visible + + for(var/V in remove) + var/obj/machinery/camera/C = V + if(QDELETED(C)) + continue + cameras_telegraphed -= C + C.in_use_lights-- + C.update_icon() + for(var/V in add) + var/obj/machinery/camera/C = V + if(QDELETED(C)) + continue + cameras_telegraphed |= C + C.in_use_lights++ + C.update_icon() + +/mob/observer/eye/aiEye/pic_in_pic/proc/disable_camera_telegraphing() + telegraph_cameras = FALSE + for(var/V in cameras_telegraphed) + var/obj/machinery/camera/C = V + if(QDELETED(C)) + continue + C.in_use_lights-- + C.update_icon() + cameras_telegraphed.Cut() + +/mob/observer/eye/aiEye/pic_in_pic/Destroy() + disable_camera_telegraphing() + if(screen && screen.ai) + screen.ai.all_eyes -= src + if(!QDELETED(screen)) + QDEL_NULL(screen) + else + screen = null + return ..() + +//AI procs + +/mob/living/silicon/ai/proc/drop_new_multicam(silent = FALSE) + if(!multicam_allowed) + if(!silent) + to_chat(src, "This action is currently disabled. Contact an administrator to enable this feature.") + return + if(!eyeobj) + return + if(multicam_screens.len >= max_multicams) + if(!silent) + to_chat(src, "Cannot place more than [max_multicams] multicamera windows.") + return + var/obj/screen/movable/pic_in_pic/ai/C = new /obj/screen/movable/pic_in_pic/ai() + C.set_view_size(3, 3, FALSE) + C.set_view_center(get_turf(eyeobj)) + C.set_ai(src) + if(!silent) + to_chat(src, "Added new multicamera window.") + return C + +/mob/living/silicon/ai/proc/toggle_multicam() + if(!multicam_allowed) + to_chat(src, "This action is currently disabled. Contact an administrator to enable this feature.") + return + if(multicam_on) + end_multicam() + else + start_multicam() + +/mob/living/silicon/ai/proc/start_multicam() + if(multicam_on || aiRestorePowerRoutine || !isturf(loc)) + return + if(!GLOB.ai_camera_room_landmark) + to_chat(src, "This function is not available at this time.") + return + multicam_on = TRUE + refresh_multicam() + to_chat(src, "Multiple-camera viewing mode activated.") + +/mob/living/silicon/ai/proc/refresh_multicam() + reset_view(GLOB.ai_camera_room_landmark) + if(client) + for(var/V in multicam_screens) + var/obj/screen/movable/pic_in_pic/P = V + P.show_to(client) + +/mob/living/silicon/ai/proc/end_multicam() + if(!multicam_on) + return + multicam_on = FALSE + select_main_multicam_window(null) + if(client) + for(var/V in multicam_screens) + var/obj/screen/movable/pic_in_pic/P = V + P.unshow_to(client) + reset_view() + to_chat(src, "Multiple-camera viewing mode deactivated.") + + +/mob/living/silicon/ai/proc/select_main_multicam_window(obj/screen/movable/pic_in_pic/ai/P) + if(master_multicam == P) + return + + if(master_multicam) + master_multicam.set_view_center(get_turf(eyeobj), FALSE) + master_multicam.unhighlight() + master_multicam = null + + if(P) + P.highlight() + eyeobj.setLoc(get_turf(P.center)) + P.set_view_center(eyeobj) + master_multicam = P diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm index 7664e57103..b7241721f1 100644 --- a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm @@ -22,7 +22,7 @@ var/emagged = 0 /obj/item/weapon/dogborg/jaws/small/attack_self(mob/user) - var/mob/living/silicon/robot.R = user + var/mob/living/silicon/robot/R = user if(R.emagged || R.emag_items) emagged = !emagged if(emagged) @@ -187,7 +187,7 @@ . += "[src] is dry." /obj/item/device/dogborg/tongue/attack_self(mob/user) - var/mob/living/silicon/robot.R = user + var/mob/living/silicon/robot/R = user if(R.emagged || R.emag_items) emagged = !emagged if(emagged) @@ -222,7 +222,7 @@ to_chat(user, "You finish licking off \the [target.name].") water.use_charge(5) qdel(target) - var/mob/living/silicon/robot.R = user + var/mob/living/silicon/robot/R = user R.cell.charge += 50 else if(istype(target,/obj/item)) if(istype(target,/obj/item/trash)) @@ -231,7 +231,7 @@ user.visible_message("[user] finishes eating \the [target.name].", "You finish eating \the [target.name].") to_chat(user, "You finish off \the [target.name].") qdel(target) - var/mob/living/silicon/robot.R = user + var/mob/living/silicon/robot/R = user R.cell.charge += 250 water.use_charge(5) return @@ -249,8 +249,8 @@ if(do_after (user, 50)) user.visible_message("[user] finishes gulping down \the [target.name].", "You finish swallowing \the [target.name].") to_chat(user, "You finish off \the [target.name], and gain some charge!") - var/mob/living/silicon/robot.R = user - var/obj/item/weapon/cell.C = target + var/mob/living/silicon/robot/R = user + var/obj/item/weapon/cell/C = target R.cell.charge += C.maxcharge / 3 water.use_charge(5) qdel(target) @@ -264,7 +264,7 @@ target.clean_blood() else if(ishuman(target)) if(src.emagged) - var/mob/living/silicon/robot.R = user + var/mob/living/silicon/robot/R = user var/mob/living/L = target if(R.cell.charge <= 666) return @@ -307,7 +307,7 @@ flags |= NOBLUDGEON /obj/item/pupscrubber/attack_self(mob/user) - var/mob/living/silicon/robot.R = user + var/mob/living/silicon/robot/R = user if(!enabled) R.scrubbing = TRUE enabled = TRUE diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index b83b7bfee9..77e0f0cbe9 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -15,14 +15,14 @@ //No longer needed, but I'll leave it here incase we plan to re-use it. /mob/living/silicon/robot/movement_delay() - var/tally = 0 //Incase I need to add stuff other than "speed" later - - tally = speed + . = speed if(module_active && istype(module_active,/obj/item/borg/combat/mobility)) - tally-=2 // VOREStation Edit + . -= 2 // VOREStation Edit - return tally+config.robot_delay + . += config.robot_delay + + . += ..() // NEW: Use power while moving. /mob/living/silicon/robot/SelfMove(turf/n, direct) diff --git a/code/modules/mob/living/silicon/robot/subtypes/lost_drone_vr.dm b/code/modules/mob/living/silicon/robot/subtypes/lost_drone_vr.dm index 63d412cb17..4416117d6c 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/lost_drone_vr.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/lost_drone_vr.dm @@ -157,7 +157,7 @@ if("corrupted") // Load them up with ion laws. var/datum/ai_laws/laws = new() // Start with an empty lawset. - for(1 to rand(1, 3)) + for(var/i=1 to rand(1, 3)) laws.add_ion_law(generate_ion_law(exclude_crew_names = TRUE)) return laws diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 2e42d6d92c..b98340baef 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -410,7 +410,7 @@ return /mob/living/silicon/reset_view() - ..() + . = ..() if(cameraFollow) cameraFollow = null diff --git a/code/modules/mob/living/simple_mob/appearance.dm b/code/modules/mob/living/simple_mob/appearance.dm index 05f758d7c4..14f09e9057 100644 --- a/code/modules/mob/living/simple_mob/appearance.dm +++ b/code/modules/mob/living/simple_mob/appearance.dm @@ -65,7 +65,7 @@ if(!eye_layer) eye_layer = image(icon, "[icon_state]-eyes") eye_layer.plane = PLANE_LIGHTING_ABOVE - + eye_layer.appearance_flags = appearance_flags //VOREStation Edit. Make eye overlays respect the mob's scaling settings. add_overlay(eye_layer) /mob/living/simple_mob/proc/remove_eyes() diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm index 71e7736ebb..3b063e1ac4 100644 --- a/code/modules/mob/living/simple_mob/simple_mob.dm +++ b/code/modules/mob/living/simple_mob/simple_mob.dm @@ -212,9 +212,7 @@ return ..() */ /mob/living/simple_mob/movement_delay() - var/tally = 0 //Incase I need to add stuff other than "speed" later - - tally = movement_cooldown + . = movement_cooldown if(force_max_speed) return -3 @@ -223,25 +221,27 @@ if(!isnull(M.haste) && M.haste == TRUE) return -3 if(!isnull(M.slowdown)) - tally += M.slowdown + . += M.slowdown // Turf related slowdown var/turf/T = get_turf(src) if(T && T.movement_cost && !hovering) // Flying mobs ignore turf-based slowdown. Aquatic mobs ignore water slowdown, and can gain bonus speed in it. if(istype(T,/turf/simulated/floor/water) && aquatic_movement) - tally -= aquatic_movement - 1 + . -= aquatic_movement - 1 else - tally += T.movement_cost + . += T.movement_cost if(purge)//Purged creatures will move more slowly. The more time before their purge stops, the slower they'll move. - if(tally <= 0) - tally = 1 - tally *= purge + if(. <= 0) + . = 1 + . *= purge if(m_intent == "walk") - tally *= 1.5 + . *= 1.5 - return tally+config.animal_delay + . += config.animal_delay + + . += ..() /mob/living/simple_mob/Stat() diff --git a/code/modules/mob/living/simple_mob/simple_mob_vr.dm b/code/modules/mob/living/simple_mob/simple_mob_vr.dm index 257aaff7f2..86380b5b26 100644 --- a/code/modules/mob/living/simple_mob/simple_mob_vr.dm +++ b/code/modules/mob/living/simple_mob/simple_mob_vr.dm @@ -66,6 +66,7 @@ var/obj/belly/B = belly for(var/mob/living/M in B) new_fullness += M.size_multiplier + new_fullness = new_fullness / size_multiplier //Divided by pred's size so a macro mob won't get macro belly from a regular prey. new_fullness = round(new_fullness, 1) // Because intervals of 0.25 are going to make sprite artists cry. vore_fullness = min(vore_capacity, new_fullness) @@ -430,4 +431,4 @@ var/armor_soak = get_armor_soak(T, "melee") T.apply_damage(20, HALLOSS,, armor_block, armor_soak) if(prob(33)) - T.apply_effect(3, WEAKEN, armor_block) \ No newline at end of file + T.apply_effect(3, WEAKEN, armor_block) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm index 7d32b7b350..6a52dd69b4 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm @@ -113,7 +113,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 3 /mob/living/simple_mob/vore/aggressive/corrupthound/MouseDrop_T(mob/living/M, mob/living/user) return diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm b/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm index 4ca3bbec4b..54afef8238 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm @@ -56,7 +56,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 3 /mob/living/simple_mob/vore/aggressive/deathclaw/MouseDrop_T(mob/living/M, mob/living/user) return diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm b/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm index e6b33604b9..323e0d9c9b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm @@ -80,7 +80,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 3 /mob/living/simple_mob/vore/aggressive/dragon/MouseDrop_T(mob/living/M, mob/living/user) return diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm b/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm index 42ee04c417..b58ebca5ae 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm @@ -72,7 +72,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 3 /mob/living/simple_mob/vore/hippo/MouseDrop_T(mob/living/M, mob/living/user) return diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm b/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm index b373dacfd7..8c9f08a471 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm @@ -46,7 +46,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 3 /mob/living/simple_mob/vore/horse/MouseDrop_T(mob/living/M, mob/living/user) return diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm b/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm index 97313f4db1..cf75159b27 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm @@ -285,7 +285,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 3 /mob/living/simple_mob/otie/MouseDrop_T(mob/living/M, mob/living/user) return 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 e0e952d001..23c6c4b1d3 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm @@ -51,7 +51,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 3 /mob/living/simple_mob/vore/aggressive/panther/MouseDrop_T(mob/living/M, mob/living/user) return diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm index 1c5443f6f5..11c19794f7 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm @@ -197,7 +197,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 3 /mob/living/simple_mob/vore/aggressive/rat/MouseDrop_T(mob/living/M, mob/living/user) return @@ -236,4 +236,4 @@ say_got_target = list("SQUEEK!") /datum/ai_holder/simple_mob/melee/rat - speak_chance = 3 + speak_chance = 2 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm b/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm index a8bc70ac0c..65c64bb9f3 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm @@ -91,6 +91,7 @@ can_buckle = TRUE buckle_movable = TRUE buckle_lying = FALSE + vore_icons = SA_ICON_LIVING | SA_ICON_REST /mob/living/simple_mob/animal/wolf/direwolf/Login() . = ..() @@ -98,7 +99,7 @@ riding_datum = new /datum/riding/simple_mob(src) verbs |= /mob/living/simple_mob/proc/animal_mount verbs |= /mob/living/proc/toggle_rider_reins - movement_cooldown = 0 + movement_cooldown = 2 /mob/living/simple_mob/animal/wolf/direwolf/MouseDrop_T(mob/living/M, mob/living/user) return diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index fc326c8d03..34a7035d22 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -15,7 +15,7 @@ if(matches) matches += " and " matches += "ID ([client.computer_id])" if(!config.disable_cid_warn_popup) - spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!") + spawn() alert("You appear to have logged in with another key this round, which is not permitted. Please contact an administrator if you believe this message to be in error.") if(matches) if(M.client) message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)].", 1) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 315a80702b..44a524155a 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -148,7 +148,18 @@ return 0 /mob/proc/movement_delay(oldloc, direct) - return 0 + . = 0 + if(locate(/obj/item/weapon/grab) in src) + . += 7 + + // Movespeed delay based on movement mode + switch(m_intent) + if("run") + if(drowsyness > 0) + . += 6 + . += config.run_speed + if("walk") + . += config.walk_speed /mob/proc/Life() // if(organStructure) @@ -218,7 +229,7 @@ else client.perspective = EYE_PERSPECTIVE client.eye = loc - return + return 1 /mob/proc/show_inv(mob/user as mob) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index c7a4a94ce8..3d0f88e7a7 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -37,6 +37,9 @@ if(isliving(usr)) var/mob/living/carbon/C = usr if(!C.get_active_hand()) + if(C.pulling) + C.stop_pulling() + return to_chat(usr, "You have nothing to drop in your hand.") return drop_item() @@ -246,26 +249,9 @@ // We are now going to move moving = 1 - var/total_delay = 0 + var/total_delay = my_mob.movement_delay(n, direct) var/pre_move_loc = loc - // Start tally'ing when we can next move - // Grabs slow you down - if(locate(/obj/item/weapon/grab) in my_mob) - total_delay += 7 - - // Movespeed delay based on movement mode - switch(my_mob.m_intent) - if("run") - if(my_mob.drowsyness > 0) - total_delay += 6 - total_delay += config.run_speed - if("walk") - total_delay += config.walk_speed - - // A billion other things can slow you down, ask the mob - total_delay += my_mob.movement_delay(n, direct) - // Confused direction randomization if(my_mob.confused) switch(my_mob.m_intent) @@ -278,7 +264,7 @@ direct = turn(direct, pick(90, -90)) n = get_step(my_mob, direct) - total_delay = TICKS2DS(-round(-(DS2TICKS(total_delay)))) //Rounded to the next tick in equivalent ds + total_delay = DS2NEARESTTICK(total_delay) //Rounded to the next tick in equivalent ds my_mob.setMoveCooldown(total_delay) . = my_mob.SelfMove(n, direct, total_delay) diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index 43b562b27e..9949b3f836 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -11,7 +11,7 @@ var/obj/effect/lobby_image = new /obj/effect/lobby_image /obj/effect/lobby_image/Initialize() icon = using_map.lobby_icon - var/known_icon_states = icon_states(icon) + var/known_icon_states = cached_icon_states(icon) for(var/lobby_screen in using_map.lobby_screens) if(!(lobby_screen in known_icon_states)) error("Lobby screen '[lobby_screen]' did not exist in the icon set [icon].") diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 314186936b..7c5b354d42 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -348,8 +348,11 @@ if(!job.is_position_available()) return 0 if(jobban_isbanned(src,rank)) return 0 if(!job.player_old_enough(src.client)) return 0 - if(!is_job_whitelisted(src,rank)) return 0 //VOREStation Code - if(!job.player_has_enough_pto(src.client)) return 0 //VOREStation Code + //VOREStation Add + if(!job.player_has_enough_playtime(src.client)) return 0 + if(!is_job_whitelisted(src,rank)) return 0 + if(!job.player_has_enough_pto(src.client)) return 0 + //VOREStation Add End return 1 @@ -365,7 +368,7 @@ if(!IsJobAvailable(rank)) alert(src,"[rank] is not available. Please try another.") return 0 - if(!attempt_vr(src,"spawn_checks_vr",list())) return 0 // VOREStation Insert + if(!spawn_checks_vr(rank)) return 0 // VOREStation Insert if(!client) return 0 @@ -391,10 +394,10 @@ character = job_master.EquipRank(character, rank, 1) //equips the human UpdateFactionList(character) - // AIs don't need a spawnpoint, they must spawn at an empty core - if(character.mind.assigned_role == "AI") + var/datum/job/J = SSjob.get_job(rank) - character = character.AIize(move=0) // AIize the character, but don't move them yet + // AIs don't need a spawnpoint, they must spawn at an empty core + if(J.mob_type & JOB_SILICON_AI) // IsJobAvailable for AI checks that there is an empty core available in this list var/obj/structure/AIcore/deactivated/C = empty_playable_ai_cores[1] @@ -402,11 +405,14 @@ character.loc = C.loc + // AIize the character, but don't move them yet + character = character.AIize(move = FALSE) // Dupe of code in /datum/controller/subsystem/ticker/proc/create_characters() for non-latespawn, unify? + AnnounceCyborg(character, rank, "has been transferred to the empty core in \the [character.loc.loc]") ticker.mode.latespawn(character) - qdel(C) - qdel(src) + qdel(C) //Deletes empty core (really?) + qdel(src) //Deletes new_player return // Equip our custom items only AFTER deploying to spawn points eh? @@ -420,18 +426,15 @@ character.buckled.set_dir(character.dir) ticker.mode.latespawn(character) - - if(character.mind.assigned_role != "Cyborg") + + if(J.mob_type & JOB_SILICON) + AnnounceCyborg(character, rank, join_message, announce_channel, character.z) + else + AnnounceArrival(character, rank, join_message, announce_channel, character.z) data_core.manifest_inject(character) ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn - - //Grab some data from the character prefs for use in random news procs. - - AnnounceArrival(character, rank, join_message, announce_channel, character.z) - else - AnnounceCyborg(character, rank, join_message, announce_channel, character.z) - - qdel(src) + + qdel(src) // Delete new_player mob /mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message, var/channel, var/zlevel) if (ticker.current_state == GAME_STATE_PLAYING) @@ -491,7 +494,6 @@ /mob/new_player/proc/create_character(var/turf/T) - if (!attempt_vr(src,"spawn_checks_vr",list())) return 0 // VOREStation Insert spawning = 1 close_spawn_windows() @@ -606,6 +608,12 @@ /mob/new_player/hear_say(var/list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null) return +/mob/new_player/hear_holopad_talk(list/message_pieces, var/verb = "says", var/mob/speaker = null) + return + +/mob/new_player/hear_holopad_talk(list/message_pieces, var/verb = "says", var/mob/speaker = null) + return + // Prevents lobby players from seeing emotes, even with ghosteyes /mob/new_player/show_message(msg, type, alt, alt_type) return diff --git a/code/modules/mob/new_player/new_player_vr.dm b/code/modules/mob/new_player/new_player_vr.dm index 711332e692..1c56e278f8 100644 --- a/code/modules/mob/new_player/new_player_vr.dm +++ b/code/modules/mob/new_player/new_player_vr.dm @@ -1,36 +1,41 @@ -/mob/new_player/proc/spawn_checks_vr() +/mob/new_player/proc/spawn_checks_vr(var/rank) var/pass = TRUE + var/datum/job/J = SSjob.get_job(rank) + + if(!J) + log_debug("Couldn't find job: [rank] for spawn_checks_vr, panic-returning that it's fine to spawn.") + return TRUE //No Flavor Text - if (config.require_flavor && client && client.prefs && client.prefs.flavor_texts && !client.prefs.flavor_texts["general"]) + if (config.require_flavor && !client?.prefs?.flavor_texts["general"] && !(J.mob_type & JOB_SILICON)) to_chat(src,"Please set your general flavor text to give a basic description of your character. Set it using the 'Set Flavor text' button on the 'General' tab in character setup, and choosing 'General' category.") pass = FALSE //No OOC notes - if (config.allow_Metadata && client && client.prefs && (isnull(client.prefs.metadata) || length(client.prefs.metadata) < 15)) + if (config.allow_Metadata && !(client?.prefs?.metadata || length(client.prefs.metadata) < 15)) to_chat(src,"Please set informative OOC notes related to ERP preferences. Set them using the 'OOC Notes' button on the 'General' tab in character setup.") pass = FALSE //Are they on the VERBOTEN LIST? - if (prevent_respawns.Find(client.prefs.real_name)) + if (prevent_respawns.Find(client?.prefs?.real_name)) to_chat(src,"You've already quit the round as this character. You can't go back now that you've free'd your job slot. Play another character, or wait for the next round.") pass = FALSE //Do they have their scale properly setup? - if(!client.prefs.size_multiplier) + if(!client?.prefs?.size_multiplier) pass = FALSE to_chat(src,"You have not set your scale yet. Do this on the VORE tab in character setup.") //Can they play? - if(!is_alien_whitelisted(src,GLOB.all_species[client.prefs.species]) && !check_rights(R_ADMIN, 0)) + if(!is_alien_whitelisted(src,GLOB.all_species[client?.prefs?.species]) && !check_rights(R_ADMIN, 0)) pass = FALSE to_chat(src,"You are not allowed to spawn in as this species.") //Custom species checks - if (client && client.prefs && client.prefs.species == "Custom Species") + if (client?.prefs?.species == "Custom Species") //Didn't name it - if(!client.prefs.custom_species) + if(!client?.prefs?.custom_species) pass = FALSE to_chat(src,"You have to name your custom species. Do this on the VORE tab in character setup.") diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 6db108fa6f..7a20d0ee8e 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -152,8 +152,8 @@ /mob/proc/find_valid_prefixes(message) var/list/prefixes = list() // [["Common", start, end], ["Gutter", start, end]] for(var/i in 1 to length(message)) - // This grabs trimmed 3 character substrings, to allow for up to 1 prefix and 1 letter language keys - var/selection = trim_right(copytext(message, i, i + 2)) // VOREStation Edit: We use uppercase keys to avoid Polaris key duplication, but this had lowertext() in it + // This grabs 3 character substrings, to allow for up to 1 prefix, 1 letter language key, and one post-key character to more strictly control where the language breaks happen + var/selection = trim_right(copytext(message, i, i + 3)) // VOREStation Edit: We use uppercase keys to avoid Polaris key duplication, but this had lowertext() in it // The first character in the selection will always be the prefix (if this is a valid language invocation) var/prefix = copytext(selection, 1, 2) var/language_key = copytext(selection, 2, 3) @@ -161,6 +161,18 @@ // Okay, we're definitely now trying to invoke a language (probably) // This "[]" is probably unnecessary but BYOND will runtime if a number is used var/datum/language/L = GLOB.language_keys["[language_key]"] + + // MULTILINGUAL_SPACE enforces a space after the language key + if(client && (client.prefs.multilingual_mode == MULTILINGUAL_SPACE) && (text2ascii(copytext(selection, 3, 4)) != 32)) // If we're looking for a space and we don't find one + continue + + // MULTILINGUAL_DOUBLE_DELIMITER enforces a delimiter (valid prefix) after the language key + if(client && (client.prefs.multilingual_mode == MULTILINGUAL_DOUBLE_DELIMITER) && !is_language_prefix(copytext(selection, 3, 4))) + continue + + if(client && (client.prefs.multilingual_mode in list(MULTILINGUAL_DEFAULT))) + selection = copytext(selection, 1, 3) // These modes only use two characters, not three + // It's kinda silly that we have to check L != null and this isn't done for us by can_speak (it runtimes instead), but w/e if(L && can_speak(L)) // So we have a valid language invocation, and we can speak that language, let's make a piece for it @@ -174,6 +186,10 @@ // This covers the case of "no prefixes in use." prefixes[++prefixes.len] = list(get_default_language(), i, i) + // If multilingualism is disabled, then after the first pass we're guaranteed to have either found a language key at the start, or else there isn't one and we're using the default for the whole message + if(client && (client.prefs.multilingual_mode == MULTILINGUAL_OFF)) + break + return prefixes /mob/proc/strip_prefixes(message, mob/prefixer = null) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 0e4e42bbeb..2607f6fbdd 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -41,11 +41,11 @@ return src -/mob/new_player/AIize() +/mob/new_player/AIize(var/move) spawning = 1 return ..() -/mob/living/carbon/human/AIize(move=1) // 'move' argument needs defining here too because BYOND is dumb +/mob/living/carbon/human/AIize(var/move = TRUE) // 'move' argument needs defining here too because BYOND is dumb if (transforming) return for(var/t in organs) @@ -53,7 +53,7 @@ return ..(move) -/mob/living/carbon/AIize() +/mob/living/carbon/AIize(var/move) if (transforming) return for(var/obj/item/W in src) @@ -64,10 +64,34 @@ invisibility = 101 return ..() -/mob/proc/AIize(move=1) +/mob/proc/AIize(var/move = TRUE) if(client) src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // stop the jams for AIs - var/mob/living/silicon/ai/O = new (loc, using_map.default_law_type,,1)//No MMI but safety is in effect. + + var/newloc = loc + if(move) + var/obj/loc_landmark + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if (sloc.name != "AI") + continue + if ((locate(/mob/living) in sloc.loc) || (locate(/obj/structure/AIcore) in sloc.loc)) + continue + loc_landmark = sloc + if (!loc_landmark) + for(var/obj/effect/landmark/tripai in landmarks_list) + if (tripai.name == "tripai") + if((locate(/mob/living) in tripai.loc) || (locate(/obj/structure/AIcore) in tripai.loc)) + continue + loc_landmark = tripai + if (!loc_landmark) + to_chat(src, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.") + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if (sloc.name == "AI") + loc_landmark = sloc + + newloc = loc_landmark.loc + + var/mob/living/silicon/ai/O = new (newloc, using_map.default_law_type,,1)//No MMI but safety is in effect. O.invisibility = 0 O.aiRestorePowerRoutine = 0 @@ -101,28 +125,6 @@ if(LANGUAGE_ROOTLOCAL in B.alternate_languages) O.add_language(LANGUAGE_ROOTLOCAL, 1) - if(move) - var/obj/loc_landmark - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name != "AI") - continue - if ((locate(/mob/living) in sloc.loc) || (locate(/obj/structure/AIcore) in sloc.loc)) - continue - loc_landmark = sloc - if (!loc_landmark) - for(var/obj/effect/landmark/tripai in landmarks_list) - if (tripai.name == "tripai") - if((locate(/mob/living) in tripai.loc) || (locate(/obj/structure/AIcore) in tripai.loc)) - continue - loc_landmark = tripai - if (!loc_landmark) - to_chat(O, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.") - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name == "AI") - loc_landmark = sloc - - O.loc = loc_landmark.loc - O.on_mob_init() O.add_ai_verbs() diff --git a/code/modules/overmap/ships/computers/ship.dm b/code/modules/overmap/ships/computers/ship.dm index 6e6304f1f8..497077a76e 100644 --- a/code/modules/overmap/ships/computers/ship.dm +++ b/code/modules/overmap/ships/computers/ship.dm @@ -58,6 +58,7 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov /obj/machinery/computer/ship/proc/look(var/mob/user) if(linked) + apply_visual(user) user.reset_view(linked) user.set_viewsize(world.view + extra_view) GLOB.moved_event.register(user, src, /obj/machinery/computer/ship/proc/unlook) diff --git a/code/modules/overmap/spacetravel.dm b/code/modules/overmap/spacetravel.dm index a51cfc3f6d..ac5846202a 100644 --- a/code/modules/overmap/spacetravel.dm +++ b/code/modules/overmap/spacetravel.dm @@ -63,11 +63,16 @@ proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A) if (!M) return + // Don't let AI eyes yeet themselves off the map + if(istype(A, /mob/observer/eye)) + return + if(A.lost_in_space()) if(!QDELETED(A)) qdel(A) return + var/nx = 1 var/ny = 1 var/nz = 1 diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm index 4c927b376e..cbbe7eeb4e 100644 --- a/code/modules/paperwork/papershredder.dm +++ b/code/modules/paperwork/papershredder.dm @@ -25,14 +25,9 @@ /obj/item/weapon/paper_bundle = 3, ) -/obj/machinery/papershredder/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/weapon/stock_parts/gear(src) - component_parts += new /obj/item/weapon/stock_parts/gear(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - RefreshParts() +/obj/machinery/papershredder/Initialize() + . = ..() + default_apply_parts() update_icon() /obj/machinery/papershredder/attackby(var/obj/item/W, var/mob/user) diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 6dcadea0a6..71a110b4bd 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -16,14 +16,9 @@ var/toner = 30 //how much toner is left! woooooo~ var/maxcopies = 10 //how many copies can be copied at once- idea shamelessly stolen from bs12's copier! -/obj/machinery/photocopier/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - RefreshParts() +/obj/machinery/photocopier/Initialize() + . = ..() + default_apply_parts() /obj/machinery/photocopier/examine(mob/user as mob) . = ..() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index d7a6e0783f..91e73c4451 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -39,6 +39,10 @@ #define POWERCHAN_ON 2 // Power channel is on until there is no power #define POWERCHAN_ON_AUTO 3 // Power channel is on until power drops below a threshold +#define NIGHTSHIFT_AUTO 1 +#define NIGHTSHIFT_NEVER 2 +#define NIGHTSHIFT_ALWAYS 3 + //NOTE: STUFF STOLEN FROM AIRLOCK.DM thx /obj/machinery/power/apc/critical @@ -121,6 +125,7 @@ var/alarms_hidden = FALSE //If power alarms from this APC are visible on consoles var/nightshift_lights = FALSE + var/nightshift_setting = NIGHTSHIFT_AUTO var/last_nightshift_switch = 0 /obj/machinery/power/apc/updateDialog() @@ -801,6 +806,7 @@ "siliconUser" = issilicon(user) || isobserver(user), //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate. "emergencyLights" = !emergency_lights, "nightshiftLights" = nightshift_lights, + "nightshiftSetting" = nightshift_setting, "powerChannels" = list( list( @@ -921,11 +927,12 @@ return 1 if(href_list["nightshift"]) - if(last_nightshift_switch > world.time + 10 SECONDS) // don't spam... + if(last_nightshift_switch > world.time - 10 SECONDS) // don't spam... to_chat(usr, "[src]'s night lighting circuit breaker is still cycling!") return 0 last_nightshift_switch = world.time - set_nightshift(!nightshift_lights) + nightshift_setting = text2num(href_list["nightshift"]) + update_nightshift() return 1 if(locked && !issilicon(usr) ) @@ -1382,8 +1389,19 @@ obj/machinery/power/apc/proc/autoset(var/cur_state, var/on) if(automated && istype(area, /area/shuttle)) return nightshift_lights = on + update_nightshift() + +/obj/machinery/power/apc/proc/update_nightshift() + var/new_state = nightshift_lights + + switch(nightshift_setting) + if(NIGHTSHIFT_NEVER) + new_state = FALSE + if(NIGHTSHIFT_ALWAYS) + new_state = TRUE + for(var/obj/machinery/light/L in area) - L.nightshift_mode(on) + L.nightshift_mode(new_state) CHECK_TICK #undef APC_UPDATE_ICON_COOLDOWN diff --git a/code/modules/power/batteryrack.dm b/code/modules/power/batteryrack.dm index d6fe46fa2b..f6bc1c9ff6 100644 --- a/code/modules/power/batteryrack.dm +++ b/code/modules/power/batteryrack.dm @@ -40,7 +40,6 @@ component_parts += new /obj/item/weapon/stock_parts/capacitor/ component_parts += new /obj/item/weapon/stock_parts/matter_bin/ // Matter Bin: Max. amount of cells. - /obj/machinery/power/smes/batteryrack/RefreshParts() var/capacitor_efficiency = 0 var/maxcells = 0 diff --git a/code/modules/power/debug_items.dm b/code/modules/power/debug_items.dm index 6fee9cce22..c7ca43705b 100644 --- a/code/modules/power/debug_items.dm +++ b/code/modules/power/debug_items.dm @@ -8,20 +8,22 @@ /obj/machinery/power/debug_items/examine(mob/user) . = ..() if(show_extended_information) - show_info(user) + . += show_info(user) /obj/machinery/power/debug_items/proc/show_info(var/mob/user) + var/list/extra_info = list() if(!powernet) - to_chat(user, "This device is not connected to a powernet") + extra_info += "This device is not connected to a powernet" return - to_chat(user, "Connected to powernet: [powernet]") - to_chat(user, "Available power: [num2text(powernet.avail, 20)] W") - to_chat(user, "Load: [num2text(powernet.viewload, 20)] W") - to_chat(user, "Has alert: [powernet.problem ? "YES" : "NO"]") - to_chat(user, "Cables: [powernet.cables.len]") - to_chat(user, "Nodes: [powernet.nodes.len]") + extra_info += "Connected to powernet: [powernet]" + extra_info += "Available power: [num2text(powernet.avail, 20)] W" + extra_info += "Load: [num2text(powernet.viewload, 20)] W" + extra_info += "Has alert: [powernet.problem ? "YES" : "NO"]" + extra_info += "Cables: [powernet.cables.len]" + extra_info += "Nodes: [powernet.nodes.len]" + return extra_info // An infinite power generator. Adds energy to connected cable. /obj/machinery/power/debug_items/infinite_generator @@ -33,8 +35,8 @@ add_avail(power_generation_rate) /obj/machinery/power/debug_items/infinite_generator/show_info(var/mob/user) - ..() - to_chat(user, "Generator is providing [num2text(power_generation_rate, 20)] W") + . = ..() + . += "Generator is providing [num2text(power_generation_rate, 20)] W" // A cable powersink, without the explosion/network alarms normal powersink causes. @@ -48,9 +50,9 @@ last_used = draw_power(power_usage_rate) /obj/machinery/power/debug_items/infinite_cable_powersink/show_info(var/mob/user) - ..() - to_chat(user, "Power sink is demanding [num2text(power_usage_rate, 20)] W") - to_chat(user, "[num2text(last_used, 20)] W was actually used last tick") + . = ..() + . += "Power sink is demanding [num2text(power_usage_rate, 20)] W" + . += "[num2text(last_used, 20)] W was actually used last tick" /obj/machinery/power/debug_items/infinite_apc_powersink @@ -60,6 +62,6 @@ active_power_usage = 0 /obj/machinery/power/debug_items/infinite_apc_powersink/show_info(var/mob/user) - ..() - to_chat(user, "Dummy load is using [num2text(active_power_usage, 20)] W") - to_chat(user, "Powered: [powered() ? "YES" : "NO"]") \ No newline at end of file + . = ..() + . += "Dummy load is using [num2text(active_power_usage, 20)] W" + . += "Powered: [powered() ? "YES" : "NO"]" diff --git a/code/modules/power/grid_checker.dm b/code/modules/power/grid_checker.dm index 93d4918af0..224eade429 100644 --- a/code/modules/power/grid_checker.dm +++ b/code/modules/power/grid_checker.dm @@ -15,17 +15,12 @@ var/wire_allow_manual_3 = FALSE var/opened = FALSE -/obj/machinery/power/grid_checker/New() - ..() +/obj/machinery/power/grid_checker/Initialize() + . = ..() connect_to_network() update_icon() wires = new(src) - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/stack/cable_coil(src, 10) - RefreshParts() + default_apply_parts() /obj/machinery/power/grid_checker/Destroy() qdel(wires) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index c2f119dfb8..33331e82f6 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -901,7 +901,7 @@ var/global/list/light_type_cache = list() var/brightness_color = LIGHT_COLOR_INCANDESCENT_TUBE var/nightshift_range = 8 - var/nightshift_power = 0.7 + var/nightshift_power = 1 var/nightshift_color = LIGHT_COLOR_NIGHTSHIFT /obj/item/weapon/light/tube @@ -921,7 +921,7 @@ var/global/list/light_type_cache = list() brightness_power = 9 nightshift_range = 10 - nightshift_power = 0.9 + nightshift_power = 1.5 /obj/item/weapon/light/bulb name = "light bulb" @@ -935,7 +935,7 @@ var/global/list/light_type_cache = list() brightness_color = LIGHT_COLOR_INCANDESCENT_BULB nightshift_range = 3 - nightshift_power = 0.35 + nightshift_power = 0.5 /obj/item/weapon/light/throw_impact(atom/hit_atom) ..() diff --git a/code/modules/power/pacman2.dm b/code/modules/power/pacman2.dm index 33fb1fb97a..26a534e222 100644 --- a/code/modules/power/pacman2.dm +++ b/code/modules/power/pacman2.dm @@ -6,8 +6,8 @@ name = "Pacman II" desc = "P.A.C.M.A.N. type II portable generator. Uses liquid phoron as a fuel source." power_gen = 4500 + circuit = /obj/item/weapon/circuitboard/pacman2 var/obj/item/weapon/tank/phoron/P = null - var/board_path = "/obj/item/weapon/circuitboard/pacman2" var/emagged = 0 var/heat = 0 /* @@ -30,16 +30,9 @@ P.air_contents.phoron -= 0.01 return - New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/stack/cable_coil(src) - component_parts += new /obj/item/stack/cable_coil(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new board_path(src) - RefreshParts() + Initialize() + . = ..() + default_apply_parts() RefreshParts() var/temp_rating = 0 diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 852d4d5d0f..10b638121f 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -112,18 +112,10 @@ /obj/machinery/power/port_gen/pacman/Initialize() . = ..() + default_apply_parts() if(anchored) connect_to_network() - -/obj/machinery/power/port_gen/pacman/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/stack/cable_coil(src, 2) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - RefreshParts() - + /obj/machinery/power/port_gen/pacman/Destroy() DropFuel() return ..() diff --git a/code/modules/power/singularity/act.dm b/code/modules/power/singularity/act.dm index 5d33ee440e..9c3a5b8621 100644 --- a/code/modules/power/singularity/act.dm +++ b/code/modules/power/singularity/act.dm @@ -47,12 +47,19 @@ return 2 /obj/singularity_pull(S, current_size) - if(simulated) - if(anchored) - if(current_size >= STAGE_FIVE) - step_towards(src, S) - else - step_towards(src, S) + set waitfor = 0 + + if(anchored) + return + + sleep(0) //this is needed or multiple items will be thrown sequentially and not simultaneously + if(current_size >= STAGE_FOUR) + step_towards(src,S) + sleep(1) + step_towards(src,S) + else if(current_size > STAGE_ONE) + step_towards(src,S) + else ..() /obj/effect/beam/singularity_pull() return @@ -60,20 +67,6 @@ /obj/effect/overlay/singularity_pull() return -/obj/item/singularity_pull(S, current_size) - spawn(0) //this is needed or multiple items will be thrown sequentially and not simultaneously - if(current_size >= STAGE_FOUR) - //throw_at(S, 14, 3) - step_towards(src,S) - sleep(1) - step_towards(src,S) - else if(current_size > STAGE_ONE) - step_towards(src,S) - else ..() - -/obj/machinery/atmospherics/pipe/singularity_pull() - return - /obj/machinery/power/supermatter/shard/singularity_act() qdel(src) return 5000 @@ -113,30 +106,6 @@ ChangeTurf(get_base_turf_by_area(src)) return 2 -/turf/simulated/floor/singularity_pull(S, current_size) - if(flooring && current_size >= STAGE_THREE) - if(prob(current_size / 2)) - var/leave_tile = TRUE - if(broken || burnt || flooring.flags & TURF_IS_FRAGILE) - leave_tile = FALSE - playsound(src, 'sound/items/crowbar.ogg', 50, 1) - make_plating(leave_tile) - -/turf/simulated/wall/singularity_pull(S, current_size) - - if(!reinf_material) - if(current_size >= STAGE_FIVE) - if(prob(75)) - dismantle_wall() - return - if(current_size == STAGE_FOUR) - if(prob(30)) - dismantle_wall() - else - if(current_size >= STAGE_FIVE) - if(prob(30)) - dismantle_wall() - /turf/space/singularity_act() return diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 2ec394bc1f..10424cee18 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -459,17 +459,17 @@ take_damage(250 / severity) /obj/machinery/power/smes/examine(var/mob/user) - ..() - to_chat(user, "The service hatch is [panel_open ? "open" : "closed"].") + . = ..() + . += "The service hatch is [panel_open ? "open" : "closed"]." if(!damage) return var/damage_percentage = round((damage / maxdamage) * 100) switch(damage_percentage) if(75 to INFINITY) - to_chat(user, "It's casing is severely damaged, and sparking circuitry may be seen through the holes!") + . += "It's casing is severely damaged, and sparking circuitry may be seen through the holes!" if(50 to 74) - to_chat(user, "It's casing is considerably damaged, and some of the internal circuits appear to be exposed!") + . += "It's casing is considerably damaged, and some of the internal circuits appear to be exposed!" if(25 to 49) - to_chat(user, "It's casing is quite seriously damaged.") + . += "It's casing is quite seriously damaged." if(0 to 24) - to_chat(user, "It's casing has some minor damage.") \ No newline at end of file + . += "It's casing has some minor damage." \ No newline at end of file diff --git a/code/modules/power/smes_construction.dm b/code/modules/power/smes_construction.dm index aadcc41ec4..558e879a87 100644 --- a/code/modules/power/smes_construction.dm +++ b/code/modules/power/smes_construction.dm @@ -41,23 +41,23 @@ // These are used on individual outposts as backup should power line be cut, or engineering outpost lost power. // 1M Charge, 150K I/O -/obj/machinery/power/smes/buildable/outpost_substation/New() - ..(0) +/obj/machinery/power/smes/buildable/outpost_substation/Initialize() + . = ..() component_parts += new /obj/item/weapon/smes_coil/weak(src) recalc_coils() // This one is pre-installed on engineering shuttle. Allows rapid charging/discharging for easier transport of power to outpost // 11M Charge, 2.5M I/O -/obj/machinery/power/smes/buildable/power_shuttle/New() - ..(0) +/obj/machinery/power/smes/buildable/power_shuttle/Initialize() + . = ..() component_parts += new /obj/item/weapon/smes_coil/super_io(src) component_parts += new /obj/item/weapon/smes_coil/super_io(src) component_parts += new /obj/item/weapon/smes_coil(src) recalc_coils() // Pre-installed and pre-charged SMES hidden from the station, for use in submaps. -/obj/machinery/power/smes/buildable/point_of_interest/New() - ..(1) +/obj/machinery/power/smes/buildable/point_of_interest/Initialize() + . = ..() charge = 1e7 // Should be enough for an individual POI. RCon = FALSE input_level = input_level_max @@ -119,7 +119,8 @@ // Proc: New() // Parameters: None // Description: Adds standard components for this SMES, and forces recalculation of properties. -/obj/machinery/power/smes/buildable/New(var/install_coils = 1) +/obj/machinery/power/smes/buildable/Initialize(var/install_coils = 1) + . = ..() component_parts = list() component_parts += new /obj/item/stack/cable_coil(src,30) wires = new /datum/wires/smes(src) @@ -129,7 +130,6 @@ for(var/i = 1, i <= cur_coils, i++) component_parts += new /obj/item/weapon/smes_coil(src) recalc_coils() - ..() // Proc: attack_hand() // Parameters: None diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index b89b906e8a..621cdcba0b 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -25,11 +25,21 @@ // Base variants are applied to everyone on the same Z level // Range variants are applied on per-range basis: numbers here are on point blank, it scales with the map size (assumes square shaped Z levels) -#define DETONATION_RADS 20 -#define DETONATION_HALLUCINATION_BASE 300 -#define DETONATION_HALLUCINATION_RANGE 300 -#define DETONATION_HALLUCINATION 600 +#define DETONATION_RADS 40 +#define DETONATION_MOB_CONCUSSION 4 // Value that will be used for Weaken() for mobs. +// Base amount of ticks for which a specific type of machine will be offline for. +- 20% added by RNG. +// This does pretty much the same thing as an electrical storm, it just affects the whole Z level instantly. +#define DETONATION_APC_OVERLOAD_PROB 10 // prob() of overloading an APC's lights. +#define DETONATION_SHUTDOWN_APC 120 // Regular APC. +#define DETONATION_SHUTDOWN_CRITAPC 10 // Critical APC. AI core and such. Considerably shorter as we don't want to kill the AI with a single blast. Still a nuisance. +#define DETONATION_SHUTDOWN_SMES 60 // SMES +#define DETONATION_SHUTDOWN_RNG_FACTOR 20 // RNG factor. Above shutdown times can be +- X%, where this setting is the percent. Do not set to 100 or more. +#define DETONATION_SOLAR_BREAK_CHANCE 60 // prob() of breaking solar arrays (this is per-panel, and only affects the Z level SM is on) + +// If power level is between these two, explosion strength will be scaled accordingly between min_explosion_power and max_explosion_power +#define DETONATION_EXPLODE_MIN_POWER 200 // If power level is this or lower, minimal detonation strength will be used +#define DETONATION_EXPLODE_MAX_POWER 2000 // If power level is this or higher maximal detonation strength will be used #define WARNING_DELAY 20 //seconds between warnings. @@ -65,7 +75,8 @@ var/pull_radius = 14 // Time in ticks between delamination ('exploding') and exploding (as in the actual boom) var/pull_time = 100 - var/explosion_power = 8 + var/min_explosion_power = 8 + var/max_explosion_power = 16 var/emergency_issued = 0 @@ -142,29 +153,71 @@ /obj/machinery/power/supermatter/proc/explode() + + set waitfor = 0 + message_admins("Supermatter exploded at ([x],[y],[z] - JMP)",0,1) log_game("SUPERMATTER([x],[y],[z]) Exploded. Power:[power], Oxygen:[oxygen], Damage:[damage], Integrity:[get_integrity()]") anchored = 1 grav_pulling = 1 exploded = 1 - var/turf/TS = get_turf(src) // The turf supermatter is on. SM being in a locker, mecha, or other container shouldn't block it's effects that way. - if(!TS) + sleep(pull_time) + var/turf/TS = get_turf(src) // The turf supermatter is on. SM being in a locker, exosuit, or other container shouldn't block it's effects that way. + if(!istype(TS)) return - for(var/z in GetConnectedZlevels(TS.z)) + + var/list/affected_z = GetConnectedZlevels(TS.z) + + // Effect 1: Radiation, weakening to all mobs on Z level + for(var/z in affected_z) SSradiation.z_radiate(locate(1, 1, z), DETONATION_RADS, 1) + for(var/mob/living/mob in living_mob_list) - var/turf/T = get_turf(mob) - if(T && (loc.z == T.z)) - if(istype(mob, /mob/living/carbon/human)) - //Hilariously enough, running into a closet should make you get hit the hardest. - var/mob/living/carbon/human/H = mob - H.hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) ) - spawn(pull_time) - explosion(get_turf(src), explosion_power, explosion_power * 2, explosion_power * 3, explosion_power * 4, 1) - spawn(5) //to allow the explosion to finish - new /obj/item/broken_sm(TS) + var/turf/TM = get_turf(mob) + if(!TM) + continue + if(!(TM.z in affected_z)) + continue + + mob.Weaken(DETONATION_MOB_CONCUSSION) + to_chat(mob, "An invisible force slams you against the ground!") + + // Effect 2: Z-level wide electrical pulse + for(var/obj/machinery/power/apc/A in machines) + if(!(A.z in affected_z)) + continue + + // Overloads lights + if(prob(DETONATION_APC_OVERLOAD_PROB)) + A.overload_lighting() + // Causes the APCs to go into system failure mode. + var/random_change = rand(100 - DETONATION_SHUTDOWN_RNG_FACTOR, 100 + DETONATION_SHUTDOWN_RNG_FACTOR) / 100 + if(A.is_critical) + A.energy_fail(round(DETONATION_SHUTDOWN_CRITAPC * random_change)) + else + A.energy_fail(round(DETONATION_SHUTDOWN_APC * random_change)) + + // Effect 3: Break solar arrays + for(var/obj/machinery/power/solar/S in machines) + if(!(S.z in affected_z)) + continue + if(prob(DETONATION_SOLAR_BREAK_CHANCE)) + S.health = -1 + S.broken() + + // Effect 4: Medium scale explosion + spawn(0) + var/explosion_power = min_explosion_power + if(power > 0) + // 0-100% where 0% is at DETONATION_EXPLODE_MIN_POWER or lower and 100% is at DETONATION_EXPLODE_MAX_POWER or higher + var/strength_percentage = between(0, (power - DETONATION_EXPLODE_MIN_POWER) / ((DETONATION_EXPLODE_MAX_POWER - DETONATION_EXPLODE_MIN_POWER) / 100), 100) + explosion_power = between(min_explosion_power, (((max_explosion_power - min_explosion_power) * (strength_percentage / 100)) + min_explosion_power), max_explosion_power) + + explosion(TS, explosion_power/2, explosion_power, max_explosion_power, explosion_power * 4, 1) qdel(src) - return + // Allow the explosion to finish + spawn(5) + new /obj/item/broken_sm(TS) //Changes color and luminosity of the light to these values if they were not already set /obj/machinery/power/supermatter/proc/shift_light(var/lum, var/clr) @@ -212,20 +265,6 @@ global_announcer.autosay(alert_msg, "Supermatter Monitor") public_alert = 0 - -/obj/machinery/power/supermatter/get_transit_zlevel() - //don't send it back to the station -- most of the time - if(prob(99)) - var/list/candidates = using_map.accessible_z_levels.Copy() - for(var/zlevel in using_map.station_levels) - candidates.Remove("[zlevel]") - candidates.Remove("[src.z]") - - if(candidates.len) - return text2num(pickweight(candidates)) - - return ..() - /obj/machinery/power/supermatter/process() var/turf/L = loc @@ -460,7 +499,8 @@ pull_radius = 5 pull_time = 45 - explosion_power = 3 + min_explosion_power = 3 + max_explosion_power = 6 /obj/machinery/power/supermatter/shard/announce_warning() //Shards don't get announcements return diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index b07cacd92b..01f4e6003a 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -201,7 +201,7 @@ /proc/magazine_icondata_cache_add(var/obj/item/ammo_magazine/M) var/list/icon_keys = list() var/list/ammo_states = list() - var/list/states = icon_states(M.icon) + var/list/states = cached_icon_states(M.icon) for(var/i = 0, i <= M.max_ammo, i++) var/ammo_state = "[M.icon_state]-[i]" if(ammo_state in states) diff --git a/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon.dm b/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon.dm index cc8240b9af..4c40da9721 100644 --- a/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon.dm +++ b/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon.dm @@ -20,6 +20,7 @@ icon_override = 'icons/vore/custom_guns_vr.dmi' item_state = "multicannon" slot_flags = SLOT_BACK + recoil = FALSE /obj/item/weapon/gun/projectile/multi_cannon/update_icon() . = ..() diff --git a/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon_cells.dm b/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon_cells.dm index 3df1ef5022..53dd7c0ad3 100644 --- a/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon_cells.dm +++ b/code/modules/projectiles/guns/energy/cell_loaded_vr/multi_cannon_cells.dm @@ -11,7 +11,7 @@ var/charge var/max_charge = 10 var/ticks = 1 - var/ticks_to_charge = 5 //10 secs per shot charged + var/ticks_to_charge = 15 //10 secs per shot charged /obj/item/ammo_casing/macrobattery/Initialize(mapload, ...) . = ..() @@ -77,7 +77,7 @@ name = "Macrobattery - LETHAL" icon_state = "macrobat_ouchie" bat_colour = "#cc3300" - projectile_type = /obj/item/projectile/beam + projectile_type = /obj/item/projectile/beam/heavylaser/lessheavy /obj/item/ammo_casing/macrobattery/healie name = "Macrobattery - RESTORE" @@ -97,4 +97,8 @@ target.adjustToxLoss(-15) target.radiation = max(target.radiation - 75, 0) //worse than mlem for rad, better for tox. else - return 1 \ No newline at end of file + return 1 + +/obj/item/projectile/beam/heavylaser/lessheavy //all bark. no (or little) bite. + damage = 15 + fire_sound = 'sound/weapons/Gunshot_cannon.ogg' \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 230bfb4bab..181514ef0c 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -365,14 +365,10 @@ /obj/item/stack/material/glass/phoronglass = list("platinum", "silicon", "silicon", "silicon"), //5 platinum, 15 silicon, ) -/obj/machinery/reagentgrinder/New() - ..() +/obj/machinery/reagentgrinder/Initialize() + . = ..() beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src) - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/weapon/stock_parts/gear(src) - RefreshParts() - return + default_apply_parts() /obj/machinery/reagentgrinder/update_icon() icon_state = "juicer"+num2text(!isnull(beaker)) diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 4cc755d158..91b04cf494 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -38,13 +38,7 @@ operating = FORWARDS setmove() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/gear(src) - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/weapon/stock_parts/gear(src) - component_parts += new /obj/item/weapon/stock_parts/motor(src) - component_parts += new /obj/item/stack/cable_coil(src,5) - RefreshParts() + default_apply_parts() /obj/machinery/conveyor/proc/setmove() if(operating == FORWARDS) diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index f9ff3adb51..468c7ff6bb 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -26,12 +26,7 @@ using metal and glass, it uses glass and reagents (usually sulphuric acid). /obj/machinery/r_n_d/circuit_imprinter/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) - component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) - RefreshParts() + default_apply_parts() /obj/machinery/r_n_d/circuit_imprinter/process() ..() diff --git a/code/modules/research/designs/misc.dm b/code/modules/research/designs/misc.dm index 8faf037136..2ce34f3485 100644 --- a/code/modules/research/designs/misc.dm +++ b/code/modules/research/designs/misc.dm @@ -63,3 +63,12 @@ datum/design/item/general/laserpointer materials = list(DEFAULT_WALL_MATERIAL = 500) build_path = /obj/item/weapon/storage/box/syndie_kit/chameleon sort_string = "TBAAB" + +/datum/design/item/general/bsflare + name = "bluespace flare" + desc = "A marker that can be detected by shuttle landing systems." + id = "bsflare" + req_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 4) + materials = list(DEFAULT_WALL_MATERIAL = 4000, MAT_GLASS = 2000, MAT_SILVER = 2000) + build_path = /obj/item/device/spaceflare + sort_string = "TBAAC" diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index a17bf370bf..78d8f9d323 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -16,13 +16,9 @@ Note: Must be placed within 3 tiles of the R&D Console idle_power_usage = 30 active_power_usage = 2500 -/obj/machinery/r_n_d/destructive_analyzer/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - RefreshParts() +/obj/machinery/r_n_d/destructive_analyzer/Initialize() + . = ..() + default_apply_parts() /obj/machinery/r_n_d/destructive_analyzer/RefreshParts() var/T = 0 diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 1de0d5bed0..b2c7362d2e 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -40,14 +40,7 @@ /obj/machinery/r_n_d/protolathe/Initialize() . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) - component_parts += new /obj/item/weapon/reagent_containers/glass/beaker(src) - RefreshParts() + default_apply_parts() /obj/machinery/r_n_d/protolathe/process() ..() diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index a1bc577bb8..4776646105 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -15,13 +15,9 @@ req_access = list(access_rd) //Only the R&D can change server settings. circuit = /obj/item/weapon/circuitboard/rdserver -/obj/machinery/r_n_d/server/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/stack/cable_coil(src) - component_parts += new /obj/item/stack/cable_coil(src) - RefreshParts() +/obj/machinery/r_n_d/server/Initialize() + . = ..() + default_apply_parts() /obj/machinery/r_n_d/server/Destroy() griefProtection() diff --git a/code/modules/resleeving/computers.dm b/code/modules/resleeving/computers.dm index 20457c98fc..d8c51a7030 100644 --- a/code/modules/resleeving/computers.dm +++ b/code/modules/resleeving/computers.dm @@ -356,7 +356,7 @@ //Body to sleeve into, but mind is in another living body. if(active_mr.mind_ref.current && active_mr.mind_ref.current.stat < DEAD) //Mind is in a body already that's alive - var/answer = alert(active_mr.mind_ref.current,"Someone is attempting to restore a backup of your mind. Do you want to abandon this body, and move there? You MAY suffer memory loss! (Same rules as CMD apply)","Resleeving","Yes","No") + var/answer = alert(active_mr.mind_ref.current,"Someone is attempting to restore a backup of your mind. Do you want to abandon this body, and move there? You MAY suffer memory loss! (Same rules as CMD apply)","Resleeving","No","Yes") //They declined to be moved. if(answer == "No") diff --git a/code/modules/shuttles/shuttle.dm b/code/modules/shuttles/shuttle.dm index 7e393c99d1..a062d2a3d3 100644 --- a/code/modules/shuttles/shuttle.dm +++ b/code/modules/shuttles/shuttle.dm @@ -30,6 +30,8 @@ var/tmp/depart_time = 0 //Similar to above, set when the shuttle leaves when long jumping. Used for progress bars. + var/debug_logging = FALSE // If set to true, the shuttle will start broadcasting its debug messages to admins + // Future Thoughts: Baystation put "docking" stuff in a subtype, leaving base type pure and free of docking stuff. Is this best? /datum/shuttle/New(_name, var/obj/effect/shuttle_landmark/initial_location) @@ -52,7 +54,8 @@ else current_location = SSshuttles.get_landmark(current_location) if(!istype(current_location)) - log_debug("UM whoops, no initial? [src]") + if(debug_logging) + log_shuttle("UM whoops, no initial? [src]") CRASH("Shuttle '[name]' could not find its starting location landmark [current_location].") if(src.name in SSshuttles.shuttles) @@ -239,14 +242,17 @@ // Returns TRUE if we actually moved, otherwise FALSE. /datum/shuttle/proc/attempt_move(var/obj/effect/shuttle_landmark/destination, var/interim = FALSE) if(current_location == destination) - log_shuttle("Shuttle [src] attempted to move to [destination] but is already there!") + if(debug_logging) + log_shuttle("Shuttle [src] attempted to move to [destination] but is already there!") return FALSE if(!destination.is_valid(src)) - log_shuttle("Shuttle [src] aborting attempt_move() because destination=[destination] is not valid") + if(debug_logging) + log_shuttle("Shuttle [src] aborting attempt_move() because destination=[destination] is not valid") return FALSE if(current_location.cannot_depart(src)) - log_shuttle("Shuttle [src] aborting attempt_move() because current_location=[current_location] refuses.") + if(debug_logging) + log_shuttle("Shuttle [src] aborting attempt_move() because current_location=[current_location] refuses.") return FALSE // Observer pattern pre-move @@ -254,19 +260,21 @@ GLOB.shuttle_pre_move_event.raise_event(src, old_location, destination) current_location.shuttle_departed(src) - log_shuttle("[src] moving to [destination]. Areas are [english_list(shuttle_area)]") + if(debug_logging) + log_shuttle("[src] moving to [destination]. Areas are [english_list(shuttle_area)]") var/list/translation = list() for(var/area/A in shuttle_area) - log_shuttle("Translating [A]") + if(debug_logging) + log_shuttle("Translating [A]") translation += get_turf_translation(get_turf(current_location), get_turf(destination), A.contents) // Actually do it! (This never fails) perform_shuttle_move(destination, translation) - + // Observer pattern post-move destination.shuttle_arrived(src) GLOB.shuttle_moved_event.raise_event(src, old_location, destination) - + return TRUE @@ -274,7 +282,8 @@ //A note to anyone overriding move in a subtype. perform_shuttle_move() must absolutely not, under any circumstances, fail to move the shuttle. //If you want to conditionally cancel shuttle launches, that logic must go in short_jump() or long_jump() /datum/shuttle/proc/perform_shuttle_move(var/obj/effect/shuttle_landmark/destination, var/list/turf_translation) - log_shuttle("perform_shuttle_move() current=[current_location] destination=[destination]") + if(debug_logging) + log_shuttle("perform_shuttle_move() current=[current_location] destination=[destination]") //to_world("move_shuttle() called for [name] leaving [origin] en route to [destination].") //to_world("area_coming_from: [origin]") diff --git a/code/modules/shuttles/shuttle_autodock.dm b/code/modules/shuttles/shuttle_autodock.dm index 4181af5b15..aa59856b50 100644 --- a/code/modules/shuttles/shuttle_autodock.dm +++ b/code/modules/shuttles/shuttle_autodock.dm @@ -65,7 +65,7 @@ current_dock_target = docking_controller_tag shuttle_docking_controller = SSshuttles.docking_registry[current_dock_target] if(current_dock_target && !shuttle_docking_controller) - to_world("warning: shuttle [src] can't find its controller with tag [current_dock_target]!") + log_shuttle("warning: shuttle [src] can't find its controller with tag [current_dock_target]!") // No toggle because this is an error message that needs to be seen /* Docking stuff */ diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm index 6d277edec1..3e3655ca5a 100644 --- a/code/modules/shuttles/shuttle_console.dm +++ b/code/modules/shuttles/shuttle_console.dm @@ -64,11 +64,13 @@ var/cannot_depart = shuttle.current_location.cannot_depart(shuttle) if(cannot_depart) to_chat(user, "[cannot_depart]") - log_shuttle("Shuttle [shuttle] cannot depart [shuttle.current_location] because: [cannot_depart].") + if(shuttle.debug_logging) + log_shuttle("Shuttle [shuttle] cannot depart [shuttle.current_location] because: [cannot_depart].") return FALSE if(!shuttle.next_location.is_valid(shuttle)) to_chat(user, "Destination zone is invalid or obstructed.") - log_shuttle("Shuttle [shuttle] destination [shuttle.next_location] is invalid.") + if(shuttle.debug_logging) + log_shuttle("Shuttle [shuttle] destination [shuttle.next_location] is invalid.") return FALSE return TRUE diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm index efb321e55c..6c584e1762 100644 --- a/code/modules/shuttles/shuttle_emergency.dm +++ b/code/modules/shuttles/shuttle_emergency.dm @@ -70,7 +70,7 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - to_chat(world, "Alert: The shuttle autopilot has been overridden. Launch sequence initiated!") + to_world("Alert: The shuttle autopilot has been overridden. Launch sequence initiated!") if(usr) log_admin("[key_name(usr)] has overridden the departure shuttle's autopilot and activated the launch sequence.") @@ -84,7 +84,7 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - to_chat(world, "Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!") + to_world("Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!") if(usr) log_admin("[key_name(usr)] has overridden the departure shuttle's autopilot and forced immediate launch.") diff --git a/code/modules/shuttles/shuttles_web.dm b/code/modules/shuttles/shuttles_web.dm index 0aebd2bf42..00d9344b00 100644 --- a/code/modules/shuttles/shuttles_web.dm +++ b/code/modules/shuttles/shuttles_web.dm @@ -181,7 +181,7 @@ my_doors[find_doors[A.id_tag]] = A find_doors -= A.id_tag for(var/lost in find_doors) - log_debug("[my_area] shuttle computer couldn't find [lost] door!") + log_shuttle("[my_area] shuttle computer couldn't find [lost] door!") if(my_sensors) var/list/find_sensors = my_sensors @@ -191,7 +191,7 @@ my_sensors[find_sensors[S.id_tag]] = S find_sensors -= S.id_tag for(var/lost in find_sensors) - log_debug("[my_area] shuttle computer couldn't find [lost] sensor!") + log_shuttle("[my_area] shuttle computer couldn't find [lost] sensor!") /obj/machinery/computer/shuttle_control/web/attackby(obj/I, mob/user) var/datum/shuttle/autodock/web_shuttle/shuttle = shuttle_controller.shuttles[shuttle_tag] diff --git a/code/modules/shuttles/web_datums.dm b/code/modules/shuttles/web_datums.dm index 3e2abf9443..bbba42dd58 100644 --- a/code/modules/shuttles/web_datums.dm +++ b/code/modules/shuttles/web_datums.dm @@ -72,7 +72,7 @@ /datum/shuttle_destination/New(var/new_master) my_landmark = SSshuttles.get_landmark(my_landmark) if(!my_landmark) - log_debug("Web shuttle destination '[name]' could not find its landmark '[my_landmark]'.") + log_debug("Web shuttle destination '[name]' could not find its landmark '[my_landmark]'.") // Important error message master = new_master /datum/shuttle_destination/Destroy() diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm index f853e224fc..249c84be73 100644 --- a/code/modules/tables/tables.dm +++ b/code/modules/tables/tables.dm @@ -30,6 +30,9 @@ var/list/table_icon_cache = list() var/item_place = 1 //allows items to be placed on the table, but not on benches. +/obj/structure/table/examine_icon() + return icon(icon=initial(icon), icon_state=initial(icon_state)) //Basically the map preview version + /obj/structure/table/proc/update_material() var/old_maxhealth = maxhealth if(!material) diff --git a/code/modules/tgs/core/_definitions.dm b/code/modules/tgs/core/_definitions.dm new file mode 100644 index 0000000000..ebf6d17c2a --- /dev/null +++ b/code/modules/tgs/core/_definitions.dm @@ -0,0 +1,2 @@ +#define TGS_UNIMPLEMENTED "___unimplemented" +#define TGS_VERSION_PARAMETER "server_service_version" diff --git a/code/modules/tgs/core/core.dm b/code/modules/tgs/core/core.dm new file mode 100644 index 0000000000..144f33926f --- /dev/null +++ b/code/modules/tgs/core/core.dm @@ -0,0 +1,171 @@ +/world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE) + var/current_api = TGS_READ_GLOBAL(tgs) + if(current_api) + TGS_ERROR_LOG("TgsNew(): TGS API datum already set ([current_api])! Was TgsNew() called more than once?") + return + +#ifdef TGS_V3_API + minimum_required_security_level = TGS_SECURITY_TRUSTED +#endif + var/raw_parameter = world.params[TGS_VERSION_PARAMETER] + if(!raw_parameter) + return + + var/datum/tgs_version/version = new(raw_parameter) + if(!version.Valid(FALSE)) + TGS_ERROR_LOG("Failed to validate TGS version parameter: [raw_parameter]!") + return + + var/api_datum + switch(version.suite) + if(3) +#ifndef TGS_V3_API + TGS_ERROR_LOG("Detected V3 API but TGS_V3_API isn't defined!") +#else + switch(version.minor) + if(2) + api_datum = /datum/tgs_api/v3210 +#endif + if(4) + switch(version.minor) + if(0) + api_datum = /datum/tgs_api/v4 + if(5) + api_datum = /datum/tgs_api/v5 + + var/datum/tgs_version/max_api_version = TgsMaximumAPIVersion(); + if(version.suite != null && version.minor != null && version.patch != null && version.deprecated_patch != null && version.deprefixed_parameter > max_api_version.deprefixed_parameter) + TGS_ERROR_LOG("Detected unknown API version! Defaulting to latest. Update the DMAPI to fix this problem.") + api_datum = /datum/tgs_api/latest + + if(!api_datum) + TGS_ERROR_LOG("Found unsupported API version: [raw_parameter]. If this is a valid version please report this, backporting is done on demand.") + return + + TGS_INFO_LOG("Activating API for version [version.deprefixed_parameter]") + var/datum/tgs_api/new_api = new api_datum(version) + + TGS_WRITE_GLOBAL(tgs, new_api) + + var/result = new_api.OnWorldNew(event_handler, minimum_required_security_level) + if(!result || result == TGS_UNIMPLEMENTED) + TGS_WRITE_GLOBAL(tgs, null) + TGS_ERROR_LOG("Failed to activate API!") + +/world/TgsMaximumAPIVersion() + return new /datum/tgs_version("5.x.x") + +/world/TgsMinimumAPIVersion() + return new /datum/tgs_version("3.2.x") + +/world/TgsInitializationComplete() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + api.OnInitializationComplete() + +/world/proc/TgsTopic(T) + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + var/result = api.OnTopic(T) + if(result != TGS_UNIMPLEMENTED) + return result + +/world/TgsRevision() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + var/result = api.Revision() + if(result != TGS_UNIMPLEMENTED) + return result + +/world/TgsReboot() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + api.OnReboot() + +/world/TgsAvailable() + return TGS_READ_GLOBAL(tgs) != null + +/world/TgsVersion() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + return api.version + +/world/TgsApiVersion() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + return api.ApiVersion() + +/world/TgsInstanceName() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + var/result = api.InstanceName() + if(result != TGS_UNIMPLEMENTED) + return result + +/world/TgsTestMerges() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + var/result = api.TestMerges() + if(result != TGS_UNIMPLEMENTED) + return result + return list() + +/world/TgsEndProcess() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + api.EndProcess() + +/world/TgsChatChannelInfo() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + var/result = api.ChatChannelInfo() + if(result != TGS_UNIMPLEMENTED) + return result + return list() + +/world/TgsChatBroadcast(message, list/channels) + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + api.ChatBroadcast(message, channels) + +/world/TgsTargetedChatBroadcast(message, admin_only) + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + api.ChatTargetedBroadcast(message, admin_only) + +/world/TgsChatPrivateMessage(message, datum/tgs_chat_user/user) + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + api.ChatPrivateMessage(message, user) + +/world/TgsSecurityLevel() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + api.SecurityLevel() + +/* +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/core/datum.dm b/code/modules/tgs/core/datum.dm new file mode 100644 index 0000000000..3adecbb556 --- /dev/null +++ b/code/modules/tgs/core/datum.dm @@ -0,0 +1,82 @@ +TGS_DEFINE_AND_SET_GLOBAL(tgs, null) + +/datum/tgs_api + var/datum/tgs_version/version + +/datum/tgs_api/New(datum/tgs_version/version) + . = ..() + src.version = version + +/datum/tgs_api/latest + parent_type = /datum/tgs_api/v5 + +TGS_PROTECT_DATUM(/datum/tgs_api) + +/datum/tgs_api/proc/ApiVersion() + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/OnWorldNew(datum/tgs_event_handler/event_handler) + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/OnInitializationComplete() + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/OnTopic(T) + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/OnReboot() + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/InstanceName() + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/TestMerges() + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/EndProcess() + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/Revision() + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/ChatChannelInfo() + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/ChatBroadcast(message, list/channels) + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/ChatTargetedBroadcast(message, admin_only) + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/ChatPrivateMessage(message, admin_only) + return TGS_UNIMPLEMENTED + +/datum/tgs_api/proc/SecurityLevel() + return TGS_UNIMPLEMENTED + +/* +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/core/tgs_version.dm b/code/modules/tgs/core/tgs_version.dm new file mode 100644 index 0000000000..a5dae1241a --- /dev/null +++ b/code/modules/tgs/core/tgs_version.dm @@ -0,0 +1,28 @@ +/datum/tgs_version/New(raw_parameter) + src.raw_parameter = raw_parameter + deprefixed_parameter = replacetext(raw_parameter, "/tg/station 13 Server v", "") + var/list/version_bits = splittext(deprefixed_parameter, ".") + + suite = text2num(version_bits[1]) + if(version_bits.len > 1) + minor = text2num(version_bits[2]) + if(version_bits.len > 2) + patch = text2num(version_bits[3]) + if(version_bits.len == 4) + deprecated_patch = text2num(version_bits[4]) + +/datum/tgs_version/proc/Valid(allow_wildcards = FALSE) + if(suite == null) + return FALSE + if(allow_wildcards) + return TRUE + return !Wildcard() + +/datum/tgs_version/Wildcard() + return minor == null || patch == null + +/datum/tgs_version/Equals(datum/tgs_version/other_version) + if(!istype(other_version)) + return FALSE + + return suite == other_version.suite && minor == other_version.minor && patch == other_version.patch && deprecated_patch == other_version.deprecated_patch diff --git a/code/modules/tgs/includes.dm b/code/modules/tgs/includes.dm new file mode 100644 index 0000000000..764adbc3a9 --- /dev/null +++ b/code/modules/tgs/includes.dm @@ -0,0 +1,45 @@ +#include "core\_definitions.dm" +#include "core\core.dm" +#include "core\datum.dm" +#include "core\tgs_version.dm" + +#ifdef TGS_V3_API +#include "v3210\api.dm" +#include "v3210\commands.dm" +#endif + +#include "v4\api.dm" +#include "v4\commands.dm" + +#include "v5\_defines.dm" +#include "v5\api.dm" +#include "v5\commands.dm" +#include "v5\chat_commands.dm" +#include "v5\undef.dm" + +/* +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v3210/api.dm b/code/modules/tgs/v3210/api.dm new file mode 100644 index 0000000000..5327b9276b --- /dev/null +++ b/code/modules/tgs/v3210/api.dm @@ -0,0 +1,255 @@ +#define REBOOT_MODE_NORMAL 0 +#define REBOOT_MODE_HARD 1 +#define REBOOT_MODE_SHUTDOWN 2 + +#define SERVICE_WORLD_PARAM "server_service" +#define SERVICE_INSTANCE_PARAM "server_instance" +#define SERVICE_PR_TEST_JSON "prtestjob.json" +#define SERVICE_INTERFACE_DLL "TGDreamDaemonBridge.dll" +#define SERVICE_INTERFACE_FUNCTION "DDEntryPoint" + +#define SERVICE_CMD_HARD_REBOOT "hard_reboot" +#define SERVICE_CMD_GRACEFUL_SHUTDOWN "graceful_shutdown" +#define SERVICE_CMD_WORLD_ANNOUNCE "world_announce" +#define SERVICE_CMD_LIST_CUSTOM "list_custom_commands" +#define SERVICE_CMD_API_COMPATIBLE "api_compat" +#define SERVICE_CMD_PLAYER_COUNT "client_count" + +#define SERVICE_CMD_PARAM_KEY "serviceCommsKey" +#define SERVICE_CMD_PARAM_COMMAND "command" +#define SERVICE_CMD_PARAM_SENDER "sender" +#define SERVICE_CMD_PARAM_CUSTOM "custom" + +#define SERVICE_REQUEST_KILL_PROCESS "killme" +#define SERVICE_REQUEST_IRC_BROADCAST "irc" +#define SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE "send2irc" +#define SERVICE_REQUEST_WORLD_REBOOT "worldreboot" +#define SERVICE_REQUEST_API_VERSION "api_ver" + +#define SERVICE_RETURN_SUCCESS "SUCCESS" + +/datum/tgs_api/v3210 + var/reboot_mode = REBOOT_MODE_NORMAL + var/comms_key + var/instance_name + var/originmastercommit + var/commit + var/list/cached_custom_tgs_chat_commands + var/warned_revison = FALSE + var/warned_custom_commands = FALSE + +/datum/tgs_api/v3210/ApiVersion() + return new /datum/tgs_version("3.2.1.0") + +/datum/tgs_api/v3210/proc/trim_left(text) + for (var/i = 1 to length(text)) + if (text2ascii(text, i) > 32) + return copytext(text, i) + return "" + +/datum/tgs_api/v3210/proc/trim_right(text) + for (var/i = length(text), i > 0, i--) + if (text2ascii(text, i) > 32) + return copytext(text, 1, i + 1) + return "" + +/datum/tgs_api/v3210/proc/file2list(filename) + return splittext(trim_left(trim_right(file2text(filename))), "\n") + +/datum/tgs_api/v3210/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level) //don't use event handling in this version + . = FALSE + + comms_key = world.params[SERVICE_WORLD_PARAM] + instance_name = world.params[SERVICE_INSTANCE_PARAM] + if(!instance_name) + instance_name = "TG Station Server" //maybe just upgraded + + var/list/logs = file2list(".git/logs/HEAD") + if(logs.len) + logs = splittext(logs[logs.len - 1], " ") + commit = logs[2] + logs = file2list(".git/logs/refs/remotes/origin/master") + if(logs.len) + originmastercommit = splittext(logs[logs.len - 1], " ")[2] + + if(world.system_type != MS_WINDOWS) + TGS_ERROR_LOG("This API version is only supported on Windows. Not running on Windows. Aborting initialization!") + return + ListServiceCustomCommands(TRUE) + var/datum/tgs_version/api_version = ApiVersion() + ExportService("[SERVICE_REQUEST_API_VERSION] [api_version.deprefixed_parameter]", TRUE) + return TRUE + +//nothing to do for v3 +/datum/tgs_api/v3210/OnInitializationComplete() + return + +/datum/tgs_api/v3210/InstanceName() + return world.params[SERVICE_INSTANCE_PARAM] + +/datum/tgs_api/v3210/proc/ExportService(command, skip_compat_check = FALSE) + . = FALSE + if(skip_compat_check && !fexists(SERVICE_INTERFACE_DLL)) + TGS_ERROR_LOG("Service parameter present but no interface DLL detected. This is symptomatic of running a service less than version 3.1! Please upgrade.") + return + call(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(instance_name, command) //trust no retval + return TRUE + +/datum/tgs_api/v3210/OnTopic(T) + var/list/params = params2list(T) + var/their_sCK = params[SERVICE_CMD_PARAM_KEY] + if(!their_sCK) + return FALSE //continue world/Topic + + if(their_sCK != comms_key) + return "Invalid comms key!"; + + var/command = params[SERVICE_CMD_PARAM_COMMAND] + if(!command) + return "No command!" + + switch(command) + if(SERVICE_CMD_API_COMPATIBLE) + return SERVICE_RETURN_SUCCESS + if(SERVICE_CMD_HARD_REBOOT) + if(reboot_mode != REBOOT_MODE_HARD) + reboot_mode = REBOOT_MODE_HARD + TGS_INFO_LOG("Hard reboot requested by service") + TGS_NOTIFY_ADMINS("The world will hard reboot at the end of the game. Requested by TGS.") + if(SERVICE_CMD_GRACEFUL_SHUTDOWN) + if(reboot_mode != REBOOT_MODE_SHUTDOWN) + reboot_mode = REBOOT_MODE_SHUTDOWN + TGS_INFO_LOG("Shutdown requested by service") + TGS_NOTIFY_ADMINS("The world will shutdown at the end of the game. Requested by TGS.") + if(SERVICE_CMD_WORLD_ANNOUNCE) + var/msg = params["message"] + if(!istext(msg) || !msg) + return "No message set!" + TGS_WORLD_ANNOUNCE(msg) + return SERVICE_RETURN_SUCCESS + if(SERVICE_CMD_PLAYER_COUNT) + return "[TGS_CLIENT_COUNT]" + if(SERVICE_CMD_LIST_CUSTOM) + return json_encode(ListServiceCustomCommands(FALSE)) + else + var/custom_command_result = HandleServiceCustomCommand(lowertext(command), params[SERVICE_CMD_PARAM_SENDER], params[SERVICE_CMD_PARAM_CUSTOM]) + if(custom_command_result) + return istext(custom_command_result) ? custom_command_result : SERVICE_RETURN_SUCCESS + return "Unknown command: [command]" + +/datum/tgs_api/v3210/OnReboot() + switch(reboot_mode) + if(REBOOT_MODE_HARD) + TGS_WORLD_ANNOUNCE("Hard reboot triggered, you will automatically reconnect...") + EndProcess() + if(REBOOT_MODE_SHUTDOWN) + TGS_WORLD_ANNOUNCE("The server is shutting down...") + EndProcess() + else + ExportService(SERVICE_REQUEST_WORLD_REBOOT) //just let em know + +/datum/tgs_api/v3210/TestMerges() + //do the best we can here as the datum can't be completed using the v3 api + . = list() + if(!fexists(SERVICE_PR_TEST_JSON)) + return + var/list/json = json_decode(file2text(SERVICE_PR_TEST_JSON)) + if(!json) + return + for(var/I in json) + var/datum/tgs_revision_information/test_merge/tm = new + tm.number = text2num(I) + var/list/entry = json[I] + tm.pull_request_commit = entry["commit"] + tm.author = entry["author"] + tm.title = entry["title"] + . += tm + +/datum/tgs_api/v3210/Revision() + if(!warned_revison) + var/datum/tgs_version/api_version = ApiVersion() + TGS_ERROR_LOG("Use of TgsRevision on [api_version.deprefixed_parameter] origin_commit only points to master!") + warned_revison = TRUE + var/datum/tgs_revision_information/ri = new + ri.commit = commit + ri.origin_commit = originmastercommit + return ri + +/datum/tgs_api/v3210/EndProcess() + sleep(world.tick_lag) //flush the buffers + ExportService(SERVICE_REQUEST_KILL_PROCESS) + +/datum/tgs_api/v3210/ChatChannelInfo() + return list() + +/datum/tgs_api/v3210/ChatBroadcast(message, list/channels) + if(channels) + return TGS_UNIMPLEMENTED + ChatTargetedBroadcast(message, TRUE) + ChatTargetedBroadcast(message, FALSE) + +/datum/tgs_api/v3210/ChatTargetedBroadcast(message, admin_only) + ExportService("[admin_only ? SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE : SERVICE_REQUEST_IRC_BROADCAST] [message]") + +/datum/tgs_api/v3210/ChatPrivateMessage(message, datum/tgs_chat_user/user) + return TGS_UNIMPLEMENTED + +/datum/tgs_api/v3210/SecurityLevel() + return TGS_SECURITY_TRUSTED + +#undef REBOOT_MODE_NORMAL +#undef REBOOT_MODE_HARD +#undef REBOOT_MODE_SHUTDOWN + +#undef SERVICE_WORLD_PARAM +#undef SERVICE_INSTANCE_PARAM +#undef SERVICE_PR_TEST_JSON +#undef SERVICE_INTERFACE_DLL +#undef SERVICE_INTERFACE_FUNCTION + +#undef SERVICE_CMD_HARD_REBOOT +#undef SERVICE_CMD_GRACEFUL_SHUTDOWN +#undef SERVICE_CMD_WORLD_ANNOUNCE +#undef SERVICE_CMD_LIST_CUSTOM +#undef SERVICE_CMD_API_COMPATIBLE +#undef SERVICE_CMD_PLAYER_COUNT + +#undef SERVICE_CMD_PARAM_KEY +#undef SERVICE_CMD_PARAM_COMMAND +#undef SERVICE_CMD_PARAM_SENDER +#undef SERVICE_CMD_PARAM_CUSTOM + +#undef SERVICE_REQUEST_KILL_PROCESS +#undef SERVICE_REQUEST_IRC_BROADCAST +#undef SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE +#undef SERVICE_REQUEST_WORLD_REBOOT +#undef SERVICE_REQUEST_API_VERSION + +#undef SERVICE_RETURN_SUCCESS + +/* +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v3210/commands.dm b/code/modules/tgs/v3210/commands.dm new file mode 100644 index 0000000000..5046631981 --- /dev/null +++ b/code/modules/tgs/v3210/commands.dm @@ -0,0 +1,78 @@ +#define SERVICE_JSON_PARAM_HELPTEXT "help_text" +#define SERVICE_JSON_PARAM_ADMINONLY "admin_only" +#define SERVICE_JSON_PARAM_REQUIREDPARAMETERS "required_parameters" + +/datum/tgs_api/v3210/proc/ListServiceCustomCommands(warnings_only) + if(!warnings_only) + . = list() + var/list/command_name_types = list() + var/list/warned_command_names = warnings_only ? list() : null + var/warned_about_the_dangers_of_robutussin = !warnings_only + for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command) + if(!warned_about_the_dangers_of_robutussin) + TGS_ERROR_LOG("Custom chat commands in [ApiVersion()] lacks the /datum/tgs_chat_user/sender.channel field!") + warned_about_the_dangers_of_robutussin = TRUE + var/datum/tgs_chat_command/stc = I + var/command_name = initial(stc.name) + if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\"")) + if(warnings_only && !warned_command_names[command_name]) + TGS_ERROR_LOG("Custom command [command_name] can't be used as it is empty or contains illegal characters!") + warned_command_names[command_name] = TRUE + continue + + if(command_name_types[command_name]) + if(warnings_only) + TGS_ERROR_LOG("Custom commands [command_name_types[command_name]] and [stc] have the same name, only [command_name_types[command_name]] will be available!") + continue + command_name_types[stc] = command_name + + if(!warnings_only) + .[command_name] = list(SERVICE_JSON_PARAM_HELPTEXT = initial(stc.help_text), SERVICE_JSON_PARAM_ADMINONLY = initial(stc.admin_only), SERVICE_JSON_PARAM_REQUIREDPARAMETERS = 0) + +/datum/tgs_api/v3210/proc/HandleServiceCustomCommand(command, sender, params) + if(!cached_custom_tgs_chat_commands) + cached_custom_tgs_chat_commands = list() + for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command) + var/datum/tgs_chat_command/stc = I + cached_custom_tgs_chat_commands[lowertext(initial(stc.name))] = stc + + var/command_type = cached_custom_tgs_chat_commands[command] + if(!command_type) + return FALSE + var/datum/tgs_chat_command/stc = new command_type + var/datum/tgs_chat_user/user = new + user.friendly_name = sender + user.mention = sender + return stc.Run(user, params) || TRUE + +/* + +#undef SERVICE_JSON_PARAM_HELPTEXT +#undef SERVICE_JSON_PARAM_ADMINONLY +#undef SERVICE_JSON_PARAM_REQUIREDPARAMETERS + +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v4/api.dm b/code/modules/tgs/v4/api.dm new file mode 100644 index 0000000000..5c98a1a7a7 --- /dev/null +++ b/code/modules/tgs/v4/api.dm @@ -0,0 +1,342 @@ +#define TGS4_PARAM_INFO_JSON "tgs_json" + +#define TGS4_INTEROP_ACCESS_IDENTIFIER "tgs_tok" + +#define TGS4_RESPONSE_SUCCESS "tgs_succ" + +#define TGS4_TOPIC_CHANGE_PORT "tgs_port" +#define TGS4_TOPIC_CHANGE_REBOOT_MODE "tgs_rmode" +#define TGS4_TOPIC_CHAT_COMMAND "tgs_chat_comm" +#define TGS4_TOPIC_EVENT "tgs_event" +#define TGS4_TOPIC_INTEROP_RESPONSE "tgs_interop" + +#define TGS4_COMM_NEW_PORT "tgs_new_port" +#define TGS4_COMM_VALIDATE "tgs_validate" +#define TGS4_COMM_SERVER_PRIMED "tgs_prime" +#define TGS4_COMM_WORLD_REBOOT "tgs_reboot" +#define TGS4_COMM_END_PROCESS "tgs_kill" +#define TGS4_COMM_CHAT "tgs_chat_send" + +#define TGS4_PARAMETER_COMMAND "tgs_com" +#define TGS4_PARAMETER_DATA "tgs_data" + +#define TGS4_PORT_CRITFAIL_MESSAGE " Must exit to let watchdog reboot..." + +#define EXPORT_TIMEOUT_DS 200 + +/datum/tgs_api/v4 + var/access_identifier + var/instance_name + var/json_path + var/chat_channels_json_path + var/chat_commands_json_path + var/server_commands_json_path + var/reboot_mode = TGS_REBOOT_MODE_NORMAL + var/security_level + + var/requesting_new_port = FALSE + + var/list/intercepted_message_queue + + var/list/custom_commands + + var/list/cached_test_merges + var/datum/tgs_revision_information/cached_revision + + var/datum/tgs_event_handler/event_handler + + var/export_lock = FALSE + var/list/last_interop_response + +/datum/tgs_api/v4/ApiVersion() + return new /datum/tgs_version("4.0.0.0") + +/datum/tgs_api/v4/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level) + json_path = world.params[TGS4_PARAM_INFO_JSON] + if(!json_path) + TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!") + return + var/json_file = file2text(json_path) + if(!json_file) + TGS_ERROR_LOG("Missing specified json file: [json_path]") + return + var/cached_json = json_decode(json_file) + if(!cached_json) + TGS_ERROR_LOG("Failed to decode info json: [json_file]") + return + + access_identifier = cached_json["accessIdentifier"] + server_commands_json_path = cached_json["serverCommandsJson"] + + if(cached_json["apiValidateOnly"]) + TGS_INFO_LOG("Validating API and exiting...") + Export(TGS4_COMM_VALIDATE, list(TGS4_PARAMETER_DATA = "[minimum_required_security_level]")) + del(world) + + security_level = cached_json["securityLevel"] + chat_channels_json_path = cached_json["chatChannelsJson"] + chat_commands_json_path = cached_json["chatCommandsJson"] + src.event_handler = event_handler + instance_name = cached_json["instanceName"] + + ListCustomCommands() + + var/list/revisionData = cached_json["revision"] + if(revisionData) + cached_revision = new + cached_revision.commit = revisionData["commitSha"] + cached_revision.origin_commit = revisionData["originCommitSha"] + + cached_test_merges = list() + var/list/json = cached_json["testMerges"] + for(var/entry in json) + var/datum/tgs_revision_information/test_merge/tm = new + tm.time_merged = text2num(entry["timeMerged"]) + + var/list/revInfo = entry["revision"] + if(revInfo) + tm.commit = revInfo["commitSha"] + tm.origin_commit = revInfo["originCommitSha"] + + tm.title = entry["titleAtMerge"] + tm.body = entry["bodyAtMerge"] + tm.url = entry["url"] + tm.author = entry["author"] + tm.number = entry["number"] + tm.pull_request_commit = entry["pullRequestRevision"] + tm.comment = entry["comment"] + + cached_test_merges += tm + + return TRUE + +/datum/tgs_api/v4/OnInitializationComplete() + Export(TGS4_COMM_SERVER_PRIMED) + + var/tgs4_secret_sleep_offline_sauce = 24051994 + var/old_sleep_offline = world.sleep_offline + world.sleep_offline = tgs4_secret_sleep_offline_sauce + sleep(1) + if(world.sleep_offline == tgs4_secret_sleep_offline_sauce) //if not someone changed it + world.sleep_offline = old_sleep_offline + +/datum/tgs_api/v4/OnTopic(T) + var/list/params = params2list(T) + var/their_sCK = params[TGS4_INTEROP_ACCESS_IDENTIFIER] + if(!their_sCK) + return FALSE //continue world/Topic + + if(their_sCK != access_identifier) + return "Invalid comms key!"; + + var/command = params[TGS4_PARAMETER_COMMAND] + if(!command) + return "No command!" + + . = TGS4_RESPONSE_SUCCESS + + switch(command) + if(TGS4_TOPIC_CHAT_COMMAND) + var/result = HandleCustomCommand(params[TGS4_PARAMETER_DATA]) + if(result == null) + result = "Error running chat command!" + return result + if(TGS4_TOPIC_EVENT) + intercepted_message_queue = list() + var/list/event_notification = json_decode(params[TGS4_PARAMETER_DATA]) + var/list/event_parameters = event_notification["Parameters"] + + var/list/event_call = list(event_notification["Type"]) + if(event_parameters) + event_call += event_parameters + + if(event_handler != null) + event_handler.HandleEvent(arglist(event_call)) + + . = json_encode(intercepted_message_queue) + intercepted_message_queue = null + return + if(TGS4_TOPIC_INTEROP_RESPONSE) + last_interop_response = json_decode(params[TGS4_PARAMETER_DATA]) + return + if(TGS4_TOPIC_CHANGE_PORT) + var/new_port = text2num(params[TGS4_PARAMETER_DATA]) + if (!(new_port > 0)) + return "Invalid port: [new_port]" + + //the topic still completes, miraculously + //I honestly didn't believe byond could do it + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port) + if(!world.OpenPort(new_port)) + return "Port change failed!" + return + if(TGS4_TOPIC_CHANGE_REBOOT_MODE) + var/new_reboot_mode = text2num(params[TGS4_PARAMETER_DATA]) + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode) + reboot_mode = new_reboot_mode + return + + return "Unknown command: [command]" + +/datum/tgs_api/v4/proc/Export(command, list/data, override_requesting_new_port = FALSE) + if(!data) + data = list() + data[TGS4_PARAMETER_COMMAND] = command + var/json = json_encode(data) + + while(requesting_new_port && !override_requesting_new_port) + sleep(1) + + //we need some port open at this point to facilitate return communication + if(!world.port) + requesting_new_port = TRUE + if(!world.OpenPort(0)) //open any port + TGS_ERROR_LOG("Unable to open random port to retrieve new port![TGS4_PORT_CRITFAIL_MESSAGE]") + del(world) + + //request a new port + export_lock = FALSE + var/list/new_port_json = Export(TGS4_COMM_NEW_PORT, list(TGS4_PARAMETER_DATA = "[world.port]"), TRUE) //stringify this on purpose + + if(!new_port_json) + TGS_ERROR_LOG("No new port response from server![TGS4_PORT_CRITFAIL_MESSAGE]") + del(world) + + var/new_port = new_port_json[TGS4_PARAMETER_DATA] + if(!isnum(new_port) || new_port <= 0) + TGS_ERROR_LOG("Malformed new port json ([json_encode(new_port_json)])![TGS4_PORT_CRITFAIL_MESSAGE]") + del(world) + + if(new_port != world.port && !world.OpenPort(new_port)) + TGS_ERROR_LOG("Unable to open port [new_port]![TGS4_PORT_CRITFAIL_MESSAGE]") + del(world) + requesting_new_port = FALSE + + while(export_lock) + sleep(1) + export_lock = TRUE + + last_interop_response = null + fdel(server_commands_json_path) + text2file(json, server_commands_json_path) + + for(var/I = 0; I < EXPORT_TIMEOUT_DS && !last_interop_response; ++I) + sleep(1) + + if(!last_interop_response) + TGS_ERROR_LOG("Failed to get export result for: [json]") + else + . = last_interop_response + + export_lock = FALSE + +/datum/tgs_api/v4/OnReboot() + var/list/result = Export(TGS4_COMM_WORLD_REBOOT) + if(!result) + return + + //okay so the standard TGS4 proceedure is: right before rebooting change the port to whatever was sent to us in the above json's data parameter + + var/port = result[TGS4_PARAMETER_DATA] + if(!isnum(port)) + return //this is valid, server may just want use to reboot + + if(port == 0) + //to byond 0 means any port and "none" means close vOv + port = "none" + + if(!world.OpenPort(port)) + TGS_ERROR_LOG("Unable to set port to [port]!") + +/datum/tgs_api/v4/InstanceName() + return instance_name + +/datum/tgs_api/v4/TestMerges() + return cached_test_merges + +/datum/tgs_api/v4/EndProcess() + Export(TGS4_COMM_END_PROCESS) + +/datum/tgs_api/v4/Revision() + return cached_revision + +/datum/tgs_api/v4/ChatBroadcast(message, list/channels) + var/list/ids + if(length(channels)) + ids = list() + for(var/I in channels) + var/datum/tgs_chat_channel/channel = I + ids += channel.id + message = list("message" = message, "channelIds" = ids) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Export(TGS4_COMM_CHAT, message) + +/datum/tgs_api/v4/ChatTargetedBroadcast(message, admin_only) + var/list/channels = list() + for(var/I in ChatChannelInfo()) + var/datum/tgs_chat_channel/channel = I + if (!channel.is_private_channel && ((channel.is_admin_channel && admin_only) || (!channel.is_admin_channel && !admin_only))) + channels += channel.id + message = list("message" = message, "channelIds" = channels) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Export(TGS4_COMM_CHAT, message) + +/datum/tgs_api/v4/ChatPrivateMessage(message, datum/tgs_chat_user/user) + message = list("message" = message, "channelIds" = list(user.channel.id)) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Export(TGS4_COMM_CHAT, message) + +/datum/tgs_api/v4/ChatChannelInfo() + . = list() + //no caching cause tgs may change this + var/list/json = json_decode(file2text(chat_channels_json_path)) + for(var/I in json) + . += DecodeChannel(I) + +/datum/tgs_api/v4/proc/DecodeChannel(channel_json) + var/datum/tgs_chat_channel/channel = new + channel.id = channel_json["id"] + channel.friendly_name = channel_json["friendlyName"] + channel.connection_name = channel_json["connectionName"] + channel.is_admin_channel = channel_json["isAdminChannel"] + channel.is_private_channel = channel_json["isPrivateChannel"] + channel.custom_tag = channel_json["tag"] + return channel + +/datum/tgs_api/v4/SecurityLevel() + return security_level + +/* +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v4/commands.dm b/code/modules/tgs/v4/commands.dm new file mode 100644 index 0000000000..1d9951bc04 --- /dev/null +++ b/code/modules/tgs/v4/commands.dm @@ -0,0 +1,69 @@ +/datum/tgs_api/v4/proc/ListCustomCommands() + var/results = list() + custom_commands = list() + for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command) + var/datum/tgs_chat_command/stc = new I + var/command_name = stc.name + if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\"")) + TGS_ERROR_LOG("Custom command [command_name] ([I]) can't be used as it is empty or contains illegal characters!") + continue + + if(results[command_name]) + var/datum/other = custom_commands[command_name] + TGS_ERROR_LOG("Custom commands [other.type] and [I] have the same name (\"[command_name]\"), only [other.type] will be available!") + continue + results += list(list("name" = command_name, "help_text" = stc.help_text, "admin_only" = stc.admin_only)) + custom_commands[command_name] = stc + + var/commands_file = chat_commands_json_path + if(!commands_file) + return + text2file(json_encode(results), commands_file) + +/datum/tgs_api/v4/proc/HandleCustomCommand(command_json) + var/list/data = json_decode(command_json) + var/command = data["command"] + var/user = data["user"] + var/params = data["params"] + + var/datum/tgs_chat_user/u = new + u.id = user["id"] + u.friendly_name = user["friendlyName"] + u.mention = user["mention"] + u.channel = DecodeChannel(user["channel"]) + + var/datum/tgs_chat_command/sc = custom_commands[command] + if(sc) + var/result = sc.Run(u, params) + if(result == null) + result = "" + return result + return "Unknown command: [command]!" + +/* + +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm new file mode 100644 index 0000000000..1117a1df50 --- /dev/null +++ b/code/modules/tgs/v5/_defines.dm @@ -0,0 +1,121 @@ +#define DMAPI5_PARAM_SERVER_PORT "tgs_port" +#define DMAPI5_PARAM_ACCESS_IDENTIFIER "tgs_key" + +#define DMAPI5_BRIDGE_DATA "data" +#define DMAPI5_TOPIC_DATA "tgs_data" + +#define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0 +#define DMAPI5_BRIDGE_COMMAND_STARTUP 1 +#define DMAPI5_BRIDGE_COMMAND_PRIME 2 +#define DMAPI5_BRIDGE_COMMAND_REBOOT 3 +#define DMAPI5_BRIDGE_COMMAND_KILL 4 +#define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5 + +#define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier" +#define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage" + +#define DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE "commandType" +#define DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT "currentPort" +#define DMAPI5_BRIDGE_PARAMETER_VERSION "version" +#define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage" +#define DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS "customCommands" +#define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel" + +#define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort" +#define DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION "runtimeInformation" + +#define DMAPI5_CHAT_MESSAGE_TEXT "text" +#define DMAPI5_CHAT_MESSAGE_CHANNEL_IDS "channelIds" + +#define DMAPI5_RUNTIME_INFORMATION_ACCESS_IDENTIFIER "accessIdentifier" +#define DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION "serverVersion" +#define DMAPI5_RUNTIME_INFORMATION_SERVER_PORT "serverPort" +#define DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY "apiValidateOnly" +#define DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME "instanceName" +#define DMAPI5_RUNTIME_INFORMATION_REVISION "revision" +#define DMAPI5_RUNTIME_INFORMATION_TEST_MERGES "testMerges" +#define DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL "securityLevel" + +#define DMAPI5_CHAT_UPDATE_CHANNELS "channels" + +#define DMAPI5_TEST_MERGE_TIME_MERGED "timeMerged" +#define DMAPI5_TEST_MERGE_REVISION "revision" +#define DMAPI5_TEST_MERGE_TITLE_AT_MERGE "titleAtMerge" +#define DMAPI5_TEST_MERGE_BODY_AT_MERGE "bodyAtMerge" +#define DMAPI5_TEST_MERGE_URL "url" +#define DMAPI5_TEST_MERGE_AUTHOR "author" +#define DMAPI5_TEST_MERGE_NUMBER "number" +#define DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION "pullRequestRevision" +#define DMAPI5_TEST_MERGE_COMMENT "comment" + +#define DMAPI5_CHAT_COMMAND_NAME "name" +#define DMAPI5_CHAT_COMMAND_PARAMS "params" +#define DMAPI5_CHAT_COMMAND_USER "user" + +#define DMAPI5_EVENT_NOTIFICATION_TYPE "type" +#define DMAPI5_EVENT_NOTIFICATION_PARAMETERS "parameters" + +#define DMAPI5_TOPIC_COMMAND_CHAT_COMMAND 0 +#define DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION 1 +#define DMAPI5_TOPIC_COMMAND_CHANGE_PORT 2 +#define DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE 3 +#define DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED 4 +#define DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE 4 +#define DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE 5 + +#define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType" +#define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand" +#define DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION "eventNotification" +#define DMAPI5_TOPIC_PARAMETER_NEW_PORT "newPort" +#define DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE "newRebootState" +#define DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME "newInstanceName" +#define DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE "chatUpdate" + +#define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE "commandResponseMessage" +#define DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES "chatResponses" + +#define DMAPI5_REVISION_INFORMATION_COMMIT_SHA "commitSha" +#define DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA "originCommitSha" + +#define DMAPI5_CHAT_USER_ID "id" +#define DMAPI5_CHAT_USER_FRIENDLY_NAME "friendlyName" +#define DMAPI5_CHAT_USER_MENTION "mention" +#define DMAPI5_CHAT_USER_CHANNEL "channel" + +#define DMAPI5_CHAT_CHANNEL_ID "id" +#define DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME "friendlyName" +#define DMAPI5_CHAT_CHANNEL_CONNECTION_NAME "connectionName" +#define DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL "isAdminChannel" +#define DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL "isPrivateChannel" +#define DMAPI5_CHAT_CHANNEL_TAG "tag" + +#define DMAPI5_CUSTOM_CHAT_COMMAND_NAME "name" +#define DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT "helpText" +#define DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY "adminOnly" + +/* +The MIT License + +Copyright (c) 2020 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm new file mode 100644 index 0000000000..32f80c0ae4 --- /dev/null +++ b/code/modules/tgs/v5/api.dm @@ -0,0 +1,352 @@ +/datum/tgs_api/v5 + var/server_port + var/access_identifier + + var/instance_name + var/security_level + + var/reboot_mode = TGS_REBOOT_MODE_NORMAL + + var/list/intercepted_message_queue + + var/list/custom_commands + + var/list/test_merges + var/datum/tgs_revision_information/revision + var/list/chat_channels + + var/datum/tgs_event_handler/event_handler + +/datum/tgs_api/v5/ApiVersion() + return new /datum/tgs_version("5.0.0") + +/datum/tgs_api/v5/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level) + src.event_handler = event_handler + + server_port = world.params[DMAPI5_PARAM_SERVER_PORT] + access_identifier = world.params[DMAPI5_PARAM_ACCESS_IDENTIFIER] + + var/datum/tgs_version/api_version = ApiVersion() + var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) + if(!istype(bridge_response)) + TGS_ERROR_LOG("Failed initial bridge request!") + return FALSE + + var/list/runtime_information = bridge_response[DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION] + if(!istype(runtime_information)) + TGS_ERROR_LOG("Failed to decode runtime information from bridge response: [json_encode(bridge_response)]!") + return FALSE + + if(runtime_information[DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY]) + TGS_INFO_LOG("DMAPI validation, exiting...") + del(world) + + security_level = runtime_information[DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL] + instance_name = runtime_information[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME] + version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION]) + + var/list/revisionData = runtime_information[DMAPI5_RUNTIME_INFORMATION_REVISION] + if(istype(revisionData)) + revision = new + revision.commit = revisionData[DMAPI5_REVISION_INFORMATION_COMMIT_SHA] + revision.origin_commit = revisionData[DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA] + else + TGS_ERROR_LOG("Failed to decode [DMAPI5_RUNTIME_INFORMATION_REVISION] from runtime information!") + + test_merges = list() + var/list/test_merge_json = runtime_information[DMAPI5_RUNTIME_INFORMATION_TEST_MERGES] + if(istype(test_merge_json)) + for(var/entry in test_merge_json) + var/datum/tgs_revision_information/test_merge/tm = new + tm.number = entry[DMAPI5_TEST_MERGE_NUMBER] + + var/list/revInfo = entry[DMAPI5_TEST_MERGE_REVISION] + if(revInfo) + tm.commit = revisionData[DMAPI5_REVISION_INFORMATION_COMMIT_SHA] + tm.origin_commit = revisionData[DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA] + else + TGS_WARNING_LOG("Failed to decode [DMAPI5_TEST_MERGE_REVISION] from test merge #[tm.number]!") + + tm.time_merged = text2num(entry[DMAPI5_TEST_MERGE_TIME_MERGED]) + tm.title = entry[DMAPI5_TEST_MERGE_TITLE_AT_MERGE] + tm.body = entry[DMAPI5_TEST_MERGE_BODY_AT_MERGE] + tm.url = entry[DMAPI5_TEST_MERGE_URL] + tm.author = entry[DMAPI5_TEST_MERGE_AUTHOR] + tm.pull_request_commit = entry[DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION] + tm.comment = entry[DMAPI5_TEST_MERGE_COMMENT] + + test_merges += tm + else + TGS_WARNING_LOG("Failed to decode [DMAPI5_RUNTIME_INFORMATION_TEST_MERGES] from runtime information!") + + chat_channels = list() + DecodeChannels(runtime_information) + + return TRUE + +/datum/tgs_api/v5/OnInitializationComplete() + Bridge(DMAPI5_BRIDGE_COMMAND_PRIME) + + var/tgs4_secret_sleep_offline_sauce = 29051994 + var/old_sleep_offline = world.sleep_offline + world.sleep_offline = tgs4_secret_sleep_offline_sauce + sleep(1) + if(world.sleep_offline == tgs4_secret_sleep_offline_sauce) //if not someone changed it + world.sleep_offline = old_sleep_offline + +/datum/tgs_api/v5/proc/TopicResponse(error_message = null) + var/list/response = list() + response[DMAPI5_RESPONSE_ERROR_MESSAGE] = error_message + + return json_encode(response) + +/datum/tgs_api/v5/OnTopic(T) + var/list/params = params2list(T) + var/json = params[DMAPI5_TOPIC_DATA] + if(!json) + return FALSE //continue world/Topic + + var/list/topic_parameters = json_decode(json) + if(!topic_parameters) + return TopicResponse("Invalid topic parameters json!"); + + var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] + if(their_sCK != access_identifier) + return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER] from: [json]!"); + + var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE] + if(!isnum(command)) + return TopicResponse("Failed to decode [DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE] from: [json]!") + + switch(command) + if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND) + var/result = HandleCustomCommand(topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND]) + if(!result) + result = TopicResponse("Error running chat command!") + return result + if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION) + intercepted_message_queue = list() + var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION] + if(!istype(event_notification)) + return TopicResponse("Invalid [DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]!") + + var/event_type = event_notification[DMAPI5_EVENT_NOTIFICATION_TYPE] + if(!isnum(event_type)) + return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_TYPE]!") + + var/list/event_parameters = event_notification[DMAPI5_EVENT_NOTIFICATION_PARAMETERS] + if(event_parameters && !istype(event_parameters)) + return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!") + + var/list/event_call = list(event_type) + if(event_parameters) + event_call += event_parameters + + if(event_handler != null) + event_handler.HandleEvent(arglist(event_call)) + + var/list/response = list() + response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue + intercepted_message_queue = null + return json_encode(response) + if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT) + var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] + if (!isnum(new_port) || !(new_port > 0)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]") + + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port) + + //the topic still completes, miraculously + //I honestly didn't believe byond could do it without exploding + if(!world.OpenPort(new_port)) + return TopicResponse("Port change failed!") + + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE) + var/new_reboot_mode = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE] + if(!isnum(new_reboot_mode)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE]!") + + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode) + + reboot_mode = new_reboot_mode + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED) + var/new_instance_name = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME] + if(!istext(new_instance_name)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]!") + + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_INSTANCE_RENAMED, new_instance_name) + + instance_name = new_instance_name + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE) + var/list/chat_update_json = topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE] + if(!istype(chat_update_json)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]!") + + DecodeChannels(chat_update_json) + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE) + var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] + if (!isnum(new_port) || !(new_port > 0)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]") + + server_port = new_port + return TopicResponse() + + return TopicResponse("Unknown command: [command]") + +/datum/tgs_api/v5/proc/Bridge(command, list/data) + if(!data) + data = list() + + data[DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE] = command + data[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] = access_identifier + + var/json = json_encode(data) + var/encoded_json = url_encode(json) + + // This is an infinite sleep until we get a response + var/export_response = world.Export("http://127.0.0.1:[server_port]/Bridge?[DMAPI5_BRIDGE_DATA]=[encoded_json]") + if(!export_response) + TGS_ERROR_LOG("Failed export request: [json]") + return + + var/response_json = file2text(export_response["CONTENT"]) + if(!response_json) + TGS_ERROR_LOG("Failed export request, missing content!") + return + + var/list/bridge_response = json_decode(response_json) + if(!bridge_response) + TGS_ERROR_LOG("Failed export request, bad json: [response_json]") + return + + var/error = bridge_response[DMAPI5_RESPONSE_ERROR_MESSAGE] + if(error) + TGS_ERROR_LOG("Failed export request, bad request: [error]") + return + + return bridge_response + +/datum/tgs_api/v5/OnReboot() + var/list/result = Bridge(DMAPI5_BRIDGE_COMMAND_REBOOT) + if(!result) + return + + //okay so the standard TGS4 proceedure is: right before rebooting change the port to whatever was sent to us in the above json's data parameter + + var/port = result[DMAPI5_BRIDGE_RESPONSE_NEW_PORT] + if(!isnum(port)) + return //this is valid, server may just want use to reboot + + if(port == 0) + //to byond 0 means any port and "none" means close vOv + port = "none" + + if(!world.OpenPort(port)) + TGS_ERROR_LOG("Unable to set port to [port]!") + +/datum/tgs_api/v5/InstanceName() + return instance_name + +/datum/tgs_api/v5/TestMerges() + return test_merges + +/datum/tgs_api/v5/EndProcess() + Bridge(DMAPI5_BRIDGE_COMMAND_KILL) + +/datum/tgs_api/v5/Revision() + return revision + +/datum/tgs_api/v5/ChatBroadcast(message, list/channels) + if(!length(channels)) + channels = ChatChannelInfo() + + var/list/ids = list() + for(var/I in channels) + var/datum/tgs_chat_channel/channel = I + ids += channel.id + + message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = ids) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + +/datum/tgs_api/v5/ChatTargetedBroadcast(message, admin_only) + var/list/channels = list() + for(var/I in ChatChannelInfo()) + var/datum/tgs_chat_channel/channel = I + if (!channel.is_private_channel && ((channel.is_admin_channel && admin_only) || (!channel.is_admin_channel && !admin_only))) + channels += channel.id + message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = channels) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + +/datum/tgs_api/v5/ChatPrivateMessage(message, datum/tgs_chat_user/user) + message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = list(user.channel.id)) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + +/datum/tgs_api/v5/ChatChannelInfo() + return chat_channels + +/datum/tgs_api/v5/proc/DecodeChannels(chat_update_json) + var/list/chat_channels_json = chat_update_json[DMAPI5_CHAT_UPDATE_CHANNELS] + if(istype(chat_channels_json)) + chat_channels.Cut() + for(var/channel_json in chat_channels_json) + var/datum/tgs_chat_channel/channel = DecodeChannel(channel_json) + if(channel) + chat_channels += channel + else + TGS_WARNING_LOG("Failed to decode [DMAPI5_CHAT_UPDATE_CHANNELS] from channel update!") + +/datum/tgs_api/v5/proc/DecodeChannel(channel_json) + var/datum/tgs_chat_channel/channel = new + channel.id = channel_json[DMAPI5_CHAT_CHANNEL_ID] + channel.friendly_name = channel_json[DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME] + channel.connection_name = channel_json[DMAPI5_CHAT_CHANNEL_CONNECTION_NAME] + channel.is_admin_channel = channel_json[DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL] + channel.is_private_channel = channel_json[DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL] + channel.custom_tag = channel_json[DMAPI5_CHAT_CHANNEL_TAG] + return channel + +/datum/tgs_api/v5/SecurityLevel() + return security_level + +/* +The MIT License + +Copyright (c) 2020 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v5/chat_commands.dm b/code/modules/tgs/v5/chat_commands.dm new file mode 100644 index 0000000000..bc73602861 --- /dev/null +++ b/code/modules/tgs/v5/chat_commands.dm @@ -0,0 +1,15 @@ +/datum/tgs_chat_command/status + name = "status" + help_text = "Shows the current production server status" + admin_only = FALSE + +/datum/tgs_chat_command/status/Run(datum/tgs_chat_user/sender, params) + return "```Players logged in: [GLOB.clients.len] - Round Duration: [roundduration2text()]```" + +/datum/tgs_chat_command/parsetest + name = "parsetest" + help_text = "Shows the current production server status" + admin_only = FALSE + +/datum/tgs_chat_command/parsetest/Run(datum/tgs_chat_user/sender, params) + return "```You passed:[params]```" diff --git a/code/modules/tgs/v5/commands.dm b/code/modules/tgs/v5/commands.dm new file mode 100644 index 0000000000..2775157656 --- /dev/null +++ b/code/modules/tgs/v5/commands.dm @@ -0,0 +1,68 @@ +/datum/tgs_api/v5/proc/ListCustomCommands() + var/results = list() + custom_commands = list() + for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command) + var/datum/tgs_chat_command/stc = new I + var/command_name = stc.name + if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\"")) + TGS_WARNING_LOG("Custom command [command_name] ([I]) can't be used as it is empty or contains illegal characters!") + continue + + if(results[command_name]) + var/datum/other = custom_commands[command_name] + TGS_WARNING_LOG("Custom commands [other.type] and [I] have the same name (\"[command_name]\"), only [other.type] will be available!") + continue + results += list(list(DMAPI5_CUSTOM_CHAT_COMMAND_NAME = command_name, DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT = stc.help_text, DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY = stc.admin_only)) + custom_commands[command_name] = stc + + return results + +/datum/tgs_api/v5/proc/HandleCustomCommand(list/command_json) + var/command = command_json[DMAPI5_CHAT_COMMAND_NAME] + var/user = command_json[DMAPI5_CHAT_COMMAND_USER] + var/params = command_json[DMAPI5_CHAT_COMMAND_PARAMS] + + var/datum/tgs_chat_user/u = new + u.id = user[DMAPI5_CHAT_USER_ID] + u.friendly_name = user[DMAPI5_CHAT_USER_FRIENDLY_NAME] + u.mention = user[DMAPI5_CHAT_USER_MENTION] + u.channel = DecodeChannel(user[DMAPI5_CHAT_USER_CHANNEL]) + + var/datum/tgs_chat_command/sc = custom_commands[command] + if(sc) + var/text_response = sc.Run(u, params) + var/list/topic_response = list() + if(!istext(text_response)) + TGS_ERROR_LOG("Custom command [command] should return a string! Got: \"[text_response]\"") + text_response = null + topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = text_response + return json_encode(topic_response) + return TopicResponse("Unknown custom chat command: [command]!") + +/* + +The MIT License + +Copyright (c) 2020 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v5/undef.dm b/code/modules/tgs/v5/undef.dm new file mode 100644 index 0000000000..72d673b9b1 --- /dev/null +++ b/code/modules/tgs/v5/undef.dm @@ -0,0 +1,121 @@ +#undef DMAPI5_PARAM_SERVER_PORT +#undef DMAPI5_PARAM_ACCESS_IDENTIFIER + +#undef DMAPI5_BRIDGE_DATA +#undef DMAPI5_TOPIC_DATA + +#undef DMAPI5_BRIDGE_COMMAND_PORT_UPDATE +#undef DMAPI5_BRIDGE_COMMAND_STARTUP +#undef DMAPI5_BRIDGE_COMMAND_PRIME +#undef DMAPI5_BRIDGE_COMMAND_REBOOT +#undef DMAPI5_BRIDGE_COMMAND_KILL +#undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND + +#undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER +#undef DMAPI5_RESPONSE_ERROR_MESSAGE + +#undef DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE +#undef DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT +#undef DMAPI5_BRIDGE_PARAMETER_VERSION +#undef DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE +#undef DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS +#undef DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL + +#undef DMAPI5_BRIDGE_RESPONSE_NEW_PORT +#undef DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION + +#undef DMAPI5_CHAT_MESSAGE_TEXT +#undef DMAPI5_CHAT_MESSAGE_CHANNEL_IDS + +#undef DMAPI5_RUNTIME_INFORMATION_ACCESS_IDENTIFIER +#undef DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION +#undef DMAPI5_RUNTIME_INFORMATION_SERVER_PORT +#undef DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY +#undef DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME +#undef DMAPI5_RUNTIME_INFORMATION_REVISION +#undef DMAPI5_RUNTIME_INFORMATION_TEST_MERGES +#undef DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL + +#undef DMAPI5_CHAT_UPDATE_CHANNELS + +#undef DMAPI5_TEST_MERGE_TIME_MERGED +#undef DMAPI5_TEST_MERGE_REVISION +#undef DMAPI5_TEST_MERGE_TITLE_AT_MERGE +#undef DMAPI5_TEST_MERGE_BODY_AT_MERGE +#undef DMAPI5_TEST_MERGE_URL +#undef DMAPI5_TEST_MERGE_AUTHOR +#undef DMAPI5_TEST_MERGE_NUMBER +#undef DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION +#undef DMAPI5_TEST_MERGE_COMMENT + +#undef DMAPI5_CHAT_COMMAND_NAME +#undef DMAPI5_CHAT_COMMAND_PARAMS +#undef DMAPI5_CHAT_COMMAND_USER + +#undef DMAPI5_EVENT_NOTIFICATION_TYPE +#undef DMAPI5_EVENT_NOTIFICATION_PARAMETERS + +#undef DMAPI5_TOPIC_COMMAND_CHAT_COMMAND +#undef DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION +#undef DMAPI5_TOPIC_COMMAND_CHANGE_PORT +#undef DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE +#undef DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED +#undef DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE +#undef DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE + +#undef DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE +#undef DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND +#undef DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION +#undef DMAPI5_TOPIC_PARAMETER_NEW_PORT +#undef DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE +#undef DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME +#undef DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE + +#undef DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE +#undef DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES + +#undef DMAPI5_REVISION_INFORMATION_COMMIT_SHA +#undef DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA + +#undef DMAPI5_CHAT_USER_ID +#undef DMAPI5_CHAT_USER_FRIENDLY_NAME +#undef DMAPI5_CHAT_USER_MENTION +#undef DMAPI5_CHAT_USER_CHANNEL + +#undef DMAPI5_CHAT_CHANNEL_ID +#undef DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME +#undef DMAPI5_CHAT_CHANNEL_CONNECTION_NAME +#undef DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL +#undef DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL +#undef DMAPI5_CHAT_CHANNEL_TAG + +#undef DMAPI5_CUSTOM_CHAT_COMMAND_NAME +#undef DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT +#undef DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY + +/* +The MIT License + +Copyright (c) 2020 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/vchat/vchat_client.dm b/code/modules/vchat/vchat_client.dm index 6e0ac509b0..8456c5225f 100644 --- a/code/modules/vchat/vchat_client.dm +++ b/code/modules/vchat/vchat_client.dm @@ -266,31 +266,45 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic var/list/partial = splittext(iconData, "{") return replacetext(copytext(partial[2], 3, -5), "\n", "") +/proc/expire_bicon_cache(key) + if(GLOB.bicon_cache[key]) + GLOB.bicon_cache -= key + return TRUE + return FALSE + +GLOBAL_LIST_EMPTY(bicon_cache) // Cache of the tag results, not the icons /proc/bicon(var/obj, var/use_class = 1, var/custom_classes = "") var/class = use_class ? "class='icon misc [custom_classes]'" : null - if (!obj) + if(!obj) return - var/static/list/bicon_cache = list() - if (isicon(obj)) - //Icon refs get reused all the time especially on temporarily made ones like chat tags, too difficult to cache. - //if (!bicon_cache["\ref[obj]"]) // Doesn't exist yet, make it. - //bicon_cache["\ref[obj]"] = icon2base64(obj) - + // Try to avoid passing bicon an /icon directly. It is better to pass it an atom so it can cache. + if(isicon(obj)) // Passed an icon directly, nothing to cache-key on, as icon refs get reused *often* return "" // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with. var/atom/A = obj - var/key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]" - if (!bicon_cache[key]) // Doesn't exist, make it. - var/icon/I = icon(A.icon, A.icon_state, SOUTH, 1) - if (ishuman(obj)) - I = getFlatIcon(obj) //Ugly - bicon_cache[key] = icon2base64(I, key) + var/key + var/changes_often = ishuman(A) || isobserver(A) // If this ends up with more, move it into a proc or var on atom. + + if(changes_often) + key = "\ref[A]" + else + key = "[istype(A.icon, /icon) ? "\ref[A.icon]" : A.icon]:[A.icon_state]" + + var/base64 = GLOB.bicon_cache[key] + // Non-human atom, no cache + if(!base64) // Doesn't exist, make it. + base64 = icon2base64(A.examine_icon(), key) + GLOB.bicon_cache[key] = base64 + if(changes_often) + addtimer(CALLBACK(GLOBAL_PROC, .proc/expire_bicon_cache, key), 50 SECONDS, TIMER_UNIQUE) + + // May add a class to the img tag created by bicon if(use_class) class = "class='icon [A.icon_state] [custom_classes]'" - return "" + return "" //Checks if the message content is a valid to_chat message /proc/is_valid_tochat_message(message) diff --git a/code/modules/vehicles/bike.dm b/code/modules/vehicles/bike.dm index 5d8abe9fbd..1d4cb49a3b 100644 --- a/code/modules/vehicles/bike.dm +++ b/code/modules/vehicles/bike.dm @@ -54,6 +54,12 @@ return ..() +/obj/vehicle/bike/CtrlClick(var/mob/user) + if(Adjacent(user) && anchored) + toggle() + else + return ..() + /obj/vehicle/bike/verb/toggle() set name = "Toggle Engine" set category = "Vehicle" @@ -71,7 +77,13 @@ turn_off() src.visible_message("\The [src] putters before turning off.", "You hear something putter slowly.") -/obj/vehicle/bike/verb/kickstand(var/mob/user as mob) //TFF 22/3/20 - Tweaking the visible_message output so it's not "You put kickstand down" to everyone. +/obj/vehicle/bike/AltClick(var/mob/user) + if(Adjacent(user)) + kickstand(user) + else + return ..() + +/obj/vehicle/bike/verb/kickstand(var/mob/user as mob) set name = "Toggle Kickstand" set category = "Vehicle" set src in view(0) diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index eb4f1141b8..939c72110e 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -197,6 +197,22 @@ . += "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition." . += "The charge meter reads [cell? round(cell.percent(), 0.01) : 0]%" + +/obj/vehicle/train/engine/CtrlClick(var/mob/user) + if(Adjacent(user)) + if(on) + stop_engine() + else + start_engine() + else + return ..() + +/obj/vehicle/train/engine/AltClick(var/mob/user) + if(Adjacent(user)) + remove_key() + else + return ..() + /obj/vehicle/train/engine/verb/start_engine() set name = "Start engine" set category = "Vehicle" diff --git a/code/modules/vore/appearance/sprite_accessories_vr.dm b/code/modules/vore/appearance/sprite_accessories_vr.dm index d7814bdaab..4f9cceb981 100644 --- a/code/modules/vore/appearance/sprite_accessories_vr.dm +++ b/code/modules/vore/appearance/sprite_accessories_vr.dm @@ -484,6 +484,8 @@ name = "tritail kitsune ears (Rosey)" desc = "" icon_state = "rosey" + do_colouration = 1 + color_blend_mode = ICON_MULTIPLY ckeys_allowed = list("joey4298") /datum/sprite_accessory/ears/aronai @@ -1030,6 +1032,8 @@ name = "pentatail kitsune tails (Rosey)" //I predict seven tails next. ~CK desc = "" icon_state = "rosey_five" + do_colouration = 1 + color_blend_mode = ICON_MULTIPLY ckeys_allowed = list("joey4298") /datum/sprite_accessory/tail/scree diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index 72575492ed..1c4079de15 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -935,7 +935,7 @@ if("Prevent Digestion") user.digestable = FALSE - message_admins("[key_name(user)] toggled their digestability to [user.digestable] ([user ? "JMP" : "null"])") + message_admins("[key_name(user)] toggled their digestability to [user.digestable] [ADMIN_COORDJMP(user)]") if(user.client.prefs_vr) user.client.prefs_vr.digestable = user.digestable @@ -1002,7 +1002,7 @@ if("Prevent Mob Predation") user.allowmobvore = FALSE - message_admins("[key_name(user)] toggled their mob vore preference to [user.allowmobvore] ([user ? "JMP" : "null"])") + message_admins("[key_name(user)] toggled their mob vore preference to [user.allowmobvore] [ADMIN_COORDJMP(user)]") if(user.client.prefs_vr) user.client.prefs_vr.allowmobvore = user.allowmobvore diff --git a/code/modules/vore/fluffstuff/custom_clothes_vr.dm b/code/modules/vore/fluffstuff/custom_clothes_vr.dm index 45db1edb3e..6927fba35d 100644 --- a/code/modules/vore/fluffstuff/custom_clothes_vr.dm +++ b/code/modules/vore/fluffstuff/custom_clothes_vr.dm @@ -1887,7 +1887,7 @@ Departamental Swimsuits, for general use species_restricted = list("exclude", SPECIES_TESHARI) -/obj/item/clothing/under/fluff/slime_skeleton/mob_can_equip(M as mob, slot) +/obj/item/clothing/under/fluff/slime_skeleton/mob_can_equip(M as mob, slot, disable_warning = FALSE) if(!..()) return 0 diff --git a/code/modules/vore/resizing/resize_vr.dm b/code/modules/vore/resizing/resize_vr.dm index b7e671e9b3..07d3a7831f 100644 --- a/code/modules/vore/resizing/resize_vr.dm +++ b/code/modules/vore/resizing/resize_vr.dm @@ -158,6 +158,10 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2 * @return false if normal code should continue, true to prevent normal code. */ /mob/living/proc/handle_micro_bump_helping(mob/living/tmob) + //Riding and being moved to us or something similar + if(tmob in buckled_mobs) + return TRUE + //Both small! Go ahead and go. if(get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY) return TRUE @@ -214,6 +218,10 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2 if(!canmove || buckled) return + //Riding and being moved to us or something similar + if(tmob in buckled_mobs) + return TRUE + //Test/set if human var/mob/living/carbon/human/pred = src if(!istype(pred)) diff --git a/code/modules/xenobio2/machinery/core_extractor.dm b/code/modules/xenobio2/machinery/core_extractor.dm index 1a23dcd758..01068e4cd1 100644 --- a/code/modules/xenobio2/machinery/core_extractor.dm +++ b/code/modules/xenobio2/machinery/core_extractor.dm @@ -18,16 +18,10 @@ var/operatingcolor = "#FFFF22" -/obj/machinery/slime/extractor/New() - ..() +/obj/machinery/slime/extractor/Initialize() + . = ..() + default_apply_parts() update_light_color() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - RefreshParts() /obj/machinery/slime/extractor/attackby(var/obj/item/W, var/mob/user) diff --git a/code/modules/xenobio2/machinery/gene_manipulators.dm b/code/modules/xenobio2/machinery/gene_manipulators.dm index 761a2a98d4..91ff77fc94 100644 --- a/code/modules/xenobio2/machinery/gene_manipulators.dm +++ b/code/modules/xenobio2/machinery/gene_manipulators.dm @@ -123,17 +123,10 @@ var/datum/xeno/traits/genetics // Currently scanned xeno genetic structure. var/degradation = 0 // Increments with each scan, stops allowing gene mods after a certain point. -/obj/machinery/xenobio/extractor/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - RefreshParts() - +/obj/machinery/xenobio/extractor/Initialize() + . = ..() + default_apply_parts() + /obj/machinery/xenobio/extractor/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W,/obj/item/xenoproduct)) if(product) @@ -265,16 +258,9 @@ var/mob/living/simple_mob/xeno/slime/occupant -/obj/machinery/xenobio/editor/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) - RefreshParts() +/obj/machinery/xenobio/editor/Initialize() + . = ..() + default_apply_parts() /obj/machinery/xenobio/editor/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W,/obj/item/weapon/grab)) diff --git a/code/modules/xenobio2/machinery/injector.dm b/code/modules/xenobio2/machinery/injector.dm index 59dfbf69c6..2c0454a8e2 100644 --- a/code/modules/xenobio2/machinery/injector.dm +++ b/code/modules/xenobio2/machinery/injector.dm @@ -19,18 +19,13 @@ circuit = /obj/item/weapon/circuitboard/xenobioinjectormachine -/obj/machinery/xenobio2/manualinjector/New() - ..() +/obj/machinery/xenobio2/manualinjector/Initialize() + . = ..() var/datum/reagents/R = new/datum/reagents(1000) reagents = R R.my_atom = src beaker = new /obj/item/weapon/reagent_containers/glass/beaker(src) - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - RefreshParts() + default_apply_parts() /obj/machinery/xenobio2/manualinjector/update_icon() if(beaker) diff --git a/code/modules/xenobio2/machinery/slime_replicator.dm b/code/modules/xenobio2/machinery/slime_replicator.dm index 4d45d6ca2a..b5e49b7c62 100644 --- a/code/modules/xenobio2/machinery/slime_replicator.dm +++ b/code/modules/xenobio2/machinery/slime_replicator.dm @@ -17,17 +17,11 @@ var/emptycolor = "#FF2222" var/operatingcolor = "#FFFF22" -/obj/machinery/slime/replicator/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - RefreshParts() +/obj/machinery/slime/replicator/Initialize() + . = ..() + default_apply_parts() update_light_color() - /obj/machinery/slime/replicator/attackby(var/obj/item/W, var/mob/user) //Let's try to deconstruct first. if(W.is_screwdriver() && !inuse) diff --git a/config/example/config.txt b/config/example/config.txt index cf7be2756f..ff0340bcea 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -531,4 +531,7 @@ SQLITE_FEEDBACK_MIN_AGE 7 #DISABLE_CID_WARN_POPUP ## Comment this out if you don't want to use the 'nightshift lighting' subsystem to adjust lights based on ingame time -ENABLE_NIGHT_SHIFTS \ No newline at end of file +ENABLE_NIGHT_SHIFTS + +## Comment this out to enable playtime restrictions for jobs in their respective departments (mostly for heads) +# USE_PLAYTIME_RESTRICTION_FOR_JOBS \ No newline at end of file diff --git a/html/changelogs/atermonera_multilingual_pref.yml b/html/changelogs/atermonera_multilingual_pref.yml new file mode 100644 index 0000000000..84552b9a13 --- /dev/null +++ b/html/changelogs/atermonera_multilingual_pref.yml @@ -0,0 +1,11 @@ +author: Atermonera +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added a preference to control multilingual parsing behaviour, with a few different modes. Should hopefully be less punishing to people who stutter and use hyphens as a language key." + - tweak: "The examine mode preference should now persist across reconnections during a single round, but if the server is fully restarted it still appears to reset. This issue is also present for the multilingual preference, and I'm still looking into it. Savefiles are crpytic." diff --git a/html/changelogs/atlantiscze-sm.yml b/html/changelogs/atlantiscze-sm.yml new file mode 100644 index 0000000000..d6d8ddbfcf --- /dev/null +++ b/html/changelogs/atlantiscze-sm.yml @@ -0,0 +1,6 @@ +author: atlantiscze + +delete-after: True + +changes: + - tweak: "Supermatter delamination effects have been tweaked. Delamination is considerably less laggy, and less directly destructive. Instead, it causes larger health hazard and secondary engineering problems such as power outage or partial damage of solar arrays." \ No newline at end of file diff --git a/icons/misc/pic_in_pic.dmi b/icons/misc/pic_in_pic.dmi new file mode 100644 index 0000000000..cdac129513 Binary files /dev/null and b/icons/misc/pic_in_pic.dmi differ diff --git a/icons/mob/chronos_mob_vr.dmi b/icons/mob/chronos_mob_vr.dmi new file mode 100644 index 0000000000..06b1ca6686 Binary files /dev/null and b/icons/mob/chronos_mob_vr.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index 4bfb8bf479..f192f80d1d 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/mob/screen_ai.dmi b/icons/mob/screen_ai.dmi index ad813aad75..ce12203c7c 100644 Binary files a/icons/mob/screen_ai.dmi and b/icons/mob/screen_ai.dmi differ diff --git a/icons/mob/species/seromi/suit.dmi b/icons/mob/species/seromi/suit.dmi index d10902a6ff..726fb11a8a 100644 Binary files a/icons/mob/species/seromi/suit.dmi and b/icons/mob/species/seromi/suit.dmi differ diff --git a/icons/mob/species/vulpkanin/helmet.dmi b/icons/mob/species/vulpkanin/helmet.dmi index 47d3fd12ab..b1490dec6d 100644 Binary files a/icons/mob/species/vulpkanin/helmet.dmi and b/icons/mob/species/vulpkanin/helmet.dmi differ diff --git a/icons/mob/species/vulpkanin/suit.dmi b/icons/mob/species/vulpkanin/suit.dmi index 452c1fca56..c70734d3ae 100644 Binary files a/icons/mob/species/vulpkanin/suit.dmi and b/icons/mob/species/vulpkanin/suit.dmi differ diff --git a/icons/mob/vore/ears_vr.dmi b/icons/mob/vore/ears_vr.dmi index c2f4bcbd98..cd9c9f1492 100644 Binary files a/icons/mob/vore/ears_vr.dmi and b/icons/mob/vore/ears_vr.dmi differ diff --git a/icons/mob/vore/tails_vr.dmi b/icons/mob/vore/tails_vr.dmi index 9bb4bf0dd3..9ba6850f30 100644 Binary files a/icons/mob/vore/tails_vr.dmi and b/icons/mob/vore/tails_vr.dmi differ diff --git a/icons/obj/butts_vr.dmi b/icons/obj/butts_vr.dmi new file mode 100644 index 0000000000..104906120d Binary files /dev/null and b/icons/obj/butts_vr.dmi differ diff --git a/icons/obj/chronos_vr.dmi b/icons/obj/chronos_vr.dmi new file mode 100644 index 0000000000..e544110b5d Binary files /dev/null and b/icons/obj/chronos_vr.dmi differ diff --git a/icons/obj/decals_vr.dmi b/icons/obj/decals_vr.dmi index 6b05d6a003..391d37b918 100644 Binary files a/icons/obj/decals_vr.dmi and b/icons/obj/decals_vr.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index ba795e6576..606e8dbfe8 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/stationobjs_vr.dmi b/icons/obj/stationobjs_vr.dmi index 3438e97b9f..5801c5302d 100644 Binary files a/icons/obj/stationobjs_vr.dmi and b/icons/obj/stationobjs_vr.dmi differ diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi index 1132fa10a9..72a49c07c7 100644 Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ diff --git a/icons/turf/outdoors.dmi b/icons/turf/outdoors.dmi index b8af78d986..8bcc4308f6 100644 Binary files a/icons/turf/outdoors.dmi and b/icons/turf/outdoors.dmi differ diff --git a/maps/southern_cross/southern_cross-1.dmm b/maps/southern_cross/southern_cross-1.dmm index da2ec6cd40..cb8e5deb27 100644 --- a/maps/southern_cross/southern_cross-1.dmm +++ b/maps/southern_cross/southern_cross-1.dmm @@ -8865,6 +8865,7 @@ "doy" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 1},/obj/machinery/newscaster{pixel_y = -30},/turf/simulated/floor/wood,/area/library) "doz" = (/obj/machinery/firealarm{dir = 1; pixel_x = 0; pixel_y = -24},/turf/simulated/floor/carpet,/area/library) "doA" = (/obj/structure/bed/chair/office/dark{dir = 1},/turf/simulated/floor/carpet,/area/library) +"doB" = (/obj/effect/shuttle_landmark{landmark_tag = "response_ship_thirddeck"; name = "SC Near Deck 3 NE"},/turf/space,/area/shuttle/response_ship/thirddeck) "doC" = (/obj/item/weapon/circuitboard/firealarm,/turf/simulated/floor/tiled/freezer,/area/construction/seconddeck/construction2) "doD" = (/obj/item/frame/light,/turf/simulated/floor/tiled/freezer,/area/construction/seconddeck/construction2) "doE" = (/turf/simulated/floor/tiled/freezer,/area/construction/seconddeck/construction2) @@ -11629,7 +11630,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaadaaaaaaaaaaafaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaadaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadAVaaaaaaaaaaafaaaaaaaaaaafaaaaaaaaadAVbjTaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafbfGaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaagaaaaaaaaaaaaaaaaaadAWdAWdAWdAWdAWdAWdAWdAWdAWdAWdAWaaaaaaaaaaaaaaaaaaaaaaaadAVaaaaaaaaaaafaaaaaaaaaaafaaaaaaaaadAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVaafdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaadaaaaaaaadaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaadaaaaaaaaaaaaaaaaaadAWdAWdAWdAWdAWdAWdAWdAWdAWdAWdAWdAWaaaaaaaaaaaaaaaaaadAXdAXdAXaafaafaafaaaaaaaaaaafaafaafdAXdAXdAXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafaafdAVdAVdAVdAVdAVaafdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafaadaafabcaadaafaafaafdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafaafaafaadaaaaaaaaaaaaaaaaaadAWdAWdAWdAWdAWdAWdAWdAWdAYdAWdAWdAWaaaaaaaaaaaaaaaaaadAVdAVdAVaaaaaaaafaaaaaaaaaaafaaaaaadAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafaafdAVdAVdAVdAVdAVaafdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafaadaafabcaadaafaafaafdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaafaafaafaadaaaaaaaaaaaaaaaaaadAWdAWdAWdAWdAWdAWdAWdAWdAYdAWdoBdAWaaaaaaaaaaaaaaaaaadAVdAVdAVaaaaaaaafaaaaaaaaaaafaaaaaadAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaafaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAZdAZdAZdAZdAZdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaadaaaaaaaaaaaaaaaaaadAWdAWdAWdAWdAWdAWdAWdAWdAWdAWdAWdAWaaaaaaaaaaaaaaaaaadAXdAXdAXaafaafaafaaaaaaaaaaafaafaafdAXdAXdAXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaafaaaaafaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaafaaaaaaaabaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAZdAZdAZdAZdAZdBadBadBadAZdAZdAZdAZdAZdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadAWdAWdAWdAWdAWdAWdAWdAWdAWdAWdAWaaaaaaaaaaaaaaaaaaaaaaaadAVaaaaaaaaaaafaaaaaaaaaaafaaaaaaaaadAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaadAVdAVdAVdAVdAVaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaafaaaaaaaaaaaaaaaaaaaaadAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAZdBadBadBadAVdAVdAVdAVdAVdBadBadBadAZdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVdAVaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadAVaaaaaaaaaaafaaaaaaaaaaafaaaaaaaaadAVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/maps/submaps/surface_submaps/wilderness/DecoupledEngine.dmm b/maps/submaps/surface_submaps/wilderness/DecoupledEngine.dmm index 840f2055c4..15a2bf604f 100644 --- a/maps/submaps/surface_submaps/wilderness/DecoupledEngine.dmm +++ b/maps/submaps/surface_submaps/wilderness/DecoupledEngine.dmm @@ -9,7 +9,6 @@ "ai" = (/obj/item/stack/material/steel,/turf/template_noop,/area/submap/DecoupledEngine) "aj" = (/turf/simulated/floor/outdoors/rocks,/area/submap/DecoupledEngine) "ak" = (/obj/structure/lattice,/obj/structure/girder/displaced,/turf/simulated/floor/outdoors/rocks,/area/submap/DecoupledEngine) -"al" = (/obj/item/projectile/bullet/magnetic/fuelrod,/turf/template_noop,/area/submap/DecoupledEngine) "am" = (/obj/item/weapon/arrow/rod,/turf/template_noop,/area/submap/DecoupledEngine) "an" = (/turf/simulated/floor/water,/area/submap/DecoupledEngine) "ao" = (/obj/structure/lattice,/turf/simulated/floor/outdoors/rocks,/area/submap/DecoupledEngine) @@ -23,10 +22,9 @@ "aw" = (/obj/structure/girder,/obj/item/stack/material/steel,/turf/simulated/floor,/area/submap/DecoupledEngine) "ax" = (/obj/structure/lattice,/obj/structure/grille/broken,/turf/simulated/floor/outdoors/rocks,/area/submap/DecoupledEngine) "ay" = (/obj/effect/floor_decal/rust,/obj/item/stack/material/steel,/turf/simulated/floor,/area/submap/DecoupledEngine) -"az" = (/obj/machinery/atmospherics/pipe/simple/visible{ icon_state = "intact"; dir = 6},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) +"az" = (/obj/machinery/atmospherics/pipe/simple/visible{icon_state = "intact"; dir = 6},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "aA" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "aB" = (/obj/structure/shuttle/engine/heater{icon_state = "heater"; dir = 4},/obj/effect/floor_decal/rust,/obj/effect/decal/cleanable/cobweb2,/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/turf/simulated/floor,/area/submap/DecoupledEngine) -"aC" = (/obj/structure/shuttle/engine/propulsion{ icon_state = "propulsion_r"; dir = 4},/turf/simulated/floor/water,/area/submap/DecoupledEngine) "aD" = (/obj/structure/lattice,/obj/structure/grille,/turf/template_noop,/area/submap/DecoupledEngine) "aE" = (/obj/structure/lattice,/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/turf/template_noop,/area/submap/DecoupledEngine) "aF" = (/obj/structure/sign/warning/radioactive{dir = 8},/turf/simulated/wall/durasteel,/area/submap/DecoupledEngine) @@ -35,7 +33,7 @@ "aI" = (/obj/effect/decal/cleanable/blood/oil/streak{amount = 0},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "aJ" = (/obj/machinery/power/rad_collector,/obj/effect/floor_decal/rust,/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 9},/turf/simulated/floor,/area/submap/DecoupledEngine) "aK" = (/obj/effect/floor_decal/rust,/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 5},/turf/simulated/floor,/area/submap/DecoupledEngine) -"aL" = (/obj/structure/grille/broken,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 4},/obj/item/weapon/material/shard/phoron,/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) +"aL" = (/obj/structure/grille/broken,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 4},/obj/item/weapon/material/shard/phoron,/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "aM" = (/obj/machinery/atmospherics/pipe/manifold4w/visible,/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "aN" = (/obj/structure/shuttle/engine/heater{icon_state = "heater"; dir = 4},/obj/effect/floor_decal/rust,/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/turf/simulated/floor,/area/submap/DecoupledEngine) "aO" = (/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_r"; dir = 4},/turf/simulated/floor/water,/area/submap/DecoupledEngine) @@ -45,8 +43,8 @@ "aS" = (/obj/structure/closet/crate/oldreactor{anchored = 1},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "aT" = (/obj/item/poi/brokenoldreactor{anchored = 1},/obj/effect/floor_decal/rust,/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 4},/turf/simulated/floor,/area/submap/DecoupledEngine) "aU" = (/obj/machinery/atmospherics/pipe/simple/visible,/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) -"aV" = (/obj/structure/grille,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 8},/turf/simulated/floor,/area/submap/DecoupledEngine) -"aW" = (/obj/machinery/atmospherics/pipe/simple/visible{ icon_state = "intact"; dir = 5},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) +"aV" = (/obj/structure/grille,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 8},/turf/simulated/floor,/area/submap/DecoupledEngine) +"aW" = (/obj/machinery/atmospherics/pipe/simple/visible{icon_state = "intact"; dir = 5},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "aX" = (/obj/structure/shuttle/engine/router,/turf/simulated/floor,/area/submap/DecoupledEngine) "aY" = (/obj/structure/shuttle/engine/propulsion{dir = 4},/turf/simulated/floor/water,/area/submap/DecoupledEngine) "aZ" = (/obj/item/stack/material/steel,/turf/simulated/floor/outdoors/rocks,/area/submap/DecoupledEngine) @@ -54,22 +52,22 @@ "bb" = (/obj/structure/lattice,/obj/structure/grille,/obj/structure/window/reinforced{dir = 2; health = 1e+006},/turf/template_noop,/area/submap/DecoupledEngine) "bc" = (/obj/structure/lattice,/obj/structure/grille,/obj/structure/window/reinforced{dir = 2; health = 1e+006},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1; health = 1e+006},/turf/template_noop,/area/submap/DecoupledEngine) "bd" = (/obj/machinery/atmospherics/pipe/tank/carbon_dioxide,/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) -"be" = (/obj/machinery/power/rad_collector,/obj/structure/window/phoronreinforced,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 8},/obj/effect/floor_decal/rust,/obj/effect/floor_decal/industrial/warning{dir = 10},/turf/simulated/floor,/area/submap/DecoupledEngine) +"be" = (/obj/machinery/power/rad_collector,/obj/structure/window/phoronreinforced,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 8},/obj/effect/floor_decal/rust,/obj/effect/floor_decal/industrial/warning{dir = 10},/turf/simulated/floor,/area/submap/DecoupledEngine) "bf" = (/obj/machinery/power/rad_collector,/obj/structure/window/phoronreinforced,/obj/effect/floor_decal/rust,/obj/effect/floor_decal/industrial/warning,/turf/simulated/floor,/area/submap/DecoupledEngine) -"bg" = (/obj/machinery/power/rad_collector,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced,/obj/effect/floor_decal/rust,/obj/effect/floor_decal/industrial/warning{dir = 6},/turf/simulated/floor,/area/submap/DecoupledEngine) +"bg" = (/obj/machinery/power/rad_collector,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced,/obj/effect/floor_decal/rust,/obj/effect/floor_decal/industrial/warning{dir = 6},/turf/simulated/floor,/area/submap/DecoupledEngine) "bh" = (/obj/structure/shuttle/engine/propulsion{dir = 4},/turf/simulated/floor/outdoors/rocks,/area/submap/DecoupledEngine) "bi" = (/obj/machinery/atmospherics/tvalve/digital{dir = 8},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "bj" = (/obj/machinery/atmospherics/binary/pump{dir = 8},/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "bk" = (/obj/machinery/atmospherics/pipe/manifold/visible,/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) -"bl" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/obj/structure/grille,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 8},/turf/simulated/floor,/area/submap/DecoupledEngine) +"bl" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/obj/structure/grille,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 8},/turf/simulated/floor,/area/submap/DecoupledEngine) "bm" = (/obj/structure/shuttle/engine/propulsion{icon_state = "propulsion_l"; dir = 4},/turf/simulated/floor/outdoors/rocks,/area/submap/DecoupledEngine) "bn" = (/obj/effect/floor_decal/rust,/obj/structure/closet/crate/radiation,/turf/simulated/floor,/area/submap/DecoupledEngine) "bo" = (/obj/effect/decal/cleanable/blood/oil,/obj/effect/floor_decal/rust,/turf/simulated/floor,/area/submap/DecoupledEngine) "bp" = (/obj/effect/floor_decal/rust,/obj/effect/decal/cleanable/dirt,/obj/item/weapon/rcd,/turf/simulated/floor,/area/submap/DecoupledEngine) "bq" = (/obj/structure/sign/warning/radioactive,/turf/simulated/wall/durasteel,/area/submap/DecoupledEngine) -"br" = (/obj/structure/grille,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 1},/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 8},/obj/structure/window/phoronreinforced,/turf/simulated/floor,/area/submap/DecoupledEngine) -"bs" = (/obj/structure/grille,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 1},/obj/structure/window/phoronreinforced,/turf/simulated/floor,/area/submap/DecoupledEngine) -"bt" = (/obj/structure/grille,/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 1},/obj/structure/window/phoronreinforced{ icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced,/turf/simulated/floor,/area/submap/DecoupledEngine) +"br" = (/obj/structure/grille,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 1},/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 8},/obj/structure/window/phoronreinforced,/turf/simulated/floor,/area/submap/DecoupledEngine) +"bs" = (/obj/structure/grille,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 1},/obj/structure/window/phoronreinforced,/turf/simulated/floor,/area/submap/DecoupledEngine) +"bt" = (/obj/structure/grille,/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 1},/obj/structure/window/phoronreinforced{icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced,/turf/simulated/floor,/area/submap/DecoupledEngine) "bu" = (/obj/structure/sign/poi/engineleft,/turf/simulated/wall/durasteel,/area/submap/DecoupledEngine) "bv" = (/obj/structure/sign/poi/engineright,/turf/simulated/wall/r_wall,/area/submap/DecoupledEngine) "bw" = (/obj/structure/girder,/turf/simulated/floor/outdoors/rocks,/area/submap/DecoupledEngine) @@ -86,12 +84,12 @@ aaababababababababababadababababacababababababababababababaa aaababafabababababababababababababababababababababababababaa aaabababababababababababababagababababababababababababababaa aaabababababadabahabababababababababaiabababababababababajaa -aaababababababakababababababababababalababababababababababaa +aaababababababakababababababababababacababababababababababaa aaababababababababababababababababababababababababajabajabaa aaabababaiababababababababababafababababamabajabajababababaa aaabababababacabababababababajajabababababajanajajajabadabaa aaabadabafababaoaoaoaoacabaoapaqaqarasatatanananajababababaa -aaamababababauavavavawaxaoapayaqazaAaBaCanananajabababababaa +aaamababababauavavavawaxaoapayaqazaAaBaOanananajabababababaa aaababauauaDaEaFaGaHaIaJaoaKaIaLaMaAaNaOananajajabababababaa aaababababaPaPaQaPaPaPaRaSaTaUaVaWaNaXaYanajajababababababaa aaababaZbabbbcavbdbdaPbebfbgaUaVazaNaXbhajajabadabajabababaa diff --git a/maps/tether/submaps/aerostat/submaps/DecoupledEngine.dmm b/maps/tether/submaps/aerostat/submaps/DecoupledEngine.dmm index 322dbbf62e..03044d8196 100644 --- a/maps/tether/submaps/aerostat/submaps/DecoupledEngine.dmm +++ b/maps/tether/submaps/aerostat/submaps/DecoupledEngine.dmm @@ -42,8 +42,9 @@ /turf/simulated/floor/outdoors/rocks, /area/submap/virgo2/DecoupledEngine) "al" = ( -/obj/item/projectile/bullet/magnetic/fuelrod, -/turf/simulated/mineral/floor/ignore_mapgen/virgo2, +/obj/effect/floor_decal/rust, +/obj/item/weapon/fuel_assembly/supermatter, +/turf/simulated/floor, /area/submap/virgo2/DecoupledEngine) "am" = ( /obj/item/weapon/arrow/rod, @@ -336,11 +337,6 @@ /obj/effect/floor_decal/rust, /turf/simulated/floor, /area/submap/virgo2/DecoupledEngine) -"be" = ( -/obj/effect/floor_decal/rust, -/obj/item/projectile/bullet/magnetic/fuelrod, -/turf/simulated/floor, -/area/submap/virgo2/DecoupledEngine) "bf" = ( /obj/machinery/power/rad_collector, /obj/structure/window/phoronreinforced, @@ -865,7 +861,7 @@ ao aw aI aP -be +al aA av br @@ -1113,7 +1109,7 @@ ab ab ad ai -al +bB ad ad ad diff --git a/maps/tether/submaps/offmap/talon2.dmm b/maps/tether/submaps/offmap/talon2.dmm index e23d847942..86b9c3669f 100644 --- a/maps/tether/submaps/offmap/talon2.dmm +++ b/maps/tether/submaps/offmap/talon2.dmm @@ -2049,7 +2049,9 @@ /obj/effect/floor_decal/borderfloor/corner2{ dir = 1 }, -/obj/machinery/computer/ship/helm, +/obj/machinery/computer/ship/helm{ + req_one_access = list(301) + }, /turf/simulated/floor/tiled/steel, /area/talon/decktwo/tech) "dD" = ( diff --git a/maps/tether/submaps/tether_misc.dmm b/maps/tether/submaps/tether_misc.dmm index e4aaa7a057..a3b97d1337 100644 --- a/maps/tether/submaps/tether_misc.dmm +++ b/maps/tether/submaps/tether_misc.dmm @@ -588,6 +588,10 @@ /turf/simulated/floor/holofloor/wood, /area/holodeck/source_courtroom) "bN" = ( +/obj/effect/landmark/ai_multicam_room, +/turf/unsimulated/ai_visible, +/area/ai_multicam_room) +"bO" = ( /obj/structure/shuttle/engine/propulsion{ icon_state = "burst_l" }, @@ -596,21 +600,8 @@ dir = 1 }, /area/shuttle/supply) -"bO" = ( -/obj/structure/shuttle/engine/propulsion, -/turf/space, -/turf/simulated/shuttle/plating/airless/carry{ - dir = 1 - }, -/area/shuttle/supply) "bP" = ( /obj/structure/shuttle/engine/propulsion, -/obj/effect/shuttle_landmark{ - base_area = /area/space; - base_turf = /turf/space; - landmark_tag = "supply_cc"; - name = "Centcom Supply Depot" - }, /turf/space, /turf/simulated/shuttle/plating/airless/carry{ dir = 1 @@ -642,8 +633,12 @@ /turf/simulated/floor/holofloor/desert, /area/holodeck/source_picnicarea) "bT" = ( -/obj/structure/shuttle/engine/propulsion{ - icon_state = "burst_r" +/obj/structure/shuttle/engine/propulsion, +/obj/effect/shuttle_landmark{ + base_area = /area/space; + base_turf = /turf/space; + landmark_tag = "supply_cc"; + name = "Centcom Supply Depot" }, /turf/space, /turf/simulated/shuttle/plating/airless/carry{ @@ -729,6 +724,9 @@ }, /turf/simulated/floor/holofloor/carpet, /area/holodeck/source_courtroom) +"cd" = ( +/turf/unsimulated/wall, +/area/ai_multicam_room) "ce" = ( /obj/effect/step_trigger/teleporter/planetary_fall/virgo3b, /turf/space/transit/south, @@ -752,6 +750,9 @@ }, /turf/space/transit/south, /area/space) +"ci" = ( +/turf/unsimulated/ai_visible, +/area/ai_multicam_room) "cj" = ( /obj/effect/floor_decal/industrial/warning{ icon_state = "warning"; @@ -759,6 +760,29 @@ }, /turf/simulated/floor/tiled/steel, /area/space) +"ck" = ( +/obj/structure/shuttle/engine/propulsion{ + icon_state = "burst_r" + }, +/turf/space, +/turf/simulated/shuttle/plating/airless/carry{ + dir = 1 + }, +/area/shuttle/supply) +"cl" = ( +/obj/effect/step_trigger/teleporter/random{ + affect_ghosts = 1; + name = "escapeshuttle_leave"; + teleport_x = 25; + teleport_x_offset = 245; + teleport_y = 25; + teleport_y_offset = 245; + teleport_z = 4; + teleport_z_offset = 4 + }, +/turf/space, +/turf/space/transit/north, +/area/space) "cs" = ( /obj/machinery/door/airlock/glass_external{ frequency = 1380; @@ -2191,20 +2215,6 @@ "Az" = ( /turf/unsimulated/beach/coastline, /area/beach) -"Bd" = ( -/obj/effect/step_trigger/teleporter/random{ - affect_ghosts = 1; - name = "escapeshuttle_leave"; - teleport_x = 25; - teleport_x_offset = 245; - teleport_y = 25; - teleport_y_offset = 245; - teleport_z = 4; - teleport_z_offset = 4 - }, -/turf/space, -/turf/space/transit/north, -/area/space) "Bw" = ( /turf/unsimulated/beach/water, /area/beach) @@ -12798,25 +12808,25 @@ ap ap ap ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd ap ap ap @@ -12940,25 +12950,25 @@ ap ap ap ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -13082,25 +13092,25 @@ ap ap ap ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -13224,25 +13234,25 @@ ap ap ap ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -13366,25 +13376,25 @@ ap ap ap ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -13508,25 +13518,25 @@ ap ap ap ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -13650,25 +13660,25 @@ aI aI aI ar -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -13792,25 +13802,25 @@ dF dF dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -13934,25 +13944,25 @@ dF ec dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -14076,25 +14086,25 @@ dF dF dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +bN +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -14218,25 +14228,25 @@ dF dF dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -14360,25 +14370,25 @@ dF dF dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -14437,10 +14447,10 @@ Jz Jz Jz Jz -Bd -Bd -Bd -Bd +cl +cl +cl +cl iO El El @@ -14502,25 +14512,25 @@ dF dF dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -14582,7 +14592,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -14644,25 +14654,25 @@ dF ec dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -14724,7 +14734,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -14786,25 +14796,25 @@ dF dF dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -14866,7 +14876,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -14928,25 +14938,25 @@ dF dF dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -15008,7 +15018,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -15070,25 +15080,25 @@ dF dF dF fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -15150,7 +15160,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -15212,25 +15222,25 @@ aL aL aL ar -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +ci +cd ap ap ap @@ -15292,7 +15302,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -15354,25 +15364,25 @@ fG dG dG fZ -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap -ap +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd +cd ap ap ap @@ -15434,7 +15444,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -15576,7 +15586,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -15718,7 +15728,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -15860,7 +15870,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -16002,7 +16012,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -16144,7 +16154,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -16286,7 +16296,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -16428,7 +16438,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -16570,7 +16580,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -16712,7 +16722,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -16854,7 +16864,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -16996,7 +17006,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -17138,7 +17148,7 @@ jf Gs Gs Gs -Bd +cl iO El El @@ -17257,30 +17267,30 @@ ap ap ap ap -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd -Bd +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl +cl iO El El @@ -20620,7 +20630,7 @@ di by bc bc -bN +bO aq ae ae @@ -20762,7 +20772,7 @@ di bn bn dE -bO +bP aq ae ae @@ -20904,7 +20914,7 @@ di bn bn dE -bP +bT aq ae ae @@ -21046,7 +21056,7 @@ bn bn bn dE -bO +bP aq ae ae @@ -21188,7 +21198,7 @@ bn bz bc bc -bT +ck aq ae ae diff --git a/maps/tether/tether-01-surface1.dmm b/maps/tether/tether-01-surface1.dmm index ba1c1625ce..caa717d6b7 100644 --- a/maps/tether/tether-01-surface1.dmm +++ b/maps/tether/tether-01-surface1.dmm @@ -53,16 +53,14 @@ name = "south bump"; pixel_y = -28 }, -/obj/structure/cable/green{ - d2 = 4; - icon_state = "0-4" +/obj/structure/cable{ + icon_state = "0-4"; + d2 = 4 }, /turf/simulated/floor/tiled/steel_dirty/virgo3b, /area/tether/surfacebase/mining_main/external) "aal" = ( -/obj/structure/cable/green{ - d1 = 2; - d2 = 8; +/obj/structure/cable{ icon_state = "2-8" }, /turf/simulated/floor/tiled/steel_dirty/virgo3b, @@ -75,11 +73,6 @@ /turf/simulated/wall, /area/tether/surfacebase/cargo/mining/airlock) "aao" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/machinery/door/airlock/glass_external{ frequency = 1379; icon_state = "door_locked"; @@ -87,6 +80,9 @@ locked = 1 }, /obj/effect/map_helper/airlock/door/ext_door, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled/steel_grid, /area/tether/surfacebase/cargo/mining/airlock) "aap" = ( @@ -131,11 +127,6 @@ /obj/effect/floor_decal/industrial/warning{ dir = 8 }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 4 }, @@ -153,9 +144,10 @@ pixel_x = -25; pixel_y = 25 }, -/obj/structure/cable/green{ - d1 = 2; - d2 = 4; +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ icon_state = "2-4" }, /turf/simulated/floor/tiled, @@ -181,7 +173,8 @@ name = "east bump"; pixel_x = 28 }, -/obj/structure/cable/green{ +/obj/structure/cable{ + d2 = 8; icon_state = "0-8" }, /turf/simulated/floor/tiled, @@ -200,11 +193,6 @@ /obj/effect/floor_decal/industrial/warning{ dir = 8 }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/effect/floor_decal/steeldecal/steel_decals7{ dir = 6 }, @@ -214,6 +202,9 @@ /obj/machinery/atmospherics/pipe/manifold/hidden/cyan{ dir = 4 }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining/airlock) "aax" = ( @@ -245,11 +236,6 @@ /obj/effect/floor_decal/industrial/warning{ dir = 8 }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 5 }, @@ -262,6 +248,9 @@ /obj/machinery/atmospherics/pipe/manifold/hidden/cyan{ dir = 4 }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining/airlock) "aaA" = ( @@ -294,11 +283,6 @@ /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining/airlock) "aaB" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/machinery/door/firedoor/glass, /obj/machinery/door/airlock/glass_external{ frequency = 1379; @@ -308,6 +292,9 @@ }, /obj/machinery/atmospherics/pipe/simple/hidden/cyan, /obj/effect/map_helper/airlock/door/int_door, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled/steel_grid, /area/tether/surfacebase/cargo/mining/airlock) "aaC" = ( @@ -360,11 +347,6 @@ /obj/effect/floor_decal/corner/brown/bordercorner2{ dir = 8 }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 4 }, @@ -375,6 +357,9 @@ dir = 6 }, /obj/machinery/atmospherics/pipe/simple/hidden/cyan, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) "aaH" = ( @@ -450,11 +435,6 @@ /obj/effect/floor_decal/corner/brown/border{ dir = 8 }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/effect/floor_decal/steeldecal/steel_decals7{ dir = 5 }, @@ -462,6 +442,9 @@ dir = 6 }, /obj/machinery/atmospherics/pipe/simple/hidden/cyan, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) "aaN" = ( @@ -498,18 +481,24 @@ /turf/simulated/floor/plating, /area/maintenance/lower/trash_pit) "aaP" = ( -/obj/machinery/door/airlock/glass_mining{ - name = "Warehouse" +/obj/effect/floor_decal/borderfloor{ + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; +/obj/effect/floor_decal/corner/brown/border{ + dir = 8 + }, +/obj/effect/floor_decal/steeldecal/steel_decals7{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/cyan, +/obj/machinery/vending/wallmed_airlock{ + pixel_x = -32 + }, +/obj/structure/cable{ icon_state = "1-2" }, -/turf/simulated/floor/tiled/steel_grid, -/area/tether/surfacebase/cargo/warehouse) +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/mining) "aaQ" = ( /obj/effect/floor_decal/borderfloor, /obj/effect/floor_decal/corner/lightgrey/border, @@ -606,6 +595,95 @@ }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) +"aaY" = ( +/obj/effect/floor_decal/borderfloor{ + dir = 10 + }, +/obj/effect/floor_decal/corner/brown/border{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/cyan, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 6 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/mining) +"aaZ" = ( +/obj/effect/floor_decal/borderfloor, +/obj/effect/floor_decal/corner/brown/border, +/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"; + pixel_x = 0 + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/mining) +"aba" = ( +/obj/effect/floor_decal/borderfloor/corner{ + dir = 8 + }, +/obj/effect/floor_decal/corner/brown/bordercorner{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8"; + pixel_x = 0 + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/mining) +"abb" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 10 + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/mining) +"abc" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/door/firedoor/glass, +/obj/machinery/atmospherics/pipe/simple/hidden/cyan, +/obj/structure/catwalk, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/machinery/door/airlock/maintenance/common{ + name = "Mining Maintenance Access" + }, +/turf/simulated/floor/tiled/techfloor, +/area/tether/surfacebase/cargo/mining) "abd" = ( /obj/machinery/atmospherics/unary/vent_pump/on, /obj/effect/floor_decal/borderfloor{ @@ -617,24 +695,26 @@ /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) "abe" = ( -/obj/effect/floor_decal/borderfloor{ +/obj/machinery/light{ dir = 8 }, +/obj/effect/floor_decal/borderfloor{ + dir = 10 + }, /obj/effect/floor_decal/corner/brown/border{ - dir = 8 + dir = 10 }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/machinery/power/apc{ + name = "south bump"; + pixel_x = 0; + pixel_y = -32 }, -/obj/effect/floor_decal/steeldecal/steel_decals7{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/obj/machinery/vending/wallmed_airlock{ - pixel_x = -32 +/obj/machinery/light_switch{ + dir = 1; + pixel_x = -13; + pixel_y = -30 }, +/obj/structure/cable, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) "abf" = ( @@ -670,18 +750,18 @@ /turf/simulated/floor/tiled, /area/rnd/hallway) "abh" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 5 + }, /obj/effect/floor_decal/borderfloor, /obj/effect/floor_decal/corner/brown/border, -/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" +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) @@ -704,40 +784,68 @@ }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) -"abl" = ( -/obj/effect/floor_decal/borderfloor/corner{ - dir = 8 - }, -/obj/effect/floor_decal/corner/brown/bordercorner{ - dir = 8 - }, +"abk" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/obj/structure/cable/green{ +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/effect/floor_decal/borderfloor, +/obj/effect/floor_decal/corner/brown/border, +/obj/structure/cable{ d1 = 4; d2 = 8; - icon_state = "4-8" + icon_state = "4-8"; + pixel_x = 0 }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, -/obj/structure/cable/green{ - d1 = 2; +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/mining) +"abl" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/effect/floor_decal/borderfloor, +/obj/effect/floor_decal/corner/brown/border, +/obj/structure/extinguisher_cabinet{ + dir = 1; + icon_state = "extinguisher_closed"; + pixel_y = -32 + }, +/obj/structure/cable{ + d1 = 4; d2 = 8; - icon_state = "2-8" + icon_state = "4-8"; + pixel_x = 0 }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) "abm" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 10 + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 10 +/obj/machinery/atmospherics/pipe/manifold/hidden/supply, +/obj/effect/floor_decal/borderfloor, +/obj/effect/floor_decal/corner/brown/border, +/obj/effect/floor_decal/borderfloor/corner2{ + dir = 9 }, -/obj/structure/cable/green{ - d1 = 2; +/obj/effect/floor_decal/corner/brown/bordercorner2{ + dir = 9 + }, +/obj/machinery/firealarm{ + dir = 1; + pixel_x = 0; + pixel_y = -24 + }, +/obj/structure/cable{ + d1 = 4; d2 = 8; - icon_state = "2-8" + icon_state = "4-8"; + pixel_x = 0 }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) @@ -825,42 +933,39 @@ /turf/simulated/floor/plating, /area/maintenance/lower/trash_pit) "abv" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/maintenance/cargo{ - name = "Mining Maintenance Access"; - req_one_access = list(48) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/obj/structure/catwalk, -/turf/simulated/floor/tiled/techfloor, +/obj/machinery/alarm{ + dir = 1; + pixel_y = -25 + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8"; + pixel_x = 0 + }, +/turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) "abw" = ( -/obj/machinery/light{ +/obj/effect/floor_decal/steeldecal/steel_decals4{ + dir = 5 + }, +/obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 8 }, -/obj/effect/floor_decal/borderfloor{ +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 10 }, -/obj/effect/floor_decal/corner/brown/border{ +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 10 }, -/obj/machinery/power/apc{ - name = "south bump"; - pixel_x = 0; - pixel_y = -32 - }, -/obj/structure/cable/green, -/obj/machinery/light_switch{ - dir = 1; - pixel_x = -13; - pixel_y = -30 +/obj/structure/cable{ + icon_state = "2-8" }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) @@ -1000,21 +1105,17 @@ /turf/simulated/floor/plating, /area/maintenance/lower/trash_pit) "abI" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5 - }, -/obj/structure/cable/green{ +/obj/structure/catwalk, +/obj/machinery/atmospherics/pipe/simple/visible/scrubbers, +/obj/machinery/atmospherics/pipe/simple/visible/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/cyan, +/obj/structure/cable{ d1 = 1; - d2 = 4; - icon_state = "1-4" + d2 = 2; + icon_state = "1-2" }, -/obj/effect/floor_decal/borderfloor, -/obj/effect/floor_decal/corner/brown/border, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/mining) +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) "abJ" = ( /obj/structure/catwalk, /obj/structure/cable{ @@ -1023,42 +1124,25 @@ /turf/simulated/floor/plating, /area/maintenance/lower/trash_pit) "abK" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 +/obj/machinery/door/airlock/glass_mining{ + name = "Warehouse" }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/effect/floor_decal/borderfloor, -/obj/effect/floor_decal/corner/brown/border, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/mining) +/turf/simulated/floor/tiled/steel_grid, +/area/tether/surfacebase/cargo/warehouse) "abL" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable{ + icon_state = "0-2"; + d2 = 2 }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/effect/floor_decal/borderfloor, -/obj/effect/floor_decal/corner/brown/border, -/obj/structure/extinguisher_cabinet{ - dir = 1; - icon_state = "extinguisher_closed"; - pixel_y = -32 - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/mining) +/turf/simulated/floor/plating, +/area/construction/vacant_mining_ops) "abM" = ( /obj/structure/catwalk, /obj/random/junk, @@ -1068,30 +1152,22 @@ /turf/simulated/floor/plating, /area/maintenance/lower/trash_pit) "abN" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" +/obj/structure/catwalk, +/obj/machinery/atmospherics/pipe/simple/visible/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ + dir = 9; + icon_state = "intact" }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply, -/obj/effect/floor_decal/borderfloor, -/obj/effect/floor_decal/corner/brown/border, -/obj/effect/floor_decal/borderfloor/corner2{ - dir = 9 +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" }, -/obj/effect/floor_decal/corner/brown/bordercorner2{ - dir = 9 - }, -/obj/machinery/firealarm{ - dir = 1; - pixel_x = 0; - pixel_y = -24 - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/mining) +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) "abO" = ( /obj/machinery/door/airlock/maintenance/common{ name = "Trash Pit Access"; @@ -1105,23 +1181,19 @@ /turf/simulated/floor/plating, /area/maintenance/lower/trash_pit) "abP" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" +/obj/effect/floor_decal/steeldecal/steel_decals4{ + dir = 9 }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ +/obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/machinery/alarm{ - dir = 1; - pixel_y = -25 - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/mining) +/turf/simulated/floor/tiled/steel_dirty, +/area/tether/surfacebase/cargo/warehouse) "abQ" = ( /obj/structure/catwalk, /obj/structure/cable{ @@ -1154,25 +1226,13 @@ /turf/simulated/wall, /area/maintenance/lower/mining_eva) "abU" = ( -/obj/effect/floor_decal/steeldecal/steel_decals4{ - dir = 5 +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/effect/floor_decal/steeldecal/steel_decals4{ - dir = 8 - }, -/obj/structure/cable/green{ - d1 = 2; - d2 = 8; - icon_state = "2-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 10 - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/mining) +/turf/simulated/floor/plating, +/area/construction/vacant_mining_ops) "abV" = ( /obj/effect/floor_decal/steeldecal/steel_decals4{ dir = 5 @@ -1182,6 +1242,17 @@ }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/mining) +"abW" = ( +/obj/structure/catwalk, +/obj/machinery/atmospherics/pipe/simple/visible/scrubbers, +/obj/machinery/atmospherics/pipe/simple/visible/supply, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) "abX" = ( /obj/structure/catwalk, /obj/effect/decal/cleanable/dirt, @@ -1220,19 +1291,16 @@ /turf/simulated/wall, /area/tether/surfacebase/cargo/warehouse) "acd" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/effect/floor_decal/steeldecal/steel_decals4{ - dir = 9 - }, -/obj/effect/floor_decal/steeldecal/steel_decals4{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled/steel_dirty, /area/tether/surfacebase/cargo/warehouse) "ace" = ( @@ -1273,18 +1341,12 @@ /turf/simulated/floor/plating, /area/maintenance/lower/mining_eva) "ach" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8"; + pixel_x = 0 }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /turf/simulated/floor/tiled/steel_dirty, /area/tether/surfacebase/cargo/warehouse) "aci" = ( @@ -1307,25 +1369,27 @@ /turf/simulated/floor/plating, /area/maintenance/lower/mining_eva) "ack" = ( -/obj/structure/cable/green{ - d1 = 4; +/obj/machinery/power/apc{ + dir = 4; + name = "east bump"; + pixel_x = 28 + }, +/obj/structure/cable{ d2 = 8; - icon_state = "4-8" + icon_state = "0-8" }, /turf/simulated/floor/tiled/steel_dirty, /area/tether/surfacebase/cargo/warehouse) "acl" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/airlock/maintenance/common, +/obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 8 - }, -/turf/simulated/floor/tiled/steel_dirty, -/area/tether/surfacebase/cargo/warehouse) +/turf/simulated/floor/plating, +/area/tether/surfacebase/cargo) "acm" = ( /obj/structure/window/reinforced, /obj/structure/closet/crate, @@ -1445,15 +1509,28 @@ /turf/simulated/floor/tiled, /area/crew_quarters/visitor_laundry) "acx" = ( -/obj/structure/cable/green{ - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ +/obj/structure/catwalk, +/obj/machinery/atmospherics/pipe/simple/visible/scrubbers{ dir = 5 }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ +/obj/machinery/atmospherics/pipe/simple/visible/supply{ dir = 5 }, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) +"acy" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/simulated/floor/tiled/steel_dirty, /area/tether/surfacebase/cargo/warehouse) "acz" = ( @@ -1469,15 +1546,101 @@ /obj/machinery/vending/loadout, /turf/simulated/floor/tiled, /area/crew_quarters/visitor_laundry) -"acE" = ( -/obj/structure/cable/green{ - d2 = 8; - icon_state = "0-8" +"acA" = ( +/obj/effect/floor_decal/borderfloor{ + dir = 1 + }, +/obj/effect/floor_decal/corner/brown/border{ + dir = 1 }, /obj/machinery/power/apc{ - dir = 4; - name = "east bump"; - pixel_x = 28 + dir = 1; + name = "north bump"; + pixel_x = 0; + pixel_y = 28 + }, +/obj/effect/floor_decal/borderfloor/corner2{ + dir = 1 + }, +/obj/effect/floor_decal/corner/brown/bordercorner2{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "0-2"; + d2 = 2 + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo) +"acB" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/disposalpipe/segment{ + dir = 2; + icon_state = "pipe-c" + }, +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo) +"acC" = ( +/obj/structure/table/rack, +/obj/random/maintenance/cargo, +/obj/random/maintenance/cargo, +/obj/random/maintenance/clean, +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) +"acD" = ( +/obj/structure/catwalk, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) +"acE" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 5 + }, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/turf/simulated/floor/tiled/steel_dirty, +/area/tether/surfacebase/cargo/warehouse) +"acF" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8"; + pixel_x = 0 + }, +/turf/simulated/floor/tiled/steel_dirty, +/area/tether/surfacebase/cargo/warehouse) +"acG" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8"; + pixel_x = 0 }, /turf/simulated/floor/tiled/steel_dirty, /area/tether/surfacebase/cargo/warehouse) @@ -1487,6 +1650,27 @@ }, /turf/simulated/floor/tiled/steel_dirty, /area/tether/surfacebase/cargo/warehouse) +"acI" = ( +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/shutters{ + dir = 8; + id = "mine_warehouse"; + name = "Warehouse Shutters" + }, +/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"; + pixel_x = 0 + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/warehouse) "acJ" = ( /obj/effect/floor_decal/borderfloor, /obj/effect/floor_decal/corner/lightgrey/border, @@ -1534,16 +1718,16 @@ /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) "acM" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/maintenance/common, -/turf/simulated/floor/plating, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) "acN" = ( /obj/structure/cable/ender{ @@ -1572,27 +1756,21 @@ /turf/simulated/floor/tiled/steel_dirty, /area/tether/surfacebase/cargo/warehouse) "acP" = ( -/obj/effect/floor_decal/borderfloor{ +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 1 }, -/obj/effect/floor_decal/corner/brown/border{ +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ dir = 1 }, -/obj/machinery/power/apc{ - dir = 1; - name = "north bump"; - pixel_x = 0; - pixel_y = 28 +/obj/structure/disposalpipe/segment{ + dir = 4; + icon_state = "pipe-c" }, -/obj/structure/cable/green{ - d2 = 2; - icon_state = "0-2" +/obj/structure/cable{ + icon_state = "2-8" }, -/obj/effect/floor_decal/borderfloor/corner2{ - dir = 1 - }, -/obj/effect/floor_decal/corner/brown/bordercorner2{ - dir = 1 +/obj/structure/cable{ + icon_state = "4-8" }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) @@ -1605,31 +1783,25 @@ /turf/simulated/floor/plating, /area/maintenance/lower/mining_eva) "acR" = ( -/obj/effect/floor_decal/borderfloor{ - dir = 10 - }, -/obj/effect/floor_decal/corner/brown/border{ - dir = 10 - }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/structure/cable/green{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 6 +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "4-8" }, /turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/mining) +/area/tether/surfacebase/cargo) "acS" = ( /obj/machinery/atmospherics/pipe/tank/air{ dir = 4 @@ -1778,6 +1950,21 @@ "adf" = ( /turf/simulated/wall, /area/tether/surfacebase/cargo) +"adg" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo) "adh" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/structure/cable/green{ @@ -1850,6 +2037,21 @@ }, /turf/simulated/floor/plating, /area/maintenance/lower/mining_eva) +"adm" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo) "adn" = ( /obj/effect/floor_decal/industrial/warning{ icon_state = "warning"; @@ -1874,65 +2076,64 @@ /turf/simulated/floor/plating, /area/maintenance/lower/mining_eva) "adq" = ( -/obj/structure/cable/green{ - 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 = 4 }, -/turf/simulated/floor/tiled/steel_dirty, -/area/tether/surfacebase/cargo/warehouse) -"adr" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, -/turf/simulated/floor/tiled/steel_dirty, -/area/tether/surfacebase/cargo/warehouse) -"ads" = ( -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/shutters{ - dir = 8; - id = "mine_warehouse"; - name = "Warehouse Shutters" - }, -/obj/structure/cable/green{ - 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 - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/warehouse) -"adt" = ( -/obj/structure/cable/green{ - 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 - }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) +"adr" = ( +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo) +"ads" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 9; + pixel_y = 0 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 9 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo) +"adt" = ( +/obj/machinery/space_heater, +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) "adu" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -1954,25 +2155,11 @@ /turf/simulated/floor/tiled, /area/hallway/lower/first_west) "adv" = ( -/obj/structure/cable/green{ - d1 = 2; - d2 = 8; - icon_state = "2-8" - }, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 4; - icon_state = "pipe-c" +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) @@ -1986,24 +2173,24 @@ /turf/simulated/floor/plating, /area/construction/vacant_mining_ops) "ady" = ( -/obj/structure/cable/green{ - d2 = 2; - icon_state = "0-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/turf/simulated/floor/plating, -/area/construction/vacant_mining_ops) +/obj/machinery/portable_atmospherics/powered/pump/filled, +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) "adz" = ( -/obj/structure/cable/green{ +/obj/structure/catwalk, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + d1 = 2; + d2 = 4; + icon_state = "2-4" + }, +/obj/structure/cable{ 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/plating, -/area/construction/vacant_mining_ops) +/turf/simulated/floor/tiled/techfloor, +/area/maintenance/lower/mining_eva) "adA" = ( /obj/structure/disposaloutlet{ dir = 8 @@ -2018,44 +2205,31 @@ /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) "adB" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/effect/floor_decal/borderfloor, +/obj/effect/floor_decal/corner/brown/border, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/structure/disposalpipe/segment{ - dir = 2; - icon_state = "pipe-c" - }, -/obj/structure/window/reinforced{ - dir = 8 +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) "adC" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 8; - icon_state = "1-8" +/obj/machinery/door/airlock/glass_mining{ + id_tag = "cargodoor"; + name = "Cargo Office"; + req_access = list(31); + req_one_access = list() }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 1 - }, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" }, /turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo) +/area/tether/surfacebase/cargo/office) "adD" = ( /obj/structure/disposalpipe/segment{ dir = 8; @@ -2239,6 +2413,44 @@ }, /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) +"adQ" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/office) +"adR" = ( +/obj/machinery/power/apc{ + dir = 8; + name = "west bump"; + pixel_x = -28 + }, +/obj/structure/bed/chair/sofa/brown/left{ + dir = 4 + }, +/obj/effect/floor_decal/borderfloor{ + dir = 8; + icon_state = "borderfloor"; + pixel_x = 0 + }, +/obj/effect/floor_decal/corner/brown/border{ + dir = 8 + }, +/obj/effect/floor_decal/borderfloor/corner2{ + dir = 8 + }, +/obj/effect/floor_decal/corner/brown/bordercorner2{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "0-4"; + d2 = 4 + }, +/turf/simulated/floor/tiled, +/area/tether/surfacebase/cargo/office) "adS" = ( /turf/simulated/floor/tiled/steel_dirty, /area/tether/surfacebase/cargo/warehouse) @@ -2252,22 +2464,11 @@ /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo/warehouse) "adU" = ( -/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; +/obj/structure/cable{ icon_state = "4-8" }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo) +/area/tether/surfacebase/cargo/office) "adV" = ( /obj/structure/table/glass, /obj/machinery/atmospherics/unary/vent_scrubber/on{ @@ -2366,62 +2567,62 @@ /turf/simulated/floor/tiled, /area/tether/surfacebase/cargo) "aea" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" + dir = 5 }, /obj/structure/disposalpipe/segment{ - dir = 4 + dir = 1; + icon_state = "pipe-c" + }, +/obj/structure/cable{ + d1 = 1; + d2 = 8; + icon_state = "1-8" }, /turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo) +/area/tether/surfacebase/cargo/office) "aeb" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 +/obj/machinery/door/airlock/maintenance/engi{ + name = "Atmospherics Substation" }, -/obj/structure/window/reinforced{ - dir = 1 +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/regular{ + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "atmoslockdown"; + layer = 1; + name = "Atmospherics Lockdown"; + opacity = 0; + open_layer = 1 }, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo) +/turf/simulated/floor/plating, +/area/maintenance/substation/surface_atmos) "aec" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/catwalk, +/obj/machinery/door/airlock/maintenance/engi{ + name = "Atmospherics"; + req_access = list(24) }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 1 +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/regular{ + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "atmoslockdown"; + layer = 1; + name = "Atmospherics Lockdown"; + opacity = 0; + open_layer = 1 }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo) +/turf/simulated/floor/plating, +/area/engineering/atmos) "aed" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -2477,23 +2678,25 @@ /turf/simulated/floor/plating, /area/maintenance/lower/trash_pit) "aej" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/machinery/door/airlock/maintenance/engi{ - name = "Atmospherics Substation" + name = "Atmospherics"; + req_access = list(24) }, /obj/machinery/door/firedoor/glass, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/door/blast/regular{ density = 0; dir = 4; icon_state = "pdoor0"; id = "atmoslockdown"; + layer = 1; name = "Atmospherics Lockdown"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /turf/simulated/floor/plating, -/area/maintenance/substation/surface_atmos) +/area/engineering/atmos/processing) "aek" = ( /obj/effect/floor_decal/techfloor, /obj/structure/railing{ @@ -2567,24 +2770,23 @@ /turf/simulated/floor/tiled, /area/hallway/lower/first_west) "aer" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 8; - icon_state = "1-8" +/obj/machinery/door/airlock/maintenance/engi{ + name = "Atmospherics"; + req_access = list(24) }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9; - pixel_y = 0 +/obj/machinery/door/firedoor, +/obj/machinery/door/blast/regular{ + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "atmoslockdown"; + layer = 1; + name = "Atmospherics Lockdown"; + opacity = 0; + open_layer = 1 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 9 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/disposalpipe/segment, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo) +/turf/simulated/floor/plating, +/area/engineering/atmos) "aes" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ @@ -2619,16 +2821,23 @@ /turf/simulated/floor/tiled, /area/hallway/lower/first_west) "aeu" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/machinery/door/airlock/maintenance/engi{ + name = "Atmospherics"; + req_access = list(24) }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/disposalpipe/segment, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo) +/obj/machinery/door/blast/regular{ + density = 0; + dir = 1; + icon_state = "pdoor0"; + id = "atmoslockdown"; + layer = 1; + name = "Atmospherics Lockdown"; + opacity = 0; + open_layer = 1 + }, +/obj/machinery/door/firedoor, +/turf/simulated/floor/plating, +/area/engineering/atmos/processing) "aev" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -2661,9 +2870,6 @@ }, /turf/simulated/floor/tiled, /area/hallway/lower/first_west) -"aex" = ( -/turf/simulated/wall, -/area/maintenance/substation/mining) "aey" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -2833,23 +3039,6 @@ }, /turf/simulated/floor/tiled, /area/tether/surfacebase/north_stairs_one) -"aeM" = ( -/obj/structure/catwalk, -/obj/machinery/atmospherics/pipe/simple/visible/scrubbers, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan{ - dir = 9; - icon_state = "intact" - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4 - }, -/turf/simulated/floor/tiled/techfloor, -/area/maintenance/lower/mining_eva) "aeN" = ( /obj/machinery/conveyor{ dir = 8; @@ -2906,19 +3095,6 @@ dir = 8 }, /area/tether/surfacebase/surface_one_hall) -"aeR" = ( -/obj/effect/floor_decal/borderfloor, -/obj/effect/floor_decal/corner/brown/border, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/disposalpipe/segment, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo) "aeS" = ( /obj/effect/floor_decal/borderfloor{ dir = 10 @@ -3092,23 +3268,6 @@ "afd" = ( /turf/simulated/floor/tiled/techfloor, /area/maintenance/lower/mining_eva) -"afe" = ( -/obj/machinery/door/airlock/glass_mining{ - id_tag = "cargodoor"; - name = "Cargo Office"; - req_access = list(31); - req_one_access = list() - }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/disposalpipe/segment, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/office) "aff" = ( /obj/machinery/door/firedoor/glass, /obj/effect/floor_decal/steeldecal/steel_decals_central1{ @@ -3118,17 +3277,6 @@ dir = 4 }, /area/tether/surfacebase/cargo) -"afg" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/disposalpipe/segment, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/office) "afh" = ( /obj/effect/floor_decal/spline/plain{ dir = 4 @@ -3320,22 +3468,6 @@ /obj/machinery/lapvend, /turf/simulated/floor/tiled, /area/storage/primary) -"afu" = ( -/obj/structure/cable/green{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5 - }, -/obj/structure/disposalpipe/segment{ - dir = 1; - icon_state = "pipe-c" - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/office) "afv" = ( /obj/structure/closet/firecloset, /turf/simulated/floor/tiled, @@ -3661,12 +3793,6 @@ /obj/structure/table/standard, /turf/simulated/floor/tiled, /area/storage/primary) -"afX" = ( -/obj/machinery/power/breakerbox/activated{ - RCon_tag = "Mining Substation Bypass" - }, -/turf/simulated/floor, -/area/maintenance/substation/mining) "afY" = ( /obj/machinery/camera/network/civilian, /turf/simulated/floor/tiled, @@ -4049,18 +4175,6 @@ }, /turf/simulated/floor/tiled/white, /area/rnd/chemistry_lab) -"aha" = ( -/obj/structure/catwalk, -/obj/machinery/atmospherics/pipe/simple/visible/scrubbers, -/obj/machinery/atmospherics/pipe/simple/visible/supply, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/turf/simulated/floor/tiled/techfloor, -/area/maintenance/lower/mining_eva) "ahc" = ( /obj/machinery/portable_atmospherics/powered/scrubber/huge/stationary{ scrub_id = "atrium" @@ -4710,25 +4824,6 @@ /obj/machinery/light/small, /turf/simulated/floor/plating, /area/storage/surface_eva) -"aiB" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/catwalk, -/obj/machinery/door/airlock/maintenance/engi{ - name = "Atmospherics"; - req_access = list(24) - }, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "atmoslockdown"; - name = "Atmospherics Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/plating, -/area/engineering/atmos) "aiD" = ( /obj/effect/floor_decal/borderfloor{ dir = 8 @@ -6154,17 +6249,6 @@ }, /turf/simulated/floor/tiled/techfloor, /area/tether/surfacebase/public_garden) -"alt" = ( -/obj/structure/catwalk, -/obj/machinery/atmospherics/pipe/simple/visible/scrubbers, -/obj/machinery/atmospherics/pipe/simple/visible/supply, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/tiled/techfloor, -/area/maintenance/lower/mining_eva) "alw" = ( /obj/effect/floor_decal/borderfloor{ dir = 10 @@ -6260,29 +6344,6 @@ }, /turf/simulated/floor/tiled, /area/tether/surfacebase/public_garden) -"alC" = ( -/obj/structure/sign/securearea{ - desc = "A warning sign which reads 'HIGH VOLTAGE'"; - icon_state = "shock"; - name = "HIGH VOLTAGE" - }, -/turf/simulated/wall, -/area/maintenance/substation/mining) -"alD" = ( -/obj/structure/catwalk, -/obj/machinery/atmospherics/pipe/simple/visible/scrubbers{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/visible/supply{ - dir = 5 - }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/tiled/techfloor, -/area/maintenance/lower/mining_eva) "alM" = ( /obj/effect/floor_decal/borderfloor{ dir = 10 @@ -6365,73 +6426,6 @@ }, /turf/simulated/floor/tiled, /area/tether/surfacebase/public_garden) -"alS" = ( -/obj/machinery/power/sensor{ - name = "Powernet Sensor - Mining Subgrid"; - name_tag = "Mining Subgrid" - }, -/obj/structure/cable/green{ - icon_state = "0-4" - }, -/obj/structure/cable/green{ - d2 = 2; - icon_state = "0-2" - }, -/obj/effect/floor_decal/industrial/warning, -/obj/random/drinkbottle, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"alT" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/effect/floor_decal/industrial/warning/corner{ - dir = 8 - }, -/obj/effect/floor_decal/rust, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"alU" = ( -/obj/structure/cable/green{ - d1 = 2; - d2 = 8; - icon_state = "2-8" - }, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/effect/floor_decal/rust, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"alV" = ( -/obj/machinery/door/airlock/engineering{ - name = "Mining Substation"; - req_one_access = list(11,24) - }, -/obj/machinery/door/firedoor/glass, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"alW" = ( -/obj/structure/catwalk, -/obj/structure/cable/green{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, -/turf/simulated/floor/tiled/techfloor, -/area/maintenance/lower/mining_eva) "alX" = ( /obj/structure/railing{ dir = 8 @@ -6552,43 +6546,6 @@ }, /turf/simulated/floor/tiled, /area/storage/primary) -"amn" = ( -/obj/machinery/power/smes/buildable{ - charge = 0; - output_attempt = 0; - outputting = 0; - RCon_tag = "Substation - Mining" - }, -/obj/structure/cable/green, -/obj/structure/cable/green{ - d2 = 2; - icon_state = "0-2" - }, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"amo" = ( -/obj/effect/floor_decal/industrial/warning{ - dir = 8 - }, -/obj/machinery/power/terminal{ - dir = 8 - }, -/obj/structure/cable{ - icon_state = "0-2"; - d2 = 2 - }, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"amp" = ( -/obj/machinery/power/apc{ - dir = 4; - name = "east bump"; - pixel_x = 28 - }, -/obj/structure/cable/green, -/obj/effect/floor_decal/rust, -/turf/simulated/floor, -/area/maintenance/substation/mining) "amq" = ( /obj/structure/railing{ dir = 8 @@ -6704,68 +6661,6 @@ }, /turf/simulated/floor/tiled, /area/storage/primary) -"amI" = ( -/obj/effect/floor_decal/industrial/warning/corner{ - dir = 1 - }, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/obj/effect/floor_decal/industrial/warning{ - dir = 8 - }, -/obj/machinery/camera/network/engineering{ - dir = 1 - }, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"amJ" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"amK" = ( -/obj/machinery/door/firedoor/glass, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/obj/machinery/door/airlock/engineering{ - name = "Mining Substation"; - req_one_access = list(11,24) - }, -/turf/simulated/floor, -/area/maintenance/substation/mining) -"amL" = ( -/obj/structure/catwalk, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/turf/simulated/floor/tiled/techfloor, -/area/maintenance/lower/mining_eva) "amM" = ( /obj/structure/railing{ dir = 8 @@ -24019,24 +23914,6 @@ "aOR" = ( /turf/simulated/wall/r_wall, /area/engineering/atmos/processing) -"aOS" = ( -/obj/machinery/door/airlock/maintenance/engi{ - name = "Atmospherics"; - req_access = list(24) - }, -/obj/machinery/door/firedoor/glass, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "atmoslockdown"; - name = "Atmospherics Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/plating, -/area/engineering/atmos/processing) "aOT" = ( /obj/effect/floor_decal/borderfloor{ dir = 8 @@ -26763,22 +26640,6 @@ }, /turf/simulated/floor/tiled/techmaint, /area/engineering/atmos) -"aTT" = ( -/obj/machinery/door/airlock/maintenance/engi{ - name = "Atmospherics"; - req_access = list(24) - }, -/obj/machinery/door/firedoor, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "atmoslockdown"; - name = "Atmospherics Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/plating, -/area/engineering/atmos) "aTU" = ( /obj/effect/floor_decal/steeldecal/steel_decals7{ dir = 6 @@ -27958,21 +27819,6 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, /area/engineering/atmos/processing) -"aVY" = ( -/obj/machinery/door/airlock/maintenance/engi{ - name = "Atmospherics"; - req_access = list(24) - }, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 1; - icon_state = "pdoor0"; - id = "atmoslockdown"; - name = "Atmospherics Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/plating, -/area/engineering/atmos/processing) "aVZ" = ( /obj/machinery/vending/boozeomat, /turf/simulated/floor/wood, @@ -30494,35 +30340,6 @@ }, /turf/simulated/floor/plating, /area/tether/surfacebase/cargo/office) -"bbs" = ( -/obj/machinery/power/apc{ - dir = 8; - name = "west bump"; - pixel_x = -28 - }, -/obj/structure/cable/green{ - d2 = 4; - icon_state = "0-4" - }, -/obj/structure/bed/chair/sofa/brown/left{ - dir = 4 - }, -/obj/effect/floor_decal/borderfloor{ - dir = 8; - icon_state = "borderfloor"; - pixel_x = 0 - }, -/obj/effect/floor_decal/corner/brown/border{ - dir = 8 - }, -/obj/effect/floor_decal/borderfloor/corner2{ - dir = 8 - }, -/obj/effect/floor_decal/corner/brown/bordercorner2{ - dir = 8 - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/office) "bbt" = ( /obj/effect/floor_decal/borderfloor{ dir = 5 @@ -30545,14 +30362,6 @@ }, /turf/simulated/floor/tiled, /area/tether/surfacebase/surface_one_hall) -"bbv" = ( -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/turf/simulated/floor/tiled, -/area/tether/surfacebase/cargo/office) "bbw" = ( /obj/structure/table/rack, /obj/random/maintenance/cargo, @@ -31822,12 +31631,6 @@ /obj/random/trash_pile, /turf/simulated/floor/plating, /area/maintenance/lower/vacant_site) -"obY" = ( -/obj/machinery/alarm{ - pixel_y = 22 - }, -/turf/simulated/floor/plating, -/area/maintenance/substation/mining) "orF" = ( /obj/machinery/light/small{ dir = 4; @@ -31891,9 +31694,6 @@ }, /turf/simulated/floor/tiled/techmaint, /area/looking_glass/lg_1) -"vNx" = ( -/turf/simulated/floor/plating, -/area/maintenance/substation/mining) "xOH" = ( /obj/effect/floor_decal/spline/plain{ dir = 8 @@ -31909,11 +31709,6 @@ }, /turf/simulated/floor/tiled/techmaint, /area/looking_glass/lg_1) -"yiv" = ( -/obj/structure/closet/crate, -/obj/random/maintenance/cargo, -/turf/simulated/floor/plating, -/area/maintenance/substation/mining) (1,1,1) = {" aaa @@ -40241,7 +40036,7 @@ aLv aJD aJD aJD -aOS +aej aPm aPN aQr @@ -41250,7 +41045,7 @@ aOR aOR aOR aOR -aVY +aeu aOR aOR aOR @@ -41933,7 +41728,7 @@ aah aah aBO aHd -aej +aeb aIe aIM aJG @@ -42031,12 +41826,12 @@ abT abT abT abT -aex -aex -aex -aex -aex -aex +abT +abT +abT +abT +abT +abT abT abT bbI @@ -42173,12 +41968,12 @@ cGJ acS acS adp -aex -yiv -alS -amn -afX -aex +abT +aah +aah +aah +aah +aah aah abT bbJ @@ -42315,12 +42110,12 @@ acj acX acX adL -aex -vNx -alT -amo -amI -aex +abT +aah +aah +aah +aah +aah aah abT bbI @@ -42457,12 +42252,12 @@ acQ adl ado adM -aex -obY -alU -amp -amJ -aex +abT +abT +abT +abT +abT +abT aah abT bbI @@ -42599,12 +42394,12 @@ aar aar abT adN -aex -alC -alV -aex -amK -alC +abT +agd +acC +adt +ady +abT abT abT bbI @@ -42736,16 +42531,16 @@ aaz aaB aaG aaM -abe -acR -abv -aha -aeM -alt -alD -alW -afA -amL +aaP +aaY +abc +abI +abN +abW +acx +acD +acD +adz amW amW and @@ -42879,7 +42674,7 @@ aaC aaH aaN aaS -abh +aaZ aar abT abT @@ -43021,8 +42816,8 @@ aan aar aar abi -abl -abw +aba +abe abT acg abT @@ -43070,7 +42865,7 @@ aFN aGs aHi aHA -aiB +aec aIT aJL aKu @@ -43163,8 +42958,8 @@ aah aah aar aaX -abm -abI +abb +abh acc acc acc @@ -43306,7 +43101,7 @@ aah aar aaX agm -abK +abk acc abZ abZ @@ -43448,7 +43243,7 @@ aah aar aaX agm -abL +abl acc adS adS @@ -43590,7 +43385,7 @@ aah aar abd abn -abN +abm acc aca adS @@ -43658,7 +43453,7 @@ aRJ aSe aSO aTr -aTT +aer aTZ aUE aUE @@ -43732,7 +43527,7 @@ aah aar aaX agm -abP +abv acc adS adS @@ -43874,12 +43669,12 @@ aah aar aaX agm -abU -aaP +abw +abK +abP acd -ach -acl -acx +acy +acE adS afM acc @@ -44019,9 +43814,9 @@ abo abV abY ace -ack +ach acH -adq +acF adS aeJ afm @@ -44161,9 +43956,9 @@ aar aar acc acf -acE +ack acO -adr +acG adS agj acc @@ -44305,12 +44100,12 @@ acc acc acc acc -ads +acI adT acc amc amP -bbs +adR aHM amc aii @@ -44447,12 +44242,12 @@ aaL aaL adf acK -adt +acM adZ aeS amw afS -bbv +adU bbC amc bbl @@ -44589,12 +44384,12 @@ aaL aaL adf acL +acP adv -aeu -aeR -afe -afg -afu +adB +adC +adQ +aea aeg bbW bbm @@ -44730,8 +44525,8 @@ aaL aaL aaL adf -acP -adC +acA +acR aee aeZ amc @@ -44873,7 +44668,7 @@ aaL aaL adf afO -adU +adg acY acY adE @@ -45015,7 +44810,7 @@ aaL aaL adf acU -aea +adm aef afb amc @@ -45157,7 +44952,7 @@ aaL aaL adf aeE -aeb +adq acY aeU amc @@ -45299,7 +45094,7 @@ aaL aaL adf adA -aec +adr aes aeY afn @@ -45437,11 +45232,11 @@ aaL aaL adw adx -ady -adz -acM -adB -aer +abL +abU +acl +acB +ads agq acY aff diff --git a/maps/tether/tether-02-surface2.dmm b/maps/tether/tether-02-surface2.dmm index 07208a4295..39011de5dd 100644 --- a/maps/tether/tether-02-surface2.dmm +++ b/maps/tether/tether-02-surface2.dmm @@ -2649,6 +2649,31 @@ }, /turf/simulated/floor/tiled/techfloor, /area/maintenance/lower/bar) +"afw" = ( +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/airlock/maintenance/command{ + req_access = list(19) + }, +/obj/structure/disposalpipe/segment, +/obj/structure/cable/green{ + icon_state = "1-2"; + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/door/blast/regular{ + closed_layer = 10; + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "bridge blast"; + layer = 1; + name = "Bridge Blast Doors"; + opacity = 0; + open_layer = 1 + }, +/turf/simulated/floor, +/area/bridge_hallway) "afx" = ( /obj/structure/catwalk, /obj/structure/cable{ @@ -3154,6 +3179,33 @@ /obj/effect/floor_decal/industrial/outline/yellow, /turf/simulated/floor/plating, /area/maintenance/lower/bar) +"agD" = ( +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/airlock/maintenance/command{ + req_access = list(19) + }, +/obj/structure/cable/green{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/door/blast/regular{ + closed_layer = 10; + density = 0; + dir = 1; + icon_state = "pdoor0"; + id = "bridge blast"; + layer = 1; + name = "Bridge Blast Doors"; + opacity = 0; + open_layer = 1 + }, +/turf/simulated/floor, +/area/bridge_hallway) "agE" = ( /obj/structure/railing{ dir = 8 @@ -3298,6 +3350,30 @@ /obj/structure/catwalk, /turf/simulated/floor/tiled/techfloor/grid, /area/maintenance/lower/bar) +"agX" = ( +/obj/structure/cable/cyan{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/cyan, +/obj/machinery/door/airlock/glass_atmos{ + name = "Atmospherics"; + req_access = list(24) + }, +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/regular{ + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "atmoslockdown"; + layer = 1; + name = "Atmospherics Lockdown"; + opacity = 0; + open_layer = 1 + }, +/turf/simulated/floor/tiled, +/area/engineering/lower/lobby) "agY" = ( /obj/structure/sign/department/chapel, /turf/simulated/wall, @@ -3376,6 +3452,29 @@ }, /turf/simulated/floor/tiled/white, /area/tether/surfacebase/medical/storage) +"ahj" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/red, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/door/airlock/glass_atmos{ + name = "Atmospherics"; + req_access = list(24) + }, +/obj/structure/disposalpipe/segment, +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/regular{ + closed_layer = 10; + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "atmoslockdown"; + layer = 1; + name = "Atmospherics Lockdown"; + opacity = 0; + open_layer = 1 + }, +/turf/simulated/floor/tiled, +/area/engineering/lower/lobby) "ahk" = ( /obj/structure/catwalk, /obj/structure/disposalpipe/segment{ @@ -7876,27 +7975,26 @@ /turf/simulated/floor/tiled/techmaint, /area/tether/surfacebase/surface_two_hall) "apQ" = ( +/obj/machinery/door/airlock/maintenance/engi{ + name = "Atmospherics"; + req_access = list(24) + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/maintenance/command{ - req_access = list(19) - }, -/obj/structure/disposalpipe/segment, -/obj/structure/cable/green{ - icon_state = "1-2"; - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/door/blast/regular{ density = 0; - dir = 4; + dir = 1; icon_state = "pdoor0"; - id = "bridge blast"; - name = "Bridge Blast Doors"; - opacity = 0 + id = "atmoslockdown"; + layer = 1; + name = "Atmospherics Lockdown"; + opacity = 0; + open_layer = 1 }, -/turf/simulated/floor, -/area/bridge_hallway) +/turf/simulated/floor/plating, +/area/engineering/atmos) "apR" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 9 @@ -9851,27 +9949,25 @@ /turf/simulated/floor/tiled, /area/engineering/lower/lobby) "atm" = ( -/obj/structure/cable/cyan{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/cyan, -/obj/machinery/door/airlock/glass_atmos{ +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/door/airlock/maintenance/engi{ name = "Atmospherics"; req_access = list(24) }, -/obj/machinery/door/firedoor/glass, +/obj/structure/catwalk, /obj/machinery/door/blast/regular{ density = 0; dir = 4; icon_state = "pdoor0"; id = "atmoslockdown"; + layer = 1; name = "Atmospherics Lockdown"; - opacity = 0 + opacity = 0; + open_layer = 1 }, -/turf/simulated/floor/tiled, -/area/engineering/lower/lobby) +/turf/simulated/floor/plating, +/area/engineering/atmos) "atn" = ( /obj/structure/cable/cyan{ d1 = 4; @@ -10833,25 +10929,29 @@ /turf/simulated/wall/r_wall, /area/engineering/lower/lobby) "avd" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/red, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/door/airlock/glass_atmos{ - name = "Atmospherics"; +/obj/machinery/door/airlock/maintenance/engi{ + name = "Drone Bay"; req_access = list(24) }, -/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, /obj/machinery/door/firedoor/glass, /obj/machinery/door/blast/regular{ density = 0; - dir = 4; + dir = 1; icon_state = "pdoor0"; id = "atmoslockdown"; + layer = 1; name = "Atmospherics Lockdown"; - opacity = 0 + opacity = 0; + open_layer = 1 }, -/turf/simulated/floor/tiled, -/area/engineering/lower/lobby) +/turf/simulated/floor/tiled/techfloor/grid, +/area/engineering/drone_fabrication) "ave" = ( /obj/effect/floor_decal/borderfloor{ dir = 1; @@ -10990,6 +11090,25 @@ }, /turf/simulated/floor/plating, /area/maintenance/lower/south) +"avp" = ( +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/airlock/maintenance/engi{ + name = "Atmospherics Balcony"; + req_access = list(24) + }, +/obj/structure/catwalk, +/obj/machinery/door/blast/regular{ + density = 0; + dir = 1; + icon_state = "pdoor0"; + id = "atmoslockdown"; + layer = 1; + name = "Atmospherics Lockdown"; + opacity = 0; + open_layer = 1 + }, +/turf/simulated/floor/plating, +/area/engineering/atmos) "avq" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ @@ -15739,25 +15858,6 @@ /obj/structure/catwalk, /turf/simulated/floor/plating, /area/maintenance/asmaint2) -"aCY" = ( -/obj/machinery/door/airlock/maintenance/engi{ - name = "Atmospherics"; - req_access = list(24) - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 1; - icon_state = "pdoor0"; - id = "atmoslockdown"; - name = "Atmospherics Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/plating, -/area/engineering/atmos) "aCZ" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -16646,24 +16746,6 @@ /obj/random/tech_supply, /turf/simulated/floor/tiled/steel_dirty, /area/maintenance/asmaint2) -"aFa" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/door/airlock/maintenance/engi{ - name = "Atmospherics"; - req_access = list(24) - }, -/obj/structure/catwalk, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "atmoslockdown"; - name = "Atmospherics Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/plating, -/area/engineering/atmos) "aFb" = ( /obj/structure/catwalk, /turf/simulated/open, @@ -24932,30 +25014,6 @@ /obj/structure/bed/padded, /turf/simulated/floor/tiled, /area/tether/surfacebase/security/solitary) -"aTK" = ( -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/maintenance/command{ - req_access = list(19) - }, -/obj/structure/cable/green{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 1; - icon_state = "pdoor0"; - id = "bridge blast"; - name = "Bridge Blast Doors"; - opacity = 0 - }, -/turf/simulated/floor, -/area/bridge_hallway) "aTL" = ( /obj/structure/cable/green{ icon_state = "4-8" @@ -26591,28 +26649,6 @@ }, /turf/simulated/floor/tiled/dark, /area/tether/surfacebase/security/brig) -"aVV" = ( -/obj/machinery/door/airlock/maintenance/engi{ - name = "Drone Bay"; - req_access = list(24) - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 1; - icon_state = "pdoor0"; - id = "atmoslockdown"; - name = "Atmospherics Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/tiled/techfloor/grid, -/area/engineering/drone_fabrication) "aVW" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -27236,23 +27272,6 @@ }, /turf/simulated/floor/reinforced, /area/rnd/outpost/xenobiology/outpost_slimepens) -"aWN" = ( -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/maintenance/engi{ - name = "Atmospherics Balcony"; - req_access = list(24) - }, -/obj/structure/catwalk, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 1; - icon_state = "pdoor0"; - id = "atmoslockdown"; - name = "Atmospherics Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/plating, -/area/engineering/atmos) "aWO" = ( /obj/machinery/atmospherics/pipe/simple/hidden/green{ icon_state = "intact"; @@ -38423,7 +38442,7 @@ auk aAT aAT aAT -aVV +avd aAT aAT aAT @@ -38560,7 +38579,7 @@ atJ axP auv azl -aCY +apQ aAT aAT aBW @@ -39282,7 +39301,7 @@ aAU aAT azl azl -aWN +avp azl azl aEp @@ -40399,7 +40418,7 @@ asF ati atT auC -atm +agX avH awx axm @@ -40683,7 +40702,7 @@ asG atk atV auE -avd +ahj avJ awz axo @@ -41798,7 +41817,7 @@ aYg aXY aqy aob -aTK +agD asc avj aWY @@ -41934,7 +41953,7 @@ aiW anx apU arp -apQ +afw apS aXG aYa @@ -42111,7 +42130,7 @@ ayh ayO azG aAB -aFa +atm aBN aCj aBO diff --git a/maps/tether/tether-03-surface3.dmm b/maps/tether/tether-03-surface3.dmm index a6148c7937..d4c6452678 100644 --- a/maps/tether/tether-03-surface3.dmm +++ b/maps/tether/tether-03-surface3.dmm @@ -13483,27 +13483,36 @@ /area/hallway/lower/third_south) "awI" = ( /obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/maintenance/command{ - req_access = list(19) +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/door/airlock/glass_security{ + id_tag = "SurfaceFoyer"; + layer = 2.8; + name = "Security"; + req_access = list(1) }, /obj/machinery/door/blast/regular{ density = 0; - dir = 4; + dir = 1; icon_state = "pdoor0"; - id = "bridge blast"; - name = "Bridge Blast Doors"; - opacity = 0 + id = "surfbriglockdown"; + layer = 1; + name = "Security Blast Doors"; + opacity = 0; + open_layer = 1 }, -/turf/simulated/floor, -/area/bridge_hallway) +/obj/structure/cable/green{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled/steel_grid, +/area/tether/surfacebase/security/lobby) "awJ" = ( /turf/simulated/wall, /area/maintenance/lower/atrium) @@ -27062,37 +27071,47 @@ /area/maintenance/lower/mining) "aTt" = ( /obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/glass_command{ - dir = 1; - name = "Bridge"; +/obj/machinery/door/airlock/maintenance/command{ req_access = list(19) }, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable/green{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; - dir = 1; + dir = 4; icon_state = "pdoor0"; id = "bridge blast"; + layer = 1; name = "Bridge Blast Doors"; - opacity = 0 + opacity = 0; + open_layer = 1 }, -/turf/simulated/floor/tiled/dark, -/area/bridge) +/turf/simulated/floor, +/area/bridge_hallway) "aTu" = ( /obj/machinery/door/firedoor/glass, /obj/machinery/door/airlock/glass_command{ + dir = 1; name = "Bridge"; req_access = list(19) }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 1; icon_state = "pdoor0"; id = "bridge blast"; + layer = 1; name = "Bridge Blast Doors"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /turf/simulated/floor/tiled/dark, /area/bridge) @@ -27758,34 +27777,26 @@ /area/tether/surfacebase/security/common) "aUy" = ( /obj/machinery/door/firedoor/glass, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 +/obj/machinery/door/airlock/glass_command{ + name = "Bridge"; + req_access = list(19) }, /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/door/airlock/glass_security{ - id_tag = "SurfaceFoyer"; - layer = 2.8; - name = "Security"; - req_access = list(1) - }, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 1; icon_state = "pdoor0"; - id = "surfbriglockdown"; - name = "Security Blast Doors"; - opacity = 0 + id = "bridge blast"; + layer = 1; + name = "Bridge Blast Doors"; + opacity = 0; + open_layer = 1 }, -/obj/structure/cable/green{ - icon_state = "4-8" - }, -/turf/simulated/floor/tiled/steel_grid, -/area/tether/surfacebase/security/lobby) +/turf/simulated/floor/tiled/dark, +/area/bridge) "aUz" = ( /obj/effect/floor_decal/steeldecal/steel_decals6{ dir = 9 @@ -29770,10 +29781,26 @@ /turf/simulated/floor/wood, /area/library) "aXx" = ( -/obj/structure/shuttle/engine/propulsion, -/turf/simulated/floor/reinforced, -/turf/simulated/shuttle/plating/carry, -/area/shuttle/tether) +/obj/structure/grille, +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/regular{ + closed_layer = 10; + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "bridge blast"; + layer = 1; + name = "Bridge Blast Doors"; + opacity = 0; + open_layer = 1 + }, +/obj/structure/window/reinforced/full, +/obj/structure/window/reinforced, +/obj/structure/cable/green{ + icon_state = "0-4" + }, +/turf/simulated/floor/plating, +/area/bridge) "aXy" = ( /obj/structure/table/standard, /obj/item/weapon/gun/energy/taser/xeno, @@ -29813,12 +29840,29 @@ /turf/simulated/floor/tiled/white, /area/rnd/outpost/xenobiology/outpost_first_aid) "aXB" = ( -/obj/machinery/atmospherics/unary/engine{ - dir = 1 +/obj/structure/grille, +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/regular{ + closed_layer = 10; + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "bridge blast"; + layer = 1; + name = "Bridge Blast Doors"; + opacity = 0; + open_layer = 1 }, -/turf/simulated/floor/reinforced, -/turf/simulated/shuttle/plating/carry, -/area/shuttle/tourbus/engines) +/obj/structure/window/reinforced/full, +/obj/structure/window/reinforced, +/obj/structure/cable/green{ + icon_state = "0-4" + }, +/obj/structure/cable/green{ + icon_state = "0-8" + }, +/turf/simulated/floor/plating, +/area/bridge) "aXC" = ( /obj/structure/bed/chair/office/dark{ dir = 8 @@ -29833,6 +29877,61 @@ }, /turf/simulated/floor/wood, /area/library) +"aXD" = ( +/obj/structure/grille, +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/regular{ + closed_layer = 10; + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "bridge blast"; + layer = 1; + name = "Bridge Blast Doors"; + opacity = 0; + open_layer = 1 + }, +/obj/structure/window/reinforced/full, +/obj/structure/window/reinforced, +/obj/structure/cable/green{ + icon_state = "0-4" + }, +/obj/structure/cable/green{ + icon_state = "0-8" + }, +/obj/structure/cable/green{ + d1 = 1; + d2 = 8; + icon_state = "1-8" + }, +/obj/structure/cable/green{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, +/turf/simulated/floor/plating, +/area/bridge) +"aXE" = ( +/obj/structure/grille, +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/blast/regular{ + closed_layer = 10; + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "bridge blast"; + layer = 1; + name = "Bridge Blast Doors"; + opacity = 0; + open_layer = 1 + }, +/obj/structure/window/reinforced/full, +/obj/structure/window/reinforced, +/obj/structure/cable/green{ + icon_state = "0-8" + }, +/turf/simulated/floor/plating, +/area/bridge) "aXF" = ( /obj/machinery/power/apc{ dir = 2; @@ -30004,6 +30103,18 @@ }, /turf/simulated/floor/tiled, /area/rnd/research/researchdivision) +"aXU" = ( +/obj/structure/shuttle/engine/propulsion, +/turf/simulated/floor/reinforced, +/turf/simulated/shuttle/plating/carry, +/area/shuttle/tether) +"aXV" = ( +/obj/machinery/atmospherics/unary/engine{ + dir = 1 + }, +/turf/simulated/floor/reinforced, +/turf/simulated/shuttle/plating/carry, +/area/shuttle/tourbus/engines) "aXW" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -31244,24 +31355,6 @@ /obj/structure/cable/green, /turf/simulated/floor/tiled, /area/crew_quarters/heads/hop) -"baq" = ( -/obj/structure/grille, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "bridge blast"; - name = "Bridge Blast Doors"; - opacity = 0 - }, -/obj/structure/window/reinforced/full, -/obj/structure/window/reinforced, -/obj/structure/cable/green{ - icon_state = "0-4" - }, -/turf/simulated/floor/plating, -/area/bridge) "bar" = ( /obj/machinery/computer/communications, /obj/machinery/light/small{ @@ -31297,58 +31390,6 @@ }, /turf/simulated/floor/tiled, /area/crew_quarters/heads/hop) -"baw" = ( -/obj/structure/grille, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "bridge blast"; - name = "Bridge Blast Doors"; - opacity = 0 - }, -/obj/structure/window/reinforced/full, -/obj/structure/window/reinforced, -/obj/structure/cable/green{ - icon_state = "0-4" - }, -/obj/structure/cable/green{ - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/bridge) -"bay" = ( -/obj/structure/grille, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "bridge blast"; - name = "Bridge Blast Doors"; - opacity = 0 - }, -/obj/structure/window/reinforced/full, -/obj/structure/window/reinforced, -/obj/structure/cable/green{ - icon_state = "0-4" - }, -/obj/structure/cable/green{ - icon_state = "0-8" - }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, -/obj/structure/cable/green{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, -/turf/simulated/floor/plating, -/area/bridge) "baz" = ( /obj/effect/floor_decal/borderfloor, /obj/effect/floor_decal/corner/lightgrey/border, @@ -31361,24 +31402,6 @@ /obj/structure/disposalpipe/segment, /turf/simulated/floor/tiled, /area/tether/surfacebase/surface_three_hall) -"baA" = ( -/obj/structure/grille, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "bridge blast"; - name = "Bridge Blast Doors"; - opacity = 0 - }, -/obj/structure/window/reinforced/full, -/obj/structure/window/reinforced, -/obj/structure/cable/green{ - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/bridge) "baG" = ( /obj/structure/bed/chair/comfy/brown{ dir = 8 @@ -42927,7 +42950,7 @@ ahy ahx ahx ahx -aUy +awI aVN aWb aWn @@ -43697,7 +43720,7 @@ mfi jHw jpB qWU -aXB +aXV aKU aOI aPb @@ -44085,7 +44108,7 @@ alj alj alj asT -aTt +aTu asT alX alX @@ -44549,7 +44572,7 @@ isR jHw gHh qWU -aXB +aXV aKU aOI aPb @@ -44657,7 +44680,7 @@ aYb aYs aYx aYE -baq +aXx bbF ajM ape @@ -44799,7 +44822,7 @@ aYb aYp aYy aYF -baw +aXB bbF ajM apf @@ -44941,7 +44964,7 @@ aYb aYp aYz aYG -baw +aXB bbF ajM apD @@ -45083,7 +45106,7 @@ aYb aYt aYA aYH -baw +aXB bbF aEq apE @@ -45207,7 +45230,7 @@ ajV akn aYO aZs -awI +aTt aEb aSE aYS @@ -45225,7 +45248,7 @@ aYo aYu aYI aPC -bay +aXD bbF avG aNE @@ -45367,7 +45390,7 @@ bae aYv aYB aYJ -baw +aXB bbF ajR akx @@ -45509,7 +45532,7 @@ bae aYb aTv aYK -baw +aXB bbF ajR aEx @@ -45651,7 +45674,7 @@ aZI aYb aYy aYL -baw +aXB bbF avH awq @@ -45793,7 +45816,7 @@ aYp aYw aYD aYM -baA +aXE bbF ajR awp @@ -46357,7 +46380,7 @@ ayx alo alo asT -aTu +aUy asT alZ alZ @@ -46534,7 +46557,7 @@ aNk uSA aNJ aNP -aXx +aXU aKU abg aOk @@ -46676,7 +46699,7 @@ aNl aNl aNK aNP -aXx +aXU aKU abg aOk @@ -46818,7 +46841,7 @@ aNm aNl aNK aNP -aXx +aXU aKU abg aOk diff --git a/maps/tether/tether-05-station1.dmm b/maps/tether/tether-05-station1.dmm index 3df928336f..8d3a0bf1f0 100644 --- a/maps/tether/tether-05-station1.dmm +++ b/maps/tether/tether-05-station1.dmm @@ -2822,12 +2822,15 @@ /obj/machinery/door/firedoor/glass, /obj/structure/disposalpipe/segment, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 8; icon_state = "pdoor0"; id = "secondary_bridge_blast"; + layer = 1; name = "Secondary Command Office Blast Doors"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /turf/simulated/floor/tiled, /area/bridge/secondary) @@ -3705,26 +3708,23 @@ /turf/simulated/floor/tiled, /area/hallway/station/atrium) "agr" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/machinery/door/airlock/command{ + name = "Secondary Command Office" }, /obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/maintenance/engi{ - name = "Asteroid Command Substation"; - req_one_access = list(10,19) - }, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 8; icon_state = "pdoor0"; id = "secondary_bridge_blast"; + layer = 1; name = "Secondary Command Office Blast Doors"; - opacity = 0 + opacity = 0; + open_layer = 1 }, -/turf/simulated/floor, -/area/maintenance/substation/spacecommand) +/turf/simulated/floor/tiled, +/area/bridge/secondary) "ags" = ( /obj/effect/floor_decal/borderfloor{ dir = 8 @@ -5113,20 +5113,29 @@ /turf/simulated/floor/carpet/bcarpet, /area/tether/station/visitorhallway/office) "aiw" = ( -/obj/machinery/door/airlock/command{ - name = "Secondary Command Office" +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2" }, /obj/machinery/door/firedoor/glass, +/obj/machinery/door/airlock/maintenance/engi{ + name = "Asteroid Command Substation"; + req_one_access = list(10,19) + }, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 8; icon_state = "pdoor0"; id = "secondary_bridge_blast"; + layer = 1; name = "Secondary Command Office Blast Doors"; - opacity = 0 + opacity = 0; + open_layer = 1 }, -/turf/simulated/floor/tiled, -/area/bridge/secondary) +/turf/simulated/floor, +/area/maintenance/substation/spacecommand) "aix" = ( /obj/structure/table/rack{ dir = 8; @@ -11605,12 +11614,15 @@ dir = 4 }, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 1; icon_state = "pdoor0"; id = "secondary_bridge_blast"; + layer = 1; name = "Secondary Command Office Blast Doors"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /turf/simulated/floor, /area/bridge/secondary/hallway) @@ -16382,12 +16394,15 @@ req_one_access = list(17) }, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 8; icon_state = "pdoor0"; id = "secondary_bridge_blast"; + layer = 1; name = "Secondary Command Office Blast Doors"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /turf/simulated/floor, /area/bridge/secondary/teleporter) @@ -17624,12 +17639,15 @@ /obj/machinery/door/firedoor/glass, /obj/machinery/door/airlock/maintenance/command, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 1; icon_state = "pdoor0"; id = "secondary_bridge_blast"; + layer = 1; name = "Secondary Command Office Blast Doors"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /turf/simulated/floor, /area/bridge/meeting_room) @@ -35267,7 +35285,7 @@ aix aBx ait aut -agr +aiw agB ahj aiu @@ -35829,7 +35847,7 @@ acm acm acp are -aiw +agr asR afd afd diff --git a/maps/tether/tether-06-station2.dmm b/maps/tether/tether-06-station2.dmm index 82e8d15d44..562b659963 100644 --- a/maps/tether/tether-06-station2.dmm +++ b/maps/tether/tether-06-station2.dmm @@ -10492,24 +10492,40 @@ /turf/simulated/wall, /area/medical/surgery_hallway) "ps" = ( -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/medical{ - name = "Medical Waiting Room"; - req_one_access = list() - }, -/obj/machinery/door/blast/shutters{ - density = 0; - dir = 2; - icon_state = "shutter0"; - id = "medbayquar"; - name = "Medbay Emergency Lockdown Shutters"; - opacity = 0 - }, /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/tiled/white, -/area/medical/surgery_hallway) +/obj/structure/cable/green{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/machinery/door/airlock/glass_engineering{ + closed_layer = 8; + layer = 2; + name = "Engineering Mezzenine"; + open_layer = 2; + req_one_access = list() + }, +/obj/machinery/door/firedoor/glass{ + closed_layer = 7; + layer = 1.5; + open_layer = 1.5 + }, +/obj/machinery/door/blast/regular{ + closed_layer = 10; + density = 0; + dir = 4; + icon_state = "pdoor0"; + id = "englockdown"; + layer = 1; + level = 1; + name = "Engineering Lockdown"; + opacity = 0; + open_layer = 1 + }, +/turf/simulated/floor/tiled/steel_grid, +/area/engineering/foyer_mezzenine) "pt" = ( /obj/effect/floor_decal/borderfloor, /obj/effect/floor_decal/corner/paleblue/border, @@ -10699,45 +10715,40 @@ /turf/simulated/floor/plating, /area/engineering/foyer_mezzenine) "pL" = ( -/obj/structure/disposalpipe/segment, /obj/machinery/door/airlock/glass_engineering{ + closed_layer = 8; + layer = 2; name = "Engineering Mezzenine"; + open_layer = 2; req_one_access = list() }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/door/firedoor/glass, -/obj/structure/cable/green{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/machinery/door/firedoor/glass{ + closed_layer = 7; + layer = 1.5; + open_layer = 1.5 }, /obj/machinery/door/blast/regular{ + closed_layer = 10; density = 0; dir = 4; icon_state = "pdoor0"; id = "englockdown"; + layer = 1; + level = 1; name = "Engineering Lockdown"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /turf/simulated/floor/tiled/steel_grid, /area/engineering/foyer_mezzenine) "pM" = ( -/obj/machinery/door/airlock/glass_engineering{ - name = "Engineering Mezzenine"; - req_one_access = list() +/obj/structure/shuttle/engine/propulsion{ + dir = 8; + icon_state = "propulsion_r" }, -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/blast/regular{ - density = 0; - dir = 4; - icon_state = "pdoor0"; - id = "englockdown"; - name = "Engineering Lockdown"; - opacity = 0 - }, -/turf/simulated/floor/tiled/steel_grid, -/area/engineering/foyer_mezzenine) +/turf/space, +/turf/simulated/shuttle/plating/airless/carry, +/area/shuttle/large_escape_pod1) "pN" = ( /obj/machinery/requests_console{ department = "Tech storage"; @@ -10804,13 +10815,27 @@ /turf/simulated/floor/tiled, /area/hallway/station/starboard) "pS" = ( -/obj/structure/shuttle/engine/propulsion{ - dir = 8; - icon_state = "propulsion_r" +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/airlock/medical{ + name = "Medical Waiting Room"; + req_one_access = list() }, -/turf/space, -/turf/simulated/shuttle/plating/airless/carry, -/area/shuttle/large_escape_pod1) +/obj/machinery/door/blast/shutters{ + closed_layer = 10; + density = 0; + dir = 2; + icon_state = "shutter0"; + id = "medbayquar"; + layer = 1; + name = "Medbay Emergency Lockdown Shutters"; + opacity = 0; + open_layer = 1 + }, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/turf/simulated/floor/tiled/white, +/area/medical/surgery_hallway) "pT" = ( /obj/structure/cable{ d1 = 1; @@ -16170,6 +16195,30 @@ }, /turf/simulated/floor/tiled/white, /area/medical/ward) +"yp" = ( +/obj/machinery/door/firedoor/glass, +/obj/machinery/door/airlock/maintenance/medical, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, +/obj/machinery/door/blast/shutters{ + closed_layer = 10; + density = 0; + dir = 8; + icon_state = "shutter0"; + id = "medbayquar"; + layer = 1; + name = "Medbay Emergency Lockdown Shutters"; + opacity = 0; + open_layer = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/simulated/floor, +/area/medical/surgery_hallway) "ys" = ( /obj/structure/table/standard, /obj/item/weapon/reagent_containers/spray/cleaner{ @@ -17512,27 +17561,6 @@ }, /turf/simulated/floor/tiled/white, /area/medical/surgery_hallway) -"AS" = ( -/obj/machinery/door/firedoor/glass, -/obj/machinery/door/airlock/maintenance/medical, -/obj/structure/cable/green{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/machinery/door/blast/shutters{ - density = 0; - dir = 8; - icon_state = "shutter0"; - id = "medbayquar"; - name = "Medbay Emergency Lockdown Shutters"; - opacity = 0 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/simulated/floor, -/area/medical/surgery_hallway) "AT" = ( /obj/structure/cable/green{ d1 = 4; @@ -30817,7 +30845,7 @@ nB nk oh ox -pL +ps qr rh rU @@ -31101,7 +31129,7 @@ nD oj oN qx -pM +pL qt rj rV @@ -32951,7 +32979,7 @@ lK Fr fH op -ps +pS qO rx sb @@ -33965,7 +33993,7 @@ zQ xf pp pp -AS +yp pp Ay BM @@ -37493,7 +37521,7 @@ ot ou ou ou -pS +pM oY sW ef diff --git a/maps/tether/tether-07-station3.dmm b/maps/tether/tether-07-station3.dmm index d3d445eb13..3878984045 100644 --- a/maps/tether/tether-07-station3.dmm +++ b/maps/tether/tether-07-station3.dmm @@ -16093,12 +16093,15 @@ name = "Medbay Lobby" }, /obj/machinery/door/blast/shutters{ + closed_layer = 10; density = 0; dir = 2; icon_state = "shutter0"; id = "medbayquar"; + layer = 1; name = "Medbay Emergency Lockdown Shutters"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /obj/effect/floor_decal/steeldecal/steel_decals_central1{ dir = 8 @@ -16476,12 +16479,15 @@ "azr" = ( /obj/machinery/door/firedoor/glass, /obj/machinery/door/blast/shutters{ + closed_layer = 10; density = 0; dir = 2; icon_state = "shutter0"; id = "medbayquar"; + layer = 1; name = "Medbay Emergency Lockdown Shutters"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, @@ -16499,12 +16505,15 @@ name = "EMT Bay" }, /obj/machinery/door/blast/shutters{ + closed_layer = 10; density = 0; dir = 2; icon_state = "shutter0"; id = "medbayquar"; + layer = 1; name = "Medbay Emergency Lockdown Shutters"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /turf/simulated/floor/tiled/dark, /area/medical/medbay_emt_bay) @@ -24584,12 +24593,15 @@ /obj/machinery/door/firedoor/glass, /obj/machinery/door/airlock/maintenance/medical, /obj/machinery/door/blast/shutters{ + closed_layer = 10; density = 0; dir = 8; icon_state = "shutter0"; id = "medbayquar"; + layer = 1; name = "Medbay Emergency Lockdown Shutters"; - opacity = 0 + opacity = 0; + open_layer = 1 }, /obj/structure/cable/green{ d1 = 4; @@ -26017,7 +26029,7 @@ /area/shuttle/medivac/engines) "aOc" = ( /obj/machinery/door/airlock/glass_mining{ - name = "Belter Shuttle"; + name = "Mining Operations"; req_access = list(31); req_one_access = list() }, diff --git a/maps/tether/tether_phoronlock.dm b/maps/tether/tether_phoronlock.dm index 4921680f15..9118284285 100644 --- a/maps/tether/tether_phoronlock.dm +++ b/maps/tether/tether_phoronlock.dm @@ -243,6 +243,7 @@ obj/machinery/airlock_sensor/phoron/airlock_exterior if(STATE_PREPARE) if (check_doors_secured()) if(target_state == TARGET_INOPEN) + playsound(master, 'sound/AI/airlockin.ogg', 100, 0) if(memory["chamber_sensor_phoron"] > memory["target_phoron"]) state = STATE_CLEAN signalScrubber(tag_scrubber, 1) // Start cleaning @@ -256,11 +257,13 @@ obj/machinery/airlock_sensor/phoron/airlock_exterior else if(memory["pump_status"] != "off") signalPump(tag_airpump, 0) else + playsound(master, 'sound/AI/airlockout.ogg', 100, 0) cycleDoors(target_state) state = STATE_IDLE target_state = TARGET_NONE if(STATE_CLEAN) + playsound(master, 'sound/machines/2beep.ogg', 100, 0) if(!check_doors_secured()) //the airlock will not allow itself to continue to cycle when any of the doors are forced open. stop_cycling() @@ -271,12 +274,14 @@ obj/machinery/airlock_sensor/phoron/airlock_exterior state = STATE_PRESSURIZE if(STATE_PRESSURIZE) + playsound(master, 'sound/machines/2beep.ogg', 100, 0) if(!check_doors_secured()) //the airlock will not allow itself to continue to cycle when any of the doors are forced open. stop_cycling() else if(memory["chamber_sensor_pressure"] >= memory["target_pressure"] * 0.95) signalPump(tag_airpump, 0) // send a signal to stop pumping. No need to wait for it tho. cycleDoors(target_state) + playsound(master, 'sound/AI/airlockdone.ogg', 100, 0) state = STATE_IDLE target_state = TARGET_NONE diff --git a/maps/virgo_minitest/virgo_minitest-1.dmm b/maps/virgo_minitest/virgo_minitest-1.dmm index 9ce7f531bf..fd81e96920 100644 --- a/maps/virgo_minitest/virgo_minitest-1.dmm +++ b/maps/virgo_minitest/virgo_minitest-1.dmm @@ -6,6 +6,7 @@ /turf/simulated/wall/r_wall, /area/tcommsat/computer) "ac" = ( +/obj/machinery/camera/network/civilian, /turf/simulated/floor/tiled/dark, /area/tcommsat/computer) "ad" = ( @@ -493,6 +494,10 @@ /obj/machinery/atmospherics/pipe/simple/visible/yellow{ dir = 4 }, +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 9 + }, /turf/simulated/floor/plating, /area/engineering/engine_room) "bc" = ( @@ -703,6 +708,10 @@ pixel_x = -25; pixel_y = 0 }, +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 4 + }, /turf/simulated/floor/plating, /area/engineering/engine_room) "br" = ( @@ -2289,6 +2298,10 @@ /obj/structure/cable{ icon_state = "0-8" }, +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 10 + }, /turf/simulated/floor/tiled, /area/crew_quarters/bar) "eU" = ( @@ -3291,10 +3304,39 @@ /turf/space, /turf/simulated/shuttle/plating/carry, /area/shuttle/overmapdemo) +"jA" = ( +/obj/machinery/cryopod, +/turf/simulated/floor/tiled, +/area/bridge) "kU" = ( /obj/structure/shuttle, /turf/simulated/shuttle/wall/voidcraft/green, /area/shuttle/overmapdemo) +"mj" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 10 + }, +/turf/simulated/floor/tiled, +/area/crew_quarters/bar) +"nM" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 9 + }, +/turf/simulated/floor/tiled, +/area/crew_quarters/cafeteria) +"nQ" = ( +/obj/machinery/cryopod/robot, +/turf/simulated/floor/tiled, +/area/bridge) +"pG" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 9 + }, +/turf/simulated/floor/tiled, +/area/bridge) "ql" = ( /obj/machinery/door/airlock/external{ frequency = 1379; @@ -3311,11 +3353,43 @@ }, /turf/simulated/shuttle/floor/voidcraft/light, /area/shuttle/overmapdemo) +"qZ" = ( +/obj/machinery/camera/network/civilian, +/turf/simulated/floor/tiled, +/area/medical/medbay) +"rn" = ( +/obj/machinery/computer/cryopod, +/turf/simulated/floor/tiled, +/area/bridge) +"rK" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 10 + }, +/turf/simulated/floor/bluegrid{ + name = "Mainframe Base"; + nitrogen = 100; + oxygen = 0; + temperature = 80 + }, +/area/tcommsat/chamber) "sA" = ( /obj/structure/shuttle/engine/heater, /turf/space, /turf/simulated/shuttle/plating/carry, /area/shuttle/multidemo) +"sB" = ( +/obj/effect/landmark{ + name = "JoinLateCyborg" + }, +/turf/simulated/floor/tiled, +/area/bridge) +"vI" = ( +/obj/effect/landmark/start{ + name = "AI" + }, +/turf/simulated/floor/tiled, +/area/crew_quarters/bar) "vP" = ( /obj/machinery/computer/ship/engines{ dir = 8; @@ -3323,6 +3397,20 @@ }, /turf/simulated/shuttle/floor/voidcraft/light, /area/shuttle/overmapdemo) +"xM" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 5 + }, +/turf/simulated/floor/tiled, +/area/crew_quarters/cafeteria) +"xX" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 4 + }, +/turf/simulated/floor/tiled, +/area/medical/medbay) "zf" = ( /obj/effect/wingrille_spawn/reinforced, /turf/simulated/shuttle/floor/voidcraft/external/light, @@ -3338,10 +3426,24 @@ "Gz" = ( /turf/simulated/shuttle/wall/voidcraft/green, /area/shuttle/overmapdemo) +"GC" = ( +/obj/machinery/camera/network/civilian, +/turf/simulated/floor/tiled, +/area/bridge) "JA" = ( /obj/effect/overmap/visitable/sector/virgo_minitest/station, /turf/space, /area/space) +"La" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 9 + }, +/turf/simulated/floor/tiled, +/area/hallway/primary/fore) "ML" = ( /obj/machinery/embedded_controller/radio/simple_docking_controller{ id_tag = "station_dock2"; @@ -3362,6 +3464,13 @@ }, /turf/simulated/shuttle/floor/voidcraft/light, /area/shuttle/overmapdemo) +"OA" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 10 + }, +/turf/simulated/floor/tiled, +/area/medical/medbay) "Pg" = ( /obj/structure/shuttle/engine/propulsion, /turf/space, @@ -3376,16 +3485,47 @@ }, /turf/simulated/floor/tiled, /area/bridge) +"Ug" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 4 + }, +/turf/simulated/floor/tiled, +/area/medical/medbay2) "Uh" = ( /obj/machinery/computer/ship/sensors{ dir = 1 }, /turf/simulated/shuttle/floor/voidcraft/light, /area/shuttle/overmapdemo) +"Vf" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 9 + }, +/turf/simulated/floor/tiled, +/area/crew_quarters/bar) +"Xm" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/camera/network/civilian, +/turf/simulated/floor/tiled, +/area/hallway/primary/fore) "XZ" = ( /obj/machinery/computer/ship/helm, /turf/simulated/shuttle/floor/voidcraft/light, /area/shuttle/overmapdemo) +"Yb" = ( +/obj/machinery/camera/network/civilian{ + icon_state = "camera"; + dir = 9 + }, +/turf/simulated/floor/tiled, +/area/medical/medbay2) (1,1,1) = {" aa @@ -4791,9 +4931,9 @@ aa aa fY gf -gf -gf -gf +rn +sB +nQ gf gf gf @@ -4996,8 +5136,8 @@ aa fY gg gf -gf -gf +gC +jA gf gx gA @@ -5205,7 +5345,7 @@ gf gf gy gf -gC +gf gf gf gf @@ -5402,7 +5542,7 @@ sA Pg aa fY -gf +GC gf gr gf @@ -5715,7 +5855,7 @@ gf gf gy gf -gC +gf gf gf gf @@ -5875,7 +6015,7 @@ bW bu bu bu -bf +rK aP aa aa @@ -6223,14 +6363,14 @@ gf gv gf gf -gf +pG gv hk hy hl gf gv -gf +pG gf gf fY @@ -6413,7 +6553,7 @@ aa aa aa fi -fo +Xm fu fi aa @@ -6595,14 +6735,14 @@ aa cF cM cM -cM +xX dd cM cM cM cM cM -cM +xX dd cM cM @@ -6906,7 +7046,7 @@ cM cM cM cM -cM +OA du cM cM @@ -7223,7 +7363,7 @@ eO eO eO eO -eO +La eO eO eO @@ -7415,7 +7555,7 @@ cM dh cM du -cM +qZ cM el cM @@ -8129,7 +8269,7 @@ cZ dm dv cZ -cZ +Yb cZ dR cZ @@ -8639,7 +8779,7 @@ cZ dl cZ cZ -cZ +Ug cZ dR cZ @@ -10298,7 +10438,7 @@ fI fS fI fI -fI +xM fS fI fI @@ -10573,6 +10713,7 @@ cC cK cR cW +vI cK cK cK @@ -10580,8 +10721,7 @@ cK cK cK cK -cK -cK +mj cR eE eL @@ -10675,7 +10815,7 @@ cC cK cR cK -cK +Vf cK cK cK @@ -11314,7 +11454,7 @@ aa aa fA fI -fI +nM fW fI fI diff --git a/maps/virgo_minitest/virgo_minitest.dm b/maps/virgo_minitest/virgo_minitest.dm index 5906fae2f6..4a7f68fbaf 100644 --- a/maps/virgo_minitest/virgo_minitest.dm +++ b/maps/virgo_minitest/virgo_minitest.dm @@ -10,7 +10,7 @@ #define USING_MAP_DATUM /datum/map/virgo_minitest - #warning Please uncheck virgo_minitest.dm before committing. + #warn Please uncheck virgo_minitest before committing #elif !defined(MAP_OVERRIDE) diff --git a/maps/virgo_minitest/virgo_minitest_defines.dm b/maps/virgo_minitest/virgo_minitest_defines.dm index 8432fb7f22..db438c6476 100644 --- a/maps/virgo_minitest/virgo_minitest_defines.dm +++ b/maps/virgo_minitest/virgo_minitest_defines.dm @@ -9,8 +9,8 @@ lobby_icon = 'icons/misc/title_vr.dmi' lobby_screens = list("tether2_night") - accessible_z_levels = list("[Z_LEVEL_MAIN_VIRGO_TESTING]" = 100) - base_turf_by_z = list("[Z_LEVEL_MAIN_VIRGO_TESTING]" = /turf/space) + accessible_z_levels = list("1" = 100) + base_turf_by_z = list("1" = /turf/space) use_overmap = TRUE //var/overmap_size = 20 // Dimensions of overmap zlevel if overmap is used. @@ -56,7 +56,7 @@ NETWORK_INTERROGATION ) - allowed_spawns = list("Arrivals Shuttle") + allowed_spawns = list("Arrivals Shuttle","Gateway","Cryogenic Storage","Cyborg Storage") /datum/map_z_level/minitest/station z = Z_LEVEL_MAIN_VIRGO_TESTING diff --git a/maps/~map_system/maps.dm b/maps/~map_system/maps.dm index cd953e8217..5b497cdbff 100644 --- a/maps/~map_system/maps.dm +++ b/maps/~map_system/maps.dm @@ -147,15 +147,14 @@ var/list/all_maps = list() /datum/map/proc/get_zlevel_time(var/z) if(!z) z = 1 - var/datum/planet/P = SSplanets.z_to_planet[z] + var/datum/planet/P = z <= SSplanets.z_to_planet.len ? SSplanets.z_to_planet[z] : null // We found a planet tied to that zlevel, give them the time - if(istype(P)) + if(P?.current_time) return P.current_time // We have to invent a time else - var/seconds_stationtime = round(station_time_in_ticks*0.1) //Not actually ticks...... - var/datum/time/T = new(seconds_stationtime) + var/datum/time/T = new (station_time_in_ds) return T // Returns a boolean for if it's night or not on a particular zlevel @@ -163,7 +162,7 @@ var/list/all_maps = list() if(!z) z = 1 var/datum/time/now = get_zlevel_time(z) - var/percent = now.seconds_stored / now.seconds_in_day + var/percent = now.seconds_stored / now.seconds_in_day //practically all of these are in DS // First quarter, last quarter if(percent < 0.25 || percent > 0.75) diff --git a/nano/templates/apc.tmpl b/nano/templates/apc.tmpl index 9b39900a81..a26abef4a0 100644 --- a/nano/templates/apc.tmpl +++ b/nano/templates/apc.tmpl @@ -206,7 +206,9 @@ Night Lighting:
- {{:helper.link(data.nightshiftLights ? 'Enabled' : 'Disabled', data.nightshiftLights ? 'power' : 'close', {'nightshift' : 1}, null)}} + {{:helper.link('Disabled', null, {'nightshift' : 2}, data.nightshiftSetting == 2 ? 'selected' : null)}} + {{:helper.link('Automatic', null, {'nightshift' : 1}, data.nightshiftSetting == 1 ? 'selected' : null)}} + {{:helper.link('Enabled', null, {'nightshift' : 3}, data.nightshiftSetting == 3 ? 'selected' : null)}}
diff --git a/nano/templates/teleport_control.tmpl b/nano/templates/teleport_control.tmpl new file mode 100644 index 0000000000..c849eb516f --- /dev/null +++ b/nano/templates/teleport_control.tmpl @@ -0,0 +1,44 @@ +
+
+
Target:
+
+ {{:helper.link(data.locked_name, null, {'select_target' : 1}, null, null)}} +
+
+ +
+
Calibrated:
+
+ {{:helper.link(data.calibrated ? 'Accurate' : 'Test Fire', data.calibrated ? 'check' : 'close', {'test_fire' : 1}, null, data.calibrated ? 'linkOn' : 'redButton')}} +
+
+ +
+
Teleporter:
+
+ {{:helper.link(data.teleporter_on ? 'Online' : 'Offline', data.teleporter_on ? 'check' : 'close', {'toggle_on' : 1}, null, data.teleporter_on ? 'linkOn' : 'redButton')}} +
+
+ +
+
Station:
+
+ {{if data.station_connected}} + Connected + {{else}} + Not Connected! + {{/if}} +
+
+ +
+
Hub:
+
+ {{if data.hub_connected}} + Connected + {{else}} + Not Connected! + {{/if}} +
+
+
\ No newline at end of file diff --git a/sound/effects/footstep/HeavySand1.ogg b/sound/effects/footstep/HeavySand1.ogg new file mode 100644 index 0000000000..68be7bed25 Binary files /dev/null and b/sound/effects/footstep/HeavySand1.ogg differ diff --git a/sound/effects/footstep/HeavySand2.ogg b/sound/effects/footstep/HeavySand2.ogg new file mode 100644 index 0000000000..6a32465a5b Binary files /dev/null and b/sound/effects/footstep/HeavySand2.ogg differ diff --git a/sound/effects/footstep/HeavySand3.ogg b/sound/effects/footstep/HeavySand3.ogg new file mode 100644 index 0000000000..c71a89cea2 Binary files /dev/null and b/sound/effects/footstep/HeavySand3.ogg differ diff --git a/sound/effects/footstep/HeavySand4.ogg b/sound/effects/footstep/HeavySand4.ogg new file mode 100644 index 0000000000..088519fb75 Binary files /dev/null and b/sound/effects/footstep/HeavySand4.ogg differ diff --git a/sound/effects/footstep/LightDirt2.ogg b/sound/effects/footstep/LightDirt2.ogg new file mode 100644 index 0000000000..324fd82370 Binary files /dev/null and b/sound/effects/footstep/LightDirt2.ogg differ diff --git a/sound/effects/footstep/LightDirt4.ogg b/sound/effects/footstep/LightDirt4.ogg new file mode 100644 index 0000000000..8a72738b21 Binary files /dev/null and b/sound/effects/footstep/LightDirt4.ogg differ diff --git a/sound/effects/footstep/LightStone1.ogg b/sound/effects/footstep/LightStone1.ogg new file mode 100644 index 0000000000..a61d3ccfa2 Binary files /dev/null and b/sound/effects/footstep/LightStone1.ogg differ diff --git a/sound/effects/footstep/LightStone2.ogg b/sound/effects/footstep/LightStone2.ogg new file mode 100644 index 0000000000..3409c1f4d8 Binary files /dev/null and b/sound/effects/footstep/LightStone2.ogg differ diff --git a/sound/effects/footstep/LightStone3.ogg b/sound/effects/footstep/LightStone3.ogg new file mode 100644 index 0000000000..e0843c62af Binary files /dev/null and b/sound/effects/footstep/LightStone3.ogg differ diff --git a/sound/effects/footstep/LightStone4.ogg b/sound/effects/footstep/LightStone4.ogg new file mode 100644 index 0000000000..b262be5f8e Binary files /dev/null and b/sound/effects/footstep/LightStone4.ogg differ diff --git a/sound/effects/footstep/MedDirt1.ogg b/sound/effects/footstep/MedDirt1.ogg new file mode 100644 index 0000000000..8951c4580a Binary files /dev/null and b/sound/effects/footstep/MedDirt1.ogg differ diff --git a/sound/effects/footstep/MedDirt2.ogg b/sound/effects/footstep/MedDirt2.ogg new file mode 100644 index 0000000000..7fee392796 Binary files /dev/null and b/sound/effects/footstep/MedDirt2.ogg differ diff --git a/sound/effects/footstep/MedDirt3.ogg b/sound/effects/footstep/MedDirt3.ogg new file mode 100644 index 0000000000..141c542f0a Binary files /dev/null and b/sound/effects/footstep/MedDirt3.ogg differ diff --git a/sound/effects/footstep/MedDirt4.ogg b/sound/effects/footstep/MedDirt4.ogg new file mode 100644 index 0000000000..7b980e6e31 Binary files /dev/null and b/sound/effects/footstep/MedDirt4.ogg differ diff --git a/sound/effects/footstep/bubbles3.ogg b/sound/effects/footstep/bubbles3.ogg new file mode 100644 index 0000000000..62070813e3 Binary files /dev/null and b/sound/effects/footstep/bubbles3.ogg differ diff --git a/sound/effects/footstep/bubbles4.ogg b/sound/effects/footstep/bubbles4.ogg new file mode 100644 index 0000000000..f94889c060 Binary files /dev/null and b/sound/effects/footstep/bubbles4.ogg differ diff --git a/sound/effects/footstep/bubbles5.ogg b/sound/effects/footstep/bubbles5.ogg new file mode 100644 index 0000000000..43eff29193 Binary files /dev/null and b/sound/effects/footstep/bubbles5.ogg differ diff --git a/sound/effects/footstep/mud1.ogg b/sound/effects/footstep/mud1.ogg new file mode 100644 index 0000000000..c0f5276e41 Binary files /dev/null and b/sound/effects/footstep/mud1.ogg differ diff --git a/sound/effects/footstep/mud2.ogg b/sound/effects/footstep/mud2.ogg new file mode 100644 index 0000000000..36b311a2de Binary files /dev/null and b/sound/effects/footstep/mud2.ogg differ diff --git a/sound/effects/footstep/mud3.ogg b/sound/effects/footstep/mud3.ogg new file mode 100644 index 0000000000..e44c7d05f3 Binary files /dev/null and b/sound/effects/footstep/mud3.ogg differ diff --git a/sound/effects/footstep/mud4.ogg b/sound/effects/footstep/mud4.ogg new file mode 100644 index 0000000000..158158125d Binary files /dev/null and b/sound/effects/footstep/mud4.ogg differ diff --git a/vorestation.dme b/vorestation.dme index 67aade51ff..f3ac8d1a3c 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -86,6 +86,8 @@ #include "code\__defines\subsystems_vr.dm" #include "code\__defines\supply.dm" #include "code\__defines\targeting.dm" +#include "code\__defines\tgs.config.dm" +#include "code\__defines\tgs.dm" #include "code\__defines\turfs.dm" #include "code\__defines\typeids.dm" #include "code\__defines\unit_tests.dm" @@ -160,6 +162,7 @@ #include "code\_onclick\hud\human.dm" #include "code\_onclick\hud\movable_screen_objects.dm" #include "code\_onclick\hud\other_mobs.dm" +#include "code\_onclick\hud\picture_in_picture.dm" #include "code\_onclick\hud\radial.dm" #include "code\_onclick\hud\radial_persistent.dm" #include "code\_onclick\hud\robot.dm" @@ -2607,6 +2610,7 @@ #include "code\modules\mob\living\silicon\ai\login.dm" #include "code\modules\mob\living\silicon\ai\logout.dm" #include "code\modules\mob\living\silicon\ai\malf.dm" +#include "code\modules\mob\living\silicon\ai\multicam.dm" #include "code\modules\mob\living\silicon\decoy\death.dm" #include "code\modules\mob\living\silicon\decoy\decoy.dm" #include "code\modules\mob\living\silicon\decoy\life.dm" @@ -3507,6 +3511,7 @@ #include "code\modules\telesci\telepad.dm" #include "code\modules\telesci\telesci_computer.dm" #include "code\modules\tension\tension.dm" +#include "code\modules\tgs\includes.dm" #include "code\modules\tooltip\tooltip.dm" #include "code\modules\turbolift\_turbolift.dm" #include "code\modules\turbolift\turbolift.dm"