Merge branch 'master' into upstream-merge-37486

This commit is contained in:
LetterJay
2018-05-21 08:59:32 -05:00
committed by GitHub
403 changed files with 10034 additions and 7488 deletions
+4 -1
View File
@@ -138,11 +138,14 @@
#define COMSIG_TRY_STORAGE_FILL_TYPE "storage_fill_type" //(type, amount = INFINITY, force = FALSE) //don't fuck this up. Force will ignore max_items, and amount is normally clamped to max_items.
#define COMSIG_TRY_STORAGE_TAKE "storage_take_obj" //(obj, new_loc, force = FALSE) - returns bool
#define COMSIG_TRY_STORAGE_QUICK_EMPTY "storage_quick_empty" //(loc) - returns bool - if loc is null it will dump at parent location.
#define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory" //(list/list_to_inject_results_into)
#define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory" //(list/list_to_inject_results_into, recursively_search_inside_storages = TRUE)
#define COMSIG_TRY_STORAGE_CAN_INSERT "storage_can_equip" //(obj/item/insertion_candidate, mob/user, silent) - returns bool
/*******Non-Signal Component Related Defines*******/
//Redirection component init flags
#define REDIRECT_TRANSFER_WITH_TURF 1
//Arch
#define ARCH_PROB "probability" //Probability for each item
#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount
+1
View File
@@ -6,6 +6,7 @@
#define PLANE_SPACE -95
#define PLANE_SPACE_PARALLAX -90
#define FLOOR_PLANE -2
#define GAME_PLANE -1
#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
#define SPACE_LAYER 1.8
+6 -1
View File
@@ -378,7 +378,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define BEAT_SLOW 2
#define BEAT_NONE 0
//http://www.byond.com/docs/ref/info.html#/atom/var/mouse_opacity
//https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity
#define MOUSE_OPACITY_TRANSPARENT 0
#define MOUSE_OPACITY_ICON 1
#define MOUSE_OPACITY_OPAQUE 2
@@ -445,3 +445,8 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define NO_INIT_PARAMETER "no-init"
#define EGG_LAYING_MESSAGES list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")
// Used by PDA and cartridge code to reduce repetitiveness of spritesheets
#define PDAIMG(what) {"<span class="pda16x16 [#what]"></span>"}
//Filters
#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, border=4, color="#04080FAA")
+1 -1
View File
@@ -258,7 +258,7 @@
// Roundstart trait system
#define MAX_TRAITS 6 //The maximum amount of traits one character can have at roundstart
#define MAX_QUIRKS 6 //The maximum amount of quirks one character can have at roundstart
// AI Toggles
#define AI_CAMERA_LUMINOSITY 5
+1
View File
@@ -64,6 +64,7 @@
#define EXP_TYPE_ANTAG "Antag"
#define EXP_TYPE_SPECIAL "Special"
#define EXP_TYPE_GHOST "Ghost"
#define EXP_TYPE_ADMIN "Admin"
//Flags in the players table in the db
#define DB_FLAG_EXEMPT 1
-128
View File
@@ -1,128 +0,0 @@
// /tg/station 13 server tools API
#define SERVICE_API_VERSION_STRING "3.2.0.2"
//CONFIGURATION
//use this define if you want to do configuration outside of this file
#ifndef SERVER_TOOLS_EXTERNAL_CONFIGURATION
//Comment this out once you've filled in the below
#error /tg/station server tools interface unconfigured
//Required interfaces (fill in with your codebase equivalent):
//create a global variable named `Name` and set it to `Value`
//These globals must not be modifiable from anywhere outside of the server tools
#define SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(Name, Value)
//Read the value in the global variable `Name`
#define SERVER_TOOLS_READ_GLOBAL(Name)
//Set the value in the global variable `Name` to `Value`
#define SERVER_TOOLS_WRITE_GLOBAL(Name, Value)
//display an announcement `message` from the server to all players
#define SERVER_TOOLS_WORLD_ANNOUNCE(message)
//Write a string `message` to a server log
#define SERVER_TOOLS_LOG(message)
//Notify current in-game administrators of a string `event`
#define SERVER_TOOLS_NOTIFY_ADMINS(event)
//The current amount of connected clients
#define SERVER_TOOLS_CLIENT_COUNT
#endif
//Required hooks:
//Put this somewhere in /world/New() that is always run
#define SERVER_TOOLS_ON_NEW ServiceInit()
//Put this somewhere in /world/Topic(T, Addr, Master, Keys) that is always run before T is modified
#define SERVER_TOOLS_ON_TOPIC var/service_topic_return = ServiceCommand(params2list(T)); if(service_topic_return) return service_topic_return
//Put at the beginning of world/Reboot(reason)
#define SERVER_TOOLS_ON_REBOOT ServiceReboot()
//Optional callable functions:
//Returns the string version of the API
#define SERVER_TOOLS_API_VERSION ServiceAPIVersion()
//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise
//No function below this succeed if this is FALSE
#define SERVER_TOOLS_PRESENT RunningService()
//Gets the current version of the service running the server
#define SERVER_TOOLS_VERSION ServiceVersion()
//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 world will reboot shortly after
#define SERVER_TOOLS_REBOOT_BYOND world.ServiceEndProcess()
/*
Gets the list of any testmerged github pull requests
"[PR Number]" => list(
"title" -> PR title
"commit" -> Full hash of commit merged
"author" -> Github username of the author of the PR
)
*/
#define SERVER_TOOLS_PR_LIST GetTestMerges()
//Sends a message to connected game chats
#define SERVER_TOOLS_CHAT_BROADCAST(message) world.ChatBroadcast(message)
//Sends a message to connected admin chats
#define SERVER_TOOLS_RELAY_BROADCAST(message) world.AdminBroadcast(message)
//IMPLEMENTATION
#define REBOOT_MODE_NORMAL 0
#define REBOOT_MODE_HARD 1
#define REBOOT_MODE_SHUTDOWN 2
#define SERVICE_WORLD_PARAM "server_service"
#define SERVICE_VERSION_PARAM "server_service_version"
#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_JSON_PARAM_HELPTEXT "help_text"
#define SERVICE_JSON_PARAM_ADMINONLY "admin_only"
#define SERVICE_JSON_PARAM_REQUIREDPARAMETERS "required_parameters"
#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"
/*
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.
*/
+2 -2
View File
@@ -1,7 +1,7 @@
//Update this whenever the db schema changes
//make sure you add an update to the schema_version stable in the db changelog
#define DB_MAJOR_VERSION 4
#define DB_MINOR_VERSION 1
#define DB_MINOR_VERSION 2
//Timing subsystem
//Don't run if there is an identical unique timer active
@@ -56,7 +56,7 @@
#define INIT_ORDER_RESEARCH 14
#define INIT_ORDER_EVENTS 13
#define INIT_ORDER_JOBS 12
#define INIT_ORDER_TRAITS 11
#define INIT_ORDER_QUIRKS 11
#define INIT_ORDER_TICKER 10
#define INIT_ORDER_MAPPING 9
#define INIT_ORDER_NETWORKS 8
+19
View File
@@ -0,0 +1,19 @@
#define TGS_EXTERNAL_CONFIGURATION
#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, "<span class='boldannounce'>[html_encode(##message)]</span>")
#define TGS_INFO_LOG(message) log_world("TGS: Info: [##message]")
#define TGS_ERROR_LOG(message) log_world("TGS: Error: [##message]")
#define TGS_NOTIFY_ADMINS(event) message_admins(##event)
#define TGS_CLIENT_COUNT GLOB.clients.len
#define TGS_PROTECT_DATUM(Path)\
##Path/can_vv_get(var_name){\
return FALSE;\
}\
##Path/vv_edit_var(var_name, var_value){\
return FALSE;\
}\
##Path/CanProcCall(procname){\
return FALSE;\
}
+202
View File
@@ -0,0 +1,202 @@
//tgstation-server DMAPI
//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
//Required interfaces (fill in with your codebase equivalent):
//create a global variable named `Name` and set it to `Value`
//These globals must not be modifiable from anywhere outside of the server tools
#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 priveledge escalation
#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 error `message` to a server log
#define TGS_ERROR_LOG(message)
//Get the number of connected /clients
#define TGS_CLIENT_COUNT
#endif
//EVENT CODES
//TODO
//REQUIRED HOOKS
//Call this somewhere in /world/New() that is always run
//event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels
/world/proc/TgsNew(datum/tgs_event_handler/event_handler)
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
/world/proc/TgsInitializationComplete()
return
//Put this somewhere in /world/Topic(T, Addr, Master, Keys) that is always run before T is modified
#define TGS_TOPIC var/tgs_topic_return = TgsTopic(T); 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 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/server_name //server name the channel resides on
var/provider_name //chat provider for the channel
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
//represents a chat user
/datum/tgs_chat_user
var/id //Internal user representation
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
/datum/tgs_event_handler/proc/HandleEvent(event_code)
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 string version of the API
/world/proc/TgsMaximumAPIVersion()
return
/world/proc/TgsMinimumAPIVersion()
return
//Gets the current version of the server tools running the server
/world/proc/TgsVersion()
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
/world/proc/TgsAvailable()
return
/world/proc/TgsInstanceName()
return
//Get the current `/datum/tgs_revision_information`
/world/proc/TgsRevision()
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.
*/
+1
View File
@@ -68,6 +68,7 @@
#define MAGIC_TRAIT "magic"
#define TRAUMA_TRAIT "trauma"
#define SPECIES_TRAIT "species"
#define ORGAN_TRAIT "organ"
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
// unique trait sources, still defines
+3
View File
@@ -128,6 +128,9 @@
/proc/log_qdel(text)
WRITE_LOG(GLOB.world_qdel_log, "QDEL: [text]")
/proc/log_query_debug(text)
WRITE_LOG(GLOB.query_debug_log, "SQL: [text]")
/* Log to both DD and the logfile. */
/proc/log_world(text)
WRITE_LOG(GLOB.world_runtime_log, text)
+1 -1
View File
@@ -359,7 +359,7 @@
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
borg_num--
if(robo.mind)
robolist += "<b>[robo.name]</b> (Played by: <b>[robo.mind.key]</b>)[robo.stat ? " <span class='redtext'>(Deactivated)</span>" : ""][borg_num ?", ":""]<br>"
robolist += "<b>[robo.name]</b> (Played by: <b>[robo.mind.key]</b>)[robo.stat == DEAD ? " <span class='redtext'>(Deactivated)</span>" : ""][borg_num ?", ":""]<br>"
parts += "[robolist]"
if(!borg_spacer)
borg_spacer = TRUE
+1 -2
View File
@@ -698,7 +698,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
var/macro = lowertext(copytext(string, next_backslash + 1, next_space))
var/rest = next_backslash > leng ? "" : copytext(string, next_space + 1)
//See http://www.byond.com/docs/ref/info.html#/DM/text/macros
//See https://secure.byond.com/docs/ref/info.html#/DM/text/macros
switch(macro)
//prefixes/agnostic
if("the")
@@ -766,4 +766,3 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
return "twelfth"
else
return "[number]\th"
+1 -1
View File
@@ -30,7 +30,7 @@
#define MIN_COMPILER_VERSION 512
#if DM_VERSION < MIN_COMPILER_VERSION
//Don't forget to update this part
#error Your version of BYOND is too out-of-date to compile this project. Go to byond.com/download and update.
#error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update.
#error You need version 512 or higher
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
GLOBAL_REAL(config, /datum/controller/configuration)
GLOBAL_DATUM_INIT(revdata, /datum/getrev, new)
GLOBAL_DATUM(revdata, /datum/getrev)
GLOBAL_VAR(host)
GLOBAL_VAR(station_name)
+2
View File
@@ -20,6 +20,8 @@ GLOBAL_VAR(world_pda_log)
GLOBAL_PROTECT(world_pda_log)
GLOBAL_VAR(world_manifest_log)
GLOBAL_PROTECT(world_manifest_log)
GLOBAL_VAR(query_debug_log)
GLOBAL_PROTECT(query_debug_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
+2
View File
@@ -167,6 +167,8 @@
/datum/hud/proc/update_parallax()
var/client/C = mymob.client
var/turf/posobj = get_turf(C.eye)
if(!posobj)
return
var/area/areaobj = posobj.loc
// Update the movement direction of the parallax if necessary (for shuttles)
+11 -1
View File
@@ -12,16 +12,26 @@
/obj/screen/plane_master/proc/Hide(override)
alpha = override || hide_alpha
//Why do plane masters need a backdrop sometimes? Read http://www.byond.com/forum/?post=2141928
//Why do plane masters need a backdrop sometimes? Read https://secure.byond.com/forum/?post=2141928
//Trust me, you need one. Period. If you don't think you do, you're doing something extremely wrong.
/obj/screen/plane_master/proc/backdrop(mob/mymob)
/obj/screen/plane_master/floor
name = "floor plane master"
plane = FLOOR_PLANE
appearance_flags = PLANE_MASTER
blend_mode = BLEND_OVERLAY
/obj/screen/plane_master/game_world
name = "game world plane master"
plane = GAME_PLANE
appearance_flags = PLANE_MASTER //should use client color
blend_mode = BLEND_OVERLAY
/obj/screen/plane_master/game_world/backdrop(mob/mymob)
if(istype(mymob) && mymob.client && mymob.client.prefs && mymob.client.prefs.ambientocclusion)
filters += AMBIENT_OCCLUSION
/obj/screen/plane_master/lighting
name = "lighting plane master"
plane = LIGHTING_PLANE
@@ -4,7 +4,7 @@
/datum/config_entry/string/address
config_entry_value = "localhost"
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
/datum/config_entry/number/port
config_entry_value = 3306
min_val = 0
@@ -24,3 +24,8 @@
/datum/config_entry/string/feedback_tableprefix
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
/datum/config_entry/number/query_debug_log_timeout
config_entry_value = 70
min_val = 1
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+5 -2
View File
@@ -199,11 +199,14 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
// Sort subsystems by display setting for easy access.
sortTim(subsystems, /proc/cmp_subsystem_display)
// Set world options.
if(sleep_offline_after_initializations)
world.sleep_offline = TRUE
world.fps = CONFIG_GET(number/fps)
var/initialized_tod = REALTIMEOFDAY
world.TgsInitializationComplete()
if(sleep_offline_after_initializations)
world.sleep_offline = TRUE
sleep(1)
if(sleep_offline_after_initializations && CONFIG_GET(flag/resume_after_initializations))
world.sleep_offline = FALSE
initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10
+2 -1
View File
@@ -29,7 +29,8 @@ SUBSYSTEM_DEF(air)
var/list/obj/machinery/atmos_machinery = list()
var/list/pipe_init_dirs_cache = list()
//atmos singletons
var/list/gas_reactions = list()
//Special functions lists
var/list/turf/active_super_conductivity = list()
+4 -3
View File
@@ -6,9 +6,10 @@ SUBSYSTEM_DEF(assets)
var/list/preload = list()
/datum/controller/subsystem/assets/Initialize(timeofday)
for(var/type in typesof(/datum/asset) - list(/datum/asset, /datum/asset/simple))
var/datum/asset/A = new type()
A.register()
for(var/type in typesof(/datum/asset))
var/datum/asset/A = type
if (type != initial(A._abstract))
get_asset_datum(type)
preload = cache.Copy() //don't preload assets generated during the round
+14
View File
@@ -231,10 +231,24 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
to_chat(usr, "<span class='danger'>A SQL error occurred during this operation, check the server logs.</span>")
/datum/DBQuery/proc/Execute(sql_query = sql, cursor_handler = default_cursor, log_error = TRUE)
var/start_time
var/timeout = CONFIG_GET(number/query_debug_log_timeout)
if(timeout)
start_time = REALTIMEOFDAY
Close()
. = _dm_db_execute(_db_query, sql_query, db_connection._db_con, cursor_handler, null)
if(!. && log_error)
log_sql("[ErrorMsg()] | Query used: [sql]")
if(timeout)
if((REALTIMEOFDAY - start_time) > timeout)
log_query_debug("Query execution started at [start_time]")
log_query_debug("Query execution ended at [REALTIMEOFDAY]")
log_query_debug("Possible slow query timeout detected.")
log_query_debug("Query used: [sql]")
slow_query_check()
/datum/DBQuery/proc/slow_query_check()
message_admins("HEY! A database query may have timed out. Did the server just hang? <a href='?_src_=holder;[HrefToken()];slowquery=yes'>\[YES\]</a>|<a href='?_src_=holder;[HrefToken()];slowquery=no'>\[NO\]</a>")
/datum/DBQuery/proc/NextRow()
return _dm_db_next_row(_db_query,item,conversions)
@@ -0,0 +1,34 @@
//Used to process and handle roundstart quirks
// - Quirk strings are used for faster checking in code
// - Quirk datums are stored and hold different effects, as well as being a vector for applying trait string
PROCESSING_SUBSYSTEM_DEF(quirks)
name = "Quirks"
init_order = INIT_ORDER_QUIRKS
flags = SS_BACKGROUND
wait = 10
runlevels = RUNLEVEL_GAME
var/list/quirks = list() //Assoc. list of all roundstart quirk datum types; "name" = /path/
var/list/quirk_points = list() //Assoc. list of quirk names and their "point cost"; positive numbers are good traits, and negative ones are bad
var/list/quirk_objects = list() //A list of all quirk objects in the game, since some may process
/datum/controller/subsystem/processing/quirks/Initialize(timeofday)
if(!quirks.len)
SetupQuirks()
..()
/datum/controller/subsystem/processing/quirks/proc/SetupQuirks()
for(var/V in subtypesof(/datum/quirk))
var/datum/quirk/T = V
quirks[initial(T.name)] = T
quirk_points[initial(T.name)] = initial(T.value)
/datum/controller/subsystem/processing/quirks/proc/AssignQuirks(mob/living/user, client/cli, spawn_effects)
GenerateQuirks(cli)
for(var/V in cli.prefs.character_quirks)
user.add_quirk(V, spawn_effects)
/datum/controller/subsystem/processing/quirks/proc/GenerateQuirks(client/user)
if(user.prefs.character_quirks.len)
return
user.prefs.character_quirks = user.prefs.all_quirks
+3 -3
View File
@@ -55,8 +55,8 @@ SUBSYSTEM_DEF(server_maint)
co.ehjax_send(data = "roundrestart")
if(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://[server]")
if(SERVER_TOOLS_PRESENT)
SSblackbox.record_feedback("text", "server_tools", 1, SERVER_TOOLS_VERSION)
SSblackbox.record_feedback("text", "server_tools_api", 1, SERVER_TOOLS_API_VERSION)
var/tgsversion = world.TgsVersion()
if(tgsversion)
SSblackbox.record_feedback("text", "server_tools", 1, tgsversion)
#undef PING_BUFFER_TIME
+2 -2
View File
@@ -158,7 +158,7 @@ SUBSYSTEM_DEF(ticker)
window_flash(C, ignorepref = TRUE) //let them know lobby has opened up.
to_chat(world, "<span class='boldnotice'>Welcome to [station_name()]!</span>")
if(CONFIG_GET(flag/irc_announce_new_game))
SERVER_TOOLS_CHAT_BROADCAST("New round starting on [SSmapping.config.map_name]!")
world.TgsTargetedChatBroadcast("New round starting on [SSmapping.config.map_name]!", FALSE)
current_state = GAME_STATE_PREGAME
//Everyone who wants to be an observer is now spawned
create_observers()
@@ -391,7 +391,7 @@ SUBSYSTEM_DEF(ticker)
if(player.mind.assigned_role != player.mind.special_role)
SSjob.EquipRank(N, player.mind.assigned_role, 0)
if(CONFIG_GET(flag/roundstart_traits))
SStraits.AssignTraits(player, N.client, TRUE)
SSquirks.AssignQuirks(player, N.client, TRUE)
CHECK_TICK
if(captainless)
for(var/mob/dead/new_player/N in GLOB.player_list)
+1 -1
View File
@@ -160,7 +160,7 @@
to_chat(owner, "<span class='warning'>You feel really lonely...</span>")
else
to_chat(owner, "<span class='warning'>You're going mad with loneliness!</span>")
owner.hallucination += 20
owner.hallucination += 30
if(5)
if(!high_stress)
+78
View File
@@ -0,0 +1,78 @@
/datum/component/armor_plate
var/amount = 0
var/maxamount = 3
var/upgrade_item = /obj/item/stack/sheet/animalhide/goliath_hide
var/datum/armor/added_armor = list("melee" = 10)
var/upgrade_name
/datum/component/armor_plate/Initialize(_maxamount,obj/item/_upgrade_item,datum/armor/_added_armor)
if(!isobj(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(COMSIG_PARENT_EXAMINE, .proc/examine)
RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/applyplate)
RegisterSignal(COMSIG_PARENT_PREQDELETED, .proc/dropplates)
if(_maxamount)
maxamount = _maxamount
if(_upgrade_item)
upgrade_item = _upgrade_item
if(_added_armor)
if(islist(_added_armor))
added_armor = getArmor(arglist(_added_armor))
else if (istype(_added_armor, /datum/armor))
added_armor = _added_armor
else
stack_trace("Invalid type [_added_armor.type] passed as _armor_item argument to armorplate component")
else
added_armor = getArmor(arglist(added_armor))
var/obj/item/typecast = upgrade_item
upgrade_name = initial(typecast.name)
/datum/component/armor_plate/proc/examine(mob/user)
//upgrade_item could also be typecast here instead
if(ismecha(parent))
if(amount)
if(amount < maxamount)
to_chat(user, "<span class='notice'>Its armor is enhanced with [amount] [upgrade_name].</span>")
else
to_chat(user, "<span class='notice'>It's wearing a fearsome carapace entirely composed of [upgrade_name] - its pilot must be an experienced monster hunter.</span>")
else
to_chat(user, "<span class='notice'>It has attachment points for strapping monster hide on for added protection.</span>")
else
if(amount)
to_chat(user, "<span class='notice'>It has been strengthened with [amount]/[maxamount] [upgrade_name].</span>")
else
to_chat(user, "<span class='notice'>It can be strengthened with up to [maxamount] [upgrade_name].</span>")
/datum/component/armor_plate/proc/applyplate(obj/item/I, mob/user, params)
if(!istype(I,upgrade_item))
return
if(amount >= maxamount)
to_chat(user, "<span class='warning'>You can't improve [parent] any further!</span>")
return
if(istype(I,/obj/item/stack))
I.use(1)
else
if(length(I.contents))
to_chat(user, "<span class='warning'>[I] cannot be used for armoring while there's something inside!</span>")
return
qdel(I)
var/obj/O = parent
amount++
O.armor = O.armor.attachArmor(added_armor)
if(ismecha(O))
var/obj/mecha/R = O
R.update_icon()
to_chat(user, "<span class='info'>You strengthen [R], improving its resistance against melee, bullet and laser damage.</span>")
else
to_chat(user, "<span class='info'>You strengthen [O], improving its resistance against melee attacks.</span>")
/datum/component/armor_plate/proc/dropplates(force)
if(ismecha(parent)) //items didn't drop the plates before and it causes erroneous behavior for the time being with collapsible helmets
for(var/i in 1 to amount)
new upgrade_item(get_turf(parent))
+6 -1
View File
@@ -1,8 +1,13 @@
/datum/component/redirect
dupe_mode = COMPONENT_DUPE_ALLOWED
/datum/component/redirect/Initialize(list/signals, datum/callback/_callback)
/datum/component/redirect/Initialize(list/signals, datum/callback/_callback, flags=NONE)
//It's not our job to verify the right signals are registered here, just do it.
if(!LAZYLEN(signals) || !istype(_callback))
return COMPONENT_INCOMPATIBLE
if(flags & REDIRECT_TRANSFER_WITH_TURF && isturf(parent))
RegisterSignal(COMSIG_TURF_CHANGE, .proc/turf_change)
RegisterSignal(signals, _callback)
/datum/component/redirect/proc/turf_change(path, new_baseturfs, flags, list/transfers)
transfers += src
+1 -7
View File
@@ -28,13 +28,7 @@
CRASH("Unable to find a blobstart landmark")
var/atom/movable/AM = parent
if(ismob(AM.loc))
var/mob/M = AM.loc
M.transferItemToLoc(AM, targetturf, TRUE) //nodrops disks when?
else if(AM.loc.SendSignal(COMSIG_CONTAINS_STORAGE))
AM.loc.SendSignal(COMSIG_TRY_STORAGE_TAKE, src, targetturf, TRUE)
else
AM.forceMove(targetturf)
AM.forceMove(targetturf)
// move the disc, so ghosts remain orbiting it even if it's "destroyed"
return targetturf
@@ -73,6 +73,8 @@
slave.refresh_mob_views()
/datum/component/storage/concrete/emp_act(severity)
if(emp_shielded)
return
var/atom/real_location = real_location()
for(var/i in real_location)
var/atom/A = i
+21 -15
View File
@@ -87,7 +87,8 @@
RegisterSignal(COMSIG_ATOM_ATTACK_PAW, .proc/on_attack_hand)
RegisterSignal(COMSIG_ATOM_EMP_ACT, .proc/emp_act)
RegisterSignal(COMSIG_ATOM_ATTACK_GHOST, .proc/show_to_ghost)
RegisterSignal(COMSIG_ATOM_EXITED, .proc/_removal_reset)
RegisterSignal(COMSIG_ATOM_ENTERED, .proc/refresh_mob_views)
RegisterSignal(COMSIG_ATOM_EXITED, .proc/_remove_and_refresh)
RegisterSignal(COMSIG_ITEM_PRE_ATTACK, .proc/preattack_intercept)
RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/attack_self)
@@ -369,10 +370,10 @@
. = TRUE //returns TRUE if any mobs actually got a close(M) call
/datum/component/storage/proc/emp_act(severity)
var/atom/A = parent
if(!isliving(A.loc) && !emp_shielded)
var/datum/component/storage/concrete/master = master()
master.emp_act(severity)
if(emp_shielded)
return
var/datum/component/storage/concrete/master = master()
master.emp_act(severity)
//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right.
//The numbers are calculated from the bottom-left The bottom-left slot being 1,1.
@@ -402,6 +403,10 @@
return FALSE
return master._removal_reset(thing)
/datum/component/storage/proc/_remove_and_refresh(atom/movable/thing)
_removal_reset(thing)
refresh_mob_views()
//Call this proc to handle the removal of an item from the storage item. The item will be moved to the new_location target, if that is null it's being deleted
/datum/component/storage/proc/remove_from_storage(atom/movable/AM, atom/new_location)
if(!istype(AM))
@@ -455,23 +460,24 @@
return FALSE
handle_item_insertion(I, FALSE, M)
/datum/component/storage/proc/return_inv()
. = list()
. += contents()
for(var/i in contents())
var/atom/a = i
GET_COMPONENT_FROM(STR, /datum/component/storage, a)
if(STR)
. += STR.return_inv()
/datum/component/storage/proc/return_inv(recursive)
var/list/ret = list()
ret |= contents()
if(recursive)
for(var/i in ret.Copy())
var/atom/A = i
A.SendSignal(COMSIG_TRY_STORAGE_RETURN_INVENTORY, ret, TRUE)
return ret
/datum/component/storage/proc/contents() //ONLY USE IF YOU NEED TO COPY CONTENTS OF REAL LOCATION, COPYING IS NOT AS FAST AS DIRECT ACCESS!
var/atom/real_location = real_location()
return real_location.contents.Copy()
/datum/component/storage/proc/signal_return_inv(list/interface)
//Abuses the fact that lists are just references, or something like that.
/datum/component/storage/proc/signal_return_inv(list/interface, recursive = TRUE)
if(!islist(interface))
return FALSE
interface |= return_inv()
interface |= return_inv(recursive)
return TRUE
/datum/component/storage/proc/mousedrop_onto(atom/over_object, mob/M)
+3
View File
@@ -1,3 +1,6 @@
/datum/proc/CanProcCall(procname)
return TRUE
/datum/proc/can_vv_get(var_name)
return TRUE
@@ -55,7 +55,7 @@ Bonus
switch(A.stage)
if(1, 2, 3, 4)
if(prob(base_message_chance) && !suppress_warning)
to_chat(M, "<span class='warning'>[pick("You feel nauseous.", "You feel like you're going to throw up!")]</span>")
to_chat(M, "<span class='warning'>[pick("You feel nauseated.", "You feel like you're going to throw up!")]</span>")
else
vomit(M)
+1 -1
View File
@@ -34,7 +34,7 @@
to_chat(H, "<span class='warning'>You feel dizzy.</span>")
H.confused += 6
if(prob(3))
to_chat(H, "<span class='warning'>You feel [pick("full", "nauseous", "sweaty", "weak", "tired", "short on breath", "uneasy")].</span>")
to_chat(H, "<span class='warning'>You feel [pick("full", "nauseated", "sweaty", "weak", "tired", "short on breath", "uneasy")].</span>")
if(3 to 4)
if(!sound)
H.playsound_local(H, 'sound/health/slowbeat.ogg',40,0, channel = CHANNEL_HEARTBEAT)
-1
View File
@@ -9,7 +9,6 @@
viable_mobtypes = list(/mob/living/carbon/human)
permeability_mod = 1
severity = DISEASE_SEVERITY_BIOHAZARD
process_dead = TRUE
/datum/disease/rhumba_beat/stage_act()
..()
+9 -8
View File
@@ -5,7 +5,7 @@
var/date
/datum/getrev/New()
testmerge = SERVER_TOOLS_PR_LIST
testmerge = world.TgsTestMerges()
log_world("Running /tg/ revision:")
var/list/logs = world.file2list(".git/logs/HEAD")
if(logs)
@@ -21,7 +21,8 @@
log_world(commit)
for(var/line in testmerge)
if(line)
var/tmcommit = testmerge[line]["commit"]
var/datum/tgs_revision_information/test_merge/tm = line
var/tmcommit = tm.commit
log_world("Test merge active of PR #[line] commit [tmcommit]")
SSblackbox.record_feedback("nested tally", "testmerged_prs", 1, list("[line]", "[tmcommit]"))
if(originmastercommit)
@@ -34,11 +35,12 @@
return ""
. = header ? "The following pull requests are currently test merged:<br>" : ""
for(var/line in testmerge)
var/cm = testmerge[line]["commit"]
var/details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["author"]) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 11)))
var/datum/tgs_revision_information/test_merge/tm = line
var/cm = tm.pull_request_commit
var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 11)))
if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder))
continue
. += "<a href=\"[CONFIG_GET(string/githuburl)]/pull/[line]\">#[line][details]</a><br>"
. += "<a href=\"[CONFIG_GET(string/githuburl)]/pull/[tm.number]\">#[tm.number][details]</a><br>"
/client/verb/showrevinfo()
set category = "OOC"
@@ -58,9 +60,8 @@
else
to_chat(src, "Master revision unknown")
to_chat(src, "Revision: [GLOB.revdata.commit]")
if(SERVER_TOOLS_PRESENT)
to_chat(src, "Server tools version: [SERVER_TOOLS_VERSION]")
to_chat(src, "Server tools API version: [SERVER_TOOLS_API_VERSION]")
if(world.TgsAvailable())
to_chat(src, "Server tools version: [world.TgsVersion()]")
to_chat(src, "<b>Current Informational Settings:</b>")
to_chat(src, "Protect Authority Roles From Traitor: [CONFIG_GET(flag/protect_roles_from_antagonist)]")
to_chat(src, "Protect Assistant Role From Traitor: [CONFIG_GET(flag/protect_assistant_from_antagonist)]")
+3
View File
@@ -29,6 +29,9 @@
/datum/radiation_wave/process()
master_turf = get_step(master_turf, move_dir)
if(!master_turf)
qdel(src)
return
steps++
var/list/atoms = get_rad_atoms()
@@ -1,94 +1,94 @@
//every trait in this folder should be coded around being applied on spawn
//these are NOT "mob traits" like GOTTAGOFAST, but exist as a medium to apply them and other different effects
/datum/trait
var/name = "Test Trait"
var/desc = "This is a test trait."
//every quirk in this folder should be coded around being applied on spawn
//these are NOT "mob quirks" like GOTTAGOFAST, but exist as a medium to apply them and other different effects
/datum/quirk
var/name = "Test Quirk"
var/desc = "This is a test quirk."
var/value = 0
var/human_only = TRUE
var/gain_text
var/lose_text
var/medical_record_text //This text will appear on medical records for the trait. Not yet implemented
var/mood_trait = FALSE //if true, this trait affects mood and is unavailable if moodlets are disabled
var/mood_quirk = FALSE //if true, this quirk affects mood and is unavailable if moodlets are disabled
var/mob_trait //if applicable, apply and remove this mob trait
var/mob/living/trait_holder
var/mob/living/quirk_holder
/datum/trait/New(mob/living/trait_mob, spawn_effects)
/datum/quirk/New(mob/living/quirk_mob, spawn_effects)
..()
if(!trait_mob || (human_only && !ishuman(trait_mob)) || trait_mob.has_trait_datum(type))
if(!quirk_mob || (human_only && !ishuman(quirk_mob)) || quirk_mob.has_quirk(type))
qdel(src)
trait_holder = trait_mob
SStraits.trait_objects += src
to_chat(trait_holder, gain_text)
trait_holder.roundstart_traits += src
quirk_holder = quirk_mob
SSquirks.quirk_objects += src
to_chat(quirk_holder, gain_text)
quirk_holder.roundstart_quirks += src
if(mob_trait)
trait_holder.add_trait(mob_trait, ROUNDSTART_TRAIT)
START_PROCESSING(SStraits, src)
quirk_holder.add_trait(mob_trait, ROUNDSTART_TRAIT)
START_PROCESSING(SSquirks, src)
add()
if(spawn_effects)
on_spawn()
addtimer(CALLBACK(src, .proc/post_add), 30)
/datum/trait/Destroy()
STOP_PROCESSING(SStraits, src)
/datum/quirk/Destroy()
STOP_PROCESSING(SSquirks, src)
remove()
if(trait_holder)
to_chat(trait_holder, lose_text)
trait_holder.roundstart_traits -= src
if(quirk_holder)
to_chat(quirk_holder, lose_text)
quirk_holder.roundstart_quirks -= src
if(mob_trait)
trait_holder.remove_trait(mob_trait, ROUNDSTART_TRAIT, TRUE)
SStraits.trait_objects -= src
quirk_holder.remove_trait(mob_trait, ROUNDSTART_TRAIT, TRUE)
SSquirks.quirk_objects -= src
return ..()
/datum/trait/proc/transfer_mob(mob/living/to_mob)
trait_holder.roundstart_traits -= src
to_mob.roundstart_traits += src
/datum/quirk/proc/transfer_mob(mob/living/to_mob)
quirk_holder.roundstart_quirks -= src
to_mob.roundstart_quirks += src
if(mob_trait)
trait_holder.remove_trait(mob_trait, ROUNDSTART_TRAIT)
quirk_holder.remove_trait(mob_trait, ROUNDSTART_TRAIT)
to_mob.add_trait(mob_trait, ROUNDSTART_TRAIT)
trait_holder = to_mob
quirk_holder = to_mob
on_transfer()
/datum/trait/proc/add() //special "on add" effects
/datum/trait/proc/on_spawn() //these should only trigger when the character is being created for the first time, i.e. roundstart/latejoin
/datum/trait/proc/remove() //special "on remove" effects
/datum/trait/proc/on_process() //process() has some special checks, so this is the actual process
/datum/trait/proc/post_add() //for text, disclaimers etc. given after you spawn in with the trait
/datum/trait/proc/on_transfer() //code called when the trait is transferred to a new mob
/datum/quirk/proc/add() //special "on add" effects
/datum/quirk/proc/on_spawn() //these should only trigger when the character is being created for the first time, i.e. roundstart/latejoin
/datum/quirk/proc/remove() //special "on remove" effects
/datum/quirk/proc/on_process() //process() has some special checks, so this is the actual process
/datum/quirk/proc/post_add() //for text, disclaimers etc. given after you spawn in with the trait
/datum/quirk/proc/on_transfer() //code called when the trait is transferred to a new mob
/datum/trait/process()
if(QDELETED(trait_holder))
trait_holder = null
/datum/quirk/process()
if(QDELETED(quirk_holder))
quirk_holder = null
qdel(src)
return
if(trait_holder.stat == DEAD)
if(quirk_holder.stat == DEAD)
return
on_process()
/mob/living/proc/get_trait_string(medical) //helper string. gets a string of all the traits the mob has
var/list/dat = list()
if(!medical)
for(var/V in roundstart_traits)
var/datum/trait/T = V
for(var/V in roundstart_quirks)
var/datum/quirk/T = V
dat += T.name
if(!dat.len)
return "None"
return dat.Join(", ")
else
for(var/V in roundstart_traits)
var/datum/trait/T = V
for(var/V in roundstart_quirks)
var/datum/quirk/T = V
dat += T.medical_record_text
if(!dat.len)
return "None"
return dat.Join("<br>")
/mob/living/proc/cleanse_trait_datums() //removes all trait datums
for(var/V in roundstart_traits)
var/datum/trait/T = V
for(var/V in roundstart_quirks)
var/datum/quirk/T = V
qdel(T)
/mob/living/proc/transfer_trait_datums(mob/living/to_mob)
for(var/V in roundstart_traits)
var/datum/trait/T = V
for(var/V in roundstart_quirks)
var/datum/quirk/T = V
T.transfer_mob(to_mob)
/*
@@ -96,7 +96,7 @@
Commented version of Nearsighted to help you add your own traits
Use this as a guideline
/datum/trait/nearsighted
/datum/quirk/nearsighted
name = "Nearsighted"
///The trait's name
@@ -116,8 +116,8 @@ Use this as a guideline
medical_record_text = "Subject has permanent nearsightedness."
///These three are self-explanatory
/datum/trait/nearsighted/on_spawn()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/nearsighted/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/clothing/glasses/regular/glasses = new(get_turf(H))
H.put_in_hands(glasses)
H.equip_to_slot(glasses, slot_glasses)
+18 -18
View File
@@ -1,7 +1,7 @@
//predominantly positive traits
//this file is named weirdly so that positive traits are listed above negative ones
/datum/trait/alcohol_tolerance
/datum/quirk/alcohol_tolerance
name = "Alcohol Tolerance"
desc = "You become drunk more slowly and suffer fewer drawbacks from alcohol."
value = 1
@@ -11,25 +11,25 @@
/datum/trait/apathetic
/datum/quirk/apathetic
name = "Apathetic"
desc = "You just don't care as much as other people. That's nice to have in a place like this, I guess."
value = 1
mood_trait = TRUE
mood_quirk = TRUE
/datum/trait/apathetic/add()
GET_COMPONENT_FROM(mood, /datum/component/mood, trait_holder)
/datum/quirk/apathetic/add()
GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder)
if(mood)
mood.mood_modifier = 0.8
/datum/trait/apathetic/remove()
GET_COMPONENT_FROM(mood, /datum/component/mood, trait_holder)
/datum/quirk/apathetic/remove()
GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder)
if(mood)
mood.mood_modifier = 1 //Change this once/if species get their own mood modifiers.
/datum/trait/freerunning
/datum/quirk/freerunning
name = "Freerunning"
desc = "You're great at quick moves! You can climb tables more quickly."
value = 2
@@ -39,16 +39,16 @@
/datum/trait/jolly
/datum/quirk/jolly
name = "Jolly"
desc = "You sometimes just feel happy, for no reason at all."
value = 1
mob_trait = TRAIT_JOLLY
mood_trait = TRUE
mood_quirk = TRUE
/datum/trait/light_step
/datum/quirk/light_step
name = "Light Step"
desc = "You walk with a gentle step, making stepping on sharp objects quieter and less painful."
value = 1
@@ -58,7 +58,7 @@
/datum/trait/night_vision
/datum/quirk/night_vision
name = "Night Vision"
desc = "You can see slightly more clearly in full darkness than most people."
value = 1
@@ -66,8 +66,8 @@
gain_text = "<span class='notice'>The shadows seem a little less dark.</span>"
lose_text = "<span class='danger'>Everything seems a little darker.</span>"
/datum/trait/night_vision/on_spawn()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/night_vision/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/organ/eyes/eyes = H.getorgan(/obj/item/organ/eyes)
if(!eyes || eyes.lighting_alpha)
return
@@ -75,7 +75,7 @@
/datum/trait/selfaware
/datum/quirk/selfaware
name = "Self-Aware"
desc = "You know your body well, and can accurately assess the extent of your wounds."
value = 2
@@ -83,7 +83,7 @@
/datum/trait/skittish
/datum/quirk/skittish
name = "Skittish"
desc = "You can conceal yourself in danger. Ctrl-shift-click a closed locker to jump into it, as long as you have access."
value = 2
@@ -91,7 +91,7 @@
/datum/trait/spiritual
/datum/quirk/spiritual
name = "Spiritual"
desc = "You're in tune with the gods, and your prayers may be more likely to be heard. Or not."
value = 1
@@ -101,7 +101,7 @@
/datum/trait/voracious
/datum/quirk/voracious
name = "Voracious"
desc = "Nothing gets between you and your food. You eat twice as fast as everyone else!"
value = 1
+69 -76
View File
@@ -1,6 +1,6 @@
//predominantly negative traits
/datum/trait/blooddeficiency
/datum/quirk/blooddeficiency
name = "Acute Blood Deficiency"
desc = "Your body can't produce enough blood to sustain itself."
value = -2
@@ -8,12 +8,12 @@
lose_text = "<span class='notice'>You feel vigorous again.</span>"
medical_record_text = "Patient requires regular treatment for blood loss due to low production of blood."
/datum/trait/blooddeficiency/on_process()
trait_holder.blood_volume -= 0.275
/datum/quirk/blooddeficiency/on_process()
quirk_holder.blood_volume -= 0.275
/datum/trait/depression
/datum/quirk/depression
name = "Depression"
desc = "You sometimes just hate life."
mob_trait = TRAIT_DEPRESSION
@@ -21,22 +21,22 @@
gain_text = "<span class='danger'>You start feeling depressed.</span>"
lose_text = "<span class='notice'>You no longer feel depressed.</span>" //if only it were that easy!
medical_record_text = "Patient has a severe mood disorder causing them to experience sudden moments of sadness."
mood_trait = TRUE
mood_quirk = TRUE
/datum/trait/family_heirloom
/datum/quirk/family_heirloom
name = "Family Heirloom"
desc = "You are the current owner of an heirloom. passed down for generations. You have to keep it safe!"
value = -1
mood_trait = TRUE
mood_quirk = TRUE
var/obj/item/heirloom
var/where_text
/datum/trait/family_heirloom/on_spawn()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/family_heirloom/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/heirloom_type
switch(trait_holder.mind.assigned_role)
switch(quirk_holder.mind.assigned_role)
if("Clown")
heirloom_type = /obj/item/bikehorn/golden
if("Mime")
@@ -56,7 +56,7 @@
/obj/item/toy/cards/deck,
/obj/item/lighter,
/obj/item/dice/d20)
heirloom = new heirloom_type(get_turf(trait_holder))
heirloom = new heirloom_type(get_turf(quirk_holder))
var/list/slots = list(
"in your backpack" = slot_in_backpack,
"in your left pocket" = slot_l_store,
@@ -65,26 +65,26 @@
var/where = H.equip_in_one_of_slots(heirloom, slots)
if(!where)
where = "at your feet"
if(where == "in your backpack")
H.back.SendSignal(COMSIG_TRY_STORAGE_SHOW, H)
else if(where == "in your backpack")
H.back.SendSignal(COMSIG_TRY_STORAGE_SHOW, H)
where_text = "<span class='boldnotice'>There is a precious family [heirloom.name] [where], passed down from generation to generation. Keep it safe!</span>"
/datum/trait/family_heirloom/post_add()
to_chat(trait_holder, where_text)
var/list/family_name = splittext(trait_holder.real_name, " ")
/datum/quirk/family_heirloom/post_add()
to_chat(quirk_holder, where_text)
var/list/family_name = splittext(quirk_holder.real_name, " ")
heirloom.name = "\improper [family_name[family_name.len]] family [heirloom.name]"
/datum/trait/family_heirloom/on_process()
if(heirloom in trait_holder.GetAllContents())
trait_holder.SendSignal(COMSIG_CLEAR_MOOD_EVENT, "family_heirloom_missing")
trait_holder.SendSignal(COMSIG_ADD_MOOD_EVENT, "family_heirloom", /datum/mood_event/family_heirloom)
/datum/quirk/family_heirloom/on_process()
if(heirloom in quirk_holder.GetAllContents())
quirk_holder.SendSignal(COMSIG_CLEAR_MOOD_EVENT, "family_heirloom_missing")
quirk_holder.SendSignal(COMSIG_ADD_MOOD_EVENT, "family_heirloom", /datum/mood_event/family_heirloom)
else
trait_holder.SendSignal(COMSIG_CLEAR_MOOD_EVENT, "family_heirloom")
trait_holder.SendSignal(COMSIG_ADD_MOOD_EVENT, "family_heirloom_missing", /datum/mood_event/family_heirloom_missing)
quirk_holder.SendSignal(COMSIG_CLEAR_MOOD_EVENT, "family_heirloom")
quirk_holder.SendSignal(COMSIG_ADD_MOOD_EVENT, "family_heirloom_missing", /datum/mood_event/family_heirloom_missing)
/datum/trait/heavy_sleeper
/datum/quirk/heavy_sleeper
name = "Heavy Sleeper"
desc = "You sleep like a rock! Whenever you're put to sleep, you sleep for a little bit longer."
value = -1
@@ -93,7 +93,7 @@
lose_text = "<span class='notice'>You feel awake again.</span>"
medical_record_text = "Patient has abnormal sleep study results and is difficult to wake up."
/datum/trait/brainproblems
/datum/quirk/brainproblems
name = "Brain Tumor"
desc = "You have a little friend in your brain that is slowly destroying it. Better bring some mannitol!"
value = -3
@@ -101,12 +101,12 @@
lose_text = "<span class='notice'>You feel wrinkled again.</span>"
medical_record_text = "Patient has a tumor in their brain that is slowly driving them to brain death."
/datum/trait/brainproblems/on_process()
trait_holder.adjustBrainLoss(0.2)
/datum/quirk/brainproblems/on_process()
quirk_holder.adjustBrainLoss(0.2)
/datum/trait/nearsighted //t. errorage
/datum/quirk/nearsighted //t. errorage
name = "Nearsighted"
desc = "You are nearsighted without prescription glasses, but spawn with a pair."
value = -1
@@ -114,11 +114,11 @@
lose_text = "<span class='notice'>You start seeing faraway things normally again.</span>"
medical_record_text = "Patient requires prescription glasses in order to counteract nearsightedness."
/datum/trait/nearsighted/add()
trait_holder.become_nearsighted(ROUNDSTART_TRAIT)
/datum/quirk/nearsighted/add()
quirk_holder.become_nearsighted(ROUNDSTART_TRAIT)
/datum/trait/nearsighted/on_spawn()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/nearsighted/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/clothing/glasses/regular/glasses = new(get_turf(H))
H.put_in_hands(glasses)
H.equip_to_slot(glasses, slot_glasses)
@@ -126,28 +126,28 @@
/datum/trait/nyctophobia
/datum/quirk/nyctophobia
name = "Nyctophobia"
desc = "As far as you can remember, you've always been afraid of the dark. While in the dark without a light source, you instinctually act careful, and constantly feel a sense of dread."
value = -1
/datum/trait/nyctophobia/on_process()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/nyctophobia/on_process()
var/mob/living/carbon/human/H = quirk_holder
if(H.dna.species.id in list("shadow", "nightmare"))
return //we're tied with the dark, so we don't get scared of it; don't cleanse outright to avoid cheese
var/turf/T = get_turf(trait_holder)
var/turf/T = get_turf(quirk_holder)
var/lums = T.get_lumcount()
if(lums <= 0.2)
if(trait_holder.m_intent == MOVE_INTENT_RUN)
to_chat(trait_holder, "<span class='warning'>Easy, easy, take it slow... you're in the dark...</span>")
trait_holder.toggle_move_intent()
trait_holder.SendSignal(COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
if(quirk_holder.m_intent == MOVE_INTENT_RUN)
to_chat(quirk_holder, "<span class='warning'>Easy, easy, take it slow... you're in the dark...</span>")
quirk_holder.toggle_move_intent()
quirk_holder.SendSignal(COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
else
trait_holder.SendSignal(COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
quirk_holder.SendSignal(COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
/datum/trait/nonviolent
/datum/quirk/nonviolent
name = "Pacifist"
desc = "The thought of violence makes you sick. So much so, in fact, that you can't hurt anyone."
value = -2
@@ -156,14 +156,14 @@
lose_text = "<span class='notice'>You think you can defend yourself again.</span>"
medical_record_text = "Patient is unusually pacifistic and cannot bring themselves to cause physical harm."
/datum/trait/nonviolent/on_process()
if(trait_holder.mind && LAZYLEN(trait_holder.mind.antag_datums))
to_chat(trait_holder, "<span class='boldannounce'>Your antagonistic nature has caused you to renounce your pacifism.</span>")
/datum/quirk/nonviolent/on_process()
if(quirk_holder.mind && LAZYLEN(quirk_holder.mind.antag_datums))
to_chat(quirk_holder, "<span class='boldannounce'>Your antagonistic nature has caused you to renounce your pacifism.</span>")
qdel(src)
/datum/trait/poor_aim
/datum/quirk/poor_aim
name = "Poor Aim"
desc = "You're terrible with guns and can't line up a straight shot to save your life. Dual-wielding is right out."
value = -1
@@ -172,7 +172,7 @@
/datum/trait/prosopagnosia
/datum/quirk/prosopagnosia
name = "Prosopagnosia"
desc = "You have a mental disorder that prevents you from being able to recognize faces at all."
value = -1
@@ -181,41 +181,41 @@
/datum/trait/prosthetic_limb
/datum/quirk/prosthetic_limb
name = "Prosthetic Limb"
desc = "An accident caused you to lose one of your limbs. Because of this, you now have a random prosthetic!"
value = -1
var/slot_string = "limb"
/datum/trait/prosthetic_limb/on_spawn()
/datum/quirk/prosthetic_limb/on_spawn()
var/limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/mob/living/carbon/human/H = trait_holder
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/bodypart/old_part = H.get_bodypart(limb_slot)
var/obj/item/bodypart/prosthetic
switch(limb_slot)
if(BODY_ZONE_L_ARM)
prosthetic = new/obj/item/bodypart/l_arm/robot/surplus(trait_holder)
prosthetic = new/obj/item/bodypart/l_arm/robot/surplus(quirk_holder)
slot_string = "left arm"
if(BODY_ZONE_R_ARM)
prosthetic = new/obj/item/bodypart/r_arm/robot/surplus(trait_holder)
prosthetic = new/obj/item/bodypart/r_arm/robot/surplus(quirk_holder)
slot_string = "right arm"
if(BODY_ZONE_L_LEG)
prosthetic = new/obj/item/bodypart/l_leg/robot/surplus(trait_holder)
prosthetic = new/obj/item/bodypart/l_leg/robot/surplus(quirk_holder)
slot_string = "left leg"
if(BODY_ZONE_R_LEG)
prosthetic = new/obj/item/bodypart/r_leg/robot/surplus(trait_holder)
prosthetic = new/obj/item/bodypart/r_leg/robot/surplus(quirk_holder)
slot_string = "right leg"
prosthetic.replace_limb(H)
qdel(old_part)
H.regenerate_icons()
/datum/trait/prosthetic_limb/post_add()
to_chat(trait_holder, "<span class='boldannounce'>Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \
/datum/quirk/prosthetic_limb/post_add()
to_chat(quirk_holder, "<span class='boldannounce'>Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \
you need to use a welding tool and cables to repair it, instead of bruise packs and ointment.</span>")
/datum/trait/insanity
/datum/quirk/insanity
name = "Reality Dissociation Syndrome"
desc = "You suffer from a severe disorder that causes very vivid hallucinations. Mindbreaker toxin can suppress its effects, and you are immune to mindbreaker's hallucinogenic properties. <b>This is not a license to grief.</b>"
value = -2
@@ -224,32 +224,25 @@
lose_text = "<span class='notice'>You feel in tune with the world again.</span>"
medical_record_text = "Patient suffers from acute Reality Dissociation Syndrome and experiences vivid hallucinations."
/datum/trait/insanity/on_process()
if(trait_holder.reagents.has_reagent("mindbreaker"))
trait_holder.hallucination = 0
/datum/quirk/insanity/on_process()
if(quirk_holder.reagents.has_reagent("mindbreaker"))
quirk_holder.hallucination = 0
return
if(prob(2)) //we'll all be mad soon enough
madness()
/datum/quirk/insanity/proc/madness()
quirk_holder.hallucination += rand(10, 25)
/datum/trait/insanity/proc/madness(mad_fools)
set waitfor = FALSE
if(!mad_fools)
mad_fools = prob(20)
if(mad_fools)
var/hallucination_type = pick(subtypesof(/datum/hallucination/rds))
new hallucination_type (trait_holder, FALSE)
else
trait_holder.hallucination += rand(10, 50)
/datum/trait/insanity/post_add() //I don't /think/ we'll need this but for newbies who think "roleplay as insane" = "license to kill" it's probably a good thing to have
if(!trait_holder.mind || trait_holder.mind.special_role)
/datum/quirk/insanity/post_add() //I don't /think/ we'll need this but for newbies who think "roleplay as insane" = "license to kill" it's probably a good thing to have
if(!quirk_holder.mind || quirk_holder.mind.special_role)
return
to_chat(trait_holder, "<span class='big bold info'>Please note that your dissociation syndrome does NOT give you the right to attack people or otherwise cause any interference to \
to_chat(quirk_holder, "<span class='big bold info'>Please note that your dissociation syndrome does NOT give you the right to attack people or otherwise cause any interference to \
the round. You are not an antagonist, and the rules will treat you the same as other crewmembers.</span>")
/datum/trait/social_anxiety
/datum/quirk/social_anxiety
name = "Social Anxiety"
desc = "Talking to people is very difficult for you, and you often stutter or even lock up."
value = -1
@@ -258,12 +251,12 @@
medical_record_text = "Patient is usually anxious in social encounters and prefers to avoid them."
var/dumb_thing = TRUE
/datum/trait/social_anxiety/on_process()
/datum/quirk/social_anxiety/on_process()
var/nearby_people = 0
for(var/mob/living/carbon/human/H in view(5, trait_holder))
for(var/mob/living/carbon/human/H in view(5, quirk_holder))
if(H.client)
nearby_people++
var/mob/living/carbon/human/H = trait_holder
var/mob/living/carbon/human/H = quirk_holder
if(prob(2 + nearby_people))
H.stuttering = max(3, H.stuttering)
else if(prob(min(3, nearby_people)) && !H.silent)
+25 -25
View File
@@ -1,7 +1,7 @@
//traits with no real impact that can be taken freely
//MAKE SURE THESE DO NOT MAJORLY IMPACT GAMEPLAY. those should be positive or negative traits.
/datum/trait/no_taste
/datum/quirk/no_taste
name = "Ageusia"
desc = "You can't taste anything! Toxic food will still poison you."
value = 0
@@ -12,75 +12,75 @@
/datum/trait/pineapple_liker
/datum/quirk/pineapple_liker
name = "Ananas Affinity"
desc = "You find yourself greatly enjoying fruits of the ananas genus. You can't seem to ever get enough of their sweet goodness!"
value = 0
gain_text = "<span class='notice'>You feel an intense craving for pineapple.</span>"
lose_text = "<span class='notice'>Your feelings towards pineapples seem to return to a lukewarm state.</span>"
/datum/trait/pineapple_liker/add()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/pineapple_liker/add()
var/mob/living/carbon/human/H = quirk_holder
var/datum/species/species = H.dna.species
species.liked_food |= PINEAPPLE
/datum/trait/pineapple_liker/remove()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/pineapple_liker/remove()
var/mob/living/carbon/human/H = quirk_holder
var/datum/species/species = H.dna.species
species.liked_food &= ~PINEAPPLE
/datum/trait/pineapple_hater
/datum/quirk/pineapple_hater
name = "Ananas Aversion"
desc = "You find yourself greatly detesting fruits of the ananas genus. Serious, how the hell can anyone say these things are good? And what kind of madman would even dare putting it on a pizza!?"
value = 0
gain_text = "<span class='notice'>You find yourself pondering what kind of idiot actually enjoys pineapples...</span>"
lose_text = "<span class='notice'>Your feelings towards pineapples seem to return to a lukewarm state.</span>"
/datum/trait/pineapple_hater/add()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/pineapple_hater/add()
var/mob/living/carbon/human/H = quirk_holder
var/datum/species/species = H.dna.species
species.disliked_food |= PINEAPPLE
/datum/trait/pineapple_hater/remove()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/pineapple_hater/remove()
var/mob/living/carbon/human/H = quirk_holder
var/datum/species/species = H.dna.species
species.disliked_food &= ~PINEAPPLE
/datum/trait/deviant_tastes
/datum/quirk/deviant_tastes
name = "Deviant Tastes"
desc = "You dislike food that most people enjoy, and find delicious what they don't."
value = 0
gain_text = "<span class='notice'>You start craving something that tastes strange.</span>"
lose_text = "<span class='notice'>You feel like eating normal food again.</span>"
/datum/trait/deviant_tastes/add()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/deviant_tastes/add()
var/mob/living/carbon/human/H = quirk_holder
var/datum/species/species = H.dna.species
var/liked = species.liked_food
species.liked_food = species.disliked_food
species.disliked_food = liked
/datum/trait/deviant_tastes/remove()
var/mob/living/carbon/human/H = trait_holder
/datum/quirk/deviant_tastes/remove()
var/mob/living/carbon/human/H = quirk_holder
var/datum/species/species = H.dna.species
species.liked_food = initial(species.liked_food)
species.disliked_food = initial(species.disliked_food)
/datum/trait/monochromatic
/datum/quirk/monochromatic
name = "Monochromacy"
desc = "You suffer from full colorblindness, and perceive nearly the entire world in blacks and whites."
value = 0
medical_record_text = "Patient is afflicted with almost complete color blindness."
/datum/trait/monochromatic/add()
trait_holder.add_client_colour(/datum/client_colour/monochrome)
/datum/quirk/monochromatic/add()
quirk_holder.add_client_colour(/datum/client_colour/monochrome)
/datum/trait/monochromatic/post_add()
if(trait_holder.mind.assigned_role == "Detective")
to_chat(trait_holder, "<span class='boldannounce'>Mmm. Nothing's ever clear on this station. It's all shades of gray...</span>")
trait_holder.playsound_local(trait_holder, 'sound/ambience/ambidet1.ogg', 50, FALSE)
/datum/quirk/monochromatic/post_add()
if(quirk_holder.mind.assigned_role == "Detective")
to_chat(quirk_holder, "<span class='boldannounce'>Mmm. Nothing's ever clear on this station. It's all shades of gray...</span>")
quirk_holder.playsound_local(quirk_holder, 'sound/ambience/ambidet1.ogg', 50, FALSE)
/datum/trait/monochromatic/remove()
trait_holder.remove_client_colour(/datum/client_colour/monochrome)
/datum/quirk/monochromatic/remove()
quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
+102 -102
View File
@@ -1,102 +1,102 @@
/datum/verbs
var/name
var/list/children
var/datum/verbs/parent
var/list/verblist
var/abstract = FALSE
//returns the master list for verbs of a type
/datum/verbs/proc/GetList()
CRASH("Abstract verblist for [type]")
//do things for each entry in Generate_list
//return value sets Generate_list[verbpath]
/datum/verbs/proc/HandleVerb(list/entry, atom/verb/verbpath, ...)
return entry
/datum/verbs/New()
var/mainlist = GetList()
var/ourentry = mainlist[type]
children = list()
verblist = list()
if (ourentry)
if (!islist(ourentry)) //some of our childern already loaded
qdel(src)
CRASH("Verb double load: [type]")
Add_children(ourentry)
mainlist[type] = src
Load_verbs(type, typesof("[type]/verb"))
var/datum/verbs/parent = mainlist[parent_type]
if (!parent)
mainlist[parent_type] = list(src)
else if (islist(parent))
parent += src
else
parent.Add_children(list(src))
/datum/verbs/proc/Set_parent(datum/verbs/_parent)
parent = _parent
if (abstract)
parent.Add_children(children)
var/list/verblistoftypes = list()
for(var/thing in verblist)
LAZYADD(verblistoftypes[verblist[thing]], thing)
for(var/verbparenttype in verblistoftypes)
parent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype])
/datum/verbs/proc/Add_children(list/kids)
if (abstract && parent)
parent.Add_children(kids)
return
for(var/thing in kids)
var/datum/verbs/item = thing
item.Set_parent(src)
if (!item.abstract)
children += item
/datum/verbs/proc/Load_verbs(verb_parent_type, list/verbs)
if (abstract && parent)
parent.Load_verbs(verb_parent_type, verbs)
return
for (var/verbpath in verbs)
verblist[verbpath] = verb_parent_type
/datum/verbs/proc/Generate_list(...)
. = list()
if (length(children))
for (var/thing in children)
var/datum/verbs/child = thing
var/list/childlist = child.Generate_list(arglist(args))
if (childlist)
var/childname = "[child]"
if (childname == "[child.type]")
var/list/tree = splittext(childname, "/")
childname = tree[tree.len]
.[child.type] = "parent=[url_encode(type)];name=[url_encode(childname)]"
. += childlist
for (var/thing in verblist)
var/atom/verb/verbpath = thing
if (!verbpath)
stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
var/list/entry = list()
entry["parent"] = "[type]"
entry["name"] = verbpath.desc
if (copytext(verbpath.name,1,2) == "@")
entry["command"] = copytext(verbpath.name,2)
else
entry["command"] = replacetext(verbpath.name, " ", "-")
.[verbpath] = HandleVerb(arglist(list(entry, verbpath) + args))
/world/proc/LoadVerbs(verb_type)
if(!ispath(verb_type, /datum/verbs) || verb_type == /datum/verbs)
CRASH("Invalid verb_type: [verb_type]")
for (var/typepath in subtypesof(verb_type))
new typepath()
/datum/verbs
var/name
var/list/children
var/datum/verbs/parent
var/list/verblist
var/abstract = FALSE
//returns the master list for verbs of a type
/datum/verbs/proc/GetList()
CRASH("Abstract verblist for [type]")
//do things for each entry in Generate_list
//return value sets Generate_list[verbpath]
/datum/verbs/proc/HandleVerb(list/entry, atom/verb/verbpath, ...)
return entry
/datum/verbs/New()
var/mainlist = GetList()
var/ourentry = mainlist[type]
children = list()
verblist = list()
if (ourentry)
if (!islist(ourentry)) //some of our childern already loaded
qdel(src)
CRASH("Verb double load: [type]")
Add_children(ourentry)
mainlist[type] = src
Load_verbs(type, typesof("[type]/verb"))
var/datum/verbs/parent = mainlist[parent_type]
if (!parent)
mainlist[parent_type] = list(src)
else if (islist(parent))
parent += src
else
parent.Add_children(list(src))
/datum/verbs/proc/Set_parent(datum/verbs/_parent)
parent = _parent
if (abstract)
parent.Add_children(children)
var/list/verblistoftypes = list()
for(var/thing in verblist)
LAZYADD(verblistoftypes[verblist[thing]], thing)
for(var/verbparenttype in verblistoftypes)
parent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype])
/datum/verbs/proc/Add_children(list/kids)
if (abstract && parent)
parent.Add_children(kids)
return
for(var/thing in kids)
var/datum/verbs/item = thing
item.Set_parent(src)
if (!item.abstract)
children += item
/datum/verbs/proc/Load_verbs(verb_parent_type, list/verbs)
if (abstract && parent)
parent.Load_verbs(verb_parent_type, verbs)
return
for (var/verbpath in verbs)
verblist[verbpath] = verb_parent_type
/datum/verbs/proc/Generate_list(...)
. = list()
if (length(children))
for (var/thing in children)
var/datum/verbs/child = thing
var/list/childlist = child.Generate_list(arglist(args))
if (childlist)
var/childname = "[child]"
if (childname == "[child.type]")
var/list/tree = splittext(childname, "/")
childname = tree[tree.len]
.[child.type] = "parent=[url_encode(type)];name=[childname]"
. += childlist
for (var/thing in verblist)
var/atom/verb/verbpath = thing
if (!verbpath)
stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
var/list/entry = list()
entry["parent"] = "[type]"
entry["name"] = verbpath.desc
if (copytext(verbpath.name,1,2) == "@")
entry["command"] = copytext(verbpath.name,2)
else
entry["command"] = replacetext(verbpath.name, " ", "-")
.[verbpath] = HandleVerb(arglist(list(entry, verbpath) + args))
/world/proc/LoadVerbs(verb_type)
if(!ispath(verb_type, /datum/verbs) || verb_type == /datum/verbs)
CRASH("Invalid verb_type: [verb_type]")
for (var/typepath in subtypesof(verb_type))
new typepath()
@@ -25,8 +25,10 @@
/datum/weather/floor_is_lava/weather_act(mob/living/L)
if(issilicon(L))
return
if(istype(L.buckled, /obj/structure/bed))
return
for(var/obj/structure/O in L.loc)
if(O.density || (L in O.buckled_mobs && istype(O, /obj/structure/bed)))
if(O.density)
return
if(L.loc.density)
return
+13 -2
View File
@@ -120,8 +120,12 @@
require_comms_key = TRUE
/datum/world_topic/namecheck/Run(list/input)
var/datum/server_tools_command/namecheck/NC = new
return NC.Run(input["sender"], input["namecheck"])
//Oh this is a hack, someone refactor the functionality out of the chat command PLS
var/datum/tgs_chat_command/namecheck/NC = new
var/datum/tgs_chat_user/user = new
user.friendly_name = input["sender"]
user.mention = user.friendly_name
return NC.Run(user, input["namecheck"])
/datum/world_topic/adminwho
keyword = "adminwho"
@@ -164,9 +168,16 @@
.["security_level"] = get_security_level()
.["round_duration"] = SSticker ? round((world.time-SSticker.round_start_time)/10) : 0
// Amount of world's ticks in seconds, useful for calculating round duration
//Time dilation stats.
.["time_dilation_current"] = SStime_track.time_dilation_current
.["time_dilation_avg"] = SStime_track.time_dilation_avg
.["time_dilation_avg_slow"] = SStime_track.time_dilation_avg_slow
.["time_dilation_avg_fast"] = SStime_track.time_dilation_avg_fast
if(SSshuttle && SSshuttle.emergency)
.["shuttle_mode"] = SSshuttle.emergency.mode
// Shuttle status, see /__DEFINES/stat.dm
.["shuttle_timer"] = SSshuttle.emergency.timeLeft()
// Shuttle timer, in seconds
+2 -1
View File
@@ -7,6 +7,7 @@
icon = 'icons/turf/areas.dmi'
icon_state = "unknown"
layer = AREA_LAYER
plane = BLACKNESS_PLANE //Keeping this on the default plane, GAME_PLANE, will make area overlays fail to render on FLOOR_PLANE.
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
@@ -518,4 +519,4 @@ GLOBAL_LIST_EMPTY(teleportlocs)
// A hook so areas can modify the incoming args
/area/proc/PlaceOnTopReact(list/new_baseturfs, turf/fake_turf_type, flags)
return flags
return flags
+1 -1
View File
@@ -211,7 +211,7 @@ Credit where due:
to_chat(L, "<span class='bold large_brass'>There is a paper in your backpack! It'll tell you if anything's changed, as well as what to expect.</span>")
to_chat(L, "<span class='alloy'>[slot] is a <b>clockwork slab</b>, a multipurpose tool used to construct machines and invoke ancient words of power. If this is your first time \
as a servant, you can find a concise tutorial in the Recollection category of its interface.</span>")
to_chat(L, "<span class='alloy italics'>If you want more information, you can find a wiki link here!</span> https://tgstation13.org/wiki/Clockwork_Cult")
to_chat(L, "<span class='alloy italics'>If you want more information, you can read <a href=\"https://tgstation13.org/wiki/Clockwork_Cult\">the wiki page</a> to learn more.</span>")
return TRUE
return FALSE
+19 -19
View File
@@ -712,6 +712,8 @@ GLOBAL_LIST_EMPTY(possible_items_special)
var/min_lings = 3 //Minimum amount of lings for this team objective to be possible
var/escape_objective_compatible = FALSE
/datum/objective/changeling_team_objective/proc/prepare()
return FALSE
//Impersonate department
//Picks as many people as it can from a department (Security,Engineer,Medical,Science)
@@ -724,6 +726,19 @@ GLOBAL_LIST_EMPTY(possible_items_special)
var/department_string = ""
/datum/objective/changeling_team_objective/impersonate_department/prepare()
var/result = FALSE
if(command_staff_only)
result = get_heads()
else
result = get_department_staff()
if(result)
update_explanation_text()
return TRUE
else
return FALSE
/datum/objective/changeling_team_objective/impersonate_department/proc/get_department_staff()
department_minds = list()
department_real_names = list()
@@ -756,9 +771,8 @@ GLOBAL_LIST_EMPTY(possible_items_special)
if(!department_minds.len)
log_game("[type] has failed to find department staff, and has removed itself. the round will continue normally")
owner.objectives -= src
qdel(src)
return
return FALSE
return TRUE
/datum/objective/changeling_team_objective/impersonate_department/proc/get_heads()
@@ -785,19 +799,8 @@ GLOBAL_LIST_EMPTY(possible_items_special)
if(!department_minds.len)
log_game("[type] has failed to find department heads, and has removed itself. the round will continue normally")
owner.objectives -= src
qdel(src)
return
/datum/objective/changeling_team_objective/impersonate_department/New(var/text)
..()
if(command_staff_only)
get_heads()
else
get_department_staff()
update_explanation_text()
return FALSE
return TRUE
/datum/objective/changeling_team_objective/impersonate_department/update_explanation_text()
@@ -862,9 +865,6 @@ GLOBAL_LIST_EMPTY(possible_items_special)
return TRUE
return FALSE
//A subtype of impersonate_department
//This subtype always picks as many command staff as it can (HoS,HoP,Cap,CE,CMO,RD)
//and tasks the lings with killing and replacing them
+1 -1
View File
@@ -41,7 +41,7 @@
name = "a hand teleporter."
targetitem = /obj/item/hand_tele
difficulty = 5
excludefromjob = list("Captain")
excludefromjob = list("Captain", "Research Director")
/datum/objective_item/steal/jetpack
name = "the Captain's jetpack."
+1
View File
@@ -4,6 +4,7 @@
icon = 'icons/obj/device.dmi'
icon_state = "ai-slipper0"
layer = PROJECTILE_HIT_THRESHHOLD_LAYER
plane = FLOOR_PLANE
anchored = TRUE
max_integrity = 200
armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
+3 -3
View File
@@ -126,7 +126,7 @@
return examine(user)
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions, list/traits)
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions, list/quirks)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -203,7 +203,7 @@
if(H)
H.faction |= factions
for(var/V in traits)
for(var/V in quirks)
new V(H)
H.set_cloned_appearance()
@@ -399,7 +399,7 @@
QDEL_IN(mob_occupant, 40)
/obj/machinery/clonepod/relaymove(mob/user)
container_resist()
container_resist(user)
/obj/machinery/clonepod/container_resist(mob/living/user)
if(user.stat == CONSCIOUS)
+4 -3
View File
@@ -291,6 +291,7 @@
/obj/machinery/computer/arcade/battle/emag_act(mob/user)
if(obj_flags & EMAGGED)
return
to_chat(user, "<span class='warning'>A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!</span>")
temp = "If you die in the game, you die for real!"
player_hp = 30
player_mp = 10
@@ -506,9 +507,9 @@
if(ORION_TRAIL_ILLNESS)
var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
if(severity == 1)
to_chat(M, "<span class='userdanger'>You suddenly feel slightly nauseous.</span>" )
to_chat(M, "<span class='userdanger'>You suddenly feel slightly nauseated.</span>" )
if(severity == 2)
to_chat(usr, "<span class='userdanger'>You suddenly feel extremely nauseous and hunch over until it passes.</span>")
to_chat(usr, "<span class='userdanger'>You suddenly feel extremely nauseated and hunch over until it passes.</span>")
M.Stun(60)
if(severity >= 3) //you didn't pray hard enough
to_chat(M, "<span class='warning'>An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit.</span>")
@@ -614,7 +615,7 @@
L.Stun(200, ignore_canstun = TRUE) //you can't run :^)
var/S = new /obj/singularity/academy(usr.loc)
addtimer(CALLBACK(src, /atom/movable/proc/say, "[S] winks out, just as suddenly as it appeared."), 50)
QDEL_IN(src, 50)
QDEL_IN(S, 50)
else
event = null
turns += 1
+6 -6
View File
@@ -71,7 +71,7 @@
if(pod.occupant)
continue //how though?
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["traits"]))
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"]))
temp = "[R.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
records -= R
@@ -400,7 +400,7 @@
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["traits"]))
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"]))
temp = "[C.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
@@ -473,10 +473,10 @@
R.fields["blood_type"] = dna.blood_type
R.fields["features"] = dna.features
R.fields["factions"] = mob_occupant.faction
R.fields["traits"] = list()
for(var/V in mob_occupant.roundstart_traits)
var/datum/trait/T = V
R.fields["traits"] += T.type
R.fields["quirks"] = list()
for(var/V in mob_occupant.roundstart_quirks)
var/datum/quirk/T = V
R.fields["quirks"] += T.type
if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
R.fields["mind"] = "[REF(mob_occupant.mind)]"
@@ -45,7 +45,7 @@
/obj/machinery/computer/communications/process()
if(..())
if(state != STATE_STATUSDISPLAY && state != STATE_CALLSHUTTLE && state != STATE_PURCHASE)
if(state != STATE_STATUSDISPLAY && state != STATE_CALLSHUTTLE && state != STATE_PURCHASE && state != STATE_VIEWMESSAGE)
updateDialog()
/obj/machinery/computer/communications/Topic(href, href_list)
+16 -15
View File
@@ -174,25 +174,26 @@
else
var/list/S = power_station.linked_stations
if(!S.len)
to_chat(user, "<span class='alert'>No connected stations located.</span>")
return
for(var/obj/machinery/teleport/station/R in S)
if(is_eligible(R))
if(is_eligible(R) && R.teleporter_hub)
var/area/A = get_area(R)
L[avoid_assoc_duplicate_keys(A.name, areaindex)] = R
if(!L.len)
to_chat(user, "<span class='alert'>No active connected stations located.</span>")
return
var/desc = input("Please select a station to lock in.", "Locking Computer") as null|anything in L
target = L[desc]
if(target)
var/obj/machinery/teleport/station/trg = target
trg.linked_stations |= power_station
trg.stat &= ~NOPOWER
if(trg.teleporter_hub)
trg.teleporter_hub.stat &= ~NOPOWER
trg.teleporter_hub.update_icon()
if(trg.teleporter_console)
trg.teleporter_console.stat &= ~NOPOWER
trg.teleporter_console.update_icon()
var/obj/machinery/teleport/station/target_station = L[desc]
if(!target_station || !target_station.teleporter_hub)
return
target = target_station.teleporter_hub
target_station.linked_stations |= power_station
target_station.stat &= ~NOPOWER
if(target_station.teleporter_hub)
target_station.teleporter_hub.stat &= ~NOPOWER
target_station.teleporter_hub.update_icon()
if(target_station.teleporter_console)
target_station.teleporter_console.stat &= ~NOPOWER
target_station.teleporter_console.update_icon()
/obj/machinery/computer/teleporter/proc/is_eligible(atom/movable/AM)
var/turf/T = get_turf(AM)
+2 -30
View File
@@ -323,12 +323,12 @@
return
else
return
else if(user.hallucinating() && ishuman(user) && prob(4) && !operating)
else if(user.hallucinating() && ishuman(user) && prob(1) && !operating)
var/mob/living/carbon/human/H = user
if(H.gloves)
var/obj/item/clothing/gloves/G = H.gloves
if(G.siemens_coefficient)//not insulated
hallucinate_shock(H)
new /datum/hallucination/shock(H)
return
if (cyclelinkedairlock)
if (!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency && allowed(user))
@@ -338,34 +338,6 @@
addtimer(CALLBACK(cyclelinkedairlock, .proc/close), 2)
..()
/obj/machinery/door/airlock/proc/hallucinate_shock(mob/living/user)
var/image/shock_image = image(user, user, dir = user.dir)
var/image/electrocution_skeleton_anim = image('icons/mob/human.dmi', user, icon_state = "electrocuted_base", layer=ABOVE_MOB_LAYER)
shock_image.color = rgb(0,0,0)
shock_image.override = TRUE
electrocution_skeleton_anim.appearance_flags |= RESET_COLOR|KEEP_APART
to_chat(user, "<span class='userdanger'>You feel a powerful shock course through your body!</span>")
if(user.client)
user.client.images |= shock_image
user.client.images |= electrocution_skeleton_anim
addtimer(CALLBACK(src, .proc/reset_hallucinate_shock_animation, user, shock_image, electrocution_skeleton_anim), 40)
user.playsound_local(get_turf(src), "sparks", 100, 1)
user.staminaloss += 50
user.Stun(40)
user.jitteriness += 1000
user.do_jitter_animation(user.jitteriness)
addtimer(CALLBACK(src, .proc/hallucinate_shock_drop, user), 20)
/obj/machinery/door/airlock/proc/reset_hallucinate_shock_animation(mob/living/user, shock_image, electrocution_skeleton_anim)
if(user.client)
user.client.images.Remove(shock_image)
user.client.images.Remove(electrocution_skeleton_anim)
/obj/machinery/door/airlock/proc/hallucinate_shock_drop(mob/living/user)
user.jitteriness = max(user.jitteriness - 990, 10) //Still jittery, but vastly less
user.Knockdown(60)
/obj/machinery/door/airlock/proc/isElectrified()
if(src.secondsElectrified != NOT_ELECTRIFIED)
return TRUE
+1 -2
View File
@@ -355,8 +355,7 @@
return
user.visible_message("<span class='notice'>[user] removes the wires from [src].</span>", \
"<span class='notice'>You remove the wiring from [src], exposing the circuit board.</span>")
var/obj/item/stack/cable_coil/B = new(get_turf(src))
B.amount = 5
new/obj/item/stack/cable_coil(get_turf(src), 5)
constructionStep = CONSTRUCTION_GUTTED
update_icon()
return
+4 -3
View File
@@ -32,6 +32,7 @@ Possible to do for anyone motivated enough:
desc = "It's a floor-mounted device for projecting holographic images."
icon_state = "holopad0"
layer = LOW_OBJ_LAYER
plane = FLOOR_PLANE
flags_1 = HEAR_1
anchored = TRUE
use_power = IDLE_POWER_USE
@@ -66,7 +67,7 @@ Possible to do for anyone motivated enough:
flags_1 = NODECONSTRUCT_1
on_network = FALSE
var/proximity_range = 1
/obj/machinery/holopad/tutorial/Initialize(mapload)
. = ..()
if(proximity_range)
@@ -86,7 +87,7 @@ Possible to do for anyone motivated enough:
replay_stop()
else if(disk && disk.record)
replay_start()
/obj/machinery/holopad/tutorial/HasProximity(atom/movable/AM)
if (!isliving(AM))
return
@@ -487,7 +488,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(QDELETED(user) || user.incapacitated() || !user.client)
return FALSE
return TRUE
//Can we display holos there
//Area check instead of line of sight check because this is a called a lot if AI wants to move around.
/obj/machinery/holopad/proc/validate_location(turf/T,check_los = FALSE)
+2 -1
View File
@@ -3,6 +3,7 @@
desc = "It's useful for igniting plasma."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "igniter0"
plane = FLOOR_PLANE
var/id = null
var/on = FALSE
anchored = TRUE
@@ -12,7 +13,7 @@
max_integrity = 300
armor = list("melee" = 50, "bullet" = 30, "laser" = 70, "energy" = 50, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
resistance_flags = FIRE_PROOF
/obj/machinery/igniter/on
on = TRUE
icon_state = "igniter1"
-143
View File
@@ -1,143 +0,0 @@
/obj/machinery/robotic_fabricator
name = "robotic fabricator"
icon = 'icons/obj/robotics.dmi'
icon_state = "fab-idle"
density = TRUE
anchored = TRUE
var/metal_amount = 0
var/operating = FALSE
var/obj/item/being_built = null
use_power = IDLE_POWER_USE
idle_power_usage = 20
active_power_usage = 5000
/obj/machinery/robotic_fabricator/attackby(obj/item/O, mob/living/user, params)
if (istype(O, /obj/item/stack/sheet/metal))
if (metal_amount < 150000)
add_overlay("fab-load-metal")
addtimer(CALLBACK(src, .proc/FinishLoadingMetal, O, user), 15)
else
to_chat(user, "\The [src] is full.")
else
return ..()
/obj/machinery/robotic_fabricator/proc/FinishLoadingMetal(obj/item/stack/sheet/metal/M, mob/living/user)
cut_overlay("fab-load-metal")
if(QDELETED(M) || QDELETED(user))
return
var/count = 0
while(metal_amount < 150000 && !QDELETED(M))
metal_amount += M.materials[MAT_METAL]
M.use(1)
count++
to_chat(user, "<span class='notice'>You insert [count] metal sheet\s into \the [src].</span>")
updateDialog()
/obj/machinery/robotic_fabricator/power_change()
if (powered())
stat &= ~NOPOWER
else
stat |= NOPOWER
/obj/machinery/robotic_fabricator/ui_interact(mob/user)
. = ..()
var/dat
if (src.operating)
dat = {"
<TT>Building [src.being_built.name].<BR>
Please wait until completion...</TT><BR>
<BR>
"}
else
dat = {"
<B>Metal Amount:</B> [min(150000, src.metal_amount)] cm<sup>3</sup> (MAX: 150,000)<BR><HR>
<BR>
<A href='?src=[REF(src)];make=1'>Left Arm (25,000 cc metal.)<BR>
<A href='?src=[REF(src)];make=2'>Right Arm (25,000 cc metal.)<BR>
<A href='?src=[REF(src)];make=3'>Left Leg (25,000 cc metal.)<BR>
<A href='?src=[REF(src)];make=4'>Right Leg (25,000 cc metal).<BR>
<A href='?src=[REF(src)];make=5'>Chest (50,000 cc metal).<BR>
<A href='?src=[REF(src)];make=6'>Head (50,000 cc metal).<BR>
<A href='?src=[REF(src)];make=7'>Robot Frame (75,000 cc metal).<BR>
"}
user << browse("<HEAD><TITLE>Robotic Fabricator Control Panel</TITLE></HEAD><TT>[dat]</TT>", "window=robot_fabricator")
onclose(user, "robot_fabricator")
return
/obj/machinery/robotic_fabricator/Topic(href, href_list)
if (..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if (href_list["make"])
if (!src.operating)
var/part_type = text2num(href_list["make"])
var/build_type = ""
var/build_time = 200
var/build_cost = 25000
switch (part_type)
if (1)
build_type = "/obj/item/bodypart/l_arm/robot"
build_time = 200
build_cost = 10000
if (2)
build_type = "/obj/item/bodypart/r_arm/robot"
build_time = 200
build_cost = 10000
if (3)
build_type = "/obj/item/bodypart/l_leg/robot"
build_time = 200
build_cost = 10000
if (4)
build_type = "/obj/item/bodypart/r_leg/robot"
build_time = 200
build_cost = 10000
if (5)
build_type = "/obj/item/bodypart/chest/robot"
build_time = 350
build_cost = 40000
if (6)
build_type = "/obj/item/bodypart/head/robot"
build_time = 350
build_cost = 5000
if (7)
build_type = "/obj/item/robot_suit"
build_time = 600
build_cost = 15000
var/building = text2path(build_type)
if (!isnull(building))
if (src.metal_amount >= build_cost)
operating = TRUE
src.use_power = ACTIVE_POWER_USE
src.metal_amount = max(0, src.metal_amount - build_cost)
src.being_built = new building(src)
src.add_overlay("fab-active")
src.updateUsrDialog()
spawn (build_time)
if (!isnull(src.being_built))
src.being_built.forceMove(drop_location())
src.being_built = null
src.use_power = IDLE_POWER_USE
operating = FALSE
cut_overlay("fab-active")
return
updateUsrDialog()
+1 -1
View File
@@ -5,7 +5,7 @@
name = "ominous beacon"
desc = "This looks suspicious..."
icon = 'icons/obj/singularity.dmi'
icon_state = "beacon"
icon_state = "beacon0"
anchored = FALSE
density = TRUE
+4 -3
View File
@@ -47,7 +47,6 @@
return
if(is_ready())
teleport(AM)
use_power(5000)
/obj/machinery/teleport/hub/attackby(obj/item/W, mob/user, params)
if(default_deconstruction_screwdriver(user, "tele-o", "tele0", W))
@@ -61,13 +60,15 @@
/obj/machinery/teleport/hub/proc/teleport(atom/movable/M as mob|obj, turf/T)
var/obj/machinery/computer/teleporter/com = power_station.teleporter_console
if (!com)
if (QDELETED(com))
return
if (!com.target)
if (QDELETED(com.target))
com.target = null
visible_message("<span class='alert'>Cannot authenticate locked on coordinates. Please reinstate coordinate matrix.</span>")
return
if (ismovableatom(M))
if(do_teleport(M, com.target))
use_power(5000)
if(!calibrated && prob(30 - ((accurate) * 10))) //oh dear a problem
if(ishuman(M))//don't remove people from the round randomly you jerks
var/mob/living/carbon/human/human = M
+1 -2
View File
@@ -65,8 +65,7 @@
return
/obj/item/stack/sheet/hairlesshide/machine_wash(obj/machinery/washing_machine/WM)
var/obj/item/stack/sheet/wetleather/WL = new(loc)
WL.amount = amount
new /obj/item/stack/sheet/wetleather(drop_location(), amount)
qdel(src)
/obj/item/clothing/suit/hooded/ian_costume/machine_wash(obj/machinery/washing_machine/WM)
@@ -367,8 +367,7 @@
return ..()
/obj/item/mecha_parts/mecha_equipment/generator/proc/generator_init()
fuel = new /obj/item/stack/sheet/mineral/plasma(src)
fuel.amount = 0
fuel = new /obj/item/stack/sheet/mineral/plasma(src, 0)
/obj/item/mecha_parts/mecha_equipment/generator/detach()
STOP_PROCESSING(SSobj, src)
@@ -472,8 +471,7 @@
var/rad_per_cycle = 3
/obj/item/mecha_parts/mecha_equipment/generator/nuclear/generator_init()
fuel = new /obj/item/stack/sheet/mineral/uranium(src)
fuel.amount = 0
fuel = new /obj/item/stack/sheet/mineral/uranium(src, 0)
/obj/item/mecha_parts/mecha_equipment/generator/nuclear/critfail()
return
@@ -301,8 +301,7 @@
/obj/item/mecha_parts/mecha_equipment/cable_layer/Initialize()
. = ..()
cable = new(src)
cable.amount = 0
cable = new(src, 0)
/obj/item/mecha_parts/mecha_equipment/cable_layer/can_attach(obj/mecha/working/M)
if(..())
@@ -333,8 +332,7 @@
if(to_load)
to_load = min(target.amount, to_load)
if(!cable)
cable = new(src)
cable.amount = 0
cable = new(src, 0)
cable.amount += to_load
target.use(to_load)
occupant_message("<span class='notice'>[to_load] meters of cable successfully loaded.</span>")
@@ -358,8 +356,7 @@
m = min(m, cable.amount)
if(m)
use_cable(m)
var/obj/item/stack/cable_coil/CC = new (get_turf(chassis))
CC.amount = m
new /obj/item/stack/cable_coil(get_turf(chassis), m)
else
occupant_message("There's no more cable on the reel.")
return
+8 -6
View File
@@ -812,16 +812,18 @@
to_chat(usr, "<span class='warning'>The [name] is already occupied!</span>")
log_append_to_last("Permission denied.")
return
var/passed
if(dna_lock)
var/passed = FALSE
if(user.has_dna())
var/mob/living/carbon/C = user
if(C.dna.unique_enzymes==dna_lock)
passed = 1
else if(operation_allowed(user))
passed = 1
if(!passed)
to_chat(user, "<span class='warning'>Access denied.</span>")
passed = TRUE
if (!passed)
to_chat(user, "<span class='warning'>Access denied. [name] is secured with a DNA lock.</span>")
log_append_to_last("Permission denied.")
return
if(!operation_allowed(user))
to_chat(user, "<span class='warning'>Access denied. Insufficient operation keycodes.</span>")
log_append_to_last("Permission denied.")
return
if(user.buckled)
+7 -4
View File
@@ -31,8 +31,6 @@
ore.forceMove(ore_box)
/obj/mecha/working/ripley/Destroy()
for(var/i=1, i <= hides, i++)
new /obj/item/stack/sheet/animalhide/goliath_hide(loc) //If a goliath-plated ripley gets killed, all the plates drop
for(var/atom/movable/A in cargo)
A.forceMove(drop_location())
step_rand(A)
@@ -49,13 +47,18 @@
/obj/mecha/working/ripley/update_icon()
..()
if (hides)
GET_COMPONENT(C,/datum/component/armor_plate)
if (C.amount)
cut_overlays()
if(hides < 3)
if(C.amount < 3)
add_overlay(occupant ? "ripley-g" : "ripley-g-open")
else
add_overlay(occupant ? "ripley-g-full" : "ripley-g-full-open")
/obj/mecha/working/ripley/Initialize()
. = ..()
AddComponent(/datum/component/armor_plate,3,/obj/item/stack/sheet/animalhide/goliath_hide,list("melee" = 10, "bullet" = 5, "laser" = 5))
/obj/mecha/working/ripley/firefighter
desc = "Autonomous Power Loader Unit. This model is refitted with additional thermal protection."
+6 -4
View File
@@ -8,7 +8,7 @@
anchored = TRUE
light_range = 3
var/movechance = 70
var/obj/item/assembly/signaler/anomaly/aSignal = null
var/obj/item/assembly/signaler/anomaly/aSignal
var/area/impact_area
var/lifespan = 990
@@ -26,10 +26,12 @@
aSignal = new(src)
aSignal.name = "[name] core"
aSignal.code = rand(1,100)
aSignal.anomaly_type = type
aSignal.frequency = rand(MIN_FREE_FREQ, MAX_FREE_FREQ)
if(ISMULTIPLE(aSignal.frequency, 2))//signaller frequencies are always uneven!
aSignal.frequency++
var/frequency = rand(MIN_FREE_FREQ, MAX_FREE_FREQ)
if(ISMULTIPLE(frequency, 2))//signaller frequencies are always uneven!
frequency++
aSignal.set_frequency(frequency)
if(new_lifespan)
lifespan = new_lifespan
@@ -1,7 +1,7 @@
/obj/effect/decal/cleanable
gender = PLURAL
layer = ABOVE_NORMAL_TURF_LAYER
var/list/random_icon_states = list()
var/list/random_icon_states = null
var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one?
@@ -1,5 +1,6 @@
/obj/effect/decal
name = "decal"
plane = FLOOR_PLANE
anchored = TRUE
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/turf_loc_check = TRUE
+3 -3
View File
@@ -27,11 +27,11 @@
///////////Mimewalls///////////
/obj/effect/forcefield/mime
icon_state = "empty"
icon_state = "nothing"
name = "invisible wall"
desc = "You have a bad feeling about this."
/obj/effect/forcefield/mime/advanced
name = "invisible blockade"
desc = "You're goona be here a while."
timeleft = 600
desc = "You're gonna be here awhile."
timeleft = 600
+114 -2
View File
@@ -5,7 +5,7 @@
var/lootcount = 1 //how many items will be spawned
var/lootdoubles = TRUE //if the same item can be spawned twice
var/list/loot //a list of possible items to spawn e.g. list(/obj/item, /obj/structure, /obj/effect)
var/fan_out_items = FALSE //Whether the items should be distributed to offsets 0,3,-3,6,-6,9,-9.. This overrides pixel_x/y on the spawner itself
var/fan_out_items = FALSE //Whether the items should be distributed to offsets 0,1,-1,2,-2,3,-3.. This overrides pixel_x/y on the spawner itself
/obj/effect/spawner/lootdrop/Initialize(mapload)
..()
@@ -26,7 +26,7 @@
spawned_loot.pixel_y = pixel_y
else
if (loot_spawned)
spawned_loot.pixel_x = spawned_loot.pixel_y = ((!(loot_spawned%2)*loot_spawned/2)*-3)+((loot_spawned%2)*(loot_spawned+1)/2*3)
spawned_loot.pixel_x = spawned_loot.pixel_y = ((!(loot_spawned%2)*loot_spawned/2)*-1)+((loot_spawned%2)*(loot_spawned+1)/2*1)
loot_spawned++
return INITIALIZE_HINT_QDEL
@@ -206,3 +206,115 @@
/obj/item/aiModule/core/full/thermurderdynamic,
/obj/item/aiModule/core/full/damaged
)
// Tech storage circuit board spawners
// For these, make sure that lootcount equals the number of list items
/obj/effect/spawner/lootdrop/techstorage
name = "generic circuit board spawner"
lootdoubles = FALSE
fan_out_items = TRUE
/obj/effect/spawner/lootdrop/techstorage/service
name = "service circuit board spawner"
lootcount = 10
loot = list(
/obj/item/circuitboard/computer/arcade/battle,
/obj/item/circuitboard/computer/arcade/orion_trail,
/obj/item/circuitboard/machine/autolathe,
/obj/item/circuitboard/computer/mining,
/obj/item/circuitboard/machine/ore_redemption,
/obj/item/circuitboard/machine/mining_equipment_vendor,
/obj/item/circuitboard/machine/microwave,
/obj/item/circuitboard/machine/chem_dispenser/drinks,
/obj/item/circuitboard/machine/chem_dispenser/drinks/beer,
/obj/item/circuitboard/computer/slot_machine
)
/obj/effect/spawner/lootdrop/techstorage/rnd
name = "RnD circuit board spawner"
lootcount = 8
loot = list(
/obj/item/circuitboard/computer/aifixer,
/obj/item/circuitboard/machine/rdserver,
/obj/item/circuitboard/computer/pandemic,
/obj/item/circuitboard/machine/mechfab,
/obj/item/circuitboard/machine/circuit_imprinter/department,
/obj/item/circuitboard/computer/teleporter,
/obj/item/circuitboard/machine/destructive_analyzer,
/obj/item/circuitboard/computer/rdconsole
)
/obj/effect/spawner/lootdrop/techstorage/security
name = "security circuit board spawner"
lootcount = 3
loot = list(
/obj/item/circuitboard/computer/secure_data,
/obj/item/circuitboard/computer/security,
/obj/item/circuitboard/computer/prisoner
)
/obj/effect/spawner/lootdrop/techstorage/engineering
name = "engineering circuit board spawner"
lootcount = 3
loot = list(
/obj/item/circuitboard/computer/atmos_alert,
/obj/item/circuitboard/computer/stationalert,
/obj/item/circuitboard/computer/powermonitor
)
/obj/effect/spawner/lootdrop/techstorage/tcomms
name = "tcomms circuit board spawner"
lootcount = 9
loot = list(
/obj/item/circuitboard/computer/message_monitor,
/obj/item/circuitboard/machine/telecomms/broadcaster,
/obj/item/circuitboard/machine/telecomms/bus,
/obj/item/circuitboard/machine/telecomms/server,
/obj/item/circuitboard/machine/telecomms/receiver,
/obj/item/circuitboard/machine/telecomms/processor,
/obj/item/circuitboard/machine/announcement_system,
/obj/item/circuitboard/computer/comm_server,
/obj/item/circuitboard/computer/comm_monitor
)
/obj/effect/spawner/lootdrop/techstorage/medical
name = "medical circuit board spawner"
lootcount = 8
loot = list(
/obj/item/circuitboard/computer/cloning,
/obj/item/circuitboard/machine/clonepod,
/obj/item/circuitboard/machine/chem_dispenser,
/obj/item/circuitboard/computer/scan_consolenew,
/obj/item/circuitboard/computer/med_data,
/obj/item/circuitboard/machine/smoke_machine,
/obj/item/circuitboard/machine/chem_master,
/obj/item/circuitboard/machine/clonescanner
)
/obj/effect/spawner/lootdrop/techstorage/AI
name = "secure AI circuit board spawner"
lootcount = 3
loot = list(
/obj/item/circuitboard/computer/aiupload,
/obj/item/circuitboard/computer/borgupload,
/obj/item/circuitboard/aicore
)
/obj/effect/spawner/lootdrop/techstorage/command
name = "secure command circuit board spawner"
lootcount = 3
loot = list(
/obj/item/circuitboard/computer/crew,
/obj/item/circuitboard/computer/communications,
/obj/item/circuitboard/computer/card
)
/obj/effect/spawner/lootdrop/techstorage/RnD_secure
name = "secure RnD circuit board spawner"
lootcount = 3
loot = list(
/obj/item/circuitboard/computer/mecha_control,
/obj/item/circuitboard/computer/apc_control,
/obj/item/circuitboard/computer/robotics
)
+15
View File
@@ -766,3 +766,18 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// Returns a numeric value for sorting items used as parts in machines, so they can be replaced by the rped
/obj/item/proc/get_part_rating()
return 0
/obj/item/doMove(atom/destination)
if (ismob(loc))
var/mob/M = loc
var/hand_index = M.get_held_index_of_item(src)
if(hand_index)
M.held_items[hand_index] = null
M.update_inv_hands()
if(M.client)
M.client.screen -= src
layer = initial(layer)
plane = initial(plane)
appearance_flags &= ~NO_CLIENT_COLOR
dropped(M)
return ..()
+2 -2
View File
@@ -138,7 +138,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
return "makepipe=[id]&type=[dirtype]"
/datum/pipe_info/meter
icon_state = "meterX"
icon_state = "meter"
dirtype = PIPE_ONEDIR
/datum/pipe_info/meter/New(label)
@@ -228,7 +228,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/icon_states/multiple_icons/pipes)
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
assets.send(user)
ui = new(user, src, ui_key, "rpd", name, 300, 550, master_ui, state)
+1 -2
View File
@@ -104,8 +104,7 @@
to_chat(user, "<span class='warning'>There is another network terminal here!</span>")
return
else
var/obj/item/stack/cable_coil/C = new /obj/item/stack/cable_coil(T)
C.amount = 10
new /obj/item/stack/cable_coil(T, 10)
to_chat(user, "<span class='notice'>You cut the cables and disassemble the unused power terminal.</span>")
qdel(E)
return TRUE
@@ -154,6 +154,10 @@
name = "Labor Camp teleporter console (Computer Board)"
build_path = /obj/machinery/computer/gulag_teleporter_computer
/obj/item/circuitboard/computer/rdconsole/production
name = "R&D Console Production Only (Computer Board)"
build_path = /obj/machinery/computer/rdconsole/production
/obj/item/circuitboard/computer/rdconsole
name = "R&D Console (Computer Board)"
build_path = /obj/machinery/computer/rdconsole/core
@@ -204,7 +204,7 @@
/obj/item/circuitboard/machine/vendor
name = "Booze-O-Mat Vendor (Machine Board)"
desc = "You could turn the \"brand selection\" dial using a screwdriver."
desc = "You can turn the \"brand selection\" dial using a screwdriver."
build_path = /obj/machinery/vending/boozeomat
req_components = list(
/obj/item/vending_refill/boozeomat = 3)
@@ -651,6 +651,7 @@
/obj/item/circuitboard/machine/chem_master
name = "ChemMaster 3000 (Machine Board)"
build_path = /obj/machinery/chem_master
desc = "You can turn the \"mode selection\" dial using a screwdriver."
req_components = list(
/obj/item/reagent_containers/glass/beaker = 2,
/obj/item/stock_parts/manipulator = 1,
@@ -840,6 +841,13 @@
/obj/item/stack/sheet/glass = 1,
/obj/item/vending_refill/donksoft = 3)
/obj/item/circuitboard/machine/vending/syndicatedonksofttoyvendor
name = "Syndicate Donksoft Toy Vendor (Machine Board)"
build_path = /obj/machinery/vending/toyliberationstation
req_components = list(
/obj/item/stack/sheet/glass = 1,
/obj/item/vending_refill/donksoft = 3)
/obj/item/circuitboard/machine/dish_drive
name = "Dish Drive (Machine Board)"
build_path = /obj/machinery/dish_drive
@@ -865,3 +873,17 @@
return
transmit = !transmit
to_chat(user, "<span class='notice'>You [transmit ? "enable" : "disable"] the board's automatic disposal transmission.</span>")
/obj/item/circuitboard/machine/stacking_unit_console
name = "Stacking Machine Console (Machine Board)"
build_path = /obj/machinery/mineral/stacking_unit_console
req_components = list(
/obj/item/stack/sheet/glass = 2,
/obj/item/stack/cable_coil = 5)
/obj/item/circuitboard/machine/stacking_machine
name = "Stacking Machine (Machine Board)"
build_path = /obj/machinery/mineral/stacking_machine
req_components = list(
/obj/item/stock_parts/manipulator = 2,
/obj/item/stock_parts/matter_bin = 2)
+1
View File
@@ -118,6 +118,7 @@
/obj/item/bikehorn/attack(mob/living/carbon/M, mob/living/carbon/user)
M.SendSignal(COMSIG_ADD_MOOD_EVENT, "honk", /datum/mood_event/honk)
return ..()
/obj/item/bikehorn/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] solemnly points the horn at [user.p_their()] temple! It looks like [user.p_theyre()] trying to commit suicide!</span>")
+2 -3
View File
@@ -170,7 +170,6 @@
to_chat(user, "<span class='warning'>You need a free hand to hold the paddles!</span>")
update_icon()
return
paddles.forceMove(user)
else
//Remove from their hands and back onto the defib unit
paddles.unwield()
@@ -276,8 +275,8 @@
name = "defibrillator paddles"
desc = "A pair of plastic-gripped paddles with flat metal surfaces that are used to deliver powerful electric shocks."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "defibpaddles"
item_state = "defibpaddles"
icon_state = "defibpaddles0"
item_state = "defibpaddles0"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+43 -42
View File
@@ -178,20 +178,20 @@ GLOBAL_LIST_EMPTY(PDAs)
. = ..()
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/pda)
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/simple/pda)
assets.send(user)
user.set_machine(src)
var/dat = "<!DOCTYPE html><html><head><title>Personal Data Assistant</title><link href=\"https://fonts.googleapis.com/css?family=Orbitron|Share+Tech+Mono|VT323\" rel=\"stylesheet\"></head><body bgcolor=\"" + background_color + "\"><style>body{" + font_mode + "}ul,ol{list-style-type: none;}a, a:link, a:visited, a:active, a:hover { color: #000000;text-decoration:none; }img {border-style:none;}a img{padding-right: 9px;}</style>"
dat += assets.css_tag()
dat += "<a href='byond://?src=[REF(src)];choice=Refresh'><img src=pda_refresh.png>Refresh</a>"
dat += "<a href='byond://?src=[REF(src)];choice=Refresh'>[PDAIMG(refresh)]Refresh</a>"
if ((!isnull(cartridge)) && (mode == 0))
dat += " | <a href='byond://?src=[REF(src)];choice=Eject'><img src=pda_eject.png>Eject [cartridge]</a>"
dat += " | <a href='byond://?src=[REF(src)];choice=Eject'>[PDAIMG(eject)]Eject [cartridge]</a>"
if (mode)
dat += " | <a href='byond://?src=[REF(src)];choice=Return'><img src=pda_menu.png>Return</a>"
dat += " | <a href='byond://?src=[REF(src)];choice=Return'>[PDAIMG(menu)]Return</a>"
if (mode == 0)
dat += "<div align=\"center\">"
@@ -205,7 +205,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if (!owner)
dat += "Warning: No owner information entered. Please swipe card.<br><br>"
dat += "<a href='byond://?src=[REF(src)];choice=Refresh'><img src=pda_refresh.png>Retry</a>"
dat += "<a href='byond://?src=[REF(src)];choice=Refresh'>[PDAIMG(refresh)]Retry</a>"
else
switch (mode)
if (0)
@@ -221,38 +221,38 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "<h4>General Functions</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=[REF(src)];choice=1'><img src=pda_notes.png>Notekeeper</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=2'><img src=pda_mail.png>Messenger</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=1'>[PDAIMG(notes)]Notekeeper</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=2'>[PDAIMG(mail)]Messenger</a></li>"
if (cartridge)
if (cartridge.access & CART_CLOWN)
dat += "<li><a href='byond://?src=[REF(src)];choice=Honk'><img src=pda_honk.png>Honk Synthesizer</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Trombone'><img src=pda_honk.png>Sad Trombone</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Honk'>[PDAIMG(honk)]Honk Synthesizer</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Trombone'>[PDAIMG(honk)]Sad Trombone</a></li>"
if (cartridge.access & CART_MANIFEST)
dat += "<li><a href='byond://?src=[REF(src)];choice=41'><img src=pda_notes.png>View Crew Manifest</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=41'>[PDAIMG(notes)]View Crew Manifest</a></li>"
if(cartridge.access & CART_STATUS_DISPLAY)
dat += "<li><a href='byond://?src=[REF(src)];choice=42'><img src=pda_status.png>Set Status Display</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=42'>[PDAIMG(status)]Set Status Display</a></li>"
dat += "</ul>"
if (cartridge.access & CART_ENGINE)
dat += "<h4>Engineering Functions</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=[REF(src)];choice=43'><img src=pda_power.png>Power Monitor</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=43'>[PDAIMG(power)]Power Monitor</a></li>"
dat += "</ul>"
if (cartridge.access & CART_MEDICAL)
dat += "<h4>Medical Functions</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=[REF(src)];choice=44'><img src=pda_medical.png>Medical Records</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Medical Scan'><img src=pda_scanner.png>[scanmode == 1 ? "Disable" : "Enable"] Medical Scanner</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=44'>[PDAIMG(medical)]Medical Records</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Medical Scan'>[PDAIMG(scanner)][scanmode == 1 ? "Disable" : "Enable"] Medical Scanner</a></li>"
dat += "</ul>"
if (cartridge.access & CART_SECURITY)
dat += "<h4>Security Functions</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=[REF(src)];choice=45'><img src=pda_cuffs.png>Security Records</A></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=45'>[PDAIMG(cuffs)]Security Records</A></li>"
dat += "</ul>"
if(cartridge.access & CART_QUARTERMASTER)
dat += "<h4>Quartermaster Functions:</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=[REF(src)];choice=47'><img src=pda_crate.png>Supply Records</A></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=47'>[PDAIMG(crate)]Supply Records</A></li>"
dat += "</ul>"
dat += "</ul>"
@@ -260,25 +260,25 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "<ul>"
if (cartridge)
if(cartridge.bot_access_flags)
dat += "<li><a href='byond://?src=[REF(src)];choice=54'><img src=pda_medbot.png>Bots Access</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=54'>[PDAIMG(medbot)]Bots Access</a></li>"
if (cartridge.access & CART_JANITOR)
dat += "<li><a href='byond://?src=[REF(src)];choice=49'><img src=pda_bucket.png>Custodial Locator</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=49'>[PDAIMG(bucket)]Custodial Locator</a></li>"
if (istype(cartridge.radio))
dat += "<li><a href='byond://?src=[REF(src)];choice=40'><img src=pda_signaler.png>Signaler System</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=40'>[PDAIMG(signaler)]Signaler System</a></li>"
if (cartridge.access & CART_NEWSCASTER)
dat += "<li><a href='byond://?src=[REF(src)];choice=53'><img src=pda_notes.png>Newscaster Access </a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=53'>[PDAIMG(notes)]Newscaster Access </a></li>"
if (cartridge.access & CART_REAGENT_SCANNER)
dat += "<li><a href='byond://?src=[REF(src)];choice=Reagent Scan'><img src=pda_reagent.png>[scanmode == 3 ? "Disable" : "Enable"] Reagent Scanner</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Reagent Scan'>[PDAIMG(reagent)][scanmode == 3 ? "Disable" : "Enable"] Reagent Scanner</a></li>"
if (cartridge.access & CART_ENGINE)
dat += "<li><a href='byond://?src=[REF(src)];choice=Halogen Counter'><img src=pda_reagent.png>[scanmode == 4 ? "Disable" : "Enable"] Halogen Counter</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Halogen Counter'>[PDAIMG(reagent)][scanmode == 4 ? "Disable" : "Enable"] Halogen Counter</a></li>"
if (cartridge.access & CART_ATMOS)
dat += "<li><a href='byond://?src=[REF(src)];choice=Gas Scan'><img src=pda_reagent.png>[scanmode == 5 ? "Disable" : "Enable"] Gas Scanner</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Gas Scan'>[PDAIMG(reagent)][scanmode == 5 ? "Disable" : "Enable"] Gas Scanner</a></li>"
if (cartridge.access & CART_REMOTE_DOOR)
dat += "<li><a href='byond://?src=[REF(src)];choice=Toggle Door'><img src=pda_rdoor.png>Toggle Remote Door</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Toggle Door'>[PDAIMG(rdoor)]Toggle Remote Door</a></li>"
if (cartridge.access & CART_DRONEPHONE)
dat += "<li><a href='byond://?src=[REF(src)];choice=Drone Phone'><img src=pda_dronephone.png>Drone Phone</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=3'><img src=pda_atmos.png>Atmospheric Scan</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Light'><img src=pda_flashlight.png>[fon ? "Disable" : "Enable"] Flashlight</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Drone Phone'>[PDAIMG(dronephone)]Drone Phone</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=3'>[PDAIMG(atmos)]Atmospheric Scan</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=Light'>[PDAIMG(flashlight)][fon ? "Disable" : "Enable"] Flashlight</a></li>"
if (pai)
if(pai.loc != src)
pai = null
@@ -289,23 +289,23 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "</ul>"
if (1)
dat += "<h4><img src=pda_notes.png> Notekeeper V2.2</h4>"
dat += "<h4>[PDAIMG(notes)] Notekeeper V2.2</h4>"
dat += "<a href='byond://?src=[REF(src)];choice=Edit'>Edit</a><br>"
if(notescanned)
dat += "(This is a scanned image, editing it may cause some text formatting to change.)<br>"
dat += "<HR><font face=\"[PEN_FONT]\">[(!notehtml ? note : notehtml)]</font>"
if (2)
dat += "<h4><img src=pda_mail.png> SpaceMessenger V3.9.6</h4>"
dat += "<a href='byond://?src=[REF(src)];choice=Toggle Ringer'><img src=pda_bell.png>Ringer: [silent == 1 ? "Off" : "On"]</a> | "
dat += "<a href='byond://?src=[REF(src)];choice=Toggle Messenger'><img src=pda_mail.png>Send / Receive: [toff == 1 ? "Off" : "On"]</a> | "
dat += "<a href='byond://?src=[REF(src)];choice=Ringtone'><img src=pda_bell.png>Set Ringtone</a> | "
dat += "<a href='byond://?src=[REF(src)];choice=21'><img src=pda_mail.png>Messages</a><br>"
dat += "<h4>[PDAIMG(mail)] SpaceMessenger V3.9.6</h4>"
dat += "<a href='byond://?src=[REF(src)];choice=Toggle Ringer'>[PDAIMG(bell)]Ringer: [silent == 1 ? "Off" : "On"]</a> | "
dat += "<a href='byond://?src=[REF(src)];choice=Toggle Messenger'>[PDAIMG(mail)]Send / Receive: [toff == 1 ? "Off" : "On"]</a> | "
dat += "<a href='byond://?src=[REF(src)];choice=Ringtone'>[PDAIMG(bell)]Set Ringtone</a> | "
dat += "<a href='byond://?src=[REF(src)];choice=21'>[PDAIMG(mail)]Messages</a><br>"
if(cartridge)
dat += cartridge.message_header()
dat += "<h4><img src=pda_menu.png> Detected PDAs</h4>"
dat += "<h4>[PDAIMG(menu)] Detected PDAs</h4>"
dat += "<ul>"
var/count = 0
@@ -326,16 +326,16 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "<a href='byond://?src=[REF(src)];choice=MessageAll'>Send To All</a>"
if(21)
dat += "<h4><img src=pda_mail.png> SpaceMessenger V3.9.6</h4>"
dat += "<a href='byond://?src=[REF(src)];choice=Clear'><img src=pda_blank.png>Clear Messages</a>"
dat += "<h4>[PDAIMG(mail)] SpaceMessenger V3.9.6</h4>"
dat += "<a href='byond://?src=[REF(src)];choice=Clear'>[PDAIMG(blank)]Clear Messages</a>"
dat += "<h4><img src=pda_mail.png> Messages</h4>"
dat += "<h4>[PDAIMG(mail)] Messages</h4>"
dat += tnote
dat += "<br>"
if (3)
dat += "<h4><img src=pda_atmos.png> Atmospheric Readings</h4>"
dat += "<h4>[PDAIMG(atmos)] Atmospheric Readings</h4>"
var/turf/T = user.loc
if (isnull(T))
@@ -617,7 +617,8 @@ GLOBAL_LIST_EMPTY(PDAs)
return
if((last_text && world.time < last_text + 10) || (everyone && last_everyone && world.time < last_everyone + PDA_SPAM_DELAY))
return
if(prob(1))
message += "\nSent from my PDA"
// Send the signal
var/list/string_targets = list()
for (var/obj/item/pda/P in targets)
@@ -742,7 +743,7 @@ GLOBAL_LIST_EMPTY(PDAs)
var/mob/M = loc
M.put_in_hands(inserted_item)
else
inserted_item.forceMove(get_turf(src))
inserted_item.forceMove(drop_location())
to_chat(usr, "<span class='notice'>You remove \the [inserted_item] from \the [src].</span>")
inserted_item = null
update_icon()
@@ -1017,4 +1018,4 @@ GLOBAL_LIST_EMPTY(PDAs)
#undef PDA_SCANNER_REAGENT
#undef PDA_SCANNER_HALOGEN
#undef PDA_SCANNER_GAS
#undef PDA_SPAM_DELAY
#undef PDA_SPAM_DELAY
@@ -21,7 +21,7 @@
// Special AI/pAI PDAs that cannot explode.
/obj/item/pda/ai
icon_state = "NONE"
icon = null
ttone = "data"
fon = FALSE
detonatable = FALSE
+18 -19
View File
@@ -207,13 +207,12 @@
frequency.post_signal(src, status_signal)
/obj/item/cartridge/proc/generate_menu(mob/user)
if(!host_pda)
return
switch(host_pda.mode)
if(40) //signaller
menu = "<h4><img src=pda_signaler.png> Remote Signaling System</h4>"
menu = "<h4>[PDAIMG(signaler)] Remote Signaling System</h4>"
menu += {"
<a href='byond://?src=[REF(src)];choice=Send Signal'>Send Signal</A><BR>
@@ -232,7 +231,7 @@ Code:
<a href='byond://?src=[REF(src)];choice=Signal Code;scode=5'>+</a><br>"}
if (41) //crew manifest
menu = "<h4><img src=pda_notes.png> Crew Manifest</h4>"
menu = "<h4>[PDAIMG(notes)] Crew Manifest</h4>"
menu += "Entries cannot be modified from this terminal.<br><br>"
if(GLOB.data_core.general)
for (var/datum/data/record/t in sortRecord(GLOB.data_core.general))
@@ -241,7 +240,7 @@ Code:
if (42) //status displays
menu = "<h4><img src=pda_status.png> Station Status Display Interlink</h4>"
menu = "<h4>[PDAIMG(status)] Station Status Display Interlink</h4>"
menu += "\[ <A HREF='?src=[REF(src)];choice=Status;statdisp=blank'>Clear</A> \]<BR>"
menu += "\[ <A HREF='?src=[REF(src)];choice=Status;statdisp=shuttle'>Shuttle ETA</A> \]<BR>"
@@ -254,7 +253,7 @@ Code:
menu += " <A HREF='?src=[REF(src)];choice=Status;statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR>"
if (43)
menu = "<h4><img src=pda_power.png> Power Monitors - Please select one</h4><BR>"
menu = "<h4>[PDAIMG(power)] Power Monitors - Please select one</h4><BR>"
powmonitor = null
powermonitors = list()
var/powercount = 0
@@ -280,7 +279,7 @@ Code:
menu += "</FONT>"
if (433)
menu = "<h4><img src=pda_power.png> Power Monitor </h4><BR>"
menu = "<h4>[PDAIMG(power)] Power Monitor </h4><BR>"
if(!powmonitor)
menu += "<span class='danger'>No connection<BR></span>"
else
@@ -307,13 +306,13 @@ Code:
menu += "</FONT></PRE>"
if (44) //medical records //This thing only displays a single screen so it's hard to really get the sub-menu stuff working.
menu = "<h4><img src=pda_medical.png> Medical Record List</h4>"
menu = "<h4>[PDAIMG(medical)] Medical Record List</h4>"
if(GLOB.data_core.general)
for(var/datum/data/record/R in sortRecord(GLOB.data_core.general))
menu += "<a href='byond://?src=[REF(src)];choice=Medical Records;target=[R.fields["id"]]'>[R.fields["id"]]: [R.fields["name"]]<br>"
menu += "<br>"
if(441)
menu = "<h4><img src=pda_medical.png> Medical Record</h4>"
menu = "<h4>[PDAIMG(medical)] Medical Record</h4>"
if(active1 in GLOB.data_core.general)
menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]<br>"
@@ -328,7 +327,7 @@ Code:
menu += "<br>"
menu += "<h4><img src=pda_medical.png> Medical Data</h4>"
menu += "<h4>[PDAIMG(medical)] Medical Data</h4>"
if(active2 in GLOB.data_core.medical)
menu += "Blood Type: [active2.fields["blood_type"]]<br><br>"
@@ -350,14 +349,14 @@ Code:
menu += "<br>"
if (45) //security records
menu = "<h4><img src=pda_cuffs.png> Security Record List</h4>"
menu = "<h4>[PDAIMG(cuffs)] Security Record List</h4>"
if(GLOB.data_core.general)
for (var/datum/data/record/R in sortRecord(GLOB.data_core.general))
menu += "<a href='byond://?src=[REF(src)];choice=Security Records;target=[R.fields["id"]]'>[R.fields["id"]]: [R.fields["name"]]<br>"
menu += "<br>"
if(451)
menu = "<h4><img src=pda_cuffs.png> Security Record</h4>"
menu = "<h4>[PDAIMG(cuffs)] Security Record</h4>"
if(active1 in GLOB.data_core.general)
menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]<br>"
@@ -372,7 +371,7 @@ Code:
menu += "<br>"
menu += "<h4><img src=pda_cuffs.png> Security Data</h4>"
menu += "<h4>[PDAIMG(cuffs)] Security Data</h4>"
if(active3 in GLOB.data_core.security)
menu += "Criminal Status: [active3.fields["criminal"]]<br>"
@@ -418,7 +417,7 @@ Code:
menu += "<br>"
if (47) //quartermaster order records
menu = "<h4><img src=pda_crate.png> Supply Record Interlink</h4>"
menu = "<h4>[PDAIMG(crate)] Supply Record Interlink</h4>"
menu += "<BR><B>Supply shuttle</B><BR>"
menu += "Location: "
@@ -449,7 +448,7 @@ Code:
menu += "</ol><font size=\"-3\">Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management."
if (49) //janitorial locator
menu = "<h4><img src=pda_bucket.png> Persistent Custodial Object Locator</h4>"
menu = "<h4>[PDAIMG(bucket)] Persistent Custodial Object Locator</h4>"
var/turf/cl = get_turf(src)
if (cl)
@@ -511,7 +510,7 @@ Code:
menu += "<br><br><A href='byond://?src=[REF(src)];choice=49'>Refresh GPS Locator</a>"
if (53) // Newscaster
menu = "<h4><img src=pda_notes.png> Newscaster Access</h4>"
menu = "<h4>[PDAIMG(notes)] Newscaster Access</h4>"
menu += "<br> Current Newsfeed: <A href='byond://?src=[REF(src)];choice=Newscaster Switch Channel'>[current_channel ? current_channel : "None"]</a> <br>"
var/datum/newscaster/feed_channel/current
for(var/datum/newscaster/feed_channel/chan in GLOB.news_network.network_channels)
@@ -533,7 +532,7 @@ Code:
menu += "<br> <A href='byond://?src=[REF(src)];choice=Newscaster Message'>Post Message</a>"
if (54) // Beepsky, Medibot, Floorbot, and Cleanbot access
menu = "<h4><img src=pda_medbot.png> Bots Interlink</h4>"
menu = "<h4>[PDAIMG(medbot)] Bots Interlink</h4>"
bot_control()
if (99) //Newscaster message permission error
menu = "<h5> ERROR : NOT AUTHORIZED [host_pda.id ? "" : "- ID SLOT EMPTY"] </h5>"
@@ -652,7 +651,7 @@ Code:
var/mob/living/simple_animal/bot/Bot
if(active_bot)
menu += "<B>[active_bot]</B><BR> Status: (<A href='byond://?src=[REF(src)];op=control;bot=[REF(active_bot)]'><img src=pda_refresh.png><i>refresh</i></A>)<BR>"
menu += "<B>[active_bot]</B><BR> Status: (<A href='byond://?src=[REF(src)];op=control;bot=[REF(active_bot)]'>[PDAIMG(refresh)]<i>refresh</i></A>)<BR>"
menu += "Model: [active_bot.model]<BR>"
menu += "Location: [get_area(active_bot)]<BR>"
menu += "Mode: [active_bot.get_mode()]"
@@ -688,9 +687,9 @@ Code:
menu += "\[<A href='byond://?src=[REF(src)];op=summon'>Summon Bot</A>\]<BR>" //summon
menu += "Keep an ID inserted to upload access codes upon summoning."
menu += "<HR><A href='byond://?src=[REF(src)];op=botlist'><img src=pda_back.png>Return to bot list</A>"
menu += "<HR><A href='byond://?src=[REF(src)];op=botlist'>[PDAIMG(back)]Return to bot list</A>"
else
menu += "<BR><A href='byond://?src=[REF(src)];op=botlist'><img src=pda_refresh.png>Scan for active bots</A><BR><BR>"
menu += "<BR><A href='byond://?src=[REF(src)];op=botlist'>[PDAIMG(refresh)]Scan for active bots</A><BR><BR>"
var/turf/current_turf = get_turf(src)
var/zlevel = current_turf.z
var/botcount = 0
@@ -131,17 +131,17 @@
update_icon()
to_chat(user, "<span class='notice'>[icon2html(src, user)] You switch [scanning ? "on" : "off"] [src].</span>")
/obj/item/geiger_counter/attack(mob/living/M, mob/user)
/obj/item/geiger_counter/afterattack(atom/target, mob/user)
if(user.a_intent == INTENT_HELP)
if(!(obj_flags & EMAGGED))
user.visible_message("<span class='notice'>[user] scans [M] with [src].</span>", "<span class='notice'>You scan [M]'s radiation levels with [src]...</span>")
addtimer(CALLBACK(src, .proc/scan, M, user), 20, TIMER_UNIQUE) // Let's not have spamming GetAllContents
user.visible_message("<span class='notice'>[user] scans [target] with [src].</span>", "<span class='notice'>You scan [target]'s radiation levels with [src]...</span>")
addtimer(CALLBACK(src, .proc/scan, target, user), 20, TIMER_UNIQUE) // Let's not have spamming GetAllContents
else
user.visible_message("<span class='notice'>[user] scans [M] with [src].</span>", "<span class='danger'>You project [src]'s stored radiation into [M]'s body!</span>")
M.rad_act(radiation_count)
user.visible_message("<span class='notice'>[user] scans [target] with [src].</span>", "<span class='danger'>You project [src]'s stored radiation into [target]!</span>")
target.rad_act(radiation_count)
radiation_count = 0
return 1
..()
return TRUE
return ..()
/obj/item/geiger_counter/proc/scan(atom/A, mob/user)
var/rad_strength = 0
@@ -161,9 +161,9 @@
to_chat(user, "<span class='boldannounce'>[icon2html(src, user)] Subject is irradiated. Radiation levels: [M.radiation].</span>")
if(rad_strength)
to_chat(user, "<span class='boldannounce'>[icon2html(src, user)] Subject has irradiated objects on them. Radioactive strength: [rad_strength]</span>")
to_chat(user, "<span class='boldannounce'>[icon2html(src, user)] Target contains radioactive contamination. Radioactive strength: [rad_strength]</span>")
else
to_chat(user, "<span class='notice'>[icon2html(src, user)] Subject is free of radioactive contamination.</span>")
to_chat(user, "<span class='notice'>[icon2html(src, user)] Target is free of radioactive contamination.</span>")
/obj/item/geiger_counter/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/screwdriver) && (obj_flags & EMAGGED))
+1 -1
View File
@@ -174,7 +174,7 @@ GAS ANALYZER
trauma_desc += B.scan_desc
trauma_text += trauma_desc
to_chat(user, "\t<span class='alert'>Cerebral traumas detected: subjects appears to be suffering from [english_list(trauma_text)].</span>")
if(C.roundstart_traits.len)
if(C.roundstart_quirks.len)
to_chat(user, "\t<span class='info'>Subject has the following physiological traits: [C.get_trait_string()].</span>")
if(advanced)
to_chat(user, "\t<span class='info'>Brain Activity Level: [(200 - M.getBrainLoss())/2]%.</span>")
@@ -58,6 +58,36 @@
attacher = user
return
//Attached device memes
/obj/item/transfer_valve/Move()
. = ..()
if(attached_device)
attached_device.holder_movement()
/obj/item/transfer_valve/dropped()
. = ..()
if(attached_device)
attached_device.dropped()
/obj/item/transfer_valve/on_found(mob/finder)
if(attached_device)
attached_device.on_found(finder)
/obj/item/transfer_valve/Crossed(atom/movable/AM as mob|obj)
. = ..()
if(attached_device)
attached_device.Crossed(AM)
/obj/item/transfer_valve/attack_hand()//Triggers mousetraps
. = ..()
if(.)
return
if(attached_device)
attached_device.attack_hand()
//These keep attached devices synced up, for example a TTV with a mouse trap being found in a bag so it's triggered, or moving the TTV with an infrared beam sensor to update the beam's direction.
/obj/item/transfer_valve/attack_self(mob/user)
user.set_machine(src)
var/dat = {"<B> Valve properties: </B>
@@ -91,8 +121,7 @@
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
attached_device.forceMove(drop_location())
attached_device.holder = null
attached_device.on_detach()
attached_device = null
update_icon()
if(href_list["device"])
@@ -127,6 +156,10 @@
underlays += J
if(attached_device)
add_overlay("device")
if(istype(attached_device, /obj/item/assembly/infra))
var/obj/item/assembly/infra/sensor = attached_device
if(sensor.on && sensor.visible)
add_overlay("proxy_beam")
/obj/item/transfer_valve/proc/merge_gases()
tank_two.air_contents.volume += tank_one.air_contents.volume
+5 -4
View File
@@ -208,12 +208,13 @@
if(stored_swap == user)
to_chat(user,"<span class='notice'>You stare at the book some more, but there doesn't seem to be anything else to learn...</span>")
return
var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new
swapper.cast(user, stored_swap, TRUE)
if(swapper.cast(list(stored_swap), user, TRUE, TRUE))
to_chat(user,"<span class='warning'>You're suddenly somewhere else... and someone else?!</span>")
to_chat(stored_swap,"<span class='warning'>Suddenly you're staring at [src] again... where are you, who are you?!</span>")
else
user.visible_message("<span class='warning'>[src] fizzles slightly as it stops glowing!</span>") //if the mind_transfer failed to transfer mobs, likely due to the target being catatonic.
to_chat(stored_swap,"<span class='warning'>You're suddenly somewhere else... and someone else?!</span>")
to_chat(user,"<span class='warning'>Suddenly you're staring at [src] again... where are you, who are you?!</span>")
stored_swap = null
/obj/item/book/granter/spell/forcewall
+1 -1
View File
@@ -87,7 +87,7 @@
return FALSE
var/turf/there = get_turf(H)
return (H.z != 0 || (there && there.z == H.z))
return (H.z != 0 || (there && there.z == here.z))
return FALSE
+5
View File
@@ -45,6 +45,11 @@
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
/obj/item/shield/riot/roman/fake
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>. It appears to be a bit flimsy."
block_chance = 0
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/shield/riot/buckler
name = "wooden buckler"
desc = "A medieval wooden buckler."
+14 -2
View File
@@ -127,6 +127,18 @@
self_delay = 20
max_amount = 12
/obj/item/stack/medical/gauze/wirecutter_act(mob/living/user, obj/item/I)
if(get_amount() < 2)
to_chat(user, "<span class='warning'>You need at least two gauze to do this!</span>")
return
new /obj/item/stack/sheet/cloth(user.drop_location())
user.visible_message("[user] cuts [src] into pieces of cloth with [I].", \
"<span class='notice'>You cut [src] into pieces of cloth with [I].</span>", \
"<span class='italics'>You hear cutting.</span>")
var/obj/item/stack/medical/gauze/R = src
src = null
R.use(2)
/obj/item/stack/medical/gauze/suicide_act(mob/living/user)
user.visible_message("<span class='suicide'>[user] begins tightening \the [src] around [user.p_their()] neck! It looks like [user.p_they()] forgot how to use medical supplies!</span>")
return OXYLOSS
@@ -155,5 +167,5 @@
grind_results = list("silver_sulfadiazine" = 10)
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! Don't they know that stuff is toxic?</span>")
return TOXLOSS
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
return TOXLOSS
@@ -82,7 +82,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
singular_name = "plasma glass sheet"
icon_state = "sheet-pglass"
item_state = "sheet-pglass"
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT/2, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 75, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/plasmaglass
@@ -133,7 +133,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
singular_name = "reinforced glass sheet"
icon_state = "sheet-rglass"
item_state = "sheet-rglass"
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT/2, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/rglass
@@ -175,7 +175,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
singular_name = "reinforced plasma glass sheet"
icon_state = "sheet-prglass"
item_state = "sheet-prglass"
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT/2, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT, MAT_METAL = MINERAL_MATERIAL_AMOUNT * 0.5,)
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/plasmarglass
@@ -195,7 +195,7 @@ GLOBAL_LIST_INIT(titaniumglass_recipes, list(
singular_name = "titanium glass sheet"
icon_state = "sheet-titaniumglass"
item_state = "sheet-titaniumglass"
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/titaniumglass
@@ -214,7 +214,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
singular_name = "plastitanium glass sheet"
icon_state = "sheet-plastitaniumglass"
item_state = "sheet-plastitaniumglass"
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT, MAT_PLASMA=MINERAL_MATERIAL_AMOUNT, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_PLASMA=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/plastitaniumglass
@@ -211,10 +211,9 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
if(W.is_sharp())
playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
user.visible_message("[user] starts cutting hair off \the [src].", "<span class='notice'>You start cutting the hair off \the [src]...</span>", "<span class='italics'>You hear the sound of a knife rubbing against flesh.</span>")
if(do_after(user,50, target = src))
if(do_after(user, 50, target = src))
to_chat(user, "<span class='notice'>You cut the hair from this [src.singular_name].</span>")
var/obj/item/stack/sheet/hairlesshide/HS = new(user.loc)
HS.amount = 1
new /obj/item/stack/sheet/hairlesshide(user.drop_location(), 1)
use(1)
else
return ..()
@@ -228,21 +227,11 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
if(exposed_temperature >= drying_threshold_temperature)
wetness--
if(wetness == 0)
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/sheet/leather/HS in src.loc)
if(HS.amount < 50)
HS.amount++
src.use(1)
wetness = initial(wetness)
break
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/sheet/leather/HS = new(src.loc)
HS.amount = 1
new /obj/item/stack/sheet/leather(drop_location(), 1)
wetness = initial(wetness)
src.use(1)
use(1)
/obj/item/stack/sheet/wetleather/microwave_act(obj/machinery/microwave/MW)
..()
var/obj/item/stack/sheet/leather/L = new(loc)
L.amount = amount
new /obj/item/stack/sheet/leather(drop_location(), amount)
qdel(src)
@@ -14,13 +14,12 @@
grind_results = list("silicon" = 20, "copper" = 5)
/obj/item/stack/light_w/attackby(obj/item/O, mob/user, params)
var/atom/Tsec = user.drop_location()
if(istype(O, /obj/item/wirecutters))
var/obj/item/stack/cable_coil/CC = new (user.loc)
CC.amount = 5
var/obj/item/stack/cable_coil/CC = new (Tsec, 5)
CC.add_fingerprint(user)
amount--
var/obj/item/stack/sheet/glass/G = new (user.loc)
var/obj/item/stack/sheet/glass/G = new (Tsec)
G.add_fingerprint(user)
if(amount <= 0)
qdel(src)
@@ -28,7 +27,6 @@
else if(istype(O, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = O
if (M.use(1))
use(1)
var/obj/item/L = new /obj/item/stack/tile/light(user.loc)
to_chat(user, "<span class='notice'>You make a light tile.</span>")
L.add_fingerprint(user)
@@ -121,6 +121,9 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
/obj/item/stack/sheet/metal/twenty
amount = 20
/obj/item/stack/sheet/metal/ten
amount = 10
/obj/item/stack/sheet/metal/five
amount = 5
@@ -349,6 +352,11 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \
if(!iscultist(user))
to_chat(user, "<span class='warning'>Only one with forbidden knowledge could hope to work this metal...</span>")
return
var/turf/T = get_turf(user) //we may have moved. adjust as needed...
var/area/A = get_area(user)
if((!is_station_level(T.z) && !is_mining_level(T.z)) || (A && !A.blob_allowed))
to_chat(user, "<span class='warning'>The veil is not weak enough here.</span>")
return FALSE
return ..()
/obj/item/stack/sheet/runed_metal/Initialize(mapload, new_amount, merge = TRUE)
+5 -2
View File
@@ -33,10 +33,13 @@
return
return TRUE
/obj/item/stack/Initialize(mapload, new_amount=null , merge = TRUE)
/obj/item/stack/Initialize(mapload, new_amount, merge = TRUE)
. = ..()
if(new_amount)
if(new_amount != null)
amount = new_amount
while(amount > max_amount)
amount -= max_amount
new type(loc, max_amount, FALSE)
if(!merge_type)
merge_type = type
if(merge)
+4 -2
View File
@@ -453,7 +453,7 @@
/obj/item/storage/backpack/duffelbag/syndie/ammo/shotgun/PopulateContents()
for(var/i in 1 to 6)
new /obj/item/ammo_box/magazine/m12g(src)
new /obj/item/ammo_box/magazine/m12g/buckshot(src)
new /obj/item/ammo_box/magazine/m12g/stun(src)
new /obj/item/ammo_box/magazine/m12g/slug(src)
new /obj/item/ammo_box/magazine/m12g/dragon(src)
@@ -479,7 +479,7 @@
/obj/item/storage/backpack/duffelbag/syndie/bulldogbundle/PopulateContents()
new /obj/item/ammo_box/magazine/m12g(src)
new /obj/item/gun/ballistic/automatic/shotgun/bulldog(src)
new /obj/item/ammo_box/magazine/m12g/buckshot(src)
new /obj/item/ammo_box/magazine/m12g/stun(src)
new /obj/item/clothing/glasses/thermal/syndi(src)
/obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle
@@ -511,6 +511,8 @@
new /obj/item/storage/box/syringes(src)
new /obj/item/ammo_box/foambox/riot(src)
new /obj/item/grenade/chem_grenade/bioterrorfoam(src)
if(prob(5))
new /obj/item/reagent_containers/food/snacks/pizza/pineapple(src)
/obj/item/storage/backpack/duffelbag/syndie/c4/PopulateContents()
for(var/i in 1 to 10)
+42
View File
@@ -966,3 +966,45 @@ obj/item/storage/box/clown
/obj/item/storage/box/holy_grenades/PopulateContents()
for(var/i in 1 to 7)
new/obj/item/grenade/chem_grenade/holy(src)
/obj/item/storage/box/stockparts/basic //for ruins where it's a bad idea to give access to an autolathe/protolathe, but still want to make stock parts accessible
name = "box of stock parts"
desc = "Contains a variety of basic stock parts."
/obj/item/storage/box/stockparts/basic/PopulateContents()
new /obj/item/stock_parts/capacitor(src)
new /obj/item/stock_parts/capacitor(src)
new /obj/item/stock_parts/capacitor(src)
new /obj/item/stock_parts/scanning_module(src)
new /obj/item/stock_parts/scanning_module(src)
new /obj/item/stock_parts/scanning_module(src)
new /obj/item/stock_parts/manipulator(src)
new /obj/item/stock_parts/manipulator(src)
new /obj/item/stock_parts/manipulator(src)
new /obj/item/stock_parts/micro_laser(src)
new /obj/item/stock_parts/micro_laser(src)
new /obj/item/stock_parts/micro_laser(src)
new /obj/item/stock_parts/matter_bin(src)
new /obj/item/stock_parts/matter_bin(src)
new /obj/item/stock_parts/matter_bin(src)
/obj/item/storage/box/stockparts/deluxe
name = "box of deluxe stock parts"
desc = "Contains a variety of deluxe stock parts."
/obj/item/storage/box/stockparts/deluxe/PopulateContents()
new /obj/item/stock_parts/capacitor/quadratic(src)
new /obj/item/stock_parts/capacitor/quadratic(src)
new /obj/item/stock_parts/capacitor/quadratic(src)
new /obj/item/stock_parts/scanning_module/triphasic(src)
new /obj/item/stock_parts/scanning_module/triphasic(src)
new /obj/item/stock_parts/scanning_module/triphasic(src)
new /obj/item/stock_parts/manipulator/femto(src)
new /obj/item/stock_parts/manipulator/femto(src)
new /obj/item/stock_parts/manipulator/femto(src)
new /obj/item/stock_parts/micro_laser/quadultra(src)
new /obj/item/stock_parts/micro_laser/quadultra(src)
new /obj/item/stock_parts/micro_laser/quadultra(src)
new /obj/item/stock_parts/matter_bin/bluespace(src)
new /obj/item/stock_parts/matter_bin/bluespace(src)
new /obj/item/stock_parts/matter_bin/bluespace(src)
@@ -111,8 +111,8 @@
new /obj/item/clothing/suit/space/hardsuit/syndi(src) // 8 tc
new /obj/item/gun/ballistic/automatic/shotgun/bulldog/unrestricted(src) // 8 tc
new /obj/item/implanter/explosive(src) // 2 tc
new /obj/item/ammo_box/magazine/m12g/buckshot(src) // 2 tc
new /obj/item/ammo_box/magazine/m12g/buckshot(src) // 2 tc
new /obj/item/ammo_box/magazine/m12g(src) // 2 tc
new /obj/item/ammo_box/magazine/m12g(src) // 2 tc
new /obj/item/grenade/plastic/c4 (src) // 1 tc
new /obj/item/grenade/plastic/c4 (src) // 1 tc
new /obj/item/card/emag(src) // 6 tc
@@ -280,7 +280,7 @@
new /obj/item/radio/headset/chameleon(src)
new /obj/item/stamp/chameleon(src)
new /obj/item/pda/chameleon(src)
new /obj/item/gun/energy/laser/chameleon(src)
//new /obj/item/gun/energy/laser/chameleon(src) //crashes the server right now. please fix it!
//5*(2*4) = 5*8 = 45, 45 damage if you hit one person with all 5 stars.
//Not counting the damage it will do while embedded (2*4 = 8, at 15% chance)
+95 -91
View File
@@ -1,91 +1,95 @@
/obj/item/storage/wallet
name = "wallet"
desc = "It can hold a few small and personal things."
icon_state = "wallet"
w_class = WEIGHT_CLASS_SMALL
resistance_flags = FLAMMABLE
slot_flags = SLOT_ID
var/obj/item/card/id/front_id = null
var/list/combined_access
/obj/item/storage/wallet/ComponentInitialize()
. = ..()
GET_COMPONENT(STR, /datum/component/storage)
STR.max_items = 4
STR.can_hold = typecacheof(list(
/obj/item/stack/spacecash,
/obj/item/card,
/obj/item/clothing/mask/cigarette,
/obj/item/flashlight/pen,
/obj/item/seeds,
/obj/item/stack/medical,
/obj/item/toy/crayon,
/obj/item/coin,
/obj/item/dice,
/obj/item/disk,
/obj/item/implanter,
/obj/item/lighter,
/obj/item/lipstick,
/obj/item/match,
/obj/item/paper,
/obj/item/pen,
/obj/item/photo,
/obj/item/reagent_containers/dropper,
/obj/item/reagent_containers/syringe,
/obj/item/screwdriver,
/obj/item/stamp))
/obj/item/storage/wallet/Exited(atom/movable/AM)
. = ..()
refreshID()
/obj/item/storage/wallet/proc/refreshID()
if(!(front_id in src))
front_id = null
for(var/obj/item/card/id/I in contents)
LAZYINITLIST(combined_access)
LAZYCLEARLIST(combined_access)
if(!front_id)
front_id = I
combined_access |= I.access
update_icon()
/obj/item/storage/wallet/Entered(atom/movable/AM)
. = ..()
refreshID()
/obj/item/storage/wallet/update_icon()
var/new_state = "wallet"
if(front_id)
new_state = "wallet_[front_id.icon_state]"
if(new_state != icon_state) //avoid so many icon state changes.
icon_state = new_state
/obj/item/storage/wallet/GetID()
return front_id
/obj/item/storage/wallet/GetAccess()
if(LAZYLEN(combined_access))
return combined_access
else
return ..()
/obj/item/storage/wallet/random
icon_state = "random_wallet"
/obj/item/storage/wallet/random/PopulateContents()
var/item1_type = pick( /obj/item/stack/spacecash/c10, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, /obj/item/stack/spacecash/c20, /obj/item/stack/spacecash/c200, /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c500)
var/item2_type
if(prob(50))
item2_type = pick( /obj/item/stack/spacecash/c10, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, /obj/item/stack/spacecash/c20, /obj/item/stack/spacecash/c200, /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c500)
var/item3_type = pick( /obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/gold, /obj/item/coin/iron, /obj/item/coin/iron, /obj/item/coin/iron )
spawn(2)
if(item1_type)
new item1_type(src)
if(item2_type)
new item2_type(src)
if(item3_type)
new item3_type(src)
update_icon()
/obj/item/storage/wallet
name = "wallet"
desc = "It can hold a few small and personal things."
icon_state = "wallet"
w_class = WEIGHT_CLASS_SMALL
resistance_flags = FLAMMABLE
slot_flags = SLOT_ID
var/obj/item/card/id/front_id = null
var/list/combined_access
/obj/item/storage/wallet/ComponentInitialize()
. = ..()
GET_COMPONENT(STR, /datum/component/storage)
STR.max_items = 4
STR.can_hold = typecacheof(list(
/obj/item/stack/spacecash,
/obj/item/card,
/obj/item/clothing/mask/cigarette,
/obj/item/flashlight/pen,
/obj/item/seeds,
/obj/item/stack/medical,
/obj/item/toy/crayon,
/obj/item/coin,
/obj/item/dice,
/obj/item/disk,
/obj/item/implanter,
/obj/item/lighter,
/obj/item/lipstick,
/obj/item/match,
/obj/item/paper,
/obj/item/pen,
/obj/item/photo,
/obj/item/reagent_containers/dropper,
/obj/item/reagent_containers/syringe,
/obj/item/screwdriver,
/obj/item/stamp))
/obj/item/storage/wallet/Exited(atom/movable/AM)
. = ..()
// The loc has not actually changed yet when this proc is called, so call
// refreshID and have it ignore the outgoing atom.
refreshID(AM)
/obj/item/storage/wallet/proc/refreshID(atom/movable/removed)
LAZYCLEARLIST(combined_access)
if(!(front_id in src) || front_id == removed)
front_id = null
for(var/obj/item/card/id/I in contents)
if(I == removed)
continue
if(!front_id)
front_id = I
LAZYINITLIST(combined_access)
combined_access |= I.access
update_icon()
/obj/item/storage/wallet/Entered(atom/movable/AM)
. = ..()
refreshID()
/obj/item/storage/wallet/update_icon()
var/new_state = "wallet"
if(front_id)
new_state = "wallet_[front_id.icon_state]"
if(new_state != icon_state) //avoid so many icon state changes.
icon_state = new_state
/obj/item/storage/wallet/GetID()
return front_id
/obj/item/storage/wallet/GetAccess()
if(LAZYLEN(combined_access))
return combined_access
else
return ..()
/obj/item/storage/wallet/random
icon_state = "random_wallet"
/obj/item/storage/wallet/random/PopulateContents()
var/item1_type = pick( /obj/item/stack/spacecash/c10, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, /obj/item/stack/spacecash/c20, /obj/item/stack/spacecash/c200, /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c500)
var/item2_type
if(prob(50))
item2_type = pick( /obj/item/stack/spacecash/c10, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, /obj/item/stack/spacecash/c20, /obj/item/stack/spacecash/c200, /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c500)
var/item3_type = pick( /obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/gold, /obj/item/coin/iron, /obj/item/coin/iron, /obj/item/coin/iron )
spawn(2)
if(item1_type)
new item1_type(src)
if(item2_type)
new item2_type(src)
if(item3_type)
new item3_type(src)
update_icon()
@@ -49,7 +49,6 @@
on = FALSE
to_chat(user, "<span class='warning'>You need a free hand to hold the mister!</span>")
return
noz.forceMove(user)
else
//Remove from their hands and put back "into" the tank
remove_noz()
+14
View File
@@ -219,3 +219,17 @@
if(active_portal_pairs[i] == P)
return DESTINATION_PORTAL
return FALSE
/obj/item/hand_tele/suicide_act(mob/user)
if(iscarbon(user))
user.visible_message("<span class='suicide'>[user] is creating a weak portal and sticking [user.p_their()] head through! It looks like [user.p_theyre()] trying to commit suicide!</span>")
var/mob/living/carbon/itemUser = user
var/obj/item/bodypart/head/head = itemUser.get_bodypart(BODY_ZONE_HEAD)
if(head)
head.drop_limb()
var/list/safeLevels = SSmapping.levels_by_any_trait(list(ZTRAIT_SPACE_RUINS, ZTRAIT_LAVA_RUINS, ZTRAIT_STATION, ZTRAIT_MINING))
head.forceMove(locate(rand(1, world.maxx), rand(1, world.maxy), pick(safeLevels)))
itemUser.visible_message("<span class='suicide'>The portal snaps closed taking [user]'s head with it!</span>")
else
itemUser.visible_message("<span class='suicide'>[user] looks even further depressed as they realize they do not have a head...and suddenly dies of shame!</span>")
return (BRUTELOSS)

Some files were not shown because too many files have changed in this diff Show More