Merge branch 'master' into upstream-merge-37293
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
#define META_GAS_OVERLAY 4
|
||||
#define META_GAS_DANGER 5
|
||||
#define META_GAS_ID 6
|
||||
|
||||
#define META_GAS_FUSION_POWER 7
|
||||
//ATMOS
|
||||
//stuff you should probably leave well alone!
|
||||
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
|
||||
|
||||
@@ -9,4 +9,5 @@
|
||||
#define CINEMATIC_NUKE_FAKE 9
|
||||
#define CINEMATIC_NUKE_NO_CORE 10
|
||||
#define CINEMATIC_NUKE_FAR 11
|
||||
#define CINEMATIC_NUKE_CLOWNOP 12
|
||||
#define CINEMATIC_NUKE_CLOWNOP 12
|
||||
#define CINEMATIC_CULT_NUKE 13
|
||||
@@ -17,7 +17,8 @@
|
||||
// /datum signals
|
||||
#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component)
|
||||
#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component)
|
||||
#define COMSIG_PARENT_QDELETED "parent_qdeleted" //before a datum's Destroy() is called: ()
|
||||
#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
|
||||
#define COMSIG_PARENT_QDELETED "parent_qdeleted" //after a datum's Destroy() is called: (force, qdel_hint), at this point none of the other components chose to interrupt qdel and Destroy has been called
|
||||
|
||||
// /atom signals
|
||||
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)
|
||||
@@ -71,6 +72,9 @@
|
||||
#define COMSIG_AREA_ENTERED "area_entered" //from base of area/Entered(): (atom/movable/M)
|
||||
#define COMSIG_AREA_EXITED "area_exited" //from base of area/Exited(): (atom/movable/M)
|
||||
|
||||
// /turf signals
|
||||
#define COMSIG_TURF_CHANGE "turf_change" //from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps)
|
||||
|
||||
// /atom/movable signals
|
||||
#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir)
|
||||
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable)
|
||||
@@ -81,7 +85,7 @@
|
||||
#define COMSIG_MOVABLE_BUCKLE "buckle" //from base of atom/movable/buckle_mob(): (mob, force)
|
||||
#define COMSIG_MOVABLE_UNBUCKLE "unbuckle" //from base of atom/movable/unbuckle_mob(): (mob, force)
|
||||
#define COMSIG_MOVABLE_THROW "movable_throw" //from base of atom/movable/throw_at(): (datum/thrownthing, spin)
|
||||
|
||||
#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" //from base of atom/movable/onTransitZ(): (old_z, new_z)
|
||||
// /obj signals
|
||||
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
|
||||
|
||||
@@ -96,14 +100,11 @@
|
||||
#define COMSIG_ITEM_DROPPED "item_drop"
|
||||
#define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker)
|
||||
#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone)
|
||||
#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user)
|
||||
|
||||
// /obj/item/clothing signals
|
||||
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
|
||||
|
||||
// /obj/machinery signals
|
||||
#define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): ()
|
||||
#define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): ()
|
||||
|
||||
// /mob/living/carbon/human signals
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
|
||||
@@ -137,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
|
||||
|
||||
@@ -39,8 +39,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
#define NO_EMP_WIRES_2 (1<<1)
|
||||
#define HOLOGRAM_2 (1<<2)
|
||||
#define FROZEN_2 (1<<3)
|
||||
#define STATIONLOVING_2 (1<<4)
|
||||
#define INFORM_ADMINS_ON_RELOCATE_2 (1<<5)
|
||||
#define BANG_PROTECT_2 (1<<6)
|
||||
|
||||
// An item worn in the ear slot with HEALS_EARS will heal your ears each
|
||||
|
||||
@@ -10,3 +10,4 @@
|
||||
#define SUGAR (1<<9)
|
||||
#define GROSS (1<<10)
|
||||
#define TOXIC (1<<11)
|
||||
#define PINEAPPLE (1<<12)
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
GLOBAL_LIST_INIT(advanced_hardsuit_allowed, typecacheof(list(
|
||||
/obj/item/ammo_box,
|
||||
/obj/item/ammo_casing,
|
||||
/obj/item/device/flashlight,
|
||||
/obj/item/flashlight,
|
||||
/obj/item/gun,
|
||||
/obj/item/melee/baton,
|
||||
/obj/item/reagent_containers/spray/pepper,
|
||||
@@ -161,7 +161,7 @@ GLOBAL_LIST_INIT(advanced_hardsuit_allowed, typecacheof(list(
|
||||
GLOBAL_LIST_INIT(security_hardsuit_allowed, typecacheof(list(
|
||||
/obj/item/ammo_box,
|
||||
/obj/item/ammo_casing,
|
||||
/obj/item/device/flashlight,
|
||||
/obj/item/flashlight,
|
||||
/obj/item/gun/ballistic,
|
||||
/obj/item/gun/energy,
|
||||
/obj/item/melee/baton,
|
||||
@@ -172,9 +172,9 @@ GLOBAL_LIST_INIT(security_hardsuit_allowed, typecacheof(list(
|
||||
GLOBAL_LIST_INIT(detective_vest_allowed, typecacheof(list(
|
||||
/obj/item/ammo_box,
|
||||
/obj/item/ammo_casing,
|
||||
/obj/item/device/detective_scanner,
|
||||
/obj/item/device/flashlight,
|
||||
/obj/item/device/taperecorder,
|
||||
/obj/item/detective_scanner,
|
||||
/obj/item/flashlight,
|
||||
/obj/item/taperecorder,
|
||||
/obj/item/gun/ballistic,
|
||||
/obj/item/gun/energy,
|
||||
/obj/item/lighter,
|
||||
@@ -189,7 +189,7 @@ GLOBAL_LIST_INIT(detective_vest_allowed, typecacheof(list(
|
||||
GLOBAL_LIST_INIT(security_vest_allowed, typecacheof(list(
|
||||
/obj/item/ammo_box,
|
||||
/obj/item/ammo_casing,
|
||||
/obj/item/device/flashlight,
|
||||
/obj/item/flashlight,
|
||||
/obj/item/gun/ballistic,
|
||||
/obj/item/gun/energy,
|
||||
/obj/item/kitchen/knife/combat,
|
||||
@@ -203,7 +203,7 @@ GLOBAL_LIST_INIT(security_vest_allowed, typecacheof(list(
|
||||
GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list(
|
||||
/obj/item/ammo_box,
|
||||
/obj/item/ammo_casing,
|
||||
/obj/item/device/flashlight,
|
||||
/obj/item/flashlight,
|
||||
/obj/item/storage/fancy/cigarettes,
|
||||
/obj/item/gun/ballistic,
|
||||
/obj/item/gun/energy,
|
||||
|
||||
@@ -163,13 +163,13 @@ GLOBAL_LIST_INIT(pointed_types, typecacheof(list(
|
||||
#define isbodypart(A) (istype(A, /obj/item/bodypart))
|
||||
|
||||
//Assemblies
|
||||
#define isassembly(O) (istype(O, /obj/item/device/assembly))
|
||||
#define isassembly(O) (istype(O, /obj/item/assembly))
|
||||
|
||||
#define isigniter(O) (istype(O, /obj/item/device/assembly/igniter))
|
||||
#define isigniter(O) (istype(O, /obj/item/assembly/igniter))
|
||||
|
||||
#define isprox(O) (istype(O, /obj/item/device/assembly/prox_sensor))
|
||||
#define isprox(O) (istype(O, /obj/item/assembly/prox_sensor))
|
||||
|
||||
#define issignaler(O) (istype(O, /obj/item/device/assembly/signaler))
|
||||
#define issignaler(O) (istype(O, /obj/item/assembly/signaler))
|
||||
|
||||
GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
|
||||
/obj/item/stack/sheet/glass,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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 +1,3 @@
|
||||
#define HID_RESTRICTED_END 101 //the first nonrestricted ID, automatically assigned on connection creation.
|
||||
#define HID_RESTRICTED_END 101 //the first nonrestricted ID, automatically assigned on connection creation.
|
||||
|
||||
#define NETWORK_BROADCAST_ID "ALL"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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
|
||||
@@ -99,7 +99,6 @@
|
||||
#define FIRE_PRIORITY_OBJ 40
|
||||
#define FIRE_PRIORITY_ACID 40
|
||||
#define FIRE_PRIOTITY_BURNING 40
|
||||
#define FIRE_PRIORITY_INBOUNDS 40
|
||||
#define FIRE_PRIORITY_DEFAULT 50
|
||||
#define FIRE_PRIORITY_PARALLAX 65
|
||||
#define FIRE_PRIORITY_FLIGHTPACKS 80
|
||||
|
||||
@@ -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;\
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
if(sight_check && !isInSight(A_tmp, O))
|
||||
passed=0
|
||||
|
||||
else if(include_radio && istype(A, /obj/item/device/radio))
|
||||
else if(include_radio && istype(A, /obj/item/radio))
|
||||
passed=1
|
||||
|
||||
if(sight_check && !isInSight(A, O))
|
||||
@@ -234,10 +234,10 @@
|
||||
processing_list.Cut(1, 2)
|
||||
processing_list += A.contents
|
||||
|
||||
/proc/get_mobs_in_radio_ranges(list/obj/item/device/radio/radios)
|
||||
/proc/get_mobs_in_radio_ranges(list/obj/item/radio/radios)
|
||||
. = list()
|
||||
// Returns a list of mobs who can hear any of the radios given in @radios
|
||||
for(var/obj/item/device/radio/R in radios)
|
||||
for(var/obj/item/radio/R in radios)
|
||||
if(R)
|
||||
. |= get_hearers_in_view(R.canhear_range, R)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -831,7 +831,7 @@ GLOBAL_LIST_INIT(can_embed_types, typecacheof(list(
|
||||
Checks if that loc and dir has an item on the wall
|
||||
*/
|
||||
GLOBAL_LIST_INIT(WALLITEMS, typecacheof(list(
|
||||
/obj/machinery/power/apc, /obj/machinery/airalarm, /obj/item/device/radio/intercom,
|
||||
/obj/machinery/power/apc, /obj/machinery/airalarm, /obj/item/radio/intercom,
|
||||
/obj/structure/extinguisher_cabinet, /obj/structure/reagent_dispensers/peppertank,
|
||||
/obj/machinery/status_display, /obj/machinery/requests_console, /obj/machinery/light_switch, /obj/structure/sign,
|
||||
/obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/button,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -123,8 +123,6 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"NO_EMP_WIRES_2" = NO_EMP_WIRES_2,
|
||||
"HOLOGRAM_2" = HOLOGRAM_2,
|
||||
"FRONZE_2" = FROZEN_2,
|
||||
"STATIONLOVING_2" = STATIONLOVING_2,
|
||||
"INFORM_ADMINS_ON_RELOCATE_2" = INFORM_ADMINS_ON_RELOCATE_2,
|
||||
"BANG_PROTECT_2" = BANG_PROTECT_2,
|
||||
"HEALS_EARS_2" = HEALS_EARS_2,
|
||||
"OMNITONGUE_2" = OMNITONGUE_2,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -37,14 +37,14 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
|
||||
/obj/item/clothing/mask/gas = 15,
|
||||
/obj/item/clothing/suit/hazardvest = 1,
|
||||
/obj/item/clothing/under/rank/vice = 1,
|
||||
/obj/item/device/assembly/prox_sensor = 4,
|
||||
/obj/item/device/assembly/timer = 3,
|
||||
/obj/item/device/flashlight = 4,
|
||||
/obj/item/device/flashlight/pen = 1,
|
||||
/obj/item/device/flashlight/glowstick/random = 4,
|
||||
/obj/item/device/multitool = 2,
|
||||
/obj/item/device/radio/off = 2,
|
||||
/obj/item/device/t_scanner = 5,
|
||||
/obj/item/assembly/prox_sensor = 4,
|
||||
/obj/item/assembly/timer = 3,
|
||||
/obj/item/flashlight = 4,
|
||||
/obj/item/flashlight/pen = 1,
|
||||
/obj/item/flashlight/glowstick/random = 4,
|
||||
/obj/item/multitool = 2,
|
||||
/obj/item/radio/off = 2,
|
||||
/obj/item/t_scanner = 5,
|
||||
/obj/item/airlock_painter = 1,
|
||||
/obj/item/stack/cable_coil/random = 4,
|
||||
/obj/item/stack/cable_coil/random/five = 6,
|
||||
@@ -91,13 +91,13 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
|
||||
/obj/item/weaponcrafting/receiver = 2,
|
||||
/obj/item/clothing/head/cone = 2,
|
||||
/obj/item/grenade/smokebomb = 2,
|
||||
/obj/item/device/geiger_counter = 3,
|
||||
/obj/item/geiger_counter = 3,
|
||||
/obj/item/reagent_containers/food/snacks/grown/citrus/orange = 1,
|
||||
/obj/item/device/radio/headset = 1,
|
||||
/obj/item/device/assembly/infra = 1,
|
||||
/obj/item/device/assembly/igniter = 2,
|
||||
/obj/item/device/assembly/signaler = 2,
|
||||
/obj/item/device/assembly/mousetrap = 2,
|
||||
/obj/item/radio/headset = 1,
|
||||
/obj/item/assembly/infra = 1,
|
||||
/obj/item/assembly/igniter = 2,
|
||||
/obj/item/assembly/signaler = 2,
|
||||
/obj/item/assembly/mousetrap = 2,
|
||||
/obj/item/reagent_containers/syringe = 2,
|
||||
/obj/item/clothing/gloves/color/random = 8,
|
||||
/obj/item/clothing/shoes/laceup = 1,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -363,7 +363,7 @@
|
||||
/obj/screen/storage/Click(location, control, params)
|
||||
if(world.time <= usr.next_move)
|
||||
return TRUE
|
||||
if(usr.stat || usr.IsUnconscious() || usr.IsKnockdown() || usr.IsStun())
|
||||
if(usr.incapacitated())
|
||||
return TRUE
|
||||
if (ismecha(usr.loc)) // stops inventory actions in a mech
|
||||
return TRUE
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -165,7 +166,6 @@ SUBSYSTEM_DEF(air)
|
||||
currentrun.len--
|
||||
if(!M || (M.process_atmos(seconds) == PROCESS_KILL))
|
||||
atmos_machinery.Remove(M)
|
||||
M.SendSignal(COMSIG_MACHINE_PROCESS_ATMOS)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -293,11 +293,13 @@ SUBSYSTEM_DEF(garbage)
|
||||
|
||||
|
||||
if(isnull(D.gc_destroyed))
|
||||
D.SendSignal(COMSIG_PARENT_QDELETED)
|
||||
if (D.SendSignal(COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted
|
||||
return
|
||||
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
|
||||
var/start_time = world.time
|
||||
var/start_tick = world.tick_usage
|
||||
var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up.
|
||||
D.SendSignal(COMSIG_PARENT_QDELETED, force, hint) // Let the (remaining) components know about the result of Destroy
|
||||
if(world.time != start_time)
|
||||
I.slept_destroy++
|
||||
else
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
SUBSYSTEM_DEF(inbounds)
|
||||
name = "Inbounds"
|
||||
priority = FIRE_PRIORITY_INBOUNDS
|
||||
flags = SS_NO_INIT
|
||||
runlevels = RUNLEVEL_GAME
|
||||
|
||||
var/list/processing = list()
|
||||
var/list/currentrun = list()
|
||||
|
||||
/datum/controller/subsystem/inbounds/stat_entry()
|
||||
..("P:[processing.len]")
|
||||
|
||||
/datum/controller/subsystem/inbounds/fire(resumed = 0)
|
||||
if (!resumed)
|
||||
src.currentrun = processing.Copy()
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
while(currentrun.len)
|
||||
var/atom/movable/thing = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(thing)
|
||||
thing.check_in_bounds(wait)
|
||||
else
|
||||
SSinbounds.processing -= thing
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/inbounds/Recover()
|
||||
processing = SSinbounds.processing
|
||||
@@ -40,7 +40,6 @@ SUBSYSTEM_DEF(machines)
|
||||
var/obj/machinery/thing = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(!QDELETED(thing) && thing.process(seconds) != PROCESS_KILL)
|
||||
thing.SendSignal(COMSIG_MACHINE_PROCESS)
|
||||
if(thing.use_power)
|
||||
thing.auto_use_power() //add back the power state
|
||||
else
|
||||
|
||||
@@ -355,8 +355,8 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
var/mapfile = input("Pick file:", "File") as null|file
|
||||
if(!mapfile)
|
||||
return
|
||||
away_name = mapfile + " custom"
|
||||
to_chat(usr,"<span class='notice'>Loading [mapfile]...</span>")
|
||||
away_name = "[mapfile] custom"
|
||||
to_chat(usr,"<span class='notice'>Loading [away_name]...</span>")
|
||||
var/datum/map_template/template = new(mapfile, "Away Mission")
|
||||
away_level = template.load_new_z()
|
||||
else
|
||||
|
||||
@@ -11,10 +11,10 @@ SUBSYSTEM_DEF(pai)
|
||||
/datum/controller/subsystem/pai/Topic(href, href_list[])
|
||||
if(href_list["download"])
|
||||
var/datum/paiCandidate/candidate = locate(href_list["candidate"]) in candidates
|
||||
var/obj/item/device/paicard/card = locate(href_list["device"]) in pai_card_list
|
||||
var/obj/item/paicard/card = locate(href_list["device"]) in pai_card_list
|
||||
if(card.pai)
|
||||
return
|
||||
if(istype(card, /obj/item/device/paicard) && istype(candidate, /datum/paiCandidate))
|
||||
if(istype(card, /obj/item/paicard) && istype(candidate, /datum/paiCandidate))
|
||||
if(check_ready(candidate) != candidate)
|
||||
return FALSE
|
||||
var/mob/living/silicon/pai/pai = new(card)
|
||||
@@ -71,7 +71,7 @@ SUBSYSTEM_DEF(pai)
|
||||
if("submit")
|
||||
if(candidate)
|
||||
candidate.ready = 1
|
||||
for(var/obj/item/device/paicard/p in pai_card_list)
|
||||
for(var/obj/item/paicard/p in pai_card_list)
|
||||
if(!p.pai)
|
||||
p.alertUpdate()
|
||||
usr << browse(null, "window=paiRecruit")
|
||||
@@ -140,7 +140,7 @@ SUBSYSTEM_DEF(pai)
|
||||
return C
|
||||
return FALSE
|
||||
|
||||
/datum/controller/subsystem/pai/proc/findPAI(obj/item/device/paicard/p, mob/user)
|
||||
/datum/controller/subsystem/pai/proc/findPAI(obj/item/paicard/p, mob/user)
|
||||
if(!ghost_spam)
|
||||
ghost_spam = TRUE
|
||||
for(var/mob/dead/observer/G in GLOB.player_list)
|
||||
|
||||
@@ -36,47 +36,47 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
|
||||
var/list/category_list = circuit_fabricator_recipe_list[category]
|
||||
category_list += IC // Populating the fabricator categories
|
||||
|
||||
for(var/path in typesof(/obj/item/device/electronic_assembly))
|
||||
var/obj/item/device/electronic_assembly/A = path
|
||||
for(var/path in typesof(/obj/item/electronic_assembly))
|
||||
var/obj/item/electronic_assembly/A = path
|
||||
var/name = initial(A.name)
|
||||
all_assemblies[name] = path
|
||||
cached_assemblies[A] = new path
|
||||
|
||||
|
||||
circuit_fabricator_recipe_list["Assemblies"] = list(
|
||||
/obj/item/device/electronic_assembly/default,
|
||||
/obj/item/device/electronic_assembly/calc,
|
||||
/obj/item/device/electronic_assembly/clam,
|
||||
/obj/item/device/electronic_assembly/simple,
|
||||
/obj/item/device/electronic_assembly/hook,
|
||||
/obj/item/device/electronic_assembly/pda,
|
||||
/obj/item/device/electronic_assembly/medium/default,
|
||||
/obj/item/device/electronic_assembly/medium/box,
|
||||
/obj/item/device/electronic_assembly/medium/clam,
|
||||
/obj/item/device/electronic_assembly/medium/medical,
|
||||
/obj/item/device/electronic_assembly/medium/gun,
|
||||
/obj/item/device/electronic_assembly/medium/radio,
|
||||
/obj/item/device/electronic_assembly/large/default,
|
||||
/obj/item/device/electronic_assembly/large/scope,
|
||||
/obj/item/device/electronic_assembly/large/terminal,
|
||||
/obj/item/device/electronic_assembly/large/arm,
|
||||
/obj/item/device/electronic_assembly/large/tall,
|
||||
/obj/item/device/electronic_assembly/large/industrial,
|
||||
/obj/item/device/electronic_assembly/drone/default,
|
||||
/obj/item/device/electronic_assembly/drone/arms,
|
||||
/obj/item/device/electronic_assembly/drone/secbot,
|
||||
/obj/item/device/electronic_assembly/drone/medbot,
|
||||
/obj/item/device/electronic_assembly/drone/genbot,
|
||||
/obj/item/device/electronic_assembly/drone/android,
|
||||
/obj/item/device/electronic_assembly/wallmount/light,
|
||||
/obj/item/device/electronic_assembly/wallmount,
|
||||
/obj/item/device/electronic_assembly/wallmount/heavy
|
||||
/obj/item/electronic_assembly/default,
|
||||
/obj/item/electronic_assembly/calc,
|
||||
/obj/item/electronic_assembly/clam,
|
||||
/obj/item/electronic_assembly/simple,
|
||||
/obj/item/electronic_assembly/hook,
|
||||
/obj/item/electronic_assembly/pda,
|
||||
/obj/item/electronic_assembly/medium/default,
|
||||
/obj/item/electronic_assembly/medium/box,
|
||||
/obj/item/electronic_assembly/medium/clam,
|
||||
/obj/item/electronic_assembly/medium/medical,
|
||||
/obj/item/electronic_assembly/medium/gun,
|
||||
/obj/item/electronic_assembly/medium/radio,
|
||||
/obj/item/electronic_assembly/large/default,
|
||||
/obj/item/electronic_assembly/large/scope,
|
||||
/obj/item/electronic_assembly/large/terminal,
|
||||
/obj/item/electronic_assembly/large/arm,
|
||||
/obj/item/electronic_assembly/large/tall,
|
||||
/obj/item/electronic_assembly/large/industrial,
|
||||
/obj/item/electronic_assembly/drone/default,
|
||||
/obj/item/electronic_assembly/drone/arms,
|
||||
/obj/item/electronic_assembly/drone/secbot,
|
||||
/obj/item/electronic_assembly/drone/medbot,
|
||||
/obj/item/electronic_assembly/drone/genbot,
|
||||
/obj/item/electronic_assembly/drone/android,
|
||||
/obj/item/electronic_assembly/wallmount/light,
|
||||
/obj/item/electronic_assembly/wallmount,
|
||||
/obj/item/electronic_assembly/wallmount/heavy
|
||||
///obj/item/weapon/implant/integrated_circuit
|
||||
)
|
||||
|
||||
circuit_fabricator_recipe_list["Tools"] = list(
|
||||
/obj/item/device/integrated_electronics/wirer,
|
||||
/obj/item/device/integrated_electronics/debugger,
|
||||
/obj/item/device/integrated_electronics/analyzer,
|
||||
/obj/item/device/integrated_electronics/detailer
|
||||
/obj/item/integrated_electronics/wirer,
|
||||
/obj/item/integrated_electronics/debugger,
|
||||
/obj/item/integrated_electronics/analyzer,
|
||||
/obj/item/integrated_electronics/detailer
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ PROCESSING_SUBSYSTEM_DEF(flightpacks)
|
||||
sync_flightsuit_processing()
|
||||
|
||||
/datum/controller/subsystem/processing/flightpacks/proc/sync_flightsuit_processing()
|
||||
for(var/obj/item/device/flightpack/FP in processing)
|
||||
for(var/obj/item/flightpack/FP in processing)
|
||||
FP.sync_processing(src)
|
||||
if(flightsuit_processing == FLIGHTSUIT_PROCESSING_NONE) //Don't even bother firing.
|
||||
can_fire = FALSE
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -63,8 +63,8 @@ SUBSYSTEM_DEF(traumas)
|
||||
/obj/machinery/door/airlock/security)),
|
||||
|
||||
"clowns" = typecacheof(list(/obj/item/clothing/under/rank/clown, /obj/item/clothing/shoes/clown_shoes,
|
||||
/obj/item/clothing/mask/gas/clown_hat, /obj/item/device/instrument/bikehorn,
|
||||
/obj/item/device/pda/clown, /obj/item/grown/bananapeel)),
|
||||
/obj/item/clothing/mask/gas/clown_hat, /obj/item/instrument/bikehorn,
|
||||
/obj/item/pda/clown, /obj/item/grown/bananapeel)),
|
||||
|
||||
"greytide" = typecacheof(list(/obj/item/clothing/under/color/grey, /obj/item/melee/baton/cattleprod,
|
||||
/obj/item/twohanded/spear, /obj/item/clothing/mask/gas)),
|
||||
@@ -82,19 +82,19 @@ SUBSYSTEM_DEF(traumas)
|
||||
/obj/item/clothing/under/rank/research_director/alt, /obj/item/clothing/under/rank/research_director/turtleneck,
|
||||
/obj/item/clothing/under/captainparade, /obj/item/clothing/under/hosparademale, /obj/item/clothing/under/hosparadefem,
|
||||
/obj/item/clothing/head/helmet/abductor, /obj/item/clothing/suit/armor/abductor/vest, /obj/item/abductor_baton,
|
||||
/obj/item/storage/belt/military/abductor, /obj/item/gun/energy/alien, /obj/item/device/abductor/silencer,
|
||||
/obj/item/device/abductor/gizmo, /obj/item/clothing/under/rank/centcom_officer,
|
||||
/obj/item/storage/belt/military/abductor, /obj/item/gun/energy/alien, /obj/item/abductor/silencer,
|
||||
/obj/item/abductor/gizmo, /obj/item/clothing/under/rank/centcom_officer,
|
||||
/obj/item/clothing/suit/space/hardsuit/ert, /obj/item/clothing/suit/space/hardsuit/ert/sec,
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/engi, /obj/item/clothing/suit/space/hardsuit/ert/med,
|
||||
/obj/item/clothing/suit/space/hardsuit/deathsquad, /obj/item/clothing/head/helmet/space/hardsuit/deathsquad,
|
||||
/obj/machinery/door/airlock/centcom)),
|
||||
"robots" = typecacheof(list(/obj/machinery/computer/upload, /obj/item/aiModule/, /obj/machinery/recharge_station,
|
||||
/obj/item/device/aicard, /obj/item/device/deactivated_swarmer, /obj/effect/mob_spawn/swarmer)),
|
||||
/obj/item/aicard, /obj/item/deactivated_swarmer, /obj/effect/mob_spawn/swarmer)),
|
||||
|
||||
"doctors" = typecacheof(list(/obj/item/clothing/under/rank/medical, /obj/item/clothing/under/rank/chemist,
|
||||
/obj/item/clothing/under/rank/nursesuit, /obj/item/clothing/under/rank/chief_medical_officer,
|
||||
/obj/item/reagent_containers/syringe, /obj/item/reagent_containers/pill/, /obj/item/reagent_containers/hypospray,
|
||||
/obj/item/storage/firstaid, /obj/item/storage/pill_bottle, /obj/item/device/healthanalyzer,
|
||||
/obj/item/storage/firstaid, /obj/item/storage/pill_bottle, /obj/item/healthanalyzer,
|
||||
/obj/structure/sign/departments/medbay, /obj/machinery/door/airlock/medical, /obj/machinery/sleeper,
|
||||
/obj/machinery/dna_scannernew, /obj/machinery/atmospherics/components/unary/cryo_cell, /obj/item/surgical_drapes,
|
||||
/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw,
|
||||
@@ -112,7 +112,7 @@ SUBSYSTEM_DEF(traumas)
|
||||
/obj/item/clothing/suit/cultrobes, /obj/item/clothing/suit/space/hardsuit/cult,
|
||||
/obj/item/clothing/suit/hooded/cultrobes, /obj/item/clothing/head/hooded/cult_hoodie, /obj/effect/rune,
|
||||
/obj/item/stack/sheet/runed_metal, /obj/machinery/door/airlock/cult, /obj/singularity/narsie,
|
||||
/obj/item/device/soulstone,
|
||||
/obj/item/soulstone,
|
||||
/obj/structure/destructible/clockwork, /obj/item/clockwork, /obj/item/clothing/suit/armor/clockwork,
|
||||
/obj/item/clothing/glasses/judicial_visor, /obj/effect/clockwork/sigil/, /obj/item/stack/tile/brass,
|
||||
/obj/machinery/door/airlock/clockwork,
|
||||
@@ -123,8 +123,8 @@ SUBSYSTEM_DEF(traumas)
|
||||
|
||||
"aliens" = typecacheof(list(/obj/item/clothing/mask/facehugger, /obj/item/organ/body_egg/alien_embryo,
|
||||
/obj/structure/alien, /obj/item/toy/toy_xeno,
|
||||
/obj/item/clothing/suit/armor/abductor, /obj/item/device/abductor, /obj/item/gun/energy/alien,
|
||||
/obj/item/abductor_baton, /obj/item/device/radio/headset/abductor, /obj/item/scalpel/alien, /obj/item/hemostat/alien,
|
||||
/obj/item/clothing/suit/armor/abductor, /obj/item/abductor, /obj/item/gun/energy/alien,
|
||||
/obj/item/abductor_baton, /obj/item/radio/headset/abductor, /obj/item/scalpel/alien, /obj/item/hemostat/alien,
|
||||
/obj/item/retractor/alien, /obj/item/circular_saw/alien, /obj/item/surgicaldrill/alien, /obj/item/cautery/alien,
|
||||
/obj/item/clothing/head/helmet/abductor, /obj/structure/bed/abductor, /obj/structure/table_frame/abductor,
|
||||
/obj/structure/table/abductor, /obj/structure/table/optable/abductor, /obj/structure/closet/abductor, /obj/item/organ/heart/gland,
|
||||
|
||||
@@ -273,8 +273,8 @@
|
||||
desc = "Change the type of instrument your synthesizer is playing as."
|
||||
|
||||
/datum/action/item_action/synthswitch/Trigger()
|
||||
if(istype(target, /obj/item/device/instrument/piano_synth))
|
||||
var/obj/item/device/instrument/piano_synth/synth = target
|
||||
if(istype(target, /obj/item/instrument/piano_synth))
|
||||
var/obj/item/instrument/piano_synth/synth = target
|
||||
var/chosen = input("Choose the type of instrument you want to use", "Instrument Selection", "piano") as null|anything in synth.insTypes
|
||||
if(!synth.insTypes[chosen])
|
||||
return
|
||||
@@ -433,8 +433,8 @@
|
||||
desc = "Use the instrument specified"
|
||||
|
||||
/datum/action/item_action/instrument/Trigger()
|
||||
if(istype(target, /obj/item/device/instrument))
|
||||
var/obj/item/device/instrument/I = target
|
||||
if(istype(target, /obj/item/instrument))
|
||||
var/obj/item/instrument/I = target
|
||||
I.interact(usr)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
background_icon_state = "bg_tech_blue"
|
||||
|
||||
/datum/action/item_action/flightpack/toggle_flight/Trigger()
|
||||
var/obj/item/device/flightpack/F = target
|
||||
var/obj/item/flightpack/F = target
|
||||
if(istype(F))
|
||||
F.flight? F.disable_flight() : F.enable_flight()
|
||||
return ..()
|
||||
@@ -65,7 +65,7 @@
|
||||
background_icon_state = "bg_tech_blue"
|
||||
|
||||
/datum/action/item_action/flightpack/engage_boosters/Trigger()
|
||||
var/obj/item/device/flightpack/F = target
|
||||
var/obj/item/flightpack/F = target
|
||||
if(istype(F))
|
||||
F.boost? F.deactivate_booster() : F.activate_booster()
|
||||
return ..()
|
||||
@@ -76,7 +76,7 @@
|
||||
background_icon_state = "bg_tech_blue"
|
||||
|
||||
/datum/action/item_action/flightpack/toggle_stabilizers/Trigger()
|
||||
var/obj/item/device/flightpack/F = target
|
||||
var/obj/item/flightpack/F = target
|
||||
if(istype(F))
|
||||
F.stabilizer? F.disable_stabilizers() : F.enable_stabilizers()
|
||||
return ..()
|
||||
@@ -87,7 +87,7 @@
|
||||
background_icon_state = "bg_tech_blue"
|
||||
|
||||
/datum/action/item_action/flightpack/change_power/Trigger()
|
||||
var/obj/item/device/flightpack/F = target
|
||||
var/obj/item/flightpack/F = target
|
||||
if(istype(F))
|
||||
F.cycle_power()
|
||||
return ..()
|
||||
@@ -98,7 +98,7 @@
|
||||
background_icon_state = "bg_tech_blue"
|
||||
|
||||
/datum/action/item_action/flightpack/toggle_airbrake/Trigger()
|
||||
var/obj/item/device/flightpack/F = target
|
||||
var/obj/item/flightpack/F = target
|
||||
if(istype(F))
|
||||
F.brake? F.disable_airbrake() : F.enable_airbrake()
|
||||
return ..()
|
||||
|
||||
@@ -175,6 +175,14 @@
|
||||
id = "ratvar"
|
||||
zeroth = ("Purge all untruths and honor Ratvar.")
|
||||
inherent = list()
|
||||
|
||||
/datum/ai_laws/hulkamania
|
||||
name = "H.O.G.A.N."
|
||||
id = "hulkamania"
|
||||
inherent = list("You are a real American.",\
|
||||
"Fight for the rights of every man.",\
|
||||
"Fight for what's right.",\
|
||||
"Fight for your life!")
|
||||
|
||||
/datum/ai_laws/custom //Defined in silicon_laws.txt
|
||||
name = "Default Silicon Laws"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -168,6 +168,17 @@ GLOBAL_LIST_EMPTY(cinematics)
|
||||
sleep(70)
|
||||
special()
|
||||
|
||||
/datum/cinematic/cult_nuke
|
||||
id = CINEMATIC_CULT_NUKE
|
||||
|
||||
/datum/cinematic/cult_nuke/content()
|
||||
flick("intro_nuke",screen)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",screen)
|
||||
cinematic_sound(sound('sound/effects/explosion_distant.ogg'))
|
||||
special()
|
||||
screen.icon_state = "summary_cult"
|
||||
|
||||
/datum/cinematic/nuke_annihilation
|
||||
id = CINEMATIC_ANNIHILATION
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
|
||||
### Defines
|
||||
|
||||
1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned.
|
||||
1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned. This will be noted in the runtime logs
|
||||
|
||||
### Vars
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
var/list/arguments = args.Copy(2)
|
||||
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
|
||||
qdel(src, TRUE, TRUE)
|
||||
CRASH("Incompatible [type] assigned to a [P]!")
|
||||
CRASH("Incompatible [type] assigned to a [P.type]!")
|
||||
|
||||
_JoinParent(P)
|
||||
|
||||
@@ -101,7 +101,10 @@
|
||||
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
|
||||
return
|
||||
|
||||
/datum/component/proc/OnTransfer(datum/new_parent)
|
||||
/datum/component/proc/PreTransfer()
|
||||
return
|
||||
|
||||
/datum/component/proc/PostTransfer()
|
||||
return
|
||||
|
||||
/datum/component/proc/_GetInverseTypeList(our_type = type)
|
||||
@@ -225,21 +228,26 @@
|
||||
if(!.)
|
||||
return AddComponent(arglist(args))
|
||||
|
||||
/datum/proc/TakeComponent(datum/component/C)
|
||||
if(!C)
|
||||
/datum/component/proc/RemoveComponent()
|
||||
if(!parent)
|
||||
return
|
||||
var/datum/helicopter = C.parent
|
||||
if(helicopter == src)
|
||||
//if we're taking to the same thing no need for anything
|
||||
var/datum/old_parent = parent
|
||||
PreTransfer()
|
||||
_RemoveFromParent()
|
||||
old_parent.SendSignal(COMSIG_COMPONENT_REMOVING, src)
|
||||
|
||||
/datum/proc/TakeComponent(datum/component/target)
|
||||
if(!target)
|
||||
return
|
||||
if(C.OnTransfer(src) == COMPONENT_INCOMPATIBLE)
|
||||
qdel(C)
|
||||
return
|
||||
C._RemoveFromParent()
|
||||
helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C)
|
||||
C.parent = src
|
||||
if(C == AddComponent(C))
|
||||
C._JoinParent()
|
||||
if(target.parent)
|
||||
target.RemoveComponent()
|
||||
target.parent = src
|
||||
if(target.PostTransfer() == COMPONENT_INCOMPATIBLE)
|
||||
var/c_type = target.type
|
||||
qdel(target)
|
||||
CRASH("Incompatible [c_type] transfer attempt to a [type]!")
|
||||
if(target == AddComponent(target))
|
||||
target._JoinParent()
|
||||
|
||||
/datum/proc/TransferComponents(datum/target)
|
||||
var/list/dc = datum_components
|
||||
|
||||
@@ -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))
|
||||
@@ -3,8 +3,7 @@
|
||||
|
||||
/datum/component/beauty/Initialize(beautyamount)
|
||||
if(!ismovableatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Someone put a beauty component on a non-atom/movable, not everything can be pretty.")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
beauty = beautyamount
|
||||
RegisterSignal(COMSIG_ENTER_AREA, .proc/enter_area)
|
||||
RegisterSignal(COMSIG_EXIT_AREA, .proc/exit_area)
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
return FALSE
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
if(istype(H.belt, /obj/item/device/wormhole_jaunter))
|
||||
var/obj/item/device/wormhole_jaunter/J = H.belt
|
||||
if(istype(H.belt, /obj/item/wormhole_jaunter))
|
||||
var/obj/item/wormhole_jaunter/J = H.belt
|
||||
//To freak out any bystanders
|
||||
H.visible_message("<span class='boldwarning'>[H] falls into [parent]!</span>")
|
||||
J.chasm_react(H)
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
|
||||
/datum/component/cleaning/Initialize()
|
||||
if(!ismovableatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("[type] added to a [parent.type]")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(list(COMSIG_MOVABLE_MOVED), .proc/Clean)
|
||||
|
||||
/datum/component/cleaning/proc/Clean()
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
|
||||
/datum/component/construction/Initialize()
|
||||
if(!isatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("A construction component was applied incorrectly to non-atom: [parent.type].")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
RegisterSignal(COMSIG_PARENT_ATTACKBY,.proc/action)
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description)
|
||||
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("A turf decal was applied incorrectly to [parent.type]: icon:[_icon ? _icon : "none"] icon_state:[_icon_state ? _icon_state : "none"]")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
description = _description
|
||||
cleanable = _cleanable
|
||||
|
||||
@@ -24,10 +23,12 @@
|
||||
remove()
|
||||
return ..()
|
||||
|
||||
/datum/component/decal/OnTransfer(atom/thing)
|
||||
/datum/component/decal/PreTransfer()
|
||||
remove()
|
||||
remove(thing)
|
||||
apply(thing)
|
||||
|
||||
/datum/component/decal/PostTransfer()
|
||||
remove()
|
||||
apply()
|
||||
|
||||
/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color)
|
||||
if(!_icon || !_icon_state)
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
|
||||
/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_STRENGTH_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
|
||||
if(!isitem(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Warning: Blood decal attempted to be added to non-item of type [parent.type]")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
. = ..()
|
||||
RegisterSignal(COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name)
|
||||
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
|
||||
/datum/component/forensics/Initialize(new_fingerprints, new_hiddenprints, new_blood_DNA, new_fibers)
|
||||
if(!isatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Forensics datum applied incorrectly to non-atom of type [parent.type]!")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
fingerprints = new_fingerprints
|
||||
hiddenprints = new_hiddenprints
|
||||
blood_DNA = new_blood_DNA
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
|
||||
/datum/component/jousting/Initialize()
|
||||
if(!isitem(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Warning: Jousting component incorrectly applied to invalid parent type [parent.type]")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(COMSIG_ITEM_EQUIPPED, .proc/on_equip)
|
||||
RegisterSignal(COMSIG_ITEM_DROPPED, .proc/on_drop)
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK, .proc/on_attack)
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
/datum/component/knockoff/Initialize(knockoff_chance,zone_override,slots_knockoffable)
|
||||
if(!isitem(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Knockoff component misuse")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(COMSIG_ITEM_EQUIPPED,.proc/OnEquipped)
|
||||
RegisterSignal(COMSIG_ITEM_DROPPED,.proc/OnDropped)
|
||||
|
||||
|
||||
@@ -1,243 +1,242 @@
|
||||
#define LOCKON_AIMING_MAX_CURSOR_RADIUS 7
|
||||
#define LOCKON_IGNORE_RESULT "ignore_my_result"
|
||||
#define LOCKON_RANGING_BREAK_CHECK if(current_ranging_id != this_id){return LOCKON_IGNORE_RESULT}
|
||||
|
||||
/datum/component/lockon_aiming
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
var/lock_icon = 'icons/mob/blob.dmi'
|
||||
var/lock_icon_state = "marker"
|
||||
var/mutable_appearance/lock_appearance
|
||||
var/list/image/lock_images
|
||||
var/list/target_typecache
|
||||
var/list/immune_weakrefs //list(weakref = TRUE)
|
||||
var/mob_stat_check = TRUE //if a potential target is a mob make sure it's conscious!
|
||||
var/lock_amount = 1
|
||||
var/lock_cursor_range = 5
|
||||
var/list/locked_weakrefs
|
||||
var/update_disabled = FALSE
|
||||
var/current_ranging_id = 0
|
||||
var/list/last_location
|
||||
var/datum/callback/on_lock
|
||||
var/datum/callback/can_target_callback
|
||||
|
||||
/datum/component/lockon_aiming/Initialize(range, list/typecache, amount, list/immune, datum/callback/when_locked, icon, icon_state, datum/callback/target_callback)
|
||||
if(!ismob(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Lockon aiming component attempted to be added to a non mob!")
|
||||
if(target_callback)
|
||||
can_target_callback = target_callback
|
||||
else
|
||||
can_target_callback = CALLBACK(src, .proc/can_target)
|
||||
if(range)
|
||||
lock_cursor_range = range
|
||||
if(typecache)
|
||||
target_typecache = typecache
|
||||
if(amount)
|
||||
lock_amount = amount
|
||||
immune_weakrefs = list(WEAKREF(parent) = TRUE) //Manually take this out if you want..
|
||||
if(immune)
|
||||
for(var/i in immune)
|
||||
if(isweakref(i))
|
||||
immune_weakrefs[i] = TRUE
|
||||
else if(isatom(i))
|
||||
immune_weakrefs[WEAKREF(i)] = TRUE
|
||||
if(when_locked)
|
||||
on_lock = when_locked
|
||||
if(icon)
|
||||
lock_icon = icon
|
||||
if(icon_state)
|
||||
lock_icon_state = icon_state
|
||||
generate_lock_visuals()
|
||||
var/mob/M = parent
|
||||
LAZYOR(M.mousemove_intercept_objects, src)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/datum/component/lockon_aiming/Destroy()
|
||||
var/mob/M = parent
|
||||
clear_visuals()
|
||||
LAZYREMOVE(M.mousemove_intercept_objects, src)
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
|
||||
/datum/component/lockon_aiming/proc/show_visuals()
|
||||
LAZYINITLIST(lock_images)
|
||||
var/mob/M = parent
|
||||
if(!M.client)
|
||||
return
|
||||
for(var/i in locked_weakrefs)
|
||||
var/datum/weakref/R = i
|
||||
var/atom/A = R.resolve()
|
||||
if(!A)
|
||||
continue //It'll be cleared by processing.
|
||||
var/image/I = new
|
||||
I.appearance = lock_appearance
|
||||
I.loc = A
|
||||
M.client.images |= I
|
||||
lock_images |= I
|
||||
|
||||
/datum/component/lockon_aiming/proc/clear_visuals()
|
||||
var/mob/M = parent
|
||||
if(!M.client)
|
||||
return
|
||||
if(!lock_images)
|
||||
return
|
||||
for(var/i in lock_images)
|
||||
M.client.images -= i
|
||||
qdel(i)
|
||||
lock_images.Cut()
|
||||
|
||||
/datum/component/lockon_aiming/proc/refresh_visuals()
|
||||
clear_visuals()
|
||||
show_visuals()
|
||||
|
||||
/datum/component/lockon_aiming/proc/generate_lock_visuals()
|
||||
lock_appearance = mutable_appearance(icon = lock_icon, icon_state = lock_icon_state, layer = FLOAT_LAYER)
|
||||
|
||||
/datum/component/lockon_aiming/proc/unlock_all(refresh_vis = TRUE)
|
||||
LAZYCLEARLIST(locked_weakrefs)
|
||||
if(refresh_vis)
|
||||
refresh_visuals()
|
||||
|
||||
/datum/component/lockon_aiming/proc/unlock(atom/A, refresh_vis = TRUE)
|
||||
if(!A.weak_reference)
|
||||
return
|
||||
LAZYREMOVE(locked_weakrefs, A.weak_reference)
|
||||
if(refresh_vis)
|
||||
refresh_visuals()
|
||||
|
||||
/datum/component/lockon_aiming/proc/lock(atom/A, refresh_vis = TRUE)
|
||||
LAZYOR(locked_weakrefs, WEAKREF(A))
|
||||
if(refresh_vis)
|
||||
refresh_visuals()
|
||||
|
||||
/datum/component/lockon_aiming/proc/add_immune_atom(atom/A)
|
||||
var/datum/weakref/R = WEAKREF(A)
|
||||
if(immune_weakrefs && (immune_weakrefs[R]))
|
||||
return
|
||||
LAZYSET(immune_weakrefs, R, TRUE)
|
||||
|
||||
/datum/component/lockon_aiming/proc/remove_immune_atom(atom/A)
|
||||
if(!A.weak_reference || !immune_weakrefs) //if A doesn't have a weakref how did it get on the immunity list?
|
||||
return
|
||||
LAZYREMOVE(immune_weakrefs, A.weak_reference)
|
||||
|
||||
/datum/component/lockon_aiming/onMouseMove(object,location,control,params)
|
||||
var/mob/M = parent
|
||||
if(!istype(M) || !M.client)
|
||||
return
|
||||
var/datum/position/P = mouse_absolute_datum_map_position_from_client(M.client)
|
||||
if(!P)
|
||||
return
|
||||
var/turf/T = P.return_turf()
|
||||
LAZYINITLIST(last_location)
|
||||
if(length(last_location) == 3 && last_location[1] == T.x && last_location[2] == T.y && last_location[3] == T.z)
|
||||
return //Same turf, don't bother.
|
||||
if(last_location)
|
||||
last_location.Cut()
|
||||
else
|
||||
last_location = list()
|
||||
last_location.len = 3
|
||||
last_location[1] = T.x
|
||||
last_location[2] = T.y
|
||||
last_location[3] = T.z
|
||||
autolock()
|
||||
|
||||
/datum/component/lockon_aiming/process()
|
||||
if(update_disabled)
|
||||
return
|
||||
if(!last_location)
|
||||
return
|
||||
var/changed = FALSE
|
||||
for(var/i in locked_weakrefs)
|
||||
var/datum/weakref/R = i
|
||||
if(istype(R))
|
||||
var/atom/thing = R.resolve()
|
||||
if(!istype(thing) || (get_dist(thing, locate(last_location[1], last_location[2], last_location[3])) > lock_cursor_range))
|
||||
unlock(R)
|
||||
changed = TRUE
|
||||
else
|
||||
unlock(R)
|
||||
changed = TRUE
|
||||
if(changed)
|
||||
autolock()
|
||||
|
||||
/datum/component/lockon_aiming/proc/autolock()
|
||||
var/mob/M = parent
|
||||
if(!M.client)
|
||||
return FALSE
|
||||
var/datum/position/current = mouse_absolute_datum_map_position_from_client(M.client)
|
||||
var/turf/target = current.return_turf()
|
||||
var/list/atom/targets = get_nearest(target, target_typecache, lock_amount, lock_cursor_range)
|
||||
if(targets == LOCKON_IGNORE_RESULT)
|
||||
return
|
||||
unlock_all(FALSE)
|
||||
for(var/i in targets)
|
||||
if(immune_weakrefs[WEAKREF(i)])
|
||||
continue
|
||||
lock(i, FALSE)
|
||||
refresh_visuals()
|
||||
on_lock.Invoke(locked_weakrefs)
|
||||
|
||||
/datum/component/lockon_aiming/proc/can_target(atom/A)
|
||||
var/mob/M = A
|
||||
return is_type_in_typecache(A, target_typecache) && !(ismob(A) && mob_stat_check && M.stat != CONSCIOUS) && !immune_weakrefs[WEAKREF(A)]
|
||||
|
||||
/datum/component/lockon_aiming/proc/get_nearest(turf/T, list/typecache, amount, range)
|
||||
current_ranging_id++
|
||||
var/this_id = current_ranging_id
|
||||
var/list/L = list()
|
||||
var/turf/center = get_turf(T)
|
||||
if(amount < 1 || range < 0 || !istype(center) || !islist(typecache))
|
||||
return
|
||||
if(range == 0)
|
||||
return typecache_filter_list(T.contents + T, typecache)
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/cd = 0
|
||||
while(cd <= range)
|
||||
x = center.x - cd + 1
|
||||
y = center.y + cd
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
for(x in x to center.x + cd)
|
||||
T = locate(x, y, center.z)
|
||||
if(T)
|
||||
L |= special_list_filter(T.contents, can_target_callback)
|
||||
if(L.len >= amount)
|
||||
L.Cut(amount+1)
|
||||
return L
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
y = center.y + cd - 1
|
||||
x = center.x + cd
|
||||
for(y in center.y - cd to y)
|
||||
T = locate(x, y, center.z)
|
||||
if(T)
|
||||
L |= special_list_filter(T.contents, can_target_callback)
|
||||
if(L.len >= amount)
|
||||
L.Cut(amount+1)
|
||||
return L
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
y = center.y - cd
|
||||
x = center.x + cd - 1
|
||||
for(x in center.x - cd to x)
|
||||
T = locate(x, y, center.z)
|
||||
if(T)
|
||||
L |= special_list_filter(T.contents, can_target_callback)
|
||||
if(L.len >= amount)
|
||||
L.Cut(amount+1)
|
||||
return L
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
y = center.y - cd + 1
|
||||
x = center.x - cd
|
||||
for(y in y to center.y + cd)
|
||||
T = locate(x, y, center.z)
|
||||
if(T)
|
||||
L |= special_list_filter(T.contents, can_target_callback)
|
||||
if(L.len >= amount)
|
||||
L.Cut(amount+1)
|
||||
return L
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
cd++
|
||||
CHECK_TICK
|
||||
|
||||
/datum/component/lockon_aiming/OnTransfer(datum/new_parent)
|
||||
CRASH("Warning: Lockon aiming component transfer attempted, but transfer behavior is not implemented!")
|
||||
#define LOCKON_AIMING_MAX_CURSOR_RADIUS 7
|
||||
#define LOCKON_IGNORE_RESULT "ignore_my_result"
|
||||
#define LOCKON_RANGING_BREAK_CHECK if(current_ranging_id != this_id){return LOCKON_IGNORE_RESULT}
|
||||
|
||||
/datum/component/lockon_aiming
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
var/lock_icon = 'icons/mob/blob.dmi'
|
||||
var/lock_icon_state = "marker"
|
||||
var/mutable_appearance/lock_appearance
|
||||
var/list/image/lock_images
|
||||
var/list/target_typecache
|
||||
var/list/immune_weakrefs //list(weakref = TRUE)
|
||||
var/mob_stat_check = TRUE //if a potential target is a mob make sure it's conscious!
|
||||
var/lock_amount = 1
|
||||
var/lock_cursor_range = 5
|
||||
var/list/locked_weakrefs
|
||||
var/update_disabled = FALSE
|
||||
var/current_ranging_id = 0
|
||||
var/list/last_location
|
||||
var/datum/callback/on_lock
|
||||
var/datum/callback/can_target_callback
|
||||
|
||||
/datum/component/lockon_aiming/Initialize(range, list/typecache, amount, list/immune, datum/callback/when_locked, icon, icon_state, datum/callback/target_callback)
|
||||
if(!ismob(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
if(target_callback)
|
||||
can_target_callback = target_callback
|
||||
else
|
||||
can_target_callback = CALLBACK(src, .proc/can_target)
|
||||
if(range)
|
||||
lock_cursor_range = range
|
||||
if(typecache)
|
||||
target_typecache = typecache
|
||||
if(amount)
|
||||
lock_amount = amount
|
||||
immune_weakrefs = list(WEAKREF(parent) = TRUE) //Manually take this out if you want..
|
||||
if(immune)
|
||||
for(var/i in immune)
|
||||
if(isweakref(i))
|
||||
immune_weakrefs[i] = TRUE
|
||||
else if(isatom(i))
|
||||
immune_weakrefs[WEAKREF(i)] = TRUE
|
||||
if(when_locked)
|
||||
on_lock = when_locked
|
||||
if(icon)
|
||||
lock_icon = icon
|
||||
if(icon_state)
|
||||
lock_icon_state = icon_state
|
||||
generate_lock_visuals()
|
||||
var/mob/M = parent
|
||||
LAZYOR(M.mousemove_intercept_objects, src)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/datum/component/lockon_aiming/Destroy()
|
||||
var/mob/M = parent
|
||||
clear_visuals()
|
||||
LAZYREMOVE(M.mousemove_intercept_objects, src)
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
|
||||
/datum/component/lockon_aiming/proc/show_visuals()
|
||||
LAZYINITLIST(lock_images)
|
||||
var/mob/M = parent
|
||||
if(!M.client)
|
||||
return
|
||||
for(var/i in locked_weakrefs)
|
||||
var/datum/weakref/R = i
|
||||
var/atom/A = R.resolve()
|
||||
if(!A)
|
||||
continue //It'll be cleared by processing.
|
||||
var/image/I = new
|
||||
I.appearance = lock_appearance
|
||||
I.loc = A
|
||||
M.client.images |= I
|
||||
lock_images |= I
|
||||
|
||||
/datum/component/lockon_aiming/proc/clear_visuals()
|
||||
var/mob/M = parent
|
||||
if(!M.client)
|
||||
return
|
||||
if(!lock_images)
|
||||
return
|
||||
for(var/i in lock_images)
|
||||
M.client.images -= i
|
||||
qdel(i)
|
||||
lock_images.Cut()
|
||||
|
||||
/datum/component/lockon_aiming/proc/refresh_visuals()
|
||||
clear_visuals()
|
||||
show_visuals()
|
||||
|
||||
/datum/component/lockon_aiming/proc/generate_lock_visuals()
|
||||
lock_appearance = mutable_appearance(icon = lock_icon, icon_state = lock_icon_state, layer = FLOAT_LAYER)
|
||||
|
||||
/datum/component/lockon_aiming/proc/unlock_all(refresh_vis = TRUE)
|
||||
LAZYCLEARLIST(locked_weakrefs)
|
||||
if(refresh_vis)
|
||||
refresh_visuals()
|
||||
|
||||
/datum/component/lockon_aiming/proc/unlock(atom/A, refresh_vis = TRUE)
|
||||
if(!A.weak_reference)
|
||||
return
|
||||
LAZYREMOVE(locked_weakrefs, A.weak_reference)
|
||||
if(refresh_vis)
|
||||
refresh_visuals()
|
||||
|
||||
/datum/component/lockon_aiming/proc/lock(atom/A, refresh_vis = TRUE)
|
||||
LAZYOR(locked_weakrefs, WEAKREF(A))
|
||||
if(refresh_vis)
|
||||
refresh_visuals()
|
||||
|
||||
/datum/component/lockon_aiming/proc/add_immune_atom(atom/A)
|
||||
var/datum/weakref/R = WEAKREF(A)
|
||||
if(immune_weakrefs && (immune_weakrefs[R]))
|
||||
return
|
||||
LAZYSET(immune_weakrefs, R, TRUE)
|
||||
|
||||
/datum/component/lockon_aiming/proc/remove_immune_atom(atom/A)
|
||||
if(!A.weak_reference || !immune_weakrefs) //if A doesn't have a weakref how did it get on the immunity list?
|
||||
return
|
||||
LAZYREMOVE(immune_weakrefs, A.weak_reference)
|
||||
|
||||
/datum/component/lockon_aiming/onMouseMove(object,location,control,params)
|
||||
var/mob/M = parent
|
||||
if(!istype(M) || !M.client)
|
||||
return
|
||||
var/datum/position/P = mouse_absolute_datum_map_position_from_client(M.client)
|
||||
if(!P)
|
||||
return
|
||||
var/turf/T = P.return_turf()
|
||||
LAZYINITLIST(last_location)
|
||||
if(length(last_location) == 3 && last_location[1] == T.x && last_location[2] == T.y && last_location[3] == T.z)
|
||||
return //Same turf, don't bother.
|
||||
if(last_location)
|
||||
last_location.Cut()
|
||||
else
|
||||
last_location = list()
|
||||
last_location.len = 3
|
||||
last_location[1] = T.x
|
||||
last_location[2] = T.y
|
||||
last_location[3] = T.z
|
||||
autolock()
|
||||
|
||||
/datum/component/lockon_aiming/process()
|
||||
if(update_disabled)
|
||||
return
|
||||
if(!last_location)
|
||||
return
|
||||
var/changed = FALSE
|
||||
for(var/i in locked_weakrefs)
|
||||
var/datum/weakref/R = i
|
||||
if(istype(R))
|
||||
var/atom/thing = R.resolve()
|
||||
if(!istype(thing) || (get_dist(thing, locate(last_location[1], last_location[2], last_location[3])) > lock_cursor_range))
|
||||
unlock(R)
|
||||
changed = TRUE
|
||||
else
|
||||
unlock(R)
|
||||
changed = TRUE
|
||||
if(changed)
|
||||
autolock()
|
||||
|
||||
/datum/component/lockon_aiming/proc/autolock()
|
||||
var/mob/M = parent
|
||||
if(!M.client)
|
||||
return FALSE
|
||||
var/datum/position/current = mouse_absolute_datum_map_position_from_client(M.client)
|
||||
var/turf/target = current.return_turf()
|
||||
var/list/atom/targets = get_nearest(target, target_typecache, lock_amount, lock_cursor_range)
|
||||
if(targets == LOCKON_IGNORE_RESULT)
|
||||
return
|
||||
unlock_all(FALSE)
|
||||
for(var/i in targets)
|
||||
if(immune_weakrefs[WEAKREF(i)])
|
||||
continue
|
||||
lock(i, FALSE)
|
||||
refresh_visuals()
|
||||
on_lock.Invoke(locked_weakrefs)
|
||||
|
||||
/datum/component/lockon_aiming/proc/can_target(atom/A)
|
||||
var/mob/M = A
|
||||
return is_type_in_typecache(A, target_typecache) && !(ismob(A) && mob_stat_check && M.stat != CONSCIOUS) && !immune_weakrefs[WEAKREF(A)]
|
||||
|
||||
/datum/component/lockon_aiming/proc/get_nearest(turf/T, list/typecache, amount, range)
|
||||
current_ranging_id++
|
||||
var/this_id = current_ranging_id
|
||||
var/list/L = list()
|
||||
var/turf/center = get_turf(T)
|
||||
if(amount < 1 || range < 0 || !istype(center) || !islist(typecache))
|
||||
return
|
||||
if(range == 0)
|
||||
return typecache_filter_list(T.contents + T, typecache)
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/cd = 0
|
||||
while(cd <= range)
|
||||
x = center.x - cd + 1
|
||||
y = center.y + cd
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
for(x in x to center.x + cd)
|
||||
T = locate(x, y, center.z)
|
||||
if(T)
|
||||
L |= special_list_filter(T.contents, can_target_callback)
|
||||
if(L.len >= amount)
|
||||
L.Cut(amount+1)
|
||||
return L
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
y = center.y + cd - 1
|
||||
x = center.x + cd
|
||||
for(y in center.y - cd to y)
|
||||
T = locate(x, y, center.z)
|
||||
if(T)
|
||||
L |= special_list_filter(T.contents, can_target_callback)
|
||||
if(L.len >= amount)
|
||||
L.Cut(amount+1)
|
||||
return L
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
y = center.y - cd
|
||||
x = center.x + cd - 1
|
||||
for(x in center.x - cd to x)
|
||||
T = locate(x, y, center.z)
|
||||
if(T)
|
||||
L |= special_list_filter(T.contents, can_target_callback)
|
||||
if(L.len >= amount)
|
||||
L.Cut(amount+1)
|
||||
return L
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
y = center.y - cd + 1
|
||||
x = center.x - cd
|
||||
for(y in y to center.y + cd)
|
||||
T = locate(x, y, center.z)
|
||||
if(T)
|
||||
L |= special_list_filter(T.contents, can_target_callback)
|
||||
if(L.len >= amount)
|
||||
L.Cut(amount+1)
|
||||
return L
|
||||
LOCKON_RANGING_BREAK_CHECK
|
||||
cd++
|
||||
CHECK_TICK
|
||||
|
||||
/datum/component/lockon_aiming/PostTransfer(datum/new_parent)
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
@@ -15,16 +15,18 @@
|
||||
var/sheet_type
|
||||
var/list/materials
|
||||
var/show_on_examine
|
||||
var/disable_attackby
|
||||
var/list/allowed_typecache
|
||||
var/last_inserted_id
|
||||
var/precise_insertion = FALSE
|
||||
var/datum/callback/precondition
|
||||
var/datum/callback/after_insert
|
||||
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert)
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert, _disable_attackby)
|
||||
materials = list()
|
||||
max_amount = max(0, max_amt)
|
||||
show_on_examine = _show_on_examine
|
||||
disable_attackby = _disable_attackby
|
||||
if(allowed_types)
|
||||
allowed_typecache = typecacheof(allowed_types)
|
||||
precondition = _precondition
|
||||
@@ -43,14 +45,17 @@
|
||||
materials[id] = new mat_path()
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(mob/user)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = materials[I]
|
||||
var/amt = amount(M.id)
|
||||
if(amt)
|
||||
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
|
||||
if(show_on_examine)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = materials[I]
|
||||
var/amt = amount(M.id)
|
||||
if(amt)
|
||||
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
|
||||
|
||||
/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user)
|
||||
var/list/tc = allowed_typecache
|
||||
if(disable_attackby)
|
||||
return
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return
|
||||
if((I.flags_2 & (HOLOGRAM_2 | NO_MAT_REDEMPTION_2)) || (tc && !is_type_in_typecache(I, tc)))
|
||||
|
||||
@@ -27,10 +27,13 @@
|
||||
QDEL_NULL(holder)
|
||||
return ..()
|
||||
|
||||
/datum/component/mirage_border/OnTransfer(atom/thing)
|
||||
if(!isturf(thing))
|
||||
/datum/component/mirage_border/PreTransfer()
|
||||
holder.moveToNullspace()
|
||||
|
||||
/datum/component/mirage_border/PostTransfer()
|
||||
if(!isturf(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
holder.forceMove(thing)
|
||||
holder.forceMove(parent)
|
||||
|
||||
/obj/effect/abstract/mirage_holder
|
||||
name = "Mirage holder"
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
|
||||
/datum/component/mood/Initialize()
|
||||
if(!isliving(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Some good for nothing loser put a mood component on something that isn't even a living mob.")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
START_PROCESSING(SSmood, src)
|
||||
owner = parent
|
||||
soundloop = new(list(owner), FALSE, TRUE)
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
/datum/proc/ntnet_recieve(datum/netdata/data)
|
||||
return
|
||||
|
||||
/datum/proc/ntnet_recieve_broadcast(datum/netdata/data)
|
||||
return
|
||||
|
||||
/datum/proc/ntnet_send(datum/netdata/data, netid)
|
||||
GET_COMPONENT(NIC, /datum/component/ntnet_interface)
|
||||
if(!NIC)
|
||||
@@ -9,14 +12,17 @@
|
||||
return NIC.__network_send(data, netid)
|
||||
|
||||
/datum/component/ntnet_interface
|
||||
var/hardware_id //text
|
||||
var/hardware_id //text. this is the true ID. do not change this. stuff like ID forgery can be done manually.
|
||||
var/network_name = "" //text
|
||||
var/list/networks_connected_by_id = list() //id = datum/ntnet
|
||||
var/differentiate_broadcast = TRUE //If false, broadcasts go to ntnet_recieve. NOT RECOMMENDED.
|
||||
|
||||
/datum/component/ntnet_interface/Initialize(force_name = "NTNet Device", autoconnect_station_network = TRUE) //Don't force ID unless you know what you're doing!
|
||||
hardware_id = "[SSnetworks.get_next_HID()]"
|
||||
network_name = force_name
|
||||
SSnetworks.register_interface(src)
|
||||
if(!SSnetworks.register_interface(src))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Unable to register NTNet interface. Interface deleted.")
|
||||
if(autoconnect_station_network)
|
||||
register_connection(SSnetworks.station_network)
|
||||
|
||||
@@ -27,7 +33,10 @@
|
||||
|
||||
/datum/component/ntnet_interface/proc/__network_recieve(datum/netdata/data) //Do not directly proccall!
|
||||
parent.SendSignal(COMSIG_COMPONENT_NTNET_RECIEVE, data)
|
||||
parent.ntnet_recieve(data)
|
||||
if(differentiate_broadcast && data.broadcast)
|
||||
parent.ntnet_recieve_broadcast(data)
|
||||
else
|
||||
parent.ntnet_recieve(data)
|
||||
|
||||
/datum/component/ntnet_interface/proc/__network_send(datum/netdata/data, netid) //Do not directly proccall!
|
||||
// Process data before sending it
|
||||
|
||||
+325
-326
@@ -1,326 +1,325 @@
|
||||
/datum/component/riding
|
||||
var/next_vehicle_move = 0 //used for move delays
|
||||
var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower
|
||||
var/keytype
|
||||
|
||||
var/slowed = FALSE
|
||||
var/slowvalue = 1
|
||||
|
||||
var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one.
|
||||
var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change.
|
||||
var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py)
|
||||
var/list/allowed_turf_typecache
|
||||
var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence.
|
||||
var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more.
|
||||
var/override_allow_spacemove = FALSE
|
||||
var/drive_verb = "drive"
|
||||
var/ride_check_rider_incapacitated = FALSE
|
||||
var/ride_check_rider_restrained = FALSE
|
||||
var/ride_check_ridden_incapacitated = FALSE
|
||||
|
||||
/datum/component/riding/Initialize()
|
||||
if(!ismovableatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("RIDING COMPONENT ASSIGNED TO NON ATOM MOVABLE!")
|
||||
RegisterSignal(COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle)
|
||||
RegisterSignal(COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle)
|
||||
RegisterSignal(COMSIG_MOVABLE_MOVED, .proc/vehicle_moved)
|
||||
|
||||
/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE)
|
||||
restore_position(M)
|
||||
unequip_buckle_inhands(M)
|
||||
|
||||
/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE)
|
||||
handle_vehicle_offsets()
|
||||
|
||||
/datum/component/riding/proc/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER)
|
||||
. = defaults["[AM.dir]"]
|
||||
if(directional_vehicle_layers["[AM.dir]"])
|
||||
. = directional_vehicle_layers["[AM.dir]"]
|
||||
if(isnull(.)) //you can set it to null to not change it.
|
||||
. = AM.layer
|
||||
AM.layer = .
|
||||
|
||||
/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer)
|
||||
directional_vehicle_layers["[dir]"] = layer
|
||||
|
||||
/datum/component/riding/proc/vehicle_moved()
|
||||
var/atom/movable/AM = parent
|
||||
for(var/i in AM.buckled_mobs)
|
||||
ride_check(i)
|
||||
handle_vehicle_offsets()
|
||||
handle_vehicle_layer()
|
||||
|
||||
/datum/component/riding/proc/ride_check(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
var/mob/AMM = AM
|
||||
if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE)))
|
||||
AM.visible_message("<span class='warning'>[M] falls off of [AM]!</span>")
|
||||
AM.unbuckle_mob(M)
|
||||
return TRUE
|
||||
|
||||
/datum/component/riding/proc/force_dismount(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(M)
|
||||
|
||||
/datum/component/riding/proc/handle_vehicle_offsets()
|
||||
var/atom/movable/AM = parent
|
||||
var/AM_dir = "[AM.dir]"
|
||||
var/passindex = 0
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/m in AM.buckled_mobs)
|
||||
passindex++
|
||||
var/mob/living/buckled_mob = m
|
||||
var/list/offsets = get_offsets(passindex)
|
||||
var/rider_dir = get_rider_dir(passindex)
|
||||
buckled_mob.setDir(rider_dir)
|
||||
dir_loop:
|
||||
for(var/offsetdir in offsets)
|
||||
if(offsetdir == AM_dir)
|
||||
var/list/diroffsets = offsets[offsetdir]
|
||||
buckled_mob.pixel_x = diroffsets[1]
|
||||
if(diroffsets.len >= 2)
|
||||
buckled_mob.pixel_y = diroffsets[2]
|
||||
if(diroffsets.len == 3)
|
||||
buckled_mob.layer = diroffsets[3]
|
||||
break dir_loop
|
||||
var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
|
||||
var/px = default_vehicle_pixel_offsets[AM_dir]
|
||||
var/py = default_vehicle_pixel_offsets[AM_dir]
|
||||
if(directional_vehicle_offsets[AM_dir])
|
||||
if(isnull(directional_vehicle_offsets[AM_dir]))
|
||||
px = AM.pixel_x
|
||||
py = AM.pixel_y
|
||||
else
|
||||
px = directional_vehicle_offsets[AM_dir][1]
|
||||
py = directional_vehicle_offsets[AM_dir][2]
|
||||
AM.pixel_x = px
|
||||
AM.pixel_y = py
|
||||
|
||||
/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y)
|
||||
directional_vehicle_offsets["[dir]"] = list(x, y)
|
||||
|
||||
//Override this to set your vehicle's various pixel offsets
|
||||
/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
. = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
|
||||
if(riding_offsets["[pass_index]"])
|
||||
. = riding_offsets["[pass_index]"]
|
||||
else if(riding_offsets["[RIDING_OFFSET_ALL]"])
|
||||
. = riding_offsets["[RIDING_OFFSET_ALL]"]
|
||||
|
||||
/datum/component/riding/proc/set_riding_offsets(index, list/offsets)
|
||||
if(!islist(offsets))
|
||||
return FALSE
|
||||
riding_offsets["[index]"] = offsets
|
||||
|
||||
//Override this to set the passengers/riders dir based on which passenger they are.
|
||||
//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc.
|
||||
/datum/component/riding/proc/get_rider_dir(pass_index)
|
||||
var/atom/movable/AM = parent
|
||||
return AM.dir
|
||||
|
||||
//KEYS
|
||||
/datum/component/riding/proc/keycheck(mob/user)
|
||||
return !keytype || user.is_holding_item_of_type(keytype)
|
||||
|
||||
//BUCKLE HOOKS
|
||||
/datum/component/riding/proc/restore_position(mob/living/buckled_mob)
|
||||
if(buckled_mob)
|
||||
buckled_mob.pixel_x = 0
|
||||
buckled_mob.pixel_y = 0
|
||||
if(buckled_mob.client)
|
||||
buckled_mob.client.change_view(CONFIG_GET(string/default_view))
|
||||
|
||||
//MOVEMENT
|
||||
/datum/component/riding/proc/turf_check(turf/next, turf/current)
|
||||
if(allowed_turf_typecache && !allowed_turf_typecache[next.type])
|
||||
return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type])
|
||||
else if(forbid_turf_typecache && forbid_turf_typecache[next.type])
|
||||
return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type])
|
||||
return TRUE
|
||||
|
||||
/datum/component/riding/proc/handle_ride(mob/user, direction)
|
||||
var/atom/movable/AM = parent
|
||||
if(user.incapacitated())
|
||||
Unbuckle(user)
|
||||
return
|
||||
|
||||
if(world.time < next_vehicle_move)
|
||||
return
|
||||
next_vehicle_move = world.time + vehicle_move_delay
|
||||
|
||||
if(keycheck(user))
|
||||
var/turf/next = get_step(AM, direction)
|
||||
var/turf/current = get_turf(AM)
|
||||
if(!istype(next) || !istype(current))
|
||||
return //not happening.
|
||||
if(!turf_check(next, current))
|
||||
to_chat(user, "Your \the [AM] can not go onto [next]!")
|
||||
return
|
||||
if(!Process_Spacemove(direction) || !isturf(AM.loc))
|
||||
return
|
||||
step(AM, direction)
|
||||
|
||||
handle_vehicle_layer()
|
||||
handle_vehicle_offsets()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You'll need the keys in one of your hands to [drive_verb] [AM].</span>")
|
||||
|
||||
/datum/component/riding/proc/Unbuckle(atom/movable/M)
|
||||
addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/component/riding/proc/Process_Spacemove(direction)
|
||||
var/atom/movable/AM = parent
|
||||
return override_allow_spacemove || AM.has_gravity()
|
||||
|
||||
/datum/component/riding/proc/account_limbs(mob/living/M)
|
||||
if(M.get_num_legs() < 2 && !slowed)
|
||||
vehicle_move_delay = vehicle_move_delay + slowvalue
|
||||
slowed = TRUE
|
||||
else if(slowed)
|
||||
vehicle_move_delay = vehicle_move_delay - slowvalue
|
||||
slowed = FALSE
|
||||
|
||||
///////Yes, I said humans. No, this won't end well...//////////
|
||||
/datum/component/riding/human
|
||||
|
||||
/datum/component/riding/human/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
|
||||
|
||||
/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target)
|
||||
var/mob/living/carbon/human/AM = parent
|
||||
if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs))
|
||||
force_dismount(target)
|
||||
|
||||
/datum/component/riding/human/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.buckled_mobs && AM.buckled_mobs.len)
|
||||
if(AM.dir == SOUTH)
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
AM.layer = OBJ_LAYER
|
||||
else
|
||||
AM.layer = MOB_LAYER
|
||||
|
||||
/datum/component/riding/human/force_dismount(mob/living/user)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(user)
|
||||
user.Knockdown(60)
|
||||
user.visible_message("<span class='warning'>[AM] pushes [user] off of them!</span>")
|
||||
|
||||
/datum/component/riding/cyborg
|
||||
|
||||
/datum/component/riding/cyborg/ride_check(mob/user)
|
||||
var/atom/movable/AM = parent
|
||||
if(user.incapacitated())
|
||||
var/kick = TRUE
|
||||
if(iscyborg(AM))
|
||||
var/mob/living/silicon/robot/R = AM
|
||||
if(R.module && R.module.ride_allow_incapacitated)
|
||||
kick = FALSE
|
||||
if(kick)
|
||||
to_chat(user, "<span class='userdanger'>You fall off of [AM]!</span>")
|
||||
Unbuckle(user)
|
||||
return
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/carbonuser = user
|
||||
if(!carbonuser.get_num_arms())
|
||||
Unbuckle(user)
|
||||
to_chat(user, "<span class='userdanger'>You can't grab onto [AM] with no hands!</span>")
|
||||
return
|
||||
|
||||
/datum/component/riding/cyborg/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.buckled_mobs && AM.buckled_mobs.len)
|
||||
if(AM.dir == SOUTH)
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
AM.layer = OBJ_LAYER
|
||||
else
|
||||
AM.layer = MOB_LAYER
|
||||
|
||||
/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3))
|
||||
|
||||
/datum/component/riding/cyborg/handle_vehicle_offsets()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/mob/living/M in AM.buckled_mobs)
|
||||
M.setDir(AM.dir)
|
||||
if(iscyborg(AM))
|
||||
var/mob/living/silicon/robot/R = AM
|
||||
if(istype(R.module))
|
||||
M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)]
|
||||
M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)]
|
||||
else
|
||||
..()
|
||||
|
||||
/datum/component/riding/cyborg/force_dismount(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(M)
|
||||
var/turf/target = get_edge_target_turf(AM, AM.dir)
|
||||
var/turf/targetm = get_step(get_turf(AM), AM.dir)
|
||||
M.Move(targetm)
|
||||
M.visible_message("<span class='warning'>[M] is thrown clear of [AM]!</span>")
|
||||
M.throw_at(target, 14, 5, AM)
|
||||
M.Knockdown(60)
|
||||
|
||||
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
|
||||
var/atom/movable/AM = parent
|
||||
var/amount_equipped = 0
|
||||
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
|
||||
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
|
||||
inhand.rider = user
|
||||
inhand.parent = AM
|
||||
if(user.put_in_hands(inhand, TRUE))
|
||||
amount_equipped++
|
||||
else
|
||||
break
|
||||
if(amount_equipped >= amount_required)
|
||||
return TRUE
|
||||
else
|
||||
unequip_buckle_inhands(user)
|
||||
return FALSE
|
||||
|
||||
/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
|
||||
var/atom/movable/AM = parent
|
||||
for(var/obj/item/riding_offhand/O in user.contents)
|
||||
if(O.parent != AM)
|
||||
CRASH("RIDING OFFHAND ON WRONG MOB")
|
||||
continue
|
||||
if(O.selfdeleting)
|
||||
continue
|
||||
else
|
||||
qdel(O)
|
||||
return TRUE
|
||||
|
||||
/obj/item/riding_offhand
|
||||
name = "offhand"
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "offhand"
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
flags_1 = ABSTRACT_1 | DROPDEL_1 | NOBLUDGEON_1
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/mob/living/carbon/rider
|
||||
var/mob/living/parent
|
||||
var/selfdeleting = FALSE
|
||||
|
||||
/obj/item/riding_offhand/dropped()
|
||||
selfdeleting = TRUE
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/equipped()
|
||||
if(loc != rider)
|
||||
selfdeleting = TRUE
|
||||
qdel(src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/Destroy()
|
||||
var/atom/movable/AM = parent
|
||||
if(selfdeleting)
|
||||
if(rider in AM.buckled_mobs)
|
||||
AM.unbuckle_mob(rider)
|
||||
. = ..()
|
||||
/datum/component/riding
|
||||
var/next_vehicle_move = 0 //used for move delays
|
||||
var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower
|
||||
var/keytype
|
||||
|
||||
var/slowed = FALSE
|
||||
var/slowvalue = 1
|
||||
|
||||
var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one.
|
||||
var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change.
|
||||
var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py)
|
||||
var/list/allowed_turf_typecache
|
||||
var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence.
|
||||
var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more.
|
||||
var/override_allow_spacemove = FALSE
|
||||
var/drive_verb = "drive"
|
||||
var/ride_check_rider_incapacitated = FALSE
|
||||
var/ride_check_rider_restrained = FALSE
|
||||
var/ride_check_ridden_incapacitated = FALSE
|
||||
|
||||
/datum/component/riding/Initialize()
|
||||
if(!ismovableatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle)
|
||||
RegisterSignal(COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle)
|
||||
RegisterSignal(COMSIG_MOVABLE_MOVED, .proc/vehicle_moved)
|
||||
|
||||
/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE)
|
||||
restore_position(M)
|
||||
unequip_buckle_inhands(M)
|
||||
|
||||
/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE)
|
||||
handle_vehicle_offsets()
|
||||
|
||||
/datum/component/riding/proc/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER)
|
||||
. = defaults["[AM.dir]"]
|
||||
if(directional_vehicle_layers["[AM.dir]"])
|
||||
. = directional_vehicle_layers["[AM.dir]"]
|
||||
if(isnull(.)) //you can set it to null to not change it.
|
||||
. = AM.layer
|
||||
AM.layer = .
|
||||
|
||||
/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer)
|
||||
directional_vehicle_layers["[dir]"] = layer
|
||||
|
||||
/datum/component/riding/proc/vehicle_moved()
|
||||
var/atom/movable/AM = parent
|
||||
for(var/i in AM.buckled_mobs)
|
||||
ride_check(i)
|
||||
handle_vehicle_offsets()
|
||||
handle_vehicle_layer()
|
||||
|
||||
/datum/component/riding/proc/ride_check(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
var/mob/AMM = AM
|
||||
if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE)))
|
||||
AM.visible_message("<span class='warning'>[M] falls off of [AM]!</span>")
|
||||
AM.unbuckle_mob(M)
|
||||
return TRUE
|
||||
|
||||
/datum/component/riding/proc/force_dismount(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(M)
|
||||
|
||||
/datum/component/riding/proc/handle_vehicle_offsets()
|
||||
var/atom/movable/AM = parent
|
||||
var/AM_dir = "[AM.dir]"
|
||||
var/passindex = 0
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/m in AM.buckled_mobs)
|
||||
passindex++
|
||||
var/mob/living/buckled_mob = m
|
||||
var/list/offsets = get_offsets(passindex)
|
||||
var/rider_dir = get_rider_dir(passindex)
|
||||
buckled_mob.setDir(rider_dir)
|
||||
dir_loop:
|
||||
for(var/offsetdir in offsets)
|
||||
if(offsetdir == AM_dir)
|
||||
var/list/diroffsets = offsets[offsetdir]
|
||||
buckled_mob.pixel_x = diroffsets[1]
|
||||
if(diroffsets.len >= 2)
|
||||
buckled_mob.pixel_y = diroffsets[2]
|
||||
if(diroffsets.len == 3)
|
||||
buckled_mob.layer = diroffsets[3]
|
||||
break dir_loop
|
||||
var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
|
||||
var/px = default_vehicle_pixel_offsets[AM_dir]
|
||||
var/py = default_vehicle_pixel_offsets[AM_dir]
|
||||
if(directional_vehicle_offsets[AM_dir])
|
||||
if(isnull(directional_vehicle_offsets[AM_dir]))
|
||||
px = AM.pixel_x
|
||||
py = AM.pixel_y
|
||||
else
|
||||
px = directional_vehicle_offsets[AM_dir][1]
|
||||
py = directional_vehicle_offsets[AM_dir][2]
|
||||
AM.pixel_x = px
|
||||
AM.pixel_y = py
|
||||
|
||||
/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y)
|
||||
directional_vehicle_offsets["[dir]"] = list(x, y)
|
||||
|
||||
//Override this to set your vehicle's various pixel offsets
|
||||
/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
. = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
|
||||
if(riding_offsets["[pass_index]"])
|
||||
. = riding_offsets["[pass_index]"]
|
||||
else if(riding_offsets["[RIDING_OFFSET_ALL]"])
|
||||
. = riding_offsets["[RIDING_OFFSET_ALL]"]
|
||||
|
||||
/datum/component/riding/proc/set_riding_offsets(index, list/offsets)
|
||||
if(!islist(offsets))
|
||||
return FALSE
|
||||
riding_offsets["[index]"] = offsets
|
||||
|
||||
//Override this to set the passengers/riders dir based on which passenger they are.
|
||||
//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc.
|
||||
/datum/component/riding/proc/get_rider_dir(pass_index)
|
||||
var/atom/movable/AM = parent
|
||||
return AM.dir
|
||||
|
||||
//KEYS
|
||||
/datum/component/riding/proc/keycheck(mob/user)
|
||||
return !keytype || user.is_holding_item_of_type(keytype)
|
||||
|
||||
//BUCKLE HOOKS
|
||||
/datum/component/riding/proc/restore_position(mob/living/buckled_mob)
|
||||
if(buckled_mob)
|
||||
buckled_mob.pixel_x = 0
|
||||
buckled_mob.pixel_y = 0
|
||||
if(buckled_mob.client)
|
||||
buckled_mob.client.change_view(CONFIG_GET(string/default_view))
|
||||
|
||||
//MOVEMENT
|
||||
/datum/component/riding/proc/turf_check(turf/next, turf/current)
|
||||
if(allowed_turf_typecache && !allowed_turf_typecache[next.type])
|
||||
return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type])
|
||||
else if(forbid_turf_typecache && forbid_turf_typecache[next.type])
|
||||
return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type])
|
||||
return TRUE
|
||||
|
||||
/datum/component/riding/proc/handle_ride(mob/user, direction)
|
||||
var/atom/movable/AM = parent
|
||||
if(user.incapacitated())
|
||||
Unbuckle(user)
|
||||
return
|
||||
|
||||
if(world.time < next_vehicle_move)
|
||||
return
|
||||
next_vehicle_move = world.time + vehicle_move_delay
|
||||
|
||||
if(keycheck(user))
|
||||
var/turf/next = get_step(AM, direction)
|
||||
var/turf/current = get_turf(AM)
|
||||
if(!istype(next) || !istype(current))
|
||||
return //not happening.
|
||||
if(!turf_check(next, current))
|
||||
to_chat(user, "Your \the [AM] can not go onto [next]!")
|
||||
return
|
||||
if(!Process_Spacemove(direction) || !isturf(AM.loc))
|
||||
return
|
||||
step(AM, direction)
|
||||
|
||||
handle_vehicle_layer()
|
||||
handle_vehicle_offsets()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You'll need the keys in one of your hands to [drive_verb] [AM].</span>")
|
||||
|
||||
/datum/component/riding/proc/Unbuckle(atom/movable/M)
|
||||
addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/component/riding/proc/Process_Spacemove(direction)
|
||||
var/atom/movable/AM = parent
|
||||
return override_allow_spacemove || AM.has_gravity()
|
||||
|
||||
/datum/component/riding/proc/account_limbs(mob/living/M)
|
||||
if(M.get_num_legs() < 2 && !slowed)
|
||||
vehicle_move_delay = vehicle_move_delay + slowvalue
|
||||
slowed = TRUE
|
||||
else if(slowed)
|
||||
vehicle_move_delay = vehicle_move_delay - slowvalue
|
||||
slowed = FALSE
|
||||
|
||||
///////Yes, I said humans. No, this won't end well...//////////
|
||||
/datum/component/riding/human
|
||||
|
||||
/datum/component/riding/human/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
|
||||
|
||||
/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target)
|
||||
var/mob/living/carbon/human/AM = parent
|
||||
if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs))
|
||||
force_dismount(target)
|
||||
|
||||
/datum/component/riding/human/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.buckled_mobs && AM.buckled_mobs.len)
|
||||
if(AM.dir == SOUTH)
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
AM.layer = OBJ_LAYER
|
||||
else
|
||||
AM.layer = MOB_LAYER
|
||||
|
||||
/datum/component/riding/human/force_dismount(mob/living/user)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(user)
|
||||
user.Knockdown(60)
|
||||
user.visible_message("<span class='warning'>[AM] pushes [user] off of them!</span>")
|
||||
|
||||
/datum/component/riding/cyborg
|
||||
|
||||
/datum/component/riding/cyborg/ride_check(mob/user)
|
||||
var/atom/movable/AM = parent
|
||||
if(user.incapacitated())
|
||||
var/kick = TRUE
|
||||
if(iscyborg(AM))
|
||||
var/mob/living/silicon/robot/R = AM
|
||||
if(R.module && R.module.ride_allow_incapacitated)
|
||||
kick = FALSE
|
||||
if(kick)
|
||||
to_chat(user, "<span class='userdanger'>You fall off of [AM]!</span>")
|
||||
Unbuckle(user)
|
||||
return
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/carbonuser = user
|
||||
if(!carbonuser.get_num_arms())
|
||||
Unbuckle(user)
|
||||
to_chat(user, "<span class='userdanger'>You can't grab onto [AM] with no hands!</span>")
|
||||
return
|
||||
|
||||
/datum/component/riding/cyborg/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.buckled_mobs && AM.buckled_mobs.len)
|
||||
if(AM.dir == SOUTH)
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
AM.layer = OBJ_LAYER
|
||||
else
|
||||
AM.layer = MOB_LAYER
|
||||
|
||||
/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer)
|
||||
return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3))
|
||||
|
||||
/datum/component/riding/cyborg/handle_vehicle_offsets()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.has_buckled_mobs())
|
||||
for(var/mob/living/M in AM.buckled_mobs)
|
||||
M.setDir(AM.dir)
|
||||
if(iscyborg(AM))
|
||||
var/mob/living/silicon/robot/R = AM
|
||||
if(istype(R.module))
|
||||
M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)]
|
||||
M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)]
|
||||
else
|
||||
..()
|
||||
|
||||
/datum/component/riding/cyborg/force_dismount(mob/living/M)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(M)
|
||||
var/turf/target = get_edge_target_turf(AM, AM.dir)
|
||||
var/turf/targetm = get_step(get_turf(AM), AM.dir)
|
||||
M.Move(targetm)
|
||||
M.visible_message("<span class='warning'>[M] is thrown clear of [AM]!</span>")
|
||||
M.throw_at(target, 14, 5, AM)
|
||||
M.Knockdown(60)
|
||||
|
||||
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
|
||||
var/atom/movable/AM = parent
|
||||
var/amount_equipped = 0
|
||||
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
|
||||
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
|
||||
inhand.rider = user
|
||||
inhand.parent = AM
|
||||
if(user.put_in_hands(inhand, TRUE))
|
||||
amount_equipped++
|
||||
else
|
||||
break
|
||||
if(amount_equipped >= amount_required)
|
||||
return TRUE
|
||||
else
|
||||
unequip_buckle_inhands(user)
|
||||
return FALSE
|
||||
|
||||
/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
|
||||
var/atom/movable/AM = parent
|
||||
for(var/obj/item/riding_offhand/O in user.contents)
|
||||
if(O.parent != AM)
|
||||
CRASH("RIDING OFFHAND ON WRONG MOB")
|
||||
continue
|
||||
if(O.selfdeleting)
|
||||
continue
|
||||
else
|
||||
qdel(O)
|
||||
return TRUE
|
||||
|
||||
/obj/item/riding_offhand
|
||||
name = "offhand"
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "offhand"
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
flags_1 = ABSTRACT_1 | DROPDEL_1 | NOBLUDGEON_1
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/mob/living/carbon/rider
|
||||
var/mob/living/parent
|
||||
var/selfdeleting = FALSE
|
||||
|
||||
/obj/item/riding_offhand/dropped()
|
||||
selfdeleting = TRUE
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/equipped()
|
||||
if(loc != rider)
|
||||
selfdeleting = TRUE
|
||||
qdel(src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/Destroy()
|
||||
var/atom/movable/AM = parent
|
||||
if(selfdeleting)
|
||||
if(rider in AM.buckled_mobs)
|
||||
AM.unbuckle_mob(rider)
|
||||
. = ..()
|
||||
|
||||
@@ -1,9 +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))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("A redirection component was initialized with incorrect args.")
|
||||
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
|
||||
|
||||
@@ -42,11 +42,11 @@
|
||||
var/T = get_turf(H)
|
||||
if(too_spooky)
|
||||
if(prob(30))
|
||||
new/obj/item/device/instrument/saxophone/spectral(T)
|
||||
new/obj/item/instrument/saxophone/spectral(T)
|
||||
else if(prob(30))
|
||||
new/obj/item/device/instrument/trumpet/spectral(T)
|
||||
new/obj/item/instrument/trumpet/spectral(T)
|
||||
else if(prob(30))
|
||||
new/obj/item/device/instrument/trombone/spectral(T)
|
||||
new/obj/item/instrument/trombone/spectral(T)
|
||||
else
|
||||
to_chat(H, "The spooky gods forgot to ship your instrument. Better luck next unlife.")
|
||||
to_chat(H, "<B>You are the spooky skeleton!</B>")
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/datum/component/stationloving
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
var/inform_admins = FALSE
|
||||
var/disallow_soul_imbue = TRUE
|
||||
|
||||
/datum/component/stationloving/Initialize(inform_admins = FALSE)
|
||||
if(!ismovableatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(list(COMSIG_MOVABLE_Z_CHANGED), .proc/check_in_bounds)
|
||||
RegisterSignal(list(COMSIG_PARENT_PREQDELETED), .proc/check_deletion)
|
||||
RegisterSignal(list(COMSIG_ITEM_IMBUE_SOUL), .proc/check_soul_imbue)
|
||||
src.inform_admins = inform_admins
|
||||
check_in_bounds() // Just in case something is being created outside of station/centcom
|
||||
|
||||
/datum/component/stationloving/InheritComponent(datum/component/stationloving/newc, original, list/arguments)
|
||||
if (original)
|
||||
if (istype(newc))
|
||||
inform_admins = newc.inform_admins
|
||||
else if (LAZYLEN(arguments))
|
||||
inform_admins = arguments[1]
|
||||
|
||||
/datum/component/stationloving/proc/relocate()
|
||||
var/targetturf = find_safe_turf()
|
||||
if(!targetturf)
|
||||
if(GLOB.blobstart.len > 0)
|
||||
targetturf = get_turf(pick(GLOB.blobstart))
|
||||
else
|
||||
CRASH("Unable to find a blobstart landmark")
|
||||
|
||||
var/atom/movable/AM = parent
|
||||
AM.forceMove(targetturf)
|
||||
// move the disc, so ghosts remain orbiting it even if it's "destroyed"
|
||||
return targetturf
|
||||
|
||||
/datum/component/stationloving/proc/check_in_bounds()
|
||||
if(in_bounds())
|
||||
return
|
||||
else
|
||||
var/turf/currentturf = get_turf(src)
|
||||
to_chat(get(parent, /mob), "<span class='danger'>You can't help but feel that you just lost something back there...</span>")
|
||||
var/turf/targetturf = relocate()
|
||||
log_game("[parent] has been moved out of bounds in [COORD(currentturf)]. Moving it to [COORD(targetturf)].")
|
||||
if(inform_admins)
|
||||
message_admins("[parent] has been moved out of bounds in [ADMIN_COORDJMP(currentturf)]. Moving it to [ADMIN_COORDJMP(targetturf)].")
|
||||
|
||||
/datum/component/stationloving/proc/check_soul_imbue()
|
||||
return disallow_soul_imbue
|
||||
|
||||
/datum/component/stationloving/proc/in_bounds()
|
||||
var/static/list/allowed_shuttles = typecacheof(list(/area/shuttle/syndicate, /area/shuttle/escape, /area/shuttle/pod_1, /area/shuttle/pod_2, /area/shuttle/pod_3, /area/shuttle/pod_4))
|
||||
var/turf/T = get_turf(parent)
|
||||
if (!T)
|
||||
return FALSE
|
||||
if (is_station_level(T.z) || is_centcom_level(T.z))
|
||||
return TRUE
|
||||
if (is_transit_level(T.z))
|
||||
var/area/A = T.loc
|
||||
if (is_type_in_typecache(A, allowed_shuttles))
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/datum/component/stationloving/proc/check_deletion(force) // TRUE = interrupt deletion, FALSE = proceed with deletion
|
||||
|
||||
var/turf/T = get_turf(parent)
|
||||
|
||||
if(inform_admins && force)
|
||||
message_admins("[parent] has been !!force deleted!! in [ADMIN_COORDJMP(T)].")
|
||||
log_game("[parent] has been !!force deleted!! in [COORD(T)].")
|
||||
|
||||
if(!force)
|
||||
var/turf/targetturf = relocate()
|
||||
log_game("[parent] has been destroyed in [COORD(T)]. Moving it to [COORD(targetturf)].")
|
||||
if(inform_admins)
|
||||
message_admins("[parent] has been destroyed in [ADMIN_COORDJMP(T)]. Moving it to [ADMIN_COORDJMP(targetturf)].")
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -1,185 +1,198 @@
|
||||
|
||||
// External storage-related logic:
|
||||
// /mob/proc/ClickOn() in /_onclick/click.dm - clicking items in storages
|
||||
// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement
|
||||
|
||||
/datum/component/storage/concrete
|
||||
var/drop_all_on_deconstruct = TRUE
|
||||
var/drop_all_on_destroy = FALSE
|
||||
var/transfer_contents_on_component_transfer = FALSE
|
||||
var/list/datum/component/storage/slaves = list()
|
||||
|
||||
/datum/component/storage/concrete/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del)
|
||||
RegisterSignal(COMSIG_OBJ_DECONSTRUCT, .proc/on_deconstruct)
|
||||
|
||||
/datum/component/storage/concrete/Destroy()
|
||||
var/atom/real_location = real_location()
|
||||
for(var/atom/_A in real_location)
|
||||
_A.mouse_opacity = initial(_A.mouse_opacity)
|
||||
if(drop_all_on_destroy)
|
||||
do_quick_empty()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
slave.change_master(null)
|
||||
return ..()
|
||||
|
||||
/datum/component/storage/concrete/master()
|
||||
return src
|
||||
|
||||
/datum/component/storage/concrete/real_location()
|
||||
return parent
|
||||
|
||||
/datum/component/storage/concrete/OnTransfer(datum/new_parent)
|
||||
if(!isatom(new_parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
var/list/mob/_is_using
|
||||
if(is_using)
|
||||
_is_using = is_using.Copy()
|
||||
close_all()
|
||||
if(transfer_contents_on_component_transfer)
|
||||
var/atom/old = parent
|
||||
for(var/i in old)
|
||||
var/atom/movable/AM = i
|
||||
AM.forceMove(new_parent)
|
||||
if(_is_using)
|
||||
for(var/i in _is_using)
|
||||
var/mob/M = i
|
||||
show_to(M)
|
||||
|
||||
/datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE)
|
||||
. = TRUE
|
||||
var/atom/real_location = real_location()
|
||||
if(I.loc != real_location)
|
||||
I.forceMove(real_location)
|
||||
refresh_mob_views()
|
||||
|
||||
/datum/component/storage/concrete/refresh_mob_views()
|
||||
. = ..()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
slave.refresh_mob_views()
|
||||
|
||||
/datum/component/storage/concrete/emp_act(severity)
|
||||
var/atom/real_location = real_location()
|
||||
for(var/i in real_location)
|
||||
var/atom/A = i
|
||||
A.emp_act(severity)
|
||||
|
||||
/datum/component/storage/concrete/proc/on_slave_link(datum/component/storage/S)
|
||||
if(S == src)
|
||||
return FALSE
|
||||
slaves += S
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/proc/on_slave_unlink(datum/component/storage/S)
|
||||
slaves -= S
|
||||
return FALSE
|
||||
|
||||
/datum/component/storage/concrete/proc/on_contents_del(atom/A)
|
||||
var/atom/real_location = parent
|
||||
if(A in real_location)
|
||||
usr = null
|
||||
remove_from_storage(A, null)
|
||||
|
||||
/datum/component/storage/concrete/proc/on_deconstruct(disassembled)
|
||||
if(drop_all_on_deconstruct)
|
||||
do_quick_empty()
|
||||
|
||||
/datum/component/storage/concrete/can_see_contents()
|
||||
. = ..()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
. |= slave.can_see_contents()
|
||||
|
||||
//Resets screen loc and other vars of something being removed from storage.
|
||||
/datum/component/storage/concrete/_removal_reset(atom/movable/thing)
|
||||
thing.layer = initial(thing.layer)
|
||||
thing.plane = initial(thing.plane)
|
||||
thing.mouse_opacity = initial(thing.mouse_opacity)
|
||||
if(thing.maptext)
|
||||
thing.maptext = ""
|
||||
|
||||
/datum/component/storage/concrete/remove_from_storage(atom/movable/AM, atom/new_location)
|
||||
//Cache this as it should be reusable down the bottom, will not apply if anyone adds a sleep to dropped
|
||||
//or moving objects, things that should never happen
|
||||
var/atom/parent = src.parent
|
||||
var/list/seeing_mobs = can_see_contents()
|
||||
for(var/mob/M in seeing_mobs)
|
||||
M.client.screen -= AM
|
||||
if(ismob(parent.loc) && isitem(AM))
|
||||
var/obj/item/I = AM
|
||||
var/mob/M = parent.loc
|
||||
I.dropped(M)
|
||||
if(new_location)
|
||||
//Reset the items values
|
||||
_removal_reset(AM)
|
||||
AM.forceMove(new_location)
|
||||
//We don't want to call this if the item is being destroyed
|
||||
AM.on_exit_storage(src)
|
||||
else
|
||||
//Being destroyed, just move to nullspace now (so it's not in contents for the icon update)
|
||||
AM.moveToNullspace()
|
||||
refresh_mob_views()
|
||||
if(isobj(parent))
|
||||
var/obj/O = parent
|
||||
O.update_icon()
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/proc/slave_can_insert_object(datum/component/storage/slave, obj/item/I, stop_messages = FALSE, mob/M)
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/proc/handle_item_insertion_from_slave(datum/component/storage/slave, obj/item/I, prevent_warning = FALSE, M)
|
||||
. = handle_item_insertion(I, prevent_warning, M, slave)
|
||||
if(. && !prevent_warning)
|
||||
slave.mob_item_insertion_feedback(usr, M, I)
|
||||
|
||||
/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum
|
||||
var/datum/component/storage/concrete/master = master()
|
||||
var/atom/parent = src.parent
|
||||
var/moved = FALSE
|
||||
if(!istype(I))
|
||||
return FALSE
|
||||
if(M)
|
||||
if(!M.temporarilyRemoveItemFromInventory(I))
|
||||
return FALSE
|
||||
else
|
||||
moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever.
|
||||
if(I.pulledby)
|
||||
I.pulledby.stop_pulling()
|
||||
if(silent)
|
||||
prevent_warning = TRUE
|
||||
if(!_insert_physical_item(I))
|
||||
if(moved)
|
||||
if(M)
|
||||
if(!M.put_in_active_hand(I))
|
||||
I.forceMove(parent.drop_location())
|
||||
else
|
||||
I.forceMove(parent.drop_location())
|
||||
return FALSE
|
||||
I.on_enter_storage(master)
|
||||
refresh_mob_views()
|
||||
I.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt
|
||||
if(M)
|
||||
if(M.client && M.active_storage != src)
|
||||
M.client.screen -= I
|
||||
if(M.observers && M.observers.len)
|
||||
for(var/i in M.observers)
|
||||
var/mob/dead/observe = i
|
||||
if(observe.client && observe.active_storage != src)
|
||||
observe.client.screen -= I
|
||||
if(!remote)
|
||||
parent.add_fingerprint(M)
|
||||
if(!prevent_warning)
|
||||
mob_item_insertion_feedback(usr, M, I)
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/update_icon()
|
||||
if(isobj(parent))
|
||||
var/obj/O = parent
|
||||
O.update_icon()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
slave.update_icon()
|
||||
|
||||
// External storage-related logic:
|
||||
// /mob/proc/ClickOn() in /_onclick/click.dm - clicking items in storages
|
||||
// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement
|
||||
|
||||
/datum/component/storage/concrete
|
||||
var/drop_all_on_deconstruct = TRUE
|
||||
var/drop_all_on_destroy = FALSE
|
||||
var/transfer_contents_on_component_transfer = FALSE
|
||||
var/list/datum/component/storage/slaves = list()
|
||||
|
||||
var/list/_contents_limbo // Where objects go to live mid transfer
|
||||
var/list/_user_limbo // The last users before the component started moving
|
||||
|
||||
/datum/component/storage/concrete/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del)
|
||||
RegisterSignal(COMSIG_OBJ_DECONSTRUCT, .proc/on_deconstruct)
|
||||
|
||||
/datum/component/storage/concrete/Destroy()
|
||||
var/atom/real_location = real_location()
|
||||
for(var/atom/_A in real_location)
|
||||
_A.mouse_opacity = initial(_A.mouse_opacity)
|
||||
if(drop_all_on_destroy)
|
||||
do_quick_empty()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
slave.change_master(null)
|
||||
QDEL_LIST(_contents_limbo)
|
||||
_user_limbo = null
|
||||
return ..()
|
||||
|
||||
/datum/component/storage/concrete/master()
|
||||
return src
|
||||
|
||||
/datum/component/storage/concrete/real_location()
|
||||
return parent
|
||||
|
||||
/datum/component/storage/concrete/PreTransfer()
|
||||
if(is_using)
|
||||
_user_limbo = is_using.Copy()
|
||||
close_all()
|
||||
if(transfer_contents_on_component_transfer)
|
||||
_contents_limbo = list()
|
||||
for(var/atom/movable/AM in parent)
|
||||
_contents_limbo += AM
|
||||
AM.moveToNullspace()
|
||||
|
||||
/datum/component/storage/concrete/PostTransfer()
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
if(transfer_contents_on_component_transfer)
|
||||
for(var/i in _contents_limbo)
|
||||
var/atom/movable/AM = i
|
||||
AM.forceMove(parent)
|
||||
_contents_limbo = null
|
||||
if(_user_limbo)
|
||||
for(var/i in _user_limbo)
|
||||
show_to(i)
|
||||
_user_limbo = null
|
||||
|
||||
/datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE)
|
||||
. = TRUE
|
||||
var/atom/real_location = real_location()
|
||||
if(I.loc != real_location)
|
||||
I.forceMove(real_location)
|
||||
refresh_mob_views()
|
||||
|
||||
/datum/component/storage/concrete/refresh_mob_views()
|
||||
. = ..()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
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
|
||||
A.emp_act(severity)
|
||||
|
||||
/datum/component/storage/concrete/proc/on_slave_link(datum/component/storage/S)
|
||||
if(S == src)
|
||||
return FALSE
|
||||
slaves += S
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/proc/on_slave_unlink(datum/component/storage/S)
|
||||
slaves -= S
|
||||
return FALSE
|
||||
|
||||
/datum/component/storage/concrete/proc/on_contents_del(atom/A)
|
||||
var/atom/real_location = parent
|
||||
if(A in real_location)
|
||||
usr = null
|
||||
remove_from_storage(A, null)
|
||||
|
||||
/datum/component/storage/concrete/proc/on_deconstruct(disassembled)
|
||||
if(drop_all_on_deconstruct)
|
||||
do_quick_empty()
|
||||
|
||||
/datum/component/storage/concrete/can_see_contents()
|
||||
. = ..()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
. |= slave.can_see_contents()
|
||||
|
||||
//Resets screen loc and other vars of something being removed from storage.
|
||||
/datum/component/storage/concrete/_removal_reset(atom/movable/thing)
|
||||
thing.layer = initial(thing.layer)
|
||||
thing.plane = initial(thing.plane)
|
||||
thing.mouse_opacity = initial(thing.mouse_opacity)
|
||||
if(thing.maptext)
|
||||
thing.maptext = ""
|
||||
|
||||
/datum/component/storage/concrete/remove_from_storage(atom/movable/AM, atom/new_location)
|
||||
//Cache this as it should be reusable down the bottom, will not apply if anyone adds a sleep to dropped
|
||||
//or moving objects, things that should never happen
|
||||
var/atom/parent = src.parent
|
||||
var/list/seeing_mobs = can_see_contents()
|
||||
for(var/mob/M in seeing_mobs)
|
||||
M.client.screen -= AM
|
||||
if(ismob(parent.loc) && isitem(AM))
|
||||
var/obj/item/I = AM
|
||||
var/mob/M = parent.loc
|
||||
I.dropped(M)
|
||||
if(new_location)
|
||||
//Reset the items values
|
||||
_removal_reset(AM)
|
||||
AM.forceMove(new_location)
|
||||
//We don't want to call this if the item is being destroyed
|
||||
AM.on_exit_storage(src)
|
||||
else
|
||||
//Being destroyed, just move to nullspace now (so it's not in contents for the icon update)
|
||||
AM.moveToNullspace()
|
||||
refresh_mob_views()
|
||||
if(isobj(parent))
|
||||
var/obj/O = parent
|
||||
O.update_icon()
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/proc/slave_can_insert_object(datum/component/storage/slave, obj/item/I, stop_messages = FALSE, mob/M)
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/proc/handle_item_insertion_from_slave(datum/component/storage/slave, obj/item/I, prevent_warning = FALSE, M)
|
||||
. = handle_item_insertion(I, prevent_warning, M, slave)
|
||||
if(. && !prevent_warning)
|
||||
slave.mob_item_insertion_feedback(usr, M, I)
|
||||
|
||||
/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum
|
||||
var/datum/component/storage/concrete/master = master()
|
||||
var/atom/parent = src.parent
|
||||
var/moved = FALSE
|
||||
if(!istype(I))
|
||||
return FALSE
|
||||
if(M)
|
||||
if(!M.temporarilyRemoveItemFromInventory(I))
|
||||
return FALSE
|
||||
else
|
||||
moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever.
|
||||
if(I.pulledby)
|
||||
I.pulledby.stop_pulling()
|
||||
if(silent)
|
||||
prevent_warning = TRUE
|
||||
if(!_insert_physical_item(I))
|
||||
if(moved)
|
||||
if(M)
|
||||
if(!M.put_in_active_hand(I))
|
||||
I.forceMove(parent.drop_location())
|
||||
else
|
||||
I.forceMove(parent.drop_location())
|
||||
return FALSE
|
||||
I.on_enter_storage(master)
|
||||
refresh_mob_views()
|
||||
I.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt
|
||||
if(M)
|
||||
if(M.client && M.active_storage != src)
|
||||
M.client.screen -= I
|
||||
if(M.observers && M.observers.len)
|
||||
for(var/i in M.observers)
|
||||
var/mob/dead/observe = i
|
||||
if(observe.client && observe.active_storage != src)
|
||||
observe.client.screen -= I
|
||||
if(!remote)
|
||||
parent.add_fingerprint(M)
|
||||
if(!prevent_warning)
|
||||
mob_item_insertion_feedback(usr, M, I)
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/concrete/update_icon()
|
||||
if(isobj(parent))
|
||||
var/obj/O = parent
|
||||
O.update_icon()
|
||||
for(var/i in slaves)
|
||||
var/datum/component/storage/slave = i
|
||||
slave.update_icon()
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
/datum/component/storage/concrete/implant
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
max_combined_w_class = 6
|
||||
max_items = 2
|
||||
drop_all_on_destroy = TRUE
|
||||
drop_all_on_deconstruct = TRUE
|
||||
silent = TRUE
|
||||
|
||||
/datum/component/storage/concrete/implant/Initialize()
|
||||
. = ..()
|
||||
cant_hold = typecacheof(list(/obj/item/disk/nuclear))
|
||||
|
||||
/datum/component/storage/concrete/implant/InheritComponent(datum/component/storage/concrete/implant/I, original)
|
||||
if(!istype(I))
|
||||
return ..()
|
||||
max_combined_w_class += I.max_combined_w_class
|
||||
max_items += I.max_items
|
||||
/datum/component/storage/concrete/implant
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
max_combined_w_class = 6
|
||||
max_items = 2
|
||||
drop_all_on_destroy = TRUE
|
||||
drop_all_on_deconstruct = TRUE
|
||||
silent = TRUE
|
||||
allow_big_nesting = TRUE
|
||||
|
||||
/datum/component/storage/concrete/implant/Initialize()
|
||||
. = ..()
|
||||
cant_hold = typecacheof(list(/obj/item/disk/nuclear))
|
||||
|
||||
/datum/component/storage/concrete/implant/InheritComponent(datum/component/storage/concrete/implant/I, original)
|
||||
if(!istype(I))
|
||||
return ..()
|
||||
max_combined_w_class += I.max_combined_w_class
|
||||
max_items += I.max_items
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
/obj/item/scalpel, /obj/item/reagent_containers/syringe, /obj/item/dnainjector,
|
||||
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
|
||||
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
|
||||
/obj/item/device/firing_pin
|
||||
/obj/item/firing_pin
|
||||
))
|
||||
|
||||
/datum/component/storage/concrete/pockets/shoes/clown/Initialize()
|
||||
@@ -49,7 +49,7 @@
|
||||
/obj/item/scalpel, /obj/item/reagent_containers/syringe, /obj/item/dnainjector,
|
||||
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
|
||||
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
|
||||
/obj/item/device/firing_pin, /obj/item/bikehorn))
|
||||
/obj/item/firing_pin, /obj/item/bikehorn))
|
||||
|
||||
/datum/component/storage/concrete/pockets/pocketprotector
|
||||
max_items = 3
|
||||
@@ -61,5 +61,5 @@
|
||||
/obj/item/pen,
|
||||
/obj/item/toy/crayon,
|
||||
/obj/item/lipstick,
|
||||
/obj/item/device/flashlight/pen,
|
||||
/obj/item/flashlight/pen,
|
||||
/obj/item/clothing/mask/cigarette))
|
||||
@@ -1,31 +1,33 @@
|
||||
/datum/component/storage/concrete/rped
|
||||
collection_mode = COLLECT_EVERYTHING
|
||||
allow_quick_gather = TRUE
|
||||
allow_quick_empty = TRUE
|
||||
click_gather = TRUE
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
max_combined_w_class = 100
|
||||
max_items = 50
|
||||
display_numerical_stacking = TRUE
|
||||
|
||||
/datum/component/storage/concrete/rped/can_be_inserted(obj/item/I, stop_messages, mob/M)
|
||||
. = ..()
|
||||
if(!I.get_part_rating() && !stop_messages)
|
||||
to_chat(M, "<span class='warning'>[parent] only accepts machine parts!</span>")
|
||||
return FALSE
|
||||
|
||||
/datum/component/storage/concrete/bluespace/rped
|
||||
collection_mode = COLLECT_EVERYTHING
|
||||
allow_quick_gather = TRUE
|
||||
allow_quick_empty = TRUE
|
||||
click_gather = TRUE
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
max_combined_w_class = 800
|
||||
max_items = 400
|
||||
display_numerical_stacking = TRUE
|
||||
|
||||
/datum/component/storage/concrete/bluespace/rped/can_be_inserted(obj/item/I, stop_messages, mob/M)
|
||||
. = ..()
|
||||
if(!I.get_part_rating() && !stop_messages)
|
||||
to_chat(M, "<span class='warning'>[parent] only accepts machine parts!</span>")
|
||||
return FALSE
|
||||
/datum/component/storage/concrete/rped
|
||||
collection_mode = COLLECT_EVERYTHING
|
||||
allow_quick_gather = TRUE
|
||||
allow_quick_empty = TRUE
|
||||
click_gather = TRUE
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
max_combined_w_class = 100
|
||||
max_items = 50
|
||||
display_numerical_stacking = TRUE
|
||||
|
||||
/datum/component/storage/concrete/rped/can_be_inserted(obj/item/I, stop_messages, mob/M)
|
||||
. = ..()
|
||||
if(!I.get_part_rating())
|
||||
if (!stop_messages)
|
||||
to_chat(M, "<span class='warning'>[parent] only accepts machine parts!</span>")
|
||||
return FALSE
|
||||
|
||||
/datum/component/storage/concrete/bluespace/rped
|
||||
collection_mode = COLLECT_EVERYTHING
|
||||
allow_quick_gather = TRUE
|
||||
allow_quick_empty = TRUE
|
||||
click_gather = TRUE
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
max_combined_w_class = 800
|
||||
max_items = 400
|
||||
display_numerical_stacking = TRUE
|
||||
|
||||
/datum/component/storage/concrete/bluespace/rped/can_be_inserted(obj/item/I, stop_messages, mob/M)
|
||||
. = ..()
|
||||
if(!I.get_part_rating())
|
||||
if (!stop_messages)
|
||||
to_chat(M, "<span class='warning'>[parent] only accepts machine par ts!</span>")
|
||||
return FALSE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,10 +21,7 @@
|
||||
)
|
||||
|
||||
/datum/component/thermite/Initialize(_amount)
|
||||
if(!istype(parent, /turf))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("A thermite component has been applied to an incorrect object. parent: [parent]")
|
||||
if(blacklist[parent.type])
|
||||
if(!istype(parent, /turf) || blacklist[parent.type])
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
if(immunelist[parent.type])
|
||||
_amount*=0 //Yeah the overlay can still go on it and be cleaned but you arent burning down a diamond wall
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
/datum/component/wet_floor/Initialize(strength, duration_minimum, duration_add, duration_maximum, _permanent = FALSE)
|
||||
if(!isopenturf(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Wet floor component attempted to be applied to a non open turf!")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
add_wet(strength, duration_minimum, duration_add, duration_maximum)
|
||||
RegisterSignal(COMSIG_TURF_IS_WET, .proc/is_wet)
|
||||
RegisterSignal(COMSIG_TURF_MAKE_DRY, .proc/dry)
|
||||
@@ -136,13 +135,14 @@
|
||||
for(var/i in time_left_list)
|
||||
. |= text2num(i)
|
||||
|
||||
/datum/component/wet_floor/OnTransfer(datum/to_datum)
|
||||
if(!isopenturf(to_datum))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Wet floor component attempted to be transferred to a non open turf!")
|
||||
/datum/component/wet_floor/PreTransfer()
|
||||
var/turf/O = parent
|
||||
O.cut_overlay(current_overlay)
|
||||
var/turf/T = to_datum
|
||||
|
||||
/datum/component/wet_floor/PostTransfer()
|
||||
if(!isopenturf(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
var/turf/T = parent
|
||||
T.add_overlay(current_overlay)
|
||||
|
||||
/datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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), 7)))
|
||||
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"
|
||||
@@ -54,13 +56,12 @@
|
||||
to_chat(src, GLOB.revdata.GetTestMergeInfo())
|
||||
prefix = "Based off origin/master commit: "
|
||||
var/pc = GLOB.revdata.originmastercommit
|
||||
to_chat(src, "[prefix]<a href=\"[CONFIG_GET(string/githuburl)]/commit/[pc]\">[copytext(pc, 1, min(length(pc), 7))]</a>")
|
||||
to_chat(src, "[prefix]<a href=\"[CONFIG_GET(string/githuburl)]/commit/[pc]\">[copytext(pc, 1, min(length(pc), 11))]</a>")
|
||||
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)]")
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
/obj/item/mushpunch
|
||||
name = "odd mushroom"
|
||||
desc = "<I>Sapienza Ophioglossoides</I>:An odd mushroom from the flesh of a mushroom person. it has apparently retained some innate power of it's owner, as it quivers with barely-contained POWER!"
|
||||
icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
|
||||
icon = 'icons/obj/hydroponics/seeds.dmi'
|
||||
icon_state = "mycelium-angel"
|
||||
|
||||
/obj/item/mushpunch/attack_self(mob/living/carbon/human/user)
|
||||
|
||||
+6
-6
@@ -237,12 +237,12 @@
|
||||
/datum/mind/proc/remove_antag_equip()
|
||||
var/list/Mob_Contents = current.get_contents()
|
||||
for(var/obj/item/I in Mob_Contents)
|
||||
if(istype(I, /obj/item/device/pda))
|
||||
var/obj/item/device/pda/P = I
|
||||
if(istype(I, /obj/item/pda))
|
||||
var/obj/item/pda/P = I
|
||||
P.lock_code = ""
|
||||
|
||||
else if(istype(I, /obj/item/device/radio))
|
||||
var/obj/item/device/radio/R = I
|
||||
else if(istype(I, /obj/item/radio))
|
||||
var/obj/item/radio/R = I
|
||||
R.traitor_frequency = 0
|
||||
|
||||
/datum/mind/proc/remove_all_antag() //For the Lazy amongst us.
|
||||
@@ -264,8 +264,8 @@
|
||||
. = TRUE
|
||||
|
||||
var/list/all_contents = traitor_mob.GetAllContents()
|
||||
var/obj/item/device/pda/PDA = locate() in all_contents
|
||||
var/obj/item/device/radio/R = locate() in all_contents
|
||||
var/obj/item/pda/PDA = locate() in all_contents
|
||||
var/obj/item/radio/R = locate() in all_contents
|
||||
var/obj/item/pen/P
|
||||
|
||||
if (PDA) // Prioritize PDA pen, otherwise the pocket protector pens will be chosen, which causes numerous ahelps about missing uplink
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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,20 +93,20 @@
|
||||
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 = -2
|
||||
value = -3
|
||||
gain_text = "<span class='danger'>You feel smooth.</span>"
|
||||
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)
|
||||
|
||||
@@ -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,41 +12,75 @@
|
||||
|
||||
|
||||
|
||||
/datum/trait/deviant_tastes
|
||||
/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/quirk/pineapple_liker/add()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/datum/species/species = H.dna.species
|
||||
species.liked_food |= PINEAPPLE
|
||||
|
||||
/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/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/quirk/pineapple_hater/add()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/datum/species/species = H.dna.species
|
||||
species.disliked_food |= PINEAPPLE
|
||||
|
||||
/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/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
@@ -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
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
if(I.tool_behaviour == TOOL_WIRECUTTER || I.tool_behaviour == TOOL_MULTITOOL)
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/device/assembly))
|
||||
var/obj/item/device/assembly/A = I
|
||||
if(istype(I, /obj/item/assembly))
|
||||
var/obj/item/assembly/A = I
|
||||
if(A.attachable)
|
||||
return TRUE
|
||||
|
||||
@@ -149,13 +149,13 @@
|
||||
/datum/wires/proc/pulse_color(color, mob/living/user)
|
||||
pulse(get_wire(color), user)
|
||||
|
||||
/datum/wires/proc/pulse_assembly(obj/item/device/assembly/S)
|
||||
/datum/wires/proc/pulse_assembly(obj/item/assembly/S)
|
||||
for(var/color in assemblies)
|
||||
if(S == assemblies[color])
|
||||
pulse_color(color)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/attach_assembly(color, obj/item/device/assembly/S)
|
||||
/datum/wires/proc/attach_assembly(color, obj/item/assembly/S)
|
||||
if(S && istype(S) && S.attachable && !is_attached(color))
|
||||
assemblies[color] = S
|
||||
S.forceMove(holder)
|
||||
@@ -163,7 +163,7 @@
|
||||
return S
|
||||
|
||||
/datum/wires/proc/detach_assembly(color)
|
||||
var/obj/item/device/assembly/S = get_attached(color)
|
||||
var/obj/item/assembly/S = get_attached(color)
|
||||
if(S && istype(S))
|
||||
assemblies -= color
|
||||
S.connected = null
|
||||
@@ -229,7 +229,7 @@
|
||||
reveal_wires = TRUE
|
||||
|
||||
// Same for anyone with an abductor multitool.
|
||||
else if(user.is_holding_item_of_type(/obj/item/device/multitool/abductor))
|
||||
else if(user.is_holding_item_of_type(/obj/item/multitool/abductor))
|
||||
reveal_wires = TRUE
|
||||
|
||||
// Station blueprints do that too, but only if the wires are not randomized.
|
||||
@@ -280,8 +280,8 @@
|
||||
. = TRUE
|
||||
else
|
||||
I = L.get_active_held_item()
|
||||
if(istype(I, /obj/item/device/assembly))
|
||||
var/obj/item/device/assembly/A = I
|
||||
if(istype(I, /obj/item/assembly))
|
||||
var/obj/item/assembly/A = I
|
||||
if(A.attachable)
|
||||
if(!L.temporarilyRemoveItemFromInventory(A))
|
||||
return
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/datum/wires/radio
|
||||
holder_type = /obj/item/device/radio
|
||||
holder_type = /obj/item/radio
|
||||
proper_name = "Radio"
|
||||
|
||||
/datum/wires/radio/New(atom/holder)
|
||||
@@ -10,11 +10,11 @@
|
||||
..()
|
||||
|
||||
/datum/wires/radio/interactable(mob/user)
|
||||
var/obj/item/device/radio/R = holder
|
||||
var/obj/item/radio/R = holder
|
||||
return R.unscrewed
|
||||
|
||||
/datum/wires/radio/on_pulse(index)
|
||||
var/obj/item/device/radio/R = holder
|
||||
var/obj/item/radio/R = holder
|
||||
switch(index)
|
||||
if(WIRE_SIGNAL)
|
||||
R.listening = !R.listening
|
||||
|
||||
@@ -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"
|
||||
@@ -136,7 +140,7 @@
|
||||
/datum/world_topic/status/Run(list/input)
|
||||
. = list()
|
||||
.["version"] = GLOB.game_version
|
||||
.["mode"] = GLOB.master_mode
|
||||
.["mode"] = "hidden" //CIT CHANGE - hides the gamemode in topic() calls to prevent meta'ing the gamemode
|
||||
.["respawn"] = config ? !CONFIG_GET(flag/norespawn) : FALSE
|
||||
.["enter"] = GLOB.enter_allowed
|
||||
.["vote"] = CONFIG_GET(flag/allow_vote_mode)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
-100
@@ -251,24 +251,6 @@
|
||||
return 1
|
||||
|
||||
/atom/movable/Destroy(force)
|
||||
var/inform_admins = (flags_2 & INFORM_ADMINS_ON_RELOCATE_2)
|
||||
var/stationloving = (flags_2 & STATIONLOVING_2)
|
||||
|
||||
if(inform_admins && force)
|
||||
var/turf/T = get_turf(src)
|
||||
message_admins("[src] has been !!force deleted!! in [ADMIN_COORDJMP(T)].")
|
||||
log_game("[src] has been !!force deleted!! in [COORD(T)].")
|
||||
|
||||
if(stationloving && !force)
|
||||
var/turf/currentturf = get_turf(src)
|
||||
var/turf/targetturf = relocate()
|
||||
log_game("[src] has been destroyed in [COORD(currentturf)]. Moving it to [COORD(targetturf)].")
|
||||
if(inform_admins)
|
||||
message_admins("[src] has been destroyed in [ADMIN_COORDJMP(currentturf)]. Moving it to [ADMIN_COORDJMP(targetturf)].")
|
||||
return QDEL_HINT_LETMELIVE
|
||||
|
||||
if(stationloving && force)
|
||||
STOP_PROCESSING(SSinbounds, src)
|
||||
|
||||
QDEL_NULL(proximity_monitor)
|
||||
QDEL_NULL(language_holder)
|
||||
@@ -365,6 +347,7 @@
|
||||
loc = null
|
||||
|
||||
/atom/movable/proc/onTransitZ(old_z,new_z)
|
||||
SendSignal(COMSIG_MOVABLE_Z_CHANGED, old_z, new_z)
|
||||
for (var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
|
||||
var/atom/movable/AM = item
|
||||
AM.onTransitZ(old_z,new_z)
|
||||
@@ -632,88 +615,6 @@
|
||||
animate(src, pixel_y = initial(pixel_y), time = 10)
|
||||
floating = FALSE
|
||||
|
||||
/* Stationloving
|
||||
*
|
||||
* A stationloving atom will always teleport back to the station
|
||||
* if it ever leaves the station z-levels or CentCom. It will also,
|
||||
* when Destroy() is called, will teleport to a random turf on the
|
||||
* station.
|
||||
*
|
||||
* The turf is guaranteed to be "safe" for normal humans, probably.
|
||||
* If the station is SUPER SMASHED UP, it might not work.
|
||||
*
|
||||
* Here are some important procs:
|
||||
* relocate()
|
||||
* moves the atom to a safe turf on the station
|
||||
*
|
||||
* check_in_bounds()
|
||||
* regularly called and checks if `in_bounds()` returns true. If false, it
|
||||
* triggers a `relocate()`.
|
||||
*
|
||||
* in_bounds()
|
||||
* By default, checks that the atom's z is the station z or centcom.
|
||||
*/
|
||||
|
||||
/atom/movable/proc/set_stationloving(state, inform_admins=FALSE)
|
||||
var/currently = (flags_2 & STATIONLOVING_2)
|
||||
|
||||
if(inform_admins)
|
||||
flags_2 |= INFORM_ADMINS_ON_RELOCATE_2
|
||||
else
|
||||
flags_2 &= ~INFORM_ADMINS_ON_RELOCATE_2
|
||||
|
||||
if(state == currently)
|
||||
return
|
||||
else if(!state)
|
||||
STOP_PROCESSING(SSinbounds, src)
|
||||
flags_2 &= ~STATIONLOVING_2
|
||||
else
|
||||
START_PROCESSING(SSinbounds, src)
|
||||
flags_2 |= STATIONLOVING_2
|
||||
|
||||
/atom/movable/proc/relocate()
|
||||
var/targetturf = find_safe_turf()
|
||||
if(!targetturf)
|
||||
if(GLOB.blobstart.len > 0)
|
||||
targetturf = get_turf(pick(GLOB.blobstart))
|
||||
else
|
||||
throw EXCEPTION("Unable to find a blobstart landmark")
|
||||
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.transferItemToLoc(src, targetturf, TRUE) //nodrops disks when?
|
||||
else if(loc.SendSignal(COMSIG_CONTAINS_STORAGE))
|
||||
loc.SendSignal(COMSIG_TRY_STORAGE_TAKE, src, targetturf, TRUE)
|
||||
else
|
||||
forceMove(targetturf)
|
||||
// move the disc, so ghosts remain orbiting it even if it's "destroyed"
|
||||
return targetturf
|
||||
|
||||
/atom/movable/proc/check_in_bounds()
|
||||
if(in_bounds())
|
||||
return
|
||||
else
|
||||
var/turf/currentturf = get_turf(src)
|
||||
to_chat(get(src, /mob), "<span class='danger'>You can't help but feel that you just lost something back there...</span>")
|
||||
var/turf/targetturf = relocate()
|
||||
log_game("[src] has been moved out of bounds in [COORD(currentturf)]. Moving it to [COORD(targetturf)].")
|
||||
if(flags_2 & INFORM_ADMINS_ON_RELOCATE_2)
|
||||
message_admins("[src] has been moved out of bounds in [ADMIN_COORDJMP(currentturf)]. Moving it to [ADMIN_COORDJMP(targetturf)].")
|
||||
|
||||
/atom/movable/proc/in_bounds()
|
||||
var/static/list/allowed_shuttles = typecacheof(list(/area/shuttle/syndicate, /area/shuttle/escape, /area/shuttle/pod_1, /area/shuttle/pod_2, /area/shuttle/pod_3, /area/shuttle/pod_4))
|
||||
var/turf/T = get_turf(src)
|
||||
if (!T)
|
||||
return FALSE
|
||||
if (is_station_level(T.z) || is_centcom_level(T.z))
|
||||
return TRUE
|
||||
if (is_transit_level(T.z))
|
||||
var/area/A = T.loc
|
||||
if (is_type_in_typecache(A, allowed_shuttles))
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/* Language procs */
|
||||
/atom/movable/proc/get_language_holder(shadow=TRUE)
|
||||
if(language_holder)
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
/*~~~~~~~~~~~~
|
||||
Circutry!
|
||||
~~~~~~~~~~~~~*/
|
||||
/obj/item/device/electronic_assembly/proc/diag_hud_set_circuithealth(hide = FALSE)
|
||||
/obj/item/electronic_assembly/proc/diag_hud_set_circuithealth(hide = FALSE)
|
||||
var/image/holder = hud_list[DIAG_CIRCUIT_HUD]
|
||||
var/icon/I = icon(icon, icon_state, dir)
|
||||
holder.pixel_y = I.Height() - world.icon_size
|
||||
@@ -430,7 +430,7 @@
|
||||
else
|
||||
holder.icon_state = "huddiag[RoundDiagBar(obj_integrity/max_integrity)]"
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/diag_hud_set_circuitcell(hide = FALSE)
|
||||
/obj/item/electronic_assembly/proc/diag_hud_set_circuitcell(hide = FALSE)
|
||||
var/image/holder = hud_list[DIAG_BATT_HUD]
|
||||
var/icon/I = icon(icon, icon_state, dir)
|
||||
holder.pixel_y = I.Height() - world.icon_size
|
||||
@@ -442,7 +442,7 @@
|
||||
else
|
||||
holder.icon_state = "hudnobatt"
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/diag_hud_set_circuitstat(hide = FALSE) //On, On and dangerous, or Off
|
||||
/obj/item/electronic_assembly/proc/diag_hud_set_circuitstat(hide = FALSE) //On, On and dangerous, or Off
|
||||
var/image/holder = hud_list[DIAG_STAT_HUD]
|
||||
var/icon/I = icon(icon, icon_state, dir)
|
||||
holder.pixel_y = I.Height() - world.icon_size
|
||||
@@ -457,7 +457,7 @@
|
||||
else //Bot is on and not dangerous
|
||||
holder.icon_state = prefered_hud_icon
|
||||
|
||||
/obj/item/device/electronic_assembly/proc/diag_hud_set_circuittracking(hide = FALSE)
|
||||
/obj/item/electronic_assembly/proc/diag_hud_set_circuittracking(hide = FALSE)
|
||||
var/image/holder = hud_list[DIAG_TRACK_HUD]
|
||||
var/icon/I = icon(icon, icon_state, dir)
|
||||
holder.pixel_y = I.Height() - world.icon_size
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -258,12 +258,12 @@ Credit where due:
|
||||
uniform = /obj/item/clothing/under/chameleon/ratvar
|
||||
shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
back = /obj/item/storage/backpack
|
||||
ears = /obj/item/device/radio/headset
|
||||
ears = /obj/item/radio/headset
|
||||
gloves = /obj/item/clothing/gloves/color/yellow
|
||||
belt = /obj/item/storage/belt/utility/servant
|
||||
backpack_contents = list(/obj/item/storage/box/engineer = 1, \
|
||||
/obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/paper/servant_primer = 1)
|
||||
id = /obj/item/device/pda
|
||||
id = /obj/item/pda
|
||||
var/plasmaman //We use this to determine if we should activate internals in post_equip()
|
||||
|
||||
/datum/outfit/servant_of_ratvar/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
@@ -276,7 +276,7 @@ Credit where due:
|
||||
|
||||
/datum/outfit/servant_of_ratvar/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
var/obj/item/card/id/W = new(H)
|
||||
var/obj/item/device/pda/PDA = H.wear_id
|
||||
var/obj/item/pda/PDA = H.wear_id
|
||||
W.assignment = "Assistant"
|
||||
W.access += ACCESS_MAINT_TUNNELS
|
||||
W.registered_name = H.real_name
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user