mirror of
https://github.com/Yawn-Wider/YWPolarisVore.git
synced 2026-08-27 07:03:37 +01:00
Merge pull request #1454 from Yawn-Wider/voreupdate-515
Voreupdate 515 [MDB IGNORE] [IDB IGNORE]
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
# This file has all the information on what versions of libraries are thrown into the code
|
||||
# For dreamchecker
|
||||
export SPACEMAN_DMM_VERSION=suite-1.7
|
||||
export SPACEMAN_DMM_VERSION=suite-1.8
|
||||
# For NanoUI + TGUI
|
||||
export NODE_VERSION=16
|
||||
# Byond Major
|
||||
export BYOND_MAJOR=514
|
||||
export BYOND_MAJOR=515
|
||||
# Byond Minor
|
||||
export BYOND_MINOR=1589
|
||||
export BYOND_MINOR=1630
|
||||
# Macro Count
|
||||
export MACRO_COUNT=4
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// atmospherics devices.
|
||||
//--------------------------------------------
|
||||
|
||||
var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "black" = PIPE_COLOR_BLACK, "purple" = PIPE_COLOR_PURPLE)
|
||||
var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "black" = PIPE_COLOR_BLACK, "orange" = PIPE_COLOR_ORANGE, "white" = PIPE_COLOR_WHITE, "purple" = PIPE_COLOR_PURPLE)
|
||||
|
||||
/proc/pipe_color_lookup(var/color)
|
||||
for(var/C in pipe_colors)
|
||||
|
||||
@@ -16,7 +16,7 @@ Pipelines + Other Objects -> Pipe network
|
||||
power_channel = ENVIRON
|
||||
var/nodealert = 0
|
||||
var/power_rating //the maximum amount of power the machine can use to do work, affects how powerful the machine is, in Watts
|
||||
|
||||
|
||||
unacidable = TRUE
|
||||
layer = ATMOS_LAYER
|
||||
plane = PLATING_PLANE
|
||||
@@ -171,6 +171,9 @@ Pipelines + Other Objects -> Pipe network
|
||||
if(construction_type)
|
||||
var/obj/item/pipe/I = new construction_type(loc, null, null, src)
|
||||
I.setPipingLayer(piping_layer)
|
||||
if(istype(I, /obj/item/pipe/trinary/flippable))
|
||||
var/obj/item/pipe/trinary/flippable/flip = I
|
||||
flip.icon_state = "[flip.icon_state][flip.mirrored ? "m" : ""]"
|
||||
transfer_fingerprints_to(I)
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
if(portData.len)
|
||||
data["ports"] = portData
|
||||
if(output)
|
||||
data["set_flow_rate"] = round(set_flow_rate*10) //because nanoui can't handle rounded decimals.
|
||||
data["last_flow_rate"] = round(last_flow_rate*10)
|
||||
data["set_flow_rate"] = round(set_flow_rate)
|
||||
data["last_flow_rate"] = round(last_flow_rate)
|
||||
|
||||
return data
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
/obj/machinery/atmospherics/omni/atmos_filter/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
|
||||
switch(action)
|
||||
if("power")
|
||||
if(!configuring)
|
||||
@@ -266,4 +266,4 @@
|
||||
else
|
||||
initialize_directions |= P.dir
|
||||
P.connect()
|
||||
P.update = 1
|
||||
P.update = 1
|
||||
|
||||
@@ -158,8 +158,8 @@
|
||||
if(portData.len)
|
||||
data["ports"] = portData
|
||||
if(output)
|
||||
data["set_flow_rate"] = round(set_flow_rate*10) //because nanoui can't handle rounded decimals.
|
||||
data["last_flow_rate"] = round(last_flow_rate*10)
|
||||
data["set_flow_rate"] = round(set_flow_rate)
|
||||
data["last_flow_rate"] = round(last_flow_rate)
|
||||
|
||||
return data
|
||||
|
||||
@@ -294,4 +294,4 @@
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/con_lock(var/port = NORTH)
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.dir == port)
|
||||
P.con_lock = !P.con_lock
|
||||
P.con_lock = !P.con_lock
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
#if DM_VERSION >= 515
|
||||
#error PLEASE MAKE SURE THAT 515 IS PROPERLY TESTED AND WORKS. ESPECIALLY THE SAVE-FILES HAVE TO WORK.
|
||||
#error Additionally: Make sure that the GitHub Workflow was updated to BYOND 515 as well.
|
||||
#endif
|
||||
|
||||
// These defines are from __513_compatibility.dm -- Please Sort
|
||||
#define CLAMP(CLVALUE, CLMIN, CLMAX) clamp(CLVALUE, CLMIN, CLMAX)
|
||||
#define TAN(x) tan(x)
|
||||
|
||||
@@ -16,5 +16,7 @@
|
||||
#define MODIFIY_ROBOT_SWAP_MODULE "Swap a Robot Module"
|
||||
#define MODIFIY_ROBOT_RESET_MODULE "Fully Reset Robot Module"
|
||||
#define MODIFIY_ROBOT_TOGGLE_ERT "Toggle ERT Module Overwrite"
|
||||
#define MODIFIY_ROBOT_LIMIT_MODULES_ADD "Restrict Modules to"
|
||||
#define MODIFIY_ROBOT_LIMIT_MODULES_REMOVE "Remove from restricted Modules"
|
||||
#define MODIFIY_ROBOT_TOGGLE_STATION_ACCESS "Toggle All Station Access Codes"
|
||||
#define MODIFIY_ROBOT_TOGGLE_CENT_ACCESS "Toggle Central Access Codes"
|
||||
|
||||
@@ -779,3 +779,20 @@
|
||||
#define ELEMENT_CONFLICT_FOUND (1<<0)
|
||||
//From reagents touch_x.
|
||||
#define COMSIG_REAGENTS_TOUCH "reagent_touch"
|
||||
|
||||
|
||||
//Moved observer stuff to DCS
|
||||
#define COMSIG_OBSERVER_MOVED "observer_move"
|
||||
#define COMSIG_OBSERVER_DESTROYED "observer_destroyed"
|
||||
#define COMSIG_OBSERVER_SHUTTLE_ADDED "observer_shuttle_added"
|
||||
#define COMSIG_OBSERVER_SHUTTLE_PRE_MOVE "observer_shuttle_premove"
|
||||
#define COMSIG_OBSERVER_SHUTTLE_MOVED "observer_shuttle_moved"
|
||||
#define COMSIG_OBSERVER_TURF_ENTERED "observer_turf_entered"
|
||||
#define COMSIG_OBSERVER_TURF_EXITED "observer_turf_exited"
|
||||
#define COMSIG_OBSERVER_Z_MOVED "observer_z_moved"
|
||||
#define COMSIG_OBSERVER_MOB_EQUIPPED "observer_mob_equipped"
|
||||
#define COMSIG_OBSERVER_ITEM_EQUIPPED "observer_item_equipped"
|
||||
#define COMSIG_OBSERVER_MOB_UNEQUIPPED "observer_mob_unequipped"
|
||||
#define COMSIG_OBSERVER_ITEM_UNEQUIPPED "observer_item_unequipped"
|
||||
#define COMSIG_OBSERVER_APC "observer_apc"
|
||||
#define COMSIG_OBSERVER_GLOBALMOVED "observer_global_move"
|
||||
|
||||
@@ -8,14 +8,15 @@
|
||||
#define INVISIBILITY_LIGHTING 20
|
||||
#define INVISIBILITY_LEVEL_ONE 35
|
||||
#define INVISIBILITY_LEVEL_TWO 45
|
||||
#define INVISIBILITY_SHADEKIN 55 //CHOMPStation change
|
||||
#define INVISIBILITY_SHADEKIN 55
|
||||
#define INVISIBILITY_OBSERVER 60
|
||||
#define INVISIBILITY_EYE 61
|
||||
|
||||
#define SEE_INVISIBLE_LIVING 25
|
||||
#define SEE_INVISIBLE_NOLIGHTING 15
|
||||
#define SEE_INVISIBLE_NOLIGHTING 15
|
||||
#define SEE_INVISIBLE_LEVEL_ONE 35
|
||||
#define SEE_INVISIBLE_LEVEL_TWO 45
|
||||
#define SEE_INVISIBILITY_SHADEKIN 55
|
||||
#define SEE_INVISIBLE_CULT 60
|
||||
#define SEE_INVISIBLE_OBSERVER 61
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define BORGTHERM 0x2
|
||||
#define BORGXRAY 0x4
|
||||
#define BORGMATERIAL 0x8
|
||||
#define BORGANOMALOUS 0x10
|
||||
|
||||
#define STANCE_ATTACK 11 // Backwards compatability
|
||||
#define STANCE_ATTACKING 12 // Ditto
|
||||
|
||||
+29
-12
@@ -1,4 +1,6 @@
|
||||
//defines that give qdel hints. these can be given as a return in destory() or by calling
|
||||
//! Defines that give qdel hints.
|
||||
//!
|
||||
//! These can be given as a return in [/atom/proc/Destroy] or by calling [/proc/qdel].
|
||||
|
||||
/// `qdel` should queue the object for deletion.
|
||||
#define QDEL_HINT_QUEUE 0
|
||||
@@ -11,41 +13,56 @@
|
||||
// Qdel should assume this object won't gc, and hard delete it posthaste.
|
||||
#define QDEL_HINT_HARDDEL_NOW 4
|
||||
|
||||
|
||||
#ifdef REFERENCE_TRACKING
|
||||
/** If REFERENCE_TRACKING is enabled, qdel will call this object's find_references() verb.
|
||||
*
|
||||
* Functionally identical to [QDEL_HINT_QUEUE] if [GC_FAILURE_HARD_LOOKUP] is not enabled in _compiler_options.dm.
|
||||
*/
|
||||
#warn TG0001 qdel REFERENCE_TRACKING enabled
|
||||
#define QDEL_HINT_FINDREFERENCE 5
|
||||
/// Behavior as [QDEL_HINT_FINDREFERENCE], but only if the GC fails and a hard delete is forced.
|
||||
#define QDEL_HINT_IFFAIL_FINDREFERENCE 6
|
||||
#endif
|
||||
|
||||
#define GC_QUEUE_CHECK 1
|
||||
#define GC_QUEUE_HARDDELETE 2
|
||||
#define GC_QUEUE_COUNT 2 //increase this when adding more steps.
|
||||
// Defines for the ssgarbage queues
|
||||
#define GC_QUEUE_FILTER 1 //! short queue to filter out quick gc successes so they don't hang around in the main queue for 5 minutes
|
||||
#define GC_QUEUE_CHECK 2 //! main queue that waits 5 minutes because thats the longest byond can hold a reference to our shit.
|
||||
#define GC_QUEUE_HARDDELETE 3 //! short queue for things that hard delete instead of going thru the gc subsystem, this is purely so if they *can* softdelete, they will soft delete rather then wasting time with a hard delete.
|
||||
#define GC_QUEUE_COUNT 3 //! Number of queues, used for allocating the nested lists. Don't forget to increase this if you add a new queue stage
|
||||
|
||||
|
||||
// Defines for the ssgarbage queue items
|
||||
#define GC_QUEUE_ITEM_QUEUE_TIME 1 //! Time this item entered the queue
|
||||
#define GC_QUEUE_ITEM_REF 2 //! Ref to the item
|
||||
#define GC_QUEUE_ITEM_GCD_DESTROYED 3 //! Item's gc_destroyed var value. Used to detect ref reuse.
|
||||
#define GC_QUEUE_ITEM_INDEX_COUNT 3 //! Number of item indexes, used for allocating the nested lists. Don't forget to increase this if you add a new queue item index
|
||||
|
||||
// Defines for the time an item has to get its reference cleaned before it fails the queue and moves to the next.
|
||||
#define GC_FILTER_QUEUE (1 SECONDS)
|
||||
#define GC_CHECK_QUEUE (5 MINUTES)
|
||||
#define GC_DEL_QUEUE (10 SECONDS)
|
||||
|
||||
|
||||
#define QDEL_ITEM_ADMINS_WARNED (1<<0) //! Set when admins are told about lag causing qdels in this type.
|
||||
#define QDEL_ITEM_SUSPENDED_FOR_LAG (1<<1) //! Set when a type can no longer be hard deleted on failure because of lag it causes while this happens.
|
||||
|
||||
// Defines for the [gc_destroyed][/datum/var/gc_destroyed] var.
|
||||
#define GC_QUEUED_FOR_QUEUING -1
|
||||
#define GC_CURRENTLY_BEING_QDELETED -2
|
||||
|
||||
#define QDELING(X) (X.gc_destroyed)
|
||||
#define QDELETED(X) (!X || X.gc_destroyed)
|
||||
#define QDELETED(X) (isnull(X) || QDELING(X))
|
||||
#define QDESTROYING(X) (!X || X.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
|
||||
|
||||
//Qdel helper macros.
|
||||
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), item), time, TIMER_STOPPABLE)
|
||||
// This is a bit hacky, we do it to avoid people relying on a return value for the macro
|
||||
// If you need that you should use QDEL_IN_STOPPABLE instead
|
||||
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time);
|
||||
#define QDEL_IN_STOPPABLE(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time, TIMER_STOPPABLE)
|
||||
#define QDEL_IN_CLIENT_TIME(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), item), time, TIMER_STOPPABLE | TIMER_CLIENT_TIME)
|
||||
#define QDEL_NULL(item) if(item) {qdel(item); item = null}
|
||||
#define QDEL_NULL(item) qdel(item); item = null
|
||||
#define QDEL_NULL_LIST QDEL_LIST_NULL
|
||||
#define QDEL_LIST_NULL(x) if(x) { for(var/y in x) { qdel(y) } ; x = null }
|
||||
#define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); }
|
||||
#define QDEL_LIST_IN(L, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(______qdel_list_wrapper), L), time, TIMER_STOPPABLE)
|
||||
#define QDEL_LIST_ASSOC(L) if(L) { for(var/I in L) { qdel(L[I]); qdel(I); } L.Cut(); }
|
||||
#define QDEL_LIST_ASSOC_VAL(L) if(L) { for(var/I in L) qdel(L[I]); L.Cut(); }
|
||||
|
||||
/proc/______qdel_list_wrapper(list/L) //the underscores are to encourage people not to use this directly.
|
||||
QDEL_LIST(L)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
// savefile ser/de //
|
||||
#define rustg_savefile_to_json(save_string) call(RUST_G, "savefile_to_json")(save_string)
|
||||
#define rustg_savefile_to_json(save_string) LIBCALL(RUST_G, "savefile_to_json")(save_string)
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
|
||||
#define span_reflex_shoot(str) ("<span class='reflex_shoot'>" + str + "</span>")
|
||||
|
||||
/* Vore messages */
|
||||
|
||||
#define span_vdanger(str) ("<span class='vdanger'>" + str + "</span>")
|
||||
#define span_vwarning(str) ("<span class='vwarning'>" + str + "</span>")
|
||||
#define span_vnotice(str) ("<span class='vnotice'>" + str + "</span>")
|
||||
|
||||
/* Languages */
|
||||
|
||||
#define span_alien(str) ("<span class='alien'>" + str + "</span>")
|
||||
|
||||
@@ -127,6 +127,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
||||
#define FIRE_PRIORITY_PING 10
|
||||
#define FIRE_PRIORITY_AI 10
|
||||
#define FIRE_PRIORITY_GARBAGE 15
|
||||
#define FIRE_PRIORITY_ASSETS 20
|
||||
#define FIRE_PRIORITY_ALARM 20
|
||||
#define FIRE_PRIORITY_CHARSETUP 25
|
||||
#define FIRE_PRIORITY_AIRFLOW 30
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
GLOBAL_LIST_EMPTY(error_last_seen)
|
||||
GLOBAL_LIST_EMPTY(error_cooldown)
|
||||
|
||||
GLOBAL_DATUM_INIT(all_observable_events, /datum/all_observable_events, new) // This is a datum. It is not a list.
|
||||
GLOBAL_DATUM_INIT(destroyed_event, /decl/observ/destroyed, new())
|
||||
//GLOBAL_DATUM_INIT(all_observable_events, /datum/all_observable_events, new) // This is a datum. It is not a list.
|
||||
//GLOBAL_DATUM_INIT(destroyed_event, /decl/observ/destroyed, new())
|
||||
|
||||
GLOBAL_VAR_INIT(timezoneOffset, 0) // The difference betwen midnight (of the host computer) and 0 world.ticks.
|
||||
|
||||
GLOBAL_VAR_INIT(TAB, " ")
|
||||
GLOBAL_VAR_INIT(TAB, " ")
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
// atoms/items/objects can be pretty and whatnot
|
||||
var/atom/A = item
|
||||
if(output_icons && isicon(A.icon) && !ismob(A)) // mobs tend to have unusable icons
|
||||
item_str += "\icon[A][bicon(A)] "
|
||||
item_str += "[bicon(A)] "
|
||||
switch(determiners)
|
||||
if(DET_NONE) item_str += A.name
|
||||
if(DET_DEFINITE) item_str += "\the [A]"
|
||||
|
||||
@@ -327,3 +327,32 @@ GLOBAL_LIST_EMPTY(mannequins)
|
||||
*/
|
||||
//Hexidecimal numbers
|
||||
var/global/list/hexNums = list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
|
||||
|
||||
// Many global vars aren't GLOB type. This puts them there to be more easily inspected.
|
||||
GLOBAL_LIST_EMPTY(legacy_globals)
|
||||
|
||||
/proc/populate_legacy_globals()
|
||||
//Note: these lists cannot be changed to a new list anywhere in code!
|
||||
//If they are, these will cause the old list to stay around!
|
||||
//Check by searching for "<GLOBAL_NAME> =" in the entire codebase
|
||||
GLOB.legacy_globals["player_list"] = player_list
|
||||
GLOB.legacy_globals["mob_list"] = mob_list
|
||||
GLOB.legacy_globals["human_mob_list"] = human_mob_list
|
||||
GLOB.legacy_globals["silicon_mob_list"] = silicon_mob_list
|
||||
GLOB.legacy_globals["ai_list"] = ai_list
|
||||
GLOB.legacy_globals["living_mob_list"] = living_mob_list
|
||||
GLOB.legacy_globals["dead_mob_list"] = dead_mob_list
|
||||
GLOB.legacy_globals["observer_mob_list"] = observer_mob_list
|
||||
GLOB.legacy_globals["listening_objects"] = listening_objects
|
||||
GLOB.legacy_globals["cleanbot_reserved_turfs"] = cleanbot_reserved_turfs
|
||||
GLOB.legacy_globals["cable_list"] = cable_list
|
||||
GLOB.legacy_globals["landmarks_list"] = landmarks_list
|
||||
GLOB.legacy_globals["event_triggers"] = event_triggers
|
||||
GLOB.legacy_globals["side_effects"] = side_effects
|
||||
GLOB.legacy_globals["mechas_list"] = mechas_list
|
||||
GLOB.legacy_globals["mannequins_"] = mannequins_
|
||||
//visual nets
|
||||
GLOB.legacy_globals["visual_nets"] = visual_nets
|
||||
GLOB.legacy_globals["cameranet"] = cameranet
|
||||
GLOB.legacy_globals["cultnet"] = cultnet
|
||||
GLOB.legacy_globals["existing_solargrubs"] = existing_solargrubs
|
||||
|
||||
@@ -240,6 +240,7 @@ var/global/list/edible_trash = list(/obj/item/broken_device,
|
||||
/obj/item/weapon/storage/wallet,
|
||||
/obj/item/weapon/storage/vore_egg,
|
||||
/obj/item/weapon/bikehorn/tinytether,
|
||||
/obj/item/weapon/entrepreneur,
|
||||
/obj/item/capture_crystal,
|
||||
/obj/item/roulette_ball,
|
||||
/obj/item/pizzabox
|
||||
|
||||
+15
-8
@@ -536,6 +536,13 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
|
||||
CRASH("get_dummy_savefile failed to create a dummy savefile: '[error]'")
|
||||
return get_dummy_savefile(from_failure = TRUE)
|
||||
|
||||
|
||||
/// Generate a filename for this asset
|
||||
/// The same asset will always lead to the same asset name
|
||||
/// (Generated names do not include file extention.)
|
||||
/proc/generate_asset_name(file)
|
||||
return "asset.[md5(fcopy_rsc(file))]"
|
||||
|
||||
/**
|
||||
* Converts an icon to base64. Operates by putting the icon in the iconCache savefile,
|
||||
* exporting it as text, and then parsing the base64 from that.
|
||||
@@ -655,12 +662,12 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
|
||||
//var/name = SANITIZE_FILENAME("[generate_asset_name(thing)].png")
|
||||
var/name = "[generate_asset_name(thing)].png"
|
||||
if (!SSassets.cache[name])
|
||||
register_asset(name, thing)
|
||||
SSassets.transport.register_asset(name, thing)
|
||||
for (var/thing2 in targets)
|
||||
send_asset(thing2, name)
|
||||
SSassets.transport.send_assets(thing2, name)
|
||||
if(sourceonly)
|
||||
return get_asset_url(name)
|
||||
return "<img class='[extra_classes] icon icon-misc' src='[get_asset_url(name)]'>"
|
||||
return SSassets.transport.get_asset_url(name)
|
||||
return "<img class='[extra_classes] icon icon-misc' src='[SSassets.transport.get_asset_url(name)]'>"
|
||||
|
||||
//its either an atom, image, or mutable_appearance, we want its icon var
|
||||
icon2collapse = thing.icon
|
||||
@@ -697,12 +704,12 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
|
||||
key = "[name_and_ref[3]].png"
|
||||
|
||||
if(!SSassets.cache[key])
|
||||
register_asset(key, rsc_ref, file_hash, icon_path)
|
||||
SSassets.transport.register_asset(key, rsc_ref, file_hash, icon_path)
|
||||
for (var/client_target in targets)
|
||||
send_asset(client_target, key)
|
||||
SSassets.transport.send_assets(client_target, key)
|
||||
if(sourceonly)
|
||||
return get_asset_url(key)
|
||||
return "<img class='[extra_classes] icon icon-[icon_state]' src='[get_asset_url(key)]'>"
|
||||
return SSassets.transport.get_asset_url(key)
|
||||
return "<img class='[extra_classes] icon icon-[icon_state]' src='[SSassets.transport.get_asset_url(key)]'>"
|
||||
|
||||
/proc/icon2base64html(target, var/custom_classes = "")
|
||||
if (!target)
|
||||
|
||||
@@ -8,10 +8,14 @@
|
||||
if(toIndex <= 0)
|
||||
toIndex += L.len + 1
|
||||
|
||||
sortInstance.L = L
|
||||
sortInstance.cmp = cmp
|
||||
sortInstance.associative = associative
|
||||
var/datum/sort_instance/SI = GLOB.sortInstance
|
||||
if(!SI)
|
||||
SI = new
|
||||
|
||||
sortInstance.timSort(fromIndex, toIndex)
|
||||
SI.L = L
|
||||
SI.cmp = cmp
|
||||
SI.associative = associative
|
||||
|
||||
SI.timSort(fromIndex, toIndex)
|
||||
|
||||
return L
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
#define MIN_GALLOP 7
|
||||
|
||||
//This is a global instance to allow much of this code to be reused. The interfaces are kept separately
|
||||
var/datum/sortInstance/sortInstance = new()
|
||||
/datum/sortInstance
|
||||
GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
|
||||
/datum/sort_instance
|
||||
//The array being sorted.
|
||||
var/list/L
|
||||
|
||||
//The comparator proc-reference
|
||||
var/cmp = /proc/cmp_numeric_asc
|
||||
var/cmp = GLOBAL_PROC_REF(cmp_numeric_asc)
|
||||
|
||||
//whether we are sorting list keys (0: L[i]) or associated values (1: L[L[i]])
|
||||
var/associative = 0
|
||||
@@ -32,7 +32,7 @@ var/datum/sortInstance/sortInstance = new()
|
||||
var/list/runLens = list()
|
||||
|
||||
|
||||
/datum/sortInstance/proc/timSort(start, end)
|
||||
/datum/sort_instance/proc/timSort(start, end)
|
||||
runBases.Cut()
|
||||
runLens.Cut()
|
||||
|
||||
@@ -97,7 +97,7 @@ lo the index of the first element in the range to be sorted
|
||||
hi the index after the last element in the range to be sorted
|
||||
start the index of the first element in the range that is not already known to be sorted
|
||||
*/
|
||||
/datum/sortInstance/proc/binarySort(lo, hi, start)
|
||||
/datum/sort_instance/proc/binarySort(lo, hi, start)
|
||||
//ASSERT(lo <= start && start <= hi)
|
||||
if(start <= lo)
|
||||
start = lo + 1
|
||||
@@ -135,7 +135,7 @@ For its intended use in a stable mergesort, the strictness of the
|
||||
definition of "descending" is needed so that the call can safely
|
||||
reverse a descending sequence without violating stability.
|
||||
*/
|
||||
/datum/sortInstance/proc/countRunAndMakeAscending(lo, hi)
|
||||
/datum/sort_instance/proc/countRunAndMakeAscending(lo, hi)
|
||||
//ASSERT(lo < hi)
|
||||
|
||||
var/runHi = lo + 1
|
||||
@@ -165,7 +165,7 @@ reverse a descending sequence without violating stability.
|
||||
|
||||
//Returns the minimum acceptable run length for an array of the specified length.
|
||||
//Natural runs shorter than this will be extended with binarySort
|
||||
/datum/sortInstance/proc/minRunLength(n)
|
||||
/datum/sort_instance/proc/minRunLength(n)
|
||||
//ASSERT(n >= 0)
|
||||
var/r = 0 //becomes 1 if any bits are shifted off
|
||||
while(n >= MIN_MERGE)
|
||||
@@ -178,7 +178,7 @@ reverse a descending sequence without violating stability.
|
||||
// runLen[i-2] > runLen[i-1]
|
||||
//This method is called each time a new run is pushed onto the stack.
|
||||
//So the invariants are guaranteed to hold for i<stackSize upon entry to the method
|
||||
/datum/sortInstance/proc/mergeCollapse()
|
||||
/datum/sort_instance/proc/mergeCollapse()
|
||||
while(runBases.len >= 2)
|
||||
var/n = runBases.len - 1
|
||||
if(n > 1 && runLens[n-1] <= runLens[n] + runLens[n+1])
|
||||
@@ -193,7 +193,7 @@ reverse a descending sequence without violating stability.
|
||||
|
||||
//Merges all runs on the stack until only one remains.
|
||||
//Called only once, to finalise the sort
|
||||
/datum/sortInstance/proc/mergeForceCollapse()
|
||||
/datum/sort_instance/proc/mergeForceCollapse()
|
||||
while(runBases.len >= 2)
|
||||
var/n = runBases.len - 1
|
||||
if(n > 1 && runLens[n-1] < runLens[n+1])
|
||||
@@ -204,7 +204,7 @@ reverse a descending sequence without violating stability.
|
||||
//Merges the two consecutive runs at stack indices i and i+1
|
||||
//Run i must be the penultimate or antepenultimate run on the stack
|
||||
//In other words, i must be equal to stackSize-2 or stackSize-3
|
||||
/datum/sortInstance/proc/mergeAt(i)
|
||||
/datum/sort_instance/proc/mergeAt(i)
|
||||
//ASSERT(runBases.len >= 2)
|
||||
//ASSERT(i >= 1)
|
||||
//ASSERT(i == runBases.len - 1 || i == runBases.len - 2)
|
||||
@@ -258,7 +258,7 @@ reverse a descending sequence without violating stability.
|
||||
|
||||
Returns the index at which to insert element 'key'
|
||||
*/
|
||||
/datum/sortInstance/proc/gallopLeft(key, base, len, hint)
|
||||
/datum/sort_instance/proc/gallopLeft(key, base, len, hint)
|
||||
//ASSERT(len > 0 && hint >= 0 && hint < len)
|
||||
|
||||
var/lastOffset = 0
|
||||
@@ -317,7 +317,7 @@ reverse a descending sequence without violating stability.
|
||||
* @param c the comparator used to order the range, and to search
|
||||
* @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k]
|
||||
*/
|
||||
/datum/sortInstance/proc/gallopRight(key, base, len, hint)
|
||||
/datum/sort_instance/proc/gallopRight(key, base, len, hint)
|
||||
//ASSERT(len > 0 && hint >= 0 && hint < len)
|
||||
|
||||
var/offset = 1
|
||||
@@ -369,7 +369,7 @@ reverse a descending sequence without violating stability.
|
||||
|
||||
//Merges two adjacent runs in-place in a stable fashion.
|
||||
//For performance this method should only be called when len1 <= len2!
|
||||
/datum/sortInstance/proc/mergeLo(base1, len1, base2, len2)
|
||||
/datum/sort_instance/proc/mergeLo(base1, len1, base2, len2)
|
||||
//ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2)
|
||||
|
||||
var/cursor1 = base1
|
||||
@@ -471,7 +471,7 @@ reverse a descending sequence without violating stability.
|
||||
//ASSERT(len1 > 1)
|
||||
|
||||
|
||||
/datum/sortInstance/proc/mergeHi(base1, len1, base2, len2)
|
||||
/datum/sort_instance/proc/mergeHi(base1, len1, base2, len2)
|
||||
//ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2)
|
||||
|
||||
var/cursor1 = base1 + len1 - 1 //start at end of sublists
|
||||
@@ -571,7 +571,7 @@ reverse a descending sequence without violating stability.
|
||||
//ASSERT(len2 > 0)
|
||||
|
||||
|
||||
/datum/sortInstance/proc/mergeSort(start, end)
|
||||
/datum/sort_instance/proc/mergeSort(start, end)
|
||||
var/remaining = end - start
|
||||
|
||||
//If array is small, do an insertion sort
|
||||
@@ -616,7 +616,7 @@ reverse a descending sequence without violating stability.
|
||||
|
||||
return L
|
||||
|
||||
/datum/sortInstance/proc/mergeAt2(i)
|
||||
/datum/sort_instance/proc/mergeAt2(i)
|
||||
var/cursor1 = runBases[i]
|
||||
var/cursor2 = runBases[i+1]
|
||||
|
||||
|
||||
@@ -348,10 +348,10 @@
|
||||
return tagdesc
|
||||
if(!text_tag_cache[tagname])
|
||||
var/icon/tag = icon(text_tag_icons, tagname)
|
||||
text_tag_cache[tagname] = bicon(tag, TRUE, "text_tag")
|
||||
text_tag_cache[tagname] = tag
|
||||
if(!C.tgui_panel.is_ready() || C.tgui_panel.oldchat)
|
||||
return "<IMG src='\ref[text_tag_icons]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"
|
||||
return text_tag_cache[tagname]
|
||||
return icon2html(text_tag_cache[tagname], C, extra_classes = "text_tag")
|
||||
|
||||
/proc/create_text_tag_old(var/tagname, var/tagdesc = tagname, var/client/C = null)
|
||||
if(!(C && C.is_preference_enabled(/datum/client_preference/chat_tags)))
|
||||
|
||||
@@ -552,3 +552,9 @@
|
||||
catch(var/exception/E)
|
||||
if(error_on_invalid_return)
|
||||
error("Exception when loading file as string: [E]")
|
||||
|
||||
|
||||
/// Return html to load a url.
|
||||
/// for use inside of browse() calls to html assets that might be loaded on a cdn.
|
||||
/proc/url2htmlloader(url)
|
||||
return {"<html><head><meta http-equiv="refresh" content="0;URL='[url]'"/></head><body onLoad="parent.location='[url]'"></body></html>"}
|
||||
|
||||
@@ -58,9 +58,11 @@
|
||||
#define ui_zonesel "EAST-1:28,SOUTH:5"
|
||||
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
|
||||
|
||||
#define ui_borg_pull "EAST-3:24,SOUTH+1:7"
|
||||
#define ui_borg_module "EAST-2:26,SOUTH+1:7"
|
||||
#define ui_borg_panel "EAST-1:28,SOUTH+1:7"
|
||||
#define ui_borg_pull "EAST-4:24,SOUTH+1:7" //borgs
|
||||
#define ui_borg_radio "EAST-2:26,SOUTH+1:7" //borgs
|
||||
#define ui_borg_panel "EAST-1:28,SOUTH+1:7" //borgs
|
||||
#define ui_borg_module "EAST-3:24,SOUTH+1:5"//borgs
|
||||
#define ui_vtec_control "EAST-3:24,SOUTH:5"//borgs
|
||||
|
||||
#define ui_ai_core "SOUTH:6,WEST:16"
|
||||
#define ui_ai_camera_list "SOUTH:6,WEST+1:16"
|
||||
@@ -197,4 +199,4 @@
|
||||
#define ui_mech_deco1_f "WEST+2:-7, SOUTH+8"
|
||||
#define ui_mech_deco2_f "WEST+2:-7, SOUTH+9"
|
||||
|
||||
#define ui_smallquad "EAST-4:22,SOUTH:5"
|
||||
#define ui_smallquad "EAST-4:22,SOUTH:5"
|
||||
|
||||
@@ -183,6 +183,13 @@
|
||||
if(!ability_master) //VOREStation Edit: S H A D E K I N
|
||||
ability_master = new /obj/screen/movable/ability_master(src)
|
||||
|
||||
|
||||
/mob/Destroy()
|
||||
..()
|
||||
if(ability_master)
|
||||
QDEL_NULL(ability_master)
|
||||
|
||||
|
||||
///////////ACTUAL ABILITIES////////////
|
||||
//This is what you click to do things//
|
||||
///////////////////////////////////////
|
||||
@@ -383,4 +390,4 @@
|
||||
A.name = object_given.name
|
||||
ability_objects.Add(A)
|
||||
if(my_mob.client)
|
||||
toggle_open(2) //forces the icons to refresh on screen
|
||||
toggle_open(2) //forces the icons to refresh on screen
|
||||
|
||||
@@ -176,6 +176,7 @@ var/list/global_huds = list(
|
||||
var/obj/screen/l_hand_hud_object
|
||||
var/obj/screen/action_intent
|
||||
var/obj/screen/move_intent
|
||||
var/obj/screen/control_vtec
|
||||
|
||||
var/list/adding
|
||||
/// Misc hud elements that are hidden when the hud is minimized
|
||||
@@ -219,6 +220,7 @@ var/list/global_huds = list(
|
||||
l_hand_hud_object = null
|
||||
action_intent = null
|
||||
move_intent = null
|
||||
control_vtec = null
|
||||
adding = null
|
||||
other = null
|
||||
other_important = null
|
||||
|
||||
@@ -25,7 +25,7 @@ var/obj/screen/robot_inventory
|
||||
using.color = HUD.ui_color
|
||||
using.alpha = HUD.ui_alpha
|
||||
using.icon_state = "radio"
|
||||
using.screen_loc = ui_movi
|
||||
using.screen_loc = ui_borg_radio
|
||||
using.layer = HUD_LAYER
|
||||
adding += using
|
||||
|
||||
@@ -81,6 +81,17 @@ var/obj/screen/robot_inventory
|
||||
adding += using
|
||||
HUD.action_intent = using
|
||||
|
||||
//Move intent (walk/run)
|
||||
using = new /obj/screen()
|
||||
using.name = "mov_intent"
|
||||
using.icon = HUD.ui_style
|
||||
using.icon_state = (m_intent == "run" ? "running" : "walking")
|
||||
using.screen_loc = ui_movi
|
||||
using.color = HUD.ui_color
|
||||
using.alpha = HUD.ui_alpha
|
||||
HUD.adding += using
|
||||
HUD.move_intent = using
|
||||
|
||||
//Health
|
||||
healths = new /obj/screen()
|
||||
healths.icon = HUD.ui_style
|
||||
@@ -206,6 +217,32 @@ var/obj/screen/robot_inventory
|
||||
client.screen += HUD.adding + HUD.other
|
||||
client.screen += client.void
|
||||
|
||||
/datum/hud/proc/toggle_vtec_control()
|
||||
if(!isrobot(mymob))
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/R = mymob
|
||||
if(!control_vtec)
|
||||
var/obj/screen/using = new /obj/screen()
|
||||
using.name = "control_vtec"
|
||||
using.icon = ui_style
|
||||
using.screen_loc = ui_vtec_control
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
control_vtec = using
|
||||
if(R.vtec_active)
|
||||
if(R.speed == 0)
|
||||
control_vtec.icon_state = "speed_0"
|
||||
else if(R.speed == -0.5)
|
||||
control_vtec.icon_state = "speed_1"
|
||||
else if(R.speed == -1)
|
||||
control_vtec.icon_state = "speed_2"
|
||||
R.m_intent = "run"
|
||||
R.hud_used.move_intent.icon_state = "running"
|
||||
R.client.screen += control_vtec
|
||||
else
|
||||
R.client.screen -= control_vtec
|
||||
R.speed = 0
|
||||
|
||||
/datum/hud/proc/toggle_show_robot_modules()
|
||||
if(!isrobot(mymob))
|
||||
@@ -276,7 +313,7 @@ var/obj/screen/robot_inventory
|
||||
else
|
||||
//Modules display is hidden
|
||||
//r.client.screen -= robot_inventory //"store" icon
|
||||
for(var/atom/A in r.module.modules)
|
||||
for(var/atom/A in r.module?.modules)
|
||||
if(r.client && (A != r.module_state_1) && (A != r.module_state_2) && (A != r.module_state_3) )
|
||||
//Module is not currently active
|
||||
r.client.screen -= A
|
||||
|
||||
@@ -272,6 +272,19 @@
|
||||
var/mob/living/L = usr
|
||||
L.resist()
|
||||
|
||||
if("control_vtec")
|
||||
if(isrobot(usr))
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
if(R.speed == 0 && R.vtec_active)
|
||||
R.speed = -0.5
|
||||
R.hud_used.control_vtec.icon_state = "speed_1"
|
||||
else if(R.speed == -0.5 && R.vtec_active)
|
||||
R.speed = -1
|
||||
R.hud_used.control_vtec.icon_state = "speed_2"
|
||||
else
|
||||
R.speed = 0
|
||||
R.hud_used.control_vtec.icon_state = "speed_0"
|
||||
|
||||
if("mov_intent")
|
||||
if(isliving(usr))
|
||||
if(iscarbon(usr))
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
ManualFollow(A)
|
||||
// Otherwise jump
|
||||
else
|
||||
following = null
|
||||
if(following)
|
||||
stop_following()
|
||||
forceMove(get_turf(A))
|
||||
|
||||
/mob/observer/dead/ClickOn(var/atom/A, var/params)
|
||||
@@ -68,9 +69,9 @@
|
||||
|
||||
// VOREStation Edit Begin
|
||||
|
||||
/obj/machinery/gateway/centerstation/attack_ghost(mob/user as mob)
|
||||
if(awaygate)
|
||||
if(user.client.holder)
|
||||
/obj/machinery/gateway/centerstation/attack_ghost(mob/user as mob)
|
||||
if(awaygate)
|
||||
if(user.client.holder)
|
||||
user.loc = awaygate.loc
|
||||
else if(active)
|
||||
user.loc = awaygate.loc
|
||||
|
||||
@@ -305,10 +305,24 @@ var/list/gamemode_cache = list()
|
||||
|
||||
var/static/invoke_youtubedl = null
|
||||
|
||||
|
||||
var/static/asset_transport
|
||||
|
||||
var/static/cache_assets = FALSE
|
||||
|
||||
var/static/save_spritesheets = FALSE
|
||||
|
||||
var/static/asset_simple_preload = FALSE
|
||||
|
||||
var/static/asset_cdn_webroot
|
||||
|
||||
var/static/asset_cdn_url
|
||||
|
||||
//Enables/Disables the appropriate mob type from obtaining the verb on spawn. Still allows admins to manually give it to them.
|
||||
var/static/allow_robot_recolor = FALSE
|
||||
var/static/allow_simple_mob_recolor = FALSE
|
||||
|
||||
|
||||
/datum/configuration/New()
|
||||
var/list/L = subtypesof(/datum/game_mode)
|
||||
for (var/T in L)
|
||||
@@ -987,6 +1001,24 @@ var/list/gamemode_cache = list()
|
||||
if("invoke_youtubedl")
|
||||
config.invoke_youtubedl = value
|
||||
|
||||
if("asset_transport")
|
||||
config.asset_transport = value
|
||||
|
||||
if("cache_assets")
|
||||
config.cache_assets = TRUE
|
||||
|
||||
if("save_spritesheets")
|
||||
config.save_spritesheets = TRUE
|
||||
|
||||
if("asset_simple_preload")
|
||||
config.asset_simple_preload = TRUE
|
||||
|
||||
if("asset_cdn_webroot")
|
||||
config.asset_cdn_webroot = value
|
||||
|
||||
if("asset_cdn_url")
|
||||
config.asset_cdn_url = value
|
||||
|
||||
else
|
||||
log_misc("Unknown setting in configuration: '[name]'")
|
||||
|
||||
|
||||
@@ -62,3 +62,5 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
|
||||
var/end_tick = world.time
|
||||
if(end_tick - start_tick)
|
||||
warning("Global [replacetext("[I]", "InitGlobal", "")] slept during initialization!")
|
||||
|
||||
populate_legacy_globals()
|
||||
|
||||
@@ -281,7 +281,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
//(higher subsystems will be sooner in the queue, adding them later in the loop means we don't have to loop thru them next queue add)
|
||||
sortTim(tickersubsystems, GLOBAL_PROC_REF(cmp_subsystem_priority))
|
||||
for(var/I in runlevel_sorted_subsystems)
|
||||
sortTim(runlevel_sorted_subsystems, GLOBAL_PROC_REF(cmp_subsystem_priority))
|
||||
sortTim(I, GLOBAL_PROC_REF(cmp_subsystem_priority))
|
||||
I += tickersubsystems
|
||||
|
||||
var/cached_runlevel = current_runlevel
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/// Allows us to lazyload asset datums
|
||||
/// Anything inserted here will fully load if directly gotten
|
||||
/// So this just serves to remove the requirement to load assets fully during init
|
||||
SUBSYSTEM_DEF(asset_loading)
|
||||
name = "Asset Loading"
|
||||
priority = FIRE_PRIORITY_ASSETS
|
||||
flags = SS_NO_INIT
|
||||
runlevels = RUNLEVEL_LOBBY|RUNLEVELS_DEFAULT
|
||||
var/list/datum/asset/generate_queue = list()
|
||||
|
||||
/datum/controller/subsystem/asset_loading/fire(resumed)
|
||||
while(length(generate_queue))
|
||||
var/datum/asset/to_load = generate_queue[generate_queue.len]
|
||||
|
||||
to_load.queued_generation()
|
||||
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
generate_queue.len--
|
||||
|
||||
/datum/controller/subsystem/asset_loading/proc/queue_asset(datum/asset/queue)
|
||||
#ifdef DO_NOT_DEFER_ASSETS
|
||||
stack_trace("We queued an instance of [queue.type] for lateloading despite not allowing it")
|
||||
#endif
|
||||
generate_queue += queue
|
||||
|
||||
/datum/controller/subsystem/asset_loading/proc/dequeue_asset(datum/asset/queue)
|
||||
generate_queue -= queue
|
||||
@@ -2,17 +2,39 @@ SUBSYSTEM_DEF(assets)
|
||||
name = "Assets"
|
||||
init_order = INIT_ORDER_ASSETS
|
||||
flags = SS_NO_FIRE
|
||||
var/list/cache = list()
|
||||
var/list/datum/asset_cache_item/cache = list()
|
||||
var/list/preload = list()
|
||||
var/datum/asset_transport/transport = new()
|
||||
|
||||
/datum/controller/subsystem/assets/Initialize(timeofday)
|
||||
for(var/typepath in typesof(/datum/asset))
|
||||
var/datum/asset/A = typepath
|
||||
if (typepath != initial(A._abstract))
|
||||
get_asset_datum(typepath)
|
||||
/datum/controller/subsystem/assets/proc/OnConfigLoad()
|
||||
var/newtransporttype = /datum/asset_transport
|
||||
switch (config.asset_transport)
|
||||
if ("webroot")
|
||||
newtransporttype = /datum/asset_transport/webroot
|
||||
|
||||
preload = cache.Copy() //don't preload assets generated during the round
|
||||
if (newtransporttype == transport.type)
|
||||
return
|
||||
|
||||
for(var/client/C in GLOB.clients)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(getFilesSlow), C, preload, FALSE), 10)
|
||||
return ..()
|
||||
var/datum/asset_transport/newtransport = new newtransporttype ()
|
||||
if (newtransport.validate_config())
|
||||
transport = newtransport
|
||||
transport.Load()
|
||||
|
||||
|
||||
|
||||
/datum/controller/subsystem/assets/Initialize()
|
||||
OnConfigLoad()
|
||||
|
||||
for(var/type in typesof(/datum/asset))
|
||||
var/datum/asset/A = type
|
||||
if (type != initial(A._abstract))
|
||||
load_asset_datum(type)
|
||||
|
||||
transport.Initialize(cache)
|
||||
|
||||
subsystem_initialized = TRUE
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
/datum/controller/subsystem/assets/Recover()
|
||||
cache = SSassets.cache
|
||||
preload = SSassets.preload
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*!
|
||||
## Debugging GC issues
|
||||
|
||||
In order to debug `qdel()` failures, there are several tools available.
|
||||
To enable these tools, define `TESTING` in [_compile_options.dm](https://github.com/tgstation/-tg-station/blob/master/code/_compile_options.dm).
|
||||
|
||||
First is a verb called "Find References", which lists **every** refererence to an object in the world. This allows you to track down any indirect or obfuscated references that you might have missed.
|
||||
|
||||
Complementing this is another verb, "qdel() then Find References".
|
||||
This does exactly what you'd expect; it calls `qdel()` on the object and then it finds all references remaining.
|
||||
This is great, because it means that `Destroy()` will have been called before it starts to find references,
|
||||
so the only references you'll find will be the ones preventing the object from `qdel()`ing gracefully.
|
||||
|
||||
If you have a datum or something you are not destroying directly (say via the singulo),
|
||||
the next tool is `QDEL_HINT_FINDREFERENCE`. You can return this in `Destroy()` (where you would normally `return ..()`),
|
||||
to print a list of references once it enters the GC queue.
|
||||
|
||||
Finally is a verb, "Show qdel() Log", which shows the deletion log that the garbage subsystem keeps. This is helpful if you are having race conditions or need to review the order of deletions.
|
||||
|
||||
Note that for any of these tools to work `TESTING` must be defined.
|
||||
By using these methods of finding references, you can make your life far, far easier when dealing with `qdel()` failures.
|
||||
*/
|
||||
|
||||
SUBSYSTEM_DEF(garbage)
|
||||
name = "Garbage"
|
||||
priority = FIRE_PRIORITY_GARBAGE
|
||||
@@ -5,8 +28,9 @@ SUBSYSTEM_DEF(garbage)
|
||||
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
|
||||
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
|
||||
init_order = INIT_ORDER_GARBAGE
|
||||
// init_stage = INITSTAGE_EARLY
|
||||
|
||||
var/list/collection_timeout = list(2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
|
||||
var/list/collection_timeout = list(GC_FILTER_QUEUE, GC_CHECK_QUEUE, GC_DEL_QUEUE) // deciseconds to wait before moving something up in the queue to the next level
|
||||
|
||||
//Stat tracking
|
||||
var/delslasttick = 0 // number of del()'s we've done this tick
|
||||
@@ -26,18 +50,16 @@ SUBSYSTEM_DEF(garbage)
|
||||
var/list/queues
|
||||
#ifdef REFERENCE_TRACKING
|
||||
var/list/reference_find_on_fail = list()
|
||||
#ifdef REFERENCE_TRACKING_DEBUG
|
||||
//Should we save found refs. Used for unit testing
|
||||
var/should_save_refs = FALSE
|
||||
#endif
|
||||
var/find_reference_on_fail_global_toggle = FALSE
|
||||
#endif
|
||||
|
||||
|
||||
/datum/controller/subsystem/garbage/PreInit()
|
||||
queues = new(GC_QUEUE_COUNT)
|
||||
pass_counts = new(GC_QUEUE_COUNT)
|
||||
fail_counts = new(GC_QUEUE_COUNT)
|
||||
for(var/i in 1 to GC_QUEUE_COUNT)
|
||||
queues[i] = list()
|
||||
pass_counts[i] = 0
|
||||
fail_counts[i] = 0
|
||||
InitQueues()
|
||||
|
||||
/datum/controller/subsystem/garbage/stat_entry(msg)
|
||||
var/list/counts = list()
|
||||
@@ -61,39 +83,48 @@ SUBSYSTEM_DEF(garbage)
|
||||
|
||||
/datum/controller/subsystem/garbage/Shutdown()
|
||||
//Adds the del() log to the qdel log file
|
||||
var/list/dellog = list()
|
||||
var/list/del_log = list()
|
||||
|
||||
//sort by how long it's wasted hard deleting
|
||||
sortTim(items, cmp=/proc/cmp_qdel_item_time, associative = TRUE)
|
||||
for(var/path in items)
|
||||
var/datum/qdel_item/I = items[path]
|
||||
dellog += "Path: [path]"
|
||||
var/list/entry = list()
|
||||
del_log[path] = entry
|
||||
|
||||
if (I.qdel_flags & QDEL_ITEM_SUSPENDED_FOR_LAG)
|
||||
dellog += "\tSUSPENDED FOR LAG"
|
||||
entry["SUSPENDED FOR LAG"] = TRUE
|
||||
if (I.failures)
|
||||
dellog += "\tFailures: [I.failures]"
|
||||
dellog += "\tqdel() Count: [I.qdels]"
|
||||
dellog += "\tDestroy() Cost: [I.destroy_time]ms"
|
||||
entry["Failures"] = I.failures
|
||||
entry["qdel() Count"] = I.qdels
|
||||
entry["Destroy() Cost (ms)"] = I.destroy_time
|
||||
|
||||
if (I.hard_deletes)
|
||||
dellog += "\tTotal Hard Deletes: [I.hard_deletes]"
|
||||
dellog += "\tTime Spent Hard Deleting: [I.hard_delete_time]ms"
|
||||
dellog += "\tHighest Time Spent Hard Deleting: [I.hard_delete_max]ms"
|
||||
entry["Total Hard Deletes"] = I.hard_deletes
|
||||
entry["Time Spend Hard Deleting (ms)"] = I.hard_delete_time
|
||||
entry["Highest Time Spend Hard Deleting (ms)"] = I.hard_delete_max
|
||||
if (I.hard_deletes_over_threshold)
|
||||
dellog += "\tHard Deletes Over Threshold: [I.hard_deletes_over_threshold]"
|
||||
entry["Hard Deletes Over Threshold"] = I.hard_deletes_over_threshold
|
||||
if (I.slept_destroy)
|
||||
dellog += "\tSleeps: [I.slept_destroy]"
|
||||
entry["Total Sleeps"] = I.slept_destroy
|
||||
if (I.no_respect_force)
|
||||
dellog += "\tIgnored force: [I.no_respect_force] times"
|
||||
entry["Total Ignored Force"] = I.no_respect_force
|
||||
if (I.no_hint)
|
||||
dellog += "\tNo hint: [I.no_hint] times"
|
||||
text2file(dellog.Join(), "[log_path]-qdel.log")
|
||||
entry["Total No Hint"] = I.no_hint
|
||||
if(LAZYLEN(I.extra_details))
|
||||
entry["Deleted Metadata"] = I.extra_details
|
||||
|
||||
log_debug("", del_log)
|
||||
|
||||
/datum/controller/subsystem/garbage/fire()
|
||||
//the fact that this resets its processing each fire (rather then resume where it left off) is intentional.
|
||||
var/queue = GC_QUEUE_CHECK
|
||||
var/queue = GC_QUEUE_FILTER
|
||||
|
||||
while (state == SS_RUNNING)
|
||||
switch (queue)
|
||||
if (GC_QUEUE_FILTER)
|
||||
HandleQueue(GC_QUEUE_FILTER)
|
||||
queue = GC_QUEUE_FILTER+1
|
||||
if (GC_QUEUE_CHECK)
|
||||
HandleQueue(GC_QUEUE_CHECK)
|
||||
queue = GC_QUEUE_CHECK+1
|
||||
@@ -103,8 +134,21 @@ SUBSYSTEM_DEF(garbage)
|
||||
state = SS_RUNNING
|
||||
break
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK)
|
||||
if (level == GC_QUEUE_CHECK)
|
||||
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/InitQueues()
|
||||
if (isnull(queues)) // Only init the queues if they don't already exist, prevents overriding of recovered lists
|
||||
queues = new(GC_QUEUE_COUNT)
|
||||
pass_counts = new(GC_QUEUE_COUNT)
|
||||
fail_counts = new(GC_QUEUE_COUNT)
|
||||
for(var/i in 1 to GC_QUEUE_COUNT)
|
||||
queues[i] = list()
|
||||
pass_counts[i] = 0
|
||||
fail_counts[i] = 0
|
||||
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_FILTER)
|
||||
if (level == GC_QUEUE_FILTER)
|
||||
delslasttick = 0
|
||||
gcedlasttick = 0
|
||||
var/cut_off_time = world.time - collection_timeout[level] //ignore entries newer then this
|
||||
@@ -119,30 +163,33 @@ SUBSYSTEM_DEF(garbage)
|
||||
|
||||
lastlevel = level
|
||||
|
||||
//We do this rather then for(var/refID in queue) because that sort of for loop copies the whole list.
|
||||
// 1 from the hard reference in the queue, and 1 from the variable used before this
|
||||
#define REFS_WE_EXPECT 2
|
||||
|
||||
//We do this rather then for(var/list/ref_info in queue) because that sort of for loop copies the whole list.
|
||||
//Normally this isn't expensive, but the gc queue can grow to 40k items, and that gets costly/causes overrun.
|
||||
for (var/i in 1 to length(queue))
|
||||
var/list/L = queue[i]
|
||||
if (length(L) < 2)
|
||||
if (length(L) < GC_QUEUE_ITEM_INDEX_COUNT)
|
||||
count++
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
|
||||
var/GCd_at_time = L[1]
|
||||
if(GCd_at_time > cut_off_time)
|
||||
var/queued_at_time = L[GC_QUEUE_ITEM_QUEUE_TIME]
|
||||
if(queued_at_time > cut_off_time)
|
||||
break // Everything else is newer, skip them
|
||||
count++
|
||||
var/refID = L[2]
|
||||
var/datum/D
|
||||
D = locate(refID)
|
||||
|
||||
if (!D || D.gc_destroyed != GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
|
||||
var/datum/D = L[GC_QUEUE_ITEM_REF]
|
||||
|
||||
// If that's all we've got, send er off
|
||||
if (refcount(D) == REFS_WE_EXPECT)
|
||||
++gcedlasttick
|
||||
++totalgcs
|
||||
pass_counts[level]++
|
||||
#ifdef REFERENCE_TRACKING
|
||||
reference_find_on_fail -= refID //It's deleted we don't care anymore.
|
||||
reference_find_on_fail -= ref(D) //It's deleted we don't care anymore.
|
||||
#endif
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
@@ -158,22 +205,33 @@ SUBSYSTEM_DEF(garbage)
|
||||
switch (level)
|
||||
if (GC_QUEUE_CHECK)
|
||||
#ifdef REFERENCE_TRACKING
|
||||
if(reference_find_on_fail[refID])
|
||||
INVOKE_ASYNC(D, /datum/proc/find_references)
|
||||
// Decides how many refs to look for (potentially)
|
||||
// Based off the remaining and the ones we can account for
|
||||
var/remaining_refs = refcount(D) - REFS_WE_EXPECT
|
||||
if(reference_find_on_fail[ref(D)])
|
||||
INVOKE_ASYNC(D, TYPE_PROC_REF(/datum,find_references), remaining_refs)
|
||||
ref_searching = TRUE
|
||||
#ifdef GC_FAILURE_HARD_LOOKUP
|
||||
else
|
||||
INVOKE_ASYNC(D, /datum/proc/find_references)
|
||||
INVOKE_ASYNC(D, TYPE_PROC_REF(/datum,find_references), remaining_refs)
|
||||
ref_searching = TRUE
|
||||
#endif
|
||||
reference_find_on_fail -= refID
|
||||
reference_find_on_fail -= ref(D)
|
||||
#endif
|
||||
var/type = D.type
|
||||
var/datum/qdel_item/I = items[type]
|
||||
|
||||
log_world("## TESTING: GC: -- \ref[D] | [type] was unable to be GC'd --")
|
||||
var/message = "## TESTING: GC: -- [ref(D)] | [type] was unable to be GC'd --"
|
||||
message = "[message] (ref count of [refcount(D)])"
|
||||
log_world(message)
|
||||
|
||||
/*var/detail = D.dump_harddel_info()
|
||||
if(detail)
|
||||
LAZYADD(I.extra_details, detail)*/
|
||||
|
||||
#ifdef TESTING
|
||||
for(var/client/admin as anything in GLOB.admins) //Using testing() here would fill the logs with ADMIN_VV garbage
|
||||
for(var/c in GLOB.admins) //Using testing() here would fill the logs with ADMIN_VV garbage
|
||||
var/client/admin = c
|
||||
if(!check_rights_for(admin, R_ADMIN))
|
||||
continue
|
||||
to_chat(admin, "## TESTING: GC: -- [ADMIN_VV(D)] | [type] was unable to be GC'd --")
|
||||
@@ -205,36 +263,41 @@ SUBSYSTEM_DEF(garbage)
|
||||
queue.Cut(1,count+1)
|
||||
count = 0
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_CHECK)
|
||||
#undef REFS_WE_EXPECT
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_FILTER)
|
||||
if (isnull(D))
|
||||
return
|
||||
if (level > GC_QUEUE_COUNT)
|
||||
HardDelete(D)
|
||||
return
|
||||
var/gctime = world.time
|
||||
var/refid = "\ref[D]"
|
||||
var/queue_time = world.time
|
||||
|
||||
if (D.gc_destroyed <= 0)
|
||||
D.gc_destroyed = queue_time
|
||||
|
||||
D.gc_destroyed = gctime
|
||||
var/list/queue = queues[level]
|
||||
|
||||
queue[++queue.len] = list(gctime, refid) // not += for byond reasons
|
||||
queue[++queue.len] = list(queue_time, D, D.gc_destroyed) // not += for byond reasons
|
||||
|
||||
//this is mainly to separate things profile wise.
|
||||
/datum/controller/subsystem/garbage/proc/HardDelete(datum/D)
|
||||
++delslasttick
|
||||
++totaldels
|
||||
var/type = D.type
|
||||
var/refID = "\ref[D]"
|
||||
var/refID = ref(D)
|
||||
var/datum/qdel_item/type_info = items[type]
|
||||
/*var/detail = D.dump_harddel_info()
|
||||
if(detail)
|
||||
LAZYADD(type_info.extra_details, detail)*/
|
||||
|
||||
var/tick_usage = TICK_USAGE
|
||||
del(D)
|
||||
tick_usage = TICK_USAGE_TO_MS(tick_usage)
|
||||
|
||||
var/datum/qdel_item/I = items[type]
|
||||
I.hard_deletes++
|
||||
I.hard_delete_time += tick_usage
|
||||
if (tick_usage > I.hard_delete_max)
|
||||
I.hard_delete_max = tick_usage
|
||||
type_info.hard_deletes++
|
||||
type_info.hard_delete_time += tick_usage
|
||||
if (tick_usage > type_info.hard_delete_max)
|
||||
type_info.hard_delete_max = tick_usage
|
||||
if (tick_usage > highest_del_ms)
|
||||
highest_del_ms = tick_usage
|
||||
highest_del_type_string = "[type]"
|
||||
@@ -245,15 +308,17 @@ SUBSYSTEM_DEF(garbage)
|
||||
postpone(time)
|
||||
var/threshold = 0.5 // Default, make a config
|
||||
if (threshold && (time > threshold SECONDS))
|
||||
if (!(I.qdel_flags & QDEL_ITEM_ADMINS_WARNED))
|
||||
log_and_message_admins("Error: [type]([refID]) took longer than [threshold] seconds to delete (took [round(time/10, 0.1)] seconds to delete)")
|
||||
I.qdel_flags |= QDEL_ITEM_ADMINS_WARNED
|
||||
I.hard_deletes_over_threshold++
|
||||
if (!(type_info.qdel_flags & QDEL_ITEM_ADMINS_WARNED))
|
||||
log_game("Error: [type]([refID]) took longer than [threshold] seconds to delete (took [round(time/10, 0.1)] seconds to delete)")
|
||||
message_admins("Error: [type]([refID]) took longer than [threshold] seconds to delete (took [round(time/10, 0.1)] seconds to delete).")
|
||||
type_info.qdel_flags |= QDEL_ITEM_ADMINS_WARNED
|
||||
type_info.hard_deletes_over_threshold++
|
||||
var/overrun_limit = 0 // Default, make a config
|
||||
if (overrun_limit && I.hard_deletes_over_threshold >= overrun_limit)
|
||||
I.qdel_flags |= QDEL_ITEM_SUSPENDED_FOR_LAG
|
||||
if (overrun_limit && type_info.hard_deletes_over_threshold >= overrun_limit)
|
||||
type_info.qdel_flags |= QDEL_ITEM_SUSPENDED_FOR_LAG
|
||||
|
||||
/datum/controller/subsystem/garbage/Recover()
|
||||
InitQueues() //We first need to create the queues before recovering data
|
||||
if (istype(SSgarbage.queues))
|
||||
for (var/i in 1 to SSgarbage.queues.len)
|
||||
queues[i] |= SSgarbage.queues[i]
|
||||
@@ -272,79 +337,85 @@ SUBSYSTEM_DEF(garbage)
|
||||
var/no_hint = 0 //!Number of times it's not even bother to give a qdel hint
|
||||
var/slept_destroy = 0 //!Number of times it's slept in its destroy
|
||||
var/qdel_flags = 0 //!Flags related to this type's trip thru qdel.
|
||||
var/list/extra_details //!Lazylist of string metadata about the deleted objects
|
||||
|
||||
/datum/qdel_item/New(mytype)
|
||||
name = "[mytype]"
|
||||
|
||||
|
||||
/// Should be treated as a replacement for the 'del' keyword.
|
||||
///
|
||||
/// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
|
||||
/proc/qdel(datum/D, force=FALSE, ...)
|
||||
if(!istype(D))
|
||||
del(D)
|
||||
/proc/qdel(datum/to_delete, force = FALSE)
|
||||
if(!istype(to_delete))
|
||||
del(to_delete)
|
||||
return
|
||||
|
||||
var/datum/qdel_item/I = SSgarbage.items[D.type]
|
||||
if (!I)
|
||||
I = SSgarbage.items[D.type] = new /datum/qdel_item(D.type)
|
||||
I.qdels++
|
||||
var/datum/qdel_item/trash = SSgarbage.items[to_delete.type]
|
||||
if (isnull(trash))
|
||||
trash = SSgarbage.items[to_delete.type] = new /datum/qdel_item(to_delete.type)
|
||||
trash.qdels++
|
||||
|
||||
if(isnull(D.gc_destroyed))
|
||||
if (SEND_SIGNAL(D, COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted
|
||||
if(!isnull(to_delete.gc_destroyed))
|
||||
if(to_delete.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
|
||||
CRASH("[to_delete.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
|
||||
return
|
||||
|
||||
if (SEND_SIGNAL(to_delete, COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted
|
||||
return
|
||||
|
||||
to_delete.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
|
||||
var/start_time = world.time
|
||||
var/start_tick = world.tick_usage
|
||||
SEND_SIGNAL(to_delete, COMSIG_PARENT_QDELETING, force) // Let the (remaining) components know about the result of Destroy
|
||||
var/hint = to_delete.Destroy(force) // Let our friend know they're about to get fucked up.
|
||||
|
||||
if(world.time != start_time)
|
||||
trash.slept_destroy++
|
||||
else
|
||||
trash.destroy_time += TICK_USAGE_TO_MS(start_tick)
|
||||
|
||||
if(isnull(to_delete))
|
||||
return
|
||||
|
||||
switch(hint)
|
||||
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
|
||||
SSgarbage.Queue(to_delete)
|
||||
if (QDEL_HINT_IWILLGC)
|
||||
to_delete.gc_destroyed = world.time
|
||||
return
|
||||
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
|
||||
var/start_time = world.time
|
||||
var/start_tick = world.tick_usage
|
||||
SEND_SIGNAL(D, COMSIG_PARENT_QDELETING, force) // Let the (remaining) components know about the result of Destroy
|
||||
var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up.
|
||||
if(world.time != start_time)
|
||||
I.slept_destroy++
|
||||
else
|
||||
I.destroy_time += TICK_USAGE_TO_MS(start_tick)
|
||||
if(!D)
|
||||
return
|
||||
switch(hint)
|
||||
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
|
||||
SSgarbage.Queue(D)
|
||||
if (QDEL_HINT_IWILLGC)
|
||||
D.gc_destroyed = world.time
|
||||
if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
|
||||
if(!force)
|
||||
to_delete.gc_destroyed = null //clear the gc variable (important!)
|
||||
return
|
||||
if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
|
||||
if(!force)
|
||||
D.gc_destroyed = null //clear the gc variable (important!)
|
||||
return
|
||||
// Returning LETMELIVE after being told to force destroy
|
||||
// indicates the objects Destroy() does not respect force
|
||||
#ifdef TESTING
|
||||
if(!I.no_respect_force)
|
||||
testing("WARNING: [D.type] has been force deleted, but is \
|
||||
returning an immortal QDEL_HINT, indicating it does \
|
||||
not respect the force flag for qdel(). It has been \
|
||||
placed in the queue, further instances of this type \
|
||||
will also be queued.")
|
||||
#endif
|
||||
I.no_respect_force++
|
||||
|
||||
SSgarbage.Queue(D)
|
||||
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete
|
||||
SSgarbage.Queue(D, GC_QUEUE_HARDDELETE)
|
||||
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
|
||||
SSgarbage.HardDelete(D)
|
||||
#ifdef REFERENCE_TRACKING
|
||||
if (QDEL_HINT_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion.
|
||||
SSgarbage.Queue(D)
|
||||
D.find_references()
|
||||
if (QDEL_HINT_IFFAIL_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled and the object fails to collect, display all references to this object.
|
||||
SSgarbage.Queue(D)
|
||||
SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
|
||||
// Returning LETMELIVE after being told to force destroy
|
||||
// indicates the objects Destroy() does not respect force
|
||||
#ifdef TESTING
|
||||
if(!trash.no_respect_force)
|
||||
testing("WARNING: [to_delete.type] has been force deleted, but is \
|
||||
returning an immortal QDEL_HINT, indicating it does \
|
||||
not respect the force flag for qdel(). It has been \
|
||||
placed in the queue, further instances of this type \
|
||||
will also be queued.")
|
||||
#endif
|
||||
else
|
||||
#ifdef TESTING
|
||||
if(!I.no_hint)
|
||||
testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
|
||||
#endif
|
||||
I.no_hint++
|
||||
SSgarbage.Queue(D)
|
||||
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
|
||||
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
|
||||
trash.no_respect_force++
|
||||
|
||||
SSgarbage.Queue(to_delete)
|
||||
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete
|
||||
SSgarbage.Queue(to_delete, GC_QUEUE_HARDDELETE)
|
||||
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
|
||||
SSgarbage.HardDelete(to_delete)
|
||||
#ifdef REFERENCE_TRACKING
|
||||
if (QDEL_HINT_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion.
|
||||
SSgarbage.Queue(to_delete)
|
||||
INVOKE_ASYNC(to_delete, TYPE_PROC_REF(/datum, find_references))
|
||||
if (QDEL_HINT_IFFAIL_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled and the object fails to collect, display all references to this object.
|
||||
SSgarbage.Queue(to_delete)
|
||||
SSgarbage.reference_find_on_fail[ref(to_delete)] = TRUE
|
||||
#endif
|
||||
else
|
||||
#ifdef TESTING
|
||||
if(!trash.no_hint)
|
||||
testing("WARNING: [to_delete.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
|
||||
#endif
|
||||
trash.no_hint++
|
||||
SSgarbage.Queue(to_delete)
|
||||
|
||||
@@ -77,23 +77,31 @@ SUBSYSTEM_DEF(overlays)
|
||||
var/list/result = list()
|
||||
var/icon/icon = subject.icon
|
||||
for (var/atom/entry as anything in sources)
|
||||
if (!entry)
|
||||
continue
|
||||
else if (istext(entry))
|
||||
result += GetStateAppearance(icon, entry)
|
||||
else if (isicon(entry))
|
||||
result += GetIconAppearance(entry)
|
||||
else
|
||||
if (isloc(entry))
|
||||
if (entry.flags & OVERLAY_QUEUED)
|
||||
entry.ImmediateOverlayUpdate()
|
||||
if (!ispath(entry))
|
||||
result += entry.appearance
|
||||
else
|
||||
var/image/image = entry
|
||||
result += image.appearance
|
||||
AppearanceListEntry(entry, result, icon)
|
||||
return result
|
||||
|
||||
//Fixes runtime with overlays present in 515
|
||||
/datum/controller/subsystem/overlays/proc/AppearanceListEntry(var/atom/entry,var/list/result,var/icon/icon)
|
||||
if (!entry)
|
||||
return
|
||||
else if(islist(entry))
|
||||
var/list/entry_list = entry
|
||||
for(var/entry_item in entry_list)
|
||||
AppearanceListEntry(entry_item)
|
||||
else if (istext(entry))
|
||||
result += GetStateAppearance(icon, entry)
|
||||
else if (isicon(entry))
|
||||
result += GetIconAppearance(entry)
|
||||
else
|
||||
if (isloc(entry))
|
||||
if (entry.flags & OVERLAY_QUEUED)
|
||||
entry.ImmediateOverlayUpdate()
|
||||
if (!ispath(entry))
|
||||
if(entry.appearance)
|
||||
result += entry.appearance
|
||||
else
|
||||
var/image/image = entry
|
||||
result += image.appearance
|
||||
|
||||
/// Enqueues the atom for an overlay update if not already queued
|
||||
/atom/proc/QueueOverlayUpdate()
|
||||
|
||||
@@ -147,14 +147,14 @@ var/list/runechat_image_cache = list()
|
||||
|
||||
// Append prefixes
|
||||
if(extra_classes.Find("virtual-speaker"))
|
||||
LAZYADD(prefixes, "\icon[runechat_image_cache["radio"]]")
|
||||
LAZYADD(prefixes, "[icon2html(runechat_image_cache["radio"],owner.client)]")
|
||||
if(extra_classes.Find("emote"))
|
||||
// Icon on both ends?
|
||||
//var/image/I = runechat_image_cache["emote"]
|
||||
//text = "\icon[I][text]\icon[I]"
|
||||
//text = "icon2html(I)[text]icon2html(I)"
|
||||
|
||||
// Icon on one end?
|
||||
//LAZYADD(prefixes, "\icon[runechat_image_cache["emote"]]")
|
||||
//LAZYADD(prefixes, "icon2html(runechat_image_cache["emote")]")
|
||||
|
||||
// Asterisks instead?
|
||||
text = "* [text] *"
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Recursive move listener
|
||||
* Can be added willy-nilly to anything where the COMSIG_OBSERVER_MOVE signal should also trigger on a parent moving.
|
||||
* Previously there was a system where COMSIG_OBSERVER_MOVE was always recursively propogated, but that was unnecessary bloat.
|
||||
*/
|
||||
/datum/component/recursive_move
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS //This makes it so pretty much nothing happens when a duplicate component is created since we don't actually override InheritComponent
|
||||
var/atom/movable/holder
|
||||
var/list/parents = list()
|
||||
var/noparents = FALSE
|
||||
|
||||
/datum/component/recursive_move/RegisterWithParent()
|
||||
. = ..()
|
||||
holder = parent
|
||||
RegisterSignal(holder, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel))
|
||||
spawn(0) // Delayed action if our holder is spawned in nullspace and then loc = target, hopefully this catches it. VV Add item does this, for example.
|
||||
if(!QDELETED(src))
|
||||
setup_parents()
|
||||
|
||||
/datum/component/recursive_move/proc/setup_parents()
|
||||
if(length(parents)) // safety check just incase this was called without clearing
|
||||
reset_parents()
|
||||
var/atom/movable/cur_parent = holder?.loc // first loc could be null
|
||||
var/recursion = 0 // safety check - max iterations
|
||||
while(istype(cur_parent) && (recursion < 64))
|
||||
if(cur_parent == cur_parent.loc) //safety check incase a thing is somehow inside itself, cancel
|
||||
log_debug("RECURSIVE_MOVE: Parent is inside itself. ([holder]) ([holder.type])")
|
||||
reset_parents()
|
||||
break
|
||||
if(cur_parent in parents) //safety check incase of circular contents. (A inside B, B inside C, C inside A), cancel
|
||||
log_debug("RECURSIVE_MOVE: Parent is inside a circular inventory. ([holder]) ([holder.type])")
|
||||
reset_parents()
|
||||
break
|
||||
recursion++
|
||||
parents += cur_parent
|
||||
RegisterSignal(cur_parent, COMSIG_ATOM_EXITED, PROC_REF(heirarchy_changed))
|
||||
RegisterSignal(cur_parent, COMSIG_PARENT_QDELETING, PROC_REF(on_qdel))
|
||||
|
||||
cur_parent = cur_parent.loc
|
||||
|
||||
if(recursion >= 64) // If we escaped due to iteration limit, cancel
|
||||
log_debug("RECURSIVE_MOVE: Parent hit recursion limit. ([holder]) ([holder.type])")
|
||||
reset_parents()
|
||||
parents.Cut()
|
||||
|
||||
if(length(parents))
|
||||
//Only need to watch top parent for movement. Everything is covered by Exited
|
||||
RegisterSignal(parents[parents.len], COMSIG_ATOM_ENTERING, PROC_REF(top_moved))
|
||||
|
||||
//If we have no parents of type atom/movable then we wait to see if that changes, checking every time our holder moves.
|
||||
if(!length(parents) && !noparents)
|
||||
noparents = TRUE
|
||||
RegisterSignal(holder, COMSIG_ATOM_ENTERING, PROC_REF(setup_parents))
|
||||
|
||||
if(length(parents) && noparents)
|
||||
noparents = FALSE
|
||||
UnregisterSignal(holder, COMSIG_ATOM_ENTERING)
|
||||
|
||||
|
||||
/datum/component/recursive_move/proc/unregister_signals()
|
||||
if(noparents) // safety check
|
||||
noparents = FALSE
|
||||
UnregisterSignal(holder, COMSIG_ATOM_ENTERING)
|
||||
if(!length(parents))
|
||||
return
|
||||
for(var/atom/movable/cur_parent in parents)
|
||||
UnregisterSignal(cur_parent, COMSIG_PARENT_QDELETING)
|
||||
UnregisterSignal(cur_parent, COMSIG_ATOM_EXITED)
|
||||
|
||||
UnregisterSignal(parents[parents.len], COMSIG_ATOM_ENTERING)
|
||||
|
||||
//Parent at top of heirarchy moved.
|
||||
/datum/component/recursive_move/proc/top_moved(var/atom/movable/am, var/atom/new_loc, var/atom/old_loc)
|
||||
SIGNAL_HANDLER
|
||||
SEND_SIGNAL(holder, COMSIG_OBSERVER_MOVED, old_loc, new_loc)
|
||||
|
||||
//One of the parents other than the top parent moved.
|
||||
/datum/component/recursive_move/proc/heirarchy_changed(var/atom/old_loc, var/atom/movable/am, var/atom/new_loc)
|
||||
SIGNAL_HANDLER
|
||||
SEND_SIGNAL(holder, COMSIG_OBSERVER_MOVED, old_loc, new_loc)
|
||||
//Rebuild our list of parents
|
||||
reset_parents()
|
||||
setup_parents()
|
||||
|
||||
//Some things will move their contents on qdel so we should prepare ourselves to be moved.
|
||||
//If this qdel does destroy our holder, on_holder_qdel will handle preperations for GC
|
||||
/datum/component/recursive_move/proc/on_qdel()
|
||||
reset_parents()
|
||||
noparents = TRUE
|
||||
RegisterSignal(holder, COMSIG_ATOM_ENTERING, PROC_REF(setup_parents))
|
||||
|
||||
/datum/component/recursive_move/proc/on_holder_qdel()
|
||||
UnregisterSignal(holder, COMSIG_PARENT_QDELETING)
|
||||
reset_parents()
|
||||
holder = null
|
||||
qdel(src)
|
||||
|
||||
/datum/component/recursive_move/Destroy()
|
||||
. = ..()
|
||||
reset_parents()
|
||||
if(holder) UnregisterSignal(holder, COMSIG_PARENT_QDELETING)
|
||||
holder = null
|
||||
|
||||
/datum/component/recursive_move/proc/reset_parents()
|
||||
unregister_signals()
|
||||
parents.Cut()
|
||||
|
||||
//the banana peel of testing stays
|
||||
/obj/item/weapon/bananapeel/testing
|
||||
name = "banana peel of testing"
|
||||
desc = "spams world log with debugging information"
|
||||
|
||||
/obj/item/weapon/bananapeel/testing/proc/shmove(var/atom/source, var/atom/old_loc, var/atom/new_loc)
|
||||
world.log << "the [source] moved from [old_loc]([old_loc.x],[old_loc.y],[old_loc.z]) to [new_loc]([new_loc.x],[new_loc.y],[new_loc.z])"
|
||||
|
||||
/obj/item/weapon/bananapeel/testing/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/recursive_move)
|
||||
RegisterSignal(src, COMSIG_OBSERVER_MOVED, PROC_REF(shmove))
|
||||
@@ -1,10 +0,0 @@
|
||||
/****************
|
||||
* Debug Support *
|
||||
****************/
|
||||
|
||||
/datum/all_observable_events
|
||||
var/list/events
|
||||
|
||||
/datum/all_observable_events/New()
|
||||
events = list()
|
||||
..()
|
||||
@@ -1 +0,0 @@
|
||||
#define CANCEL_MOVE_EVENT -55
|
||||
@@ -5,11 +5,12 @@
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /datum/destroyed_instance: The instance that was destroyed.
|
||||
|
||||
/*
|
||||
/decl/observ/destroyed
|
||||
name = "Destroyed"
|
||||
*/
|
||||
//Deprecated in favor of Comsigs
|
||||
|
||||
/datum/Destroy()
|
||||
if(GLOB.destroyed_event)
|
||||
GLOB.destroyed_event.raise_event(src)
|
||||
SEND_SIGNAL(src,COMSIG_OBSERVER_DESTROYED)
|
||||
. = ..()
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Observer Pattern Implementation: Direction Set
|
||||
// Registration type: /atom
|
||||
//
|
||||
// Raised when: An /atom changes dir using the set_dir() proc.
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /atom/dir_changer: The instance that changed direction
|
||||
// /old_dir: The dir before the change.
|
||||
// /new_dir: The dir after the change.
|
||||
|
||||
GLOBAL_DATUM_INIT(dir_set_event, /decl/observ/dir_set, new)
|
||||
|
||||
/decl/observ/dir_set
|
||||
name = "Direction Set"
|
||||
expected_type = /atom
|
||||
|
||||
/decl/observ/dir_set/register(var/atom/dir_changer, var/datum/listener, var/proc_call)
|
||||
. = ..()
|
||||
|
||||
// Listen to the parent if possible.
|
||||
if(. && istype(dir_changer.loc, /atom/movable)) // We don't care about registering to turfs.
|
||||
register(dir_changer.loc, dir_changer, /atom/proc/recursive_dir_set)
|
||||
|
||||
/*********************
|
||||
* Direction Handling *
|
||||
*********************/
|
||||
|
||||
/atom/movable/Entered(var/atom/movable/am, atom/old_loc)
|
||||
. = ..()
|
||||
if(. != CANCEL_MOVE_EVENT && GLOB.dir_set_event.has_listeners(am))
|
||||
GLOB.dir_set_event.register(src, am, /atom/proc/recursive_dir_set)
|
||||
|
||||
/atom/movable/Exited(var/atom/movable/am, atom/old_loc)
|
||||
. = ..()
|
||||
GLOB.dir_set_event.unregister(src, am, /atom/proc/recursive_dir_set)
|
||||
@@ -7,6 +7,7 @@
|
||||
// /mob/equipper: The mob that equipped the item.
|
||||
// /obj/item/item: The equipped item.
|
||||
// slot: The slot equipped to.
|
||||
/*
|
||||
GLOBAL_DATUM_INIT(mob_equipped_event, /decl/observ/mob_equipped, new)
|
||||
|
||||
/decl/observ/mob_equipped
|
||||
@@ -27,12 +28,13 @@ GLOBAL_DATUM_INIT(item_equipped_event, /decl/observ/item_equipped, new)
|
||||
/decl/observ/item_equipped
|
||||
name = "Item Equipped"
|
||||
expected_type = /obj/item
|
||||
|
||||
*/
|
||||
//Deprecated in favor of comsigs
|
||||
/********************
|
||||
* Equipped Handling *
|
||||
********************/
|
||||
|
||||
/obj/item/equipped(var/mob/user, var/slot)
|
||||
. = ..()
|
||||
GLOB.mob_equipped_event.raise_event(user, src, slot)
|
||||
GLOB.item_equipped_event.raise_event(src, user, slot)
|
||||
SEND_SIGNAL(user, COMSIG_OBSERVER_MOB_EQUIPPED, src, slot)
|
||||
SEND_SIGNAL(src, COMSIG_OBSERVER_ITEM_EQUIPPED, user, slot)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
/atom/movable/proc/recursive_move(var/atom/movable/am, var/old_loc, var/new_loc)
|
||||
GLOB.moved_event.raise_event(src, old_loc, new_loc)
|
||||
|
||||
SEND_SIGNAL(src,COMSIG_OBSERVER_MOVED, old_loc, new_loc)
|
||||
*/
|
||||
/atom/movable/proc/move_to_destination(var/atom/movable/am, var/old_loc, var/new_loc)
|
||||
var/turf/T = get_turf(new_loc)
|
||||
if(T && T != loc)
|
||||
@@ -12,10 +13,12 @@
|
||||
/datum/proc/qdel_self()
|
||||
qdel(src)
|
||||
|
||||
/proc/register_all_movement(var/event_source, var/listener)
|
||||
GLOB.moved_event.register(event_source, listener, /atom/movable/proc/recursive_move)
|
||||
GLOB.dir_set_event.register(event_source, listener, /atom/proc/recursive_dir_set)
|
||||
/*
|
||||
/proc/register_all_movement(var/event_source, var/datum/listener)
|
||||
listener.RegisterSignal(event_source,COMSIG_OBSERVER_MOVED, /atom/movable/proc/recursive_move)
|
||||
//GLOB.dir_set_event.register(event_source, listener, /atom/proc/recursive_dir_set)
|
||||
|
||||
/proc/unregister_all_movement(var/event_source, var/listener)
|
||||
GLOB.moved_event.unregister(event_source, listener, /atom/movable/proc/recursive_move)
|
||||
GLOB.dir_set_event.unregister(event_source, listener, /atom/proc/recursive_dir_set)
|
||||
/proc/unregister_all_movement(var/event_source, var/datum/listener)
|
||||
listener.UnregisterSignal(event_source,COMSIG_OBSERVER_MOVED)
|
||||
//GLOB.dir_set_event.unregister(event_source, listener, /atom/proc/recursive_dir_set)
|
||||
*/
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Observer Pattern Implementation: Logged in
|
||||
// Registration type: /mob
|
||||
//
|
||||
// Raised when: A mob logs in (not client)
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /mob/joiner: The mob that has logged in
|
||||
|
||||
GLOBAL_DATUM_INIT(logged_in_event, /decl/observ/logged_in, new)
|
||||
|
||||
/decl/observ/logged_in
|
||||
name = "Logged In"
|
||||
expected_type = /mob
|
||||
|
||||
/*****************
|
||||
* Login Handling *
|
||||
*****************/
|
||||
|
||||
/mob/Login()
|
||||
..()
|
||||
GLOB.logged_in_event.raise_event(src)
|
||||
@@ -8,9 +8,10 @@
|
||||
// /atom/old_loc: The loc before the move.
|
||||
// /atom/new_loc: The loc after the move.
|
||||
|
||||
|
||||
/*
|
||||
GLOBAL_DATUM_INIT(moved_event, /decl/observ/moved, new)
|
||||
|
||||
|
||||
/decl/observ/moved
|
||||
name = "Moved"
|
||||
expected_type = /atom/movable
|
||||
@@ -21,28 +22,30 @@ GLOBAL_DATUM_INIT(moved_event, /decl/observ/moved, new)
|
||||
// Listen to the parent if possible.
|
||||
if(. && istype(mover.loc, expected_type))
|
||||
register(mover.loc, mover, /atom/movable/proc/recursive_move)
|
||||
*/
|
||||
//Deprecated in favor of comsigs
|
||||
|
||||
/********************
|
||||
* Movement Handling *
|
||||
********************/
|
||||
/*
|
||||
/atom/movable/Entered(var/atom/movable/am, atom/old_loc)
|
||||
. = ..()
|
||||
if(GLOB.moved_event.has_listeners(am))
|
||||
GLOB.moved_event.register(src, am, /atom/movable/proc/recursive_move)
|
||||
am.RegisterSignal(src,COMSIG_OBSERVER_MOVED, /atom/movable/proc/recursive_move, override = TRUE)
|
||||
|
||||
/atom/movable/Exited(var/atom/movable/am, atom/old_loc)
|
||||
. = ..()
|
||||
GLOB.moved_event.unregister(src, am, /atom/movable/proc/recursive_move)
|
||||
|
||||
am.UnregisterSignal(src,COMSIG_OBSERVER_MOVED)
|
||||
*/
|
||||
// Entered() typically lifts the moved event, but in the case of null-space we'll have to handle it.
|
||||
/atom/movable/Move()
|
||||
var/old_loc = loc
|
||||
. = ..()
|
||||
if(. && !loc)
|
||||
GLOB.moved_event.raise_event(src, old_loc, null)
|
||||
SEND_SIGNAL(src,COMSIG_OBSERVER_MOVED, old_loc, null)
|
||||
|
||||
/atom/movable/forceMove(atom/destination)
|
||||
var/old_loc = loc
|
||||
. = ..()
|
||||
if(. && !loc)
|
||||
GLOB.moved_event.raise_event(src, old_loc, null)
|
||||
SEND_SIGNAL(src,COMSIG_OBSERVER_MOVED, old_loc, null)
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
//
|
||||
// Observer Pattern Implementation
|
||||
//
|
||||
// Implements a basic observer pattern with the following main procs:
|
||||
//
|
||||
// /decl/observ/proc/is_listening(var/event_source, var/datum/listener, var/proc_call)
|
||||
// event_source: The instance which is generating events.
|
||||
// listener: The instance which may be listening to events by event_source
|
||||
// proc_call: Optional. The specific proc to call when the event is raised.
|
||||
//
|
||||
// Returns true if listener is listening for events by event_source, and proc_call supplied is either null or one of the proc that will be called when an event is raised.
|
||||
//
|
||||
// /decl/observ/proc/has_listeners(var/event_source)
|
||||
// event_source: The instance which is generating events.
|
||||
//
|
||||
// Returns true if the given event_source has any listeners at all, globally or to specific event sources.
|
||||
//
|
||||
// /decl/observ/proc/register(var/event_source, var/datum/listener, var/proc_call)
|
||||
// event_source: The instance you wish to receive events from.
|
||||
// listener: The instance/owner of the proc to call when an event is raised by the event_source.
|
||||
// proc_call: The proc to call when an event is raised.
|
||||
//
|
||||
// It is possible to register the same listener to the same event_source multiple times as long as it is using different proc_calls.
|
||||
// Registering again using the same event_source, listener, and proc_call that has been registered previously will have no additional effect.
|
||||
// I.e.: The proc_call will still only be called once per raised event. That particular proc_call will only have to be unregistered once.
|
||||
//
|
||||
// When proc_call is called the first argument is always the source of the event (event_source).
|
||||
// Additional arguments may or may not be supplied, see individual event definition files (destroyed.dm, moved.dm, etc.) for details.
|
||||
//
|
||||
// The instance making the register() call is also responsible for calling unregister(), see below for additonal details, including when event_source is destroyed.
|
||||
// This can be handled by listening to the event_source's destroyed event, unregistering in the listener's Destroy() proc, etc.
|
||||
//
|
||||
// /decl/observ/proc/unregister(var/event_source, var/datum/listener, var/proc_call)
|
||||
// event_source: The instance you wish to stop receiving events from.
|
||||
// listener: The instance which will no longer receive the events.
|
||||
// proc_call: Optional: The proc_call to unregister.
|
||||
//
|
||||
// Unregisters the listener from the event_source.
|
||||
// If a proc_call has been supplied only that particular proc_call will be unregistered. If the proc_call isn't currently registered there will be no effect.
|
||||
// If no proc_call has been supplied, the listener will have all registrations made to the given event_source undone.
|
||||
//
|
||||
// /decl/observ/proc/register_global(var/datum/listener, var/proc_call)
|
||||
// listener: The instance/owner of the proc to call when an event is raised by any and all sources.
|
||||
// proc_call: The proc to call when an event is raised.
|
||||
//
|
||||
// Works very much the same as register(), only the listener/proc_call will receive all relevant events from all event sources.
|
||||
// Global registrations can overlap with registrations made to specific event sources and these will not affect each other.
|
||||
//
|
||||
// /decl/observ/proc/unregister_global(var/datum/listener, var/proc_call)
|
||||
// listener: The instance/owner of the proc which will no longer receive the events.
|
||||
// proc_call: Optional: The proc_call to unregister.
|
||||
//
|
||||
// Works very much the same as unregister(), only it undoes global registrations instead.
|
||||
//
|
||||
// /decl/observ/proc/raise_event(src, ...)
|
||||
// Should never be called unless implementing a new event type.
|
||||
// The first argument shall always be the event_source belonging to the event. Beyond that there are no restrictions.
|
||||
|
||||
/decl/observ
|
||||
var/name = "Unnamed Event" // The name of this event, used mainly for debug/VV purposes. The list of event managers can be reached through the "Debug Controller" verb, selecting the "Observation" entry.
|
||||
var/expected_type = /datum // The expected event source for this event. register() will CRASH() if it receives an unexpected type.
|
||||
var/list/event_sources = list() // Associative list of event sources, each with their own associative list. This associative list contains an instance/list of procs to call when the event is raised.
|
||||
var/list/global_listeners = list() // Associative list of instances that listen to all events of this type (as opposed to events belonging to a specific source) and the proc to call.
|
||||
|
||||
/decl/observ/New()
|
||||
GLOB.all_observable_events.events += src
|
||||
. = ..()
|
||||
|
||||
/decl/observ/proc/is_listening(var/event_source, var/datum/listener, var/proc_call)
|
||||
// Return whether there are global listeners unless the event source is given.
|
||||
if (!event_source)
|
||||
return !!global_listeners.len
|
||||
|
||||
// Return whether anything is listening to a source, if no listener is given.
|
||||
if (!listener)
|
||||
return global_listeners.len || (event_source in event_sources)
|
||||
|
||||
// Return false if nothing is associated with that source.
|
||||
if (!(event_source in event_sources))
|
||||
return FALSE
|
||||
|
||||
// Get and check the listeners for the reuqested event.
|
||||
var/listeners = event_sources[event_source]
|
||||
if (!(listener in listeners))
|
||||
return FALSE
|
||||
|
||||
// Return true unless a specific callback needs checked.
|
||||
if (!proc_call)
|
||||
return TRUE
|
||||
|
||||
// Check if the specific callback exists.
|
||||
var/list/callback = listeners[listener]
|
||||
if (!callback)
|
||||
return FALSE
|
||||
|
||||
return (proc_call in callback)
|
||||
|
||||
/decl/observ/proc/has_listeners(var/event_source)
|
||||
return is_listening(event_source)
|
||||
|
||||
/decl/observ/proc/register(var/datum/event_source, var/datum/listener, var/proc_call)
|
||||
// Sanity checking.
|
||||
if (!(event_source && listener && proc_call))
|
||||
return FALSE
|
||||
if (istype(event_source, /decl/observ))
|
||||
return FALSE
|
||||
|
||||
// Crash if the event source is the wrong type.
|
||||
if (!istype(event_source, expected_type))
|
||||
CRASH("Unexpected type. Expected [expected_type], was [event_source.type]")
|
||||
|
||||
// Setup the listeners for this source if needed.
|
||||
var/list/listeners = event_sources[event_source]
|
||||
if (!listeners)
|
||||
listeners = list()
|
||||
event_sources[event_source] = listeners
|
||||
|
||||
// Make sure the callbacks are a list.
|
||||
var/list/callbacks = listeners[listener]
|
||||
if (!callbacks)
|
||||
callbacks = list()
|
||||
listeners[listener] = callbacks
|
||||
|
||||
// If the proc_call is already registered skip
|
||||
if(proc_call in callbacks)
|
||||
return FALSE
|
||||
|
||||
// Add the callback, and return true.
|
||||
callbacks += proc_call
|
||||
return TRUE
|
||||
|
||||
/decl/observ/proc/unregister(var/event_source, var/datum/listener, var/proc_call)
|
||||
// Sanity.
|
||||
if (!(event_source && listener && (event_source in event_sources)))
|
||||
return FALSE
|
||||
|
||||
// Return false if nothing is listening for this event.
|
||||
var/list/listeners = event_sources[event_source]
|
||||
if (!listeners)
|
||||
return FALSE
|
||||
|
||||
// Remove all callbacks if no specific one is given.
|
||||
if (!proc_call)
|
||||
if(listeners.Remove(listener))
|
||||
// Perform some cleanup and return true.
|
||||
if (!listeners.len)
|
||||
event_sources -= event_source
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// See if the listener is registered.
|
||||
var/list/callbacks = listeners[listener]
|
||||
if (!callbacks)
|
||||
return FALSE
|
||||
|
||||
// See if the callback exists.
|
||||
if(!callbacks.Remove(proc_call))
|
||||
return FALSE
|
||||
|
||||
if (!callbacks.len)
|
||||
listeners -= listener
|
||||
if (!listeners.len)
|
||||
event_sources -= event_source
|
||||
return TRUE
|
||||
|
||||
/decl/observ/proc/register_global(var/datum/listener, var/proc_call)
|
||||
// Sanity.
|
||||
if (!(listener && proc_call))
|
||||
return FALSE
|
||||
|
||||
// Make sure the callbacks are setup.
|
||||
var/list/callbacks = global_listeners[listener]
|
||||
if (!callbacks)
|
||||
callbacks = list()
|
||||
global_listeners[listener] = callbacks
|
||||
|
||||
// Add the callback and return true.
|
||||
callbacks |= proc_call
|
||||
return TRUE
|
||||
|
||||
/decl/observ/proc/unregister_global(var/datum/listener, var/proc_call)
|
||||
// Return false unless the listener is set as a global listener.
|
||||
if (!(listener && (listener in global_listeners)))
|
||||
return FALSE
|
||||
|
||||
// Remove all callbacks if no specific one is given.
|
||||
if (!proc_call)
|
||||
global_listeners -= listener
|
||||
return TRUE
|
||||
|
||||
// See if the listener is registered.
|
||||
var/list/callbacks = global_listeners[listener]
|
||||
if (!callbacks)
|
||||
return FALSE
|
||||
|
||||
// See if the callback exists.
|
||||
if(!callbacks.Remove(proc_call))
|
||||
return FALSE
|
||||
|
||||
if (!callbacks.len)
|
||||
global_listeners -= listener
|
||||
return TRUE
|
||||
|
||||
/decl/observ/proc/raise_event()
|
||||
// Sanity
|
||||
if (!args.len)
|
||||
return FALSE
|
||||
|
||||
// Call the global listeners.
|
||||
for (var/datum/listener in global_listeners)
|
||||
var/list/callbacks = global_listeners[listener]
|
||||
for (var/proc_call in callbacks)
|
||||
|
||||
// If the callback crashes, record the error and remove it.
|
||||
try
|
||||
call(listener, proc_call)(arglist(args))
|
||||
catch (var/exception/e)
|
||||
error("[e.name] - [e.file] - [e.line]")
|
||||
error(e.desc)
|
||||
unregister_global(listener, proc_call)
|
||||
|
||||
// Call the listeners for this specific event source, if they exist.
|
||||
var/source = args[1]
|
||||
if (source in event_sources)
|
||||
var/list/listeners = event_sources[source]
|
||||
for (var/datum/listener in listeners)
|
||||
var/list/callbacks = listeners[listener]
|
||||
for (var/proc_call in callbacks)
|
||||
|
||||
// If the callback crashes, record the error and remove it.
|
||||
try
|
||||
call(listener, proc_call)(arglist(args))
|
||||
catch (var/exception/e)
|
||||
error("[e.name] - [e.file] - [e.line]")
|
||||
error(e.desc)
|
||||
unregister(source, listener, proc_call)
|
||||
|
||||
return TRUE
|
||||
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /area: The area experiencing the power change
|
||||
|
||||
/*
|
||||
GLOBAL_DATUM_INIT(apc_event, /decl/observ/area_power_change, new)
|
||||
|
||||
/decl/observ/area_power_change
|
||||
@@ -15,7 +15,9 @@ GLOBAL_DATUM_INIT(apc_event, /decl/observ/area_power_change, new)
|
||||
/********************
|
||||
* Movement Handling *
|
||||
********************/
|
||||
*/
|
||||
//Deprecated in favor of comsigs
|
||||
|
||||
/area/power_change()
|
||||
. = ..()
|
||||
GLOB.apc_event.raise_event(src)
|
||||
SEND_SIGNAL(src,COMSIG_OBSERVER_APC)
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /datum/shuttle/shuttle: the new shuttle
|
||||
|
||||
/*
|
||||
GLOBAL_DATUM_INIT(shuttle_added, /decl/observ/shuttle_added, new)
|
||||
|
||||
/decl/observ/shuttle_added
|
||||
name = "Shuttle Added"
|
||||
expected_type = /datum/shuttle
|
||||
*/
|
||||
//Deprecated in favor of comsigs
|
||||
|
||||
/*****************************
|
||||
* Shuttle Added Handling *
|
||||
@@ -19,4 +21,4 @@ GLOBAL_DATUM_INIT(shuttle_added, /decl/observ/shuttle_added, new)
|
||||
/datum/controller/subsystem/shuttles/initialize_shuttle()
|
||||
. = ..()
|
||||
if(.)
|
||||
GLOB.shuttle_added.raise_event(.)
|
||||
SEND_SIGNAL(SSshuttles,COMSIG_OBSERVER_SHUTTLE_ADDED,.)
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// Observer Pattern Implementation: Shuttle Moved
|
||||
// Registration type: /datum/shuttle/autodock
|
||||
//
|
||||
// Raised when: A shuttle has moved to a new landmark.
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /datum/shuttle/shuttle: the shuttle moving
|
||||
// /obj/effect/shuttle_landmark/old_location: the old location's shuttle landmark
|
||||
// /obj/effect/shuttle_landmark/new_location: the new location's shuttle landmark
|
||||
|
||||
// Observer Pattern Implementation: Shuttle Pre Move
|
||||
// Registration type: /datum/shuttle/autodock
|
||||
//
|
||||
// Raised when: A shuttle is about to move to a new landmark.
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /datum/shuttle/shuttle: the shuttle moving
|
||||
// /obj/effect/shuttle_landmark/old_location: the old location's shuttle landmark
|
||||
// /obj/effect/shuttle_landmark/new_location: the new location's shuttle landmark
|
||||
|
||||
GLOBAL_DATUM_INIT(shuttle_moved_event, /decl/observ/shuttle_moved, new)
|
||||
|
||||
/decl/observ/shuttle_moved
|
||||
name = "Shuttle Moved"
|
||||
expected_type = /datum/shuttle
|
||||
|
||||
GLOBAL_DATUM_INIT(shuttle_pre_move_event, /decl/observ/shuttle_pre_move, new)
|
||||
|
||||
/decl/observ/shuttle_pre_move
|
||||
name = "Shuttle Pre Move"
|
||||
expected_type = /datum/shuttle
|
||||
|
||||
/*****************
|
||||
* Shuttle Moved/Pre Move Handling *
|
||||
*****************/
|
||||
|
||||
// Located in modules/shuttle/shuttle.dm
|
||||
// Proc: /datum/shuttle/proc/attempt_move()
|
||||
@@ -7,12 +7,14 @@
|
||||
// /mob/living/stat_mob: The mob whose stat changed
|
||||
// /old_stat: Status before the change.
|
||||
// /new_stat: Status after the change.
|
||||
|
||||
GLOBAL_DATUM_INIT(stat_set_event, /decl/observ/stat_set, new)
|
||||
/*
|
||||
stat_set_event, /decl/observ/stat_set, new)
|
||||
|
||||
/decl/observ/stat_set
|
||||
name = "Stat Set"
|
||||
expected_type = /mob/living
|
||||
*/
|
||||
//Deprecated in favor of Comsigs
|
||||
|
||||
/****************
|
||||
* Stat Handling *
|
||||
@@ -21,7 +23,7 @@ GLOBAL_DATUM_INIT(stat_set_event, /decl/observ/stat_set, new)
|
||||
var/old_stat = stat
|
||||
. = ..()
|
||||
if(stat != old_stat)
|
||||
GLOB.stat_set_event.raise_event(src, old_stat, new_stat)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_STATCHANGE, old_stat, new_stat)
|
||||
|
||||
if(isbelly(src.loc))
|
||||
var/obj/belly/ourbelly = src.loc
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// Observer Pattern Implementation: Turf Changed
|
||||
// Registration type: /turf
|
||||
//
|
||||
// Raised when: A turf has been changed using the ChangeTurf proc.
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /turf/affected: The turf that has changed
|
||||
// /old_density: Density before the change
|
||||
// /new_density: Density after the change
|
||||
// /old_opacity: Opacity before the change
|
||||
// /new_opacity: Opacity after the change
|
||||
|
||||
var/decl/observ/turf_changed/turf_changed_event = new()
|
||||
|
||||
/decl/observ/turf_changed
|
||||
name = "Turf Changed"
|
||||
expected_type = /turf
|
||||
|
||||
/************************
|
||||
* Turf Changed Handling *
|
||||
************************/
|
||||
|
||||
/turf/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors)
|
||||
var/old_density = density
|
||||
var/old_opacity = opacity
|
||||
. = ..(N, tell_universe, force_lighting_update, preserve_outdoors)
|
||||
if(.)
|
||||
turf_changed_event.raise_event(src, old_density, density, old_opacity, opacity)
|
||||
@@ -8,7 +8,7 @@
|
||||
// /atom/movable/moving_instance: The instance that entered/exited
|
||||
// /atom/old_loc / /atom/new_loc: The previous/new loc of the mover
|
||||
|
||||
|
||||
/*
|
||||
GLOBAL_DATUM_INIT(turf_entered_event, /decl/observ/turf_entered, new)
|
||||
GLOBAL_DATUM_INIT(turf_exited_event, /decl/observ/turf_exited, new)
|
||||
|
||||
@@ -20,14 +20,18 @@ GLOBAL_DATUM_INIT(turf_exited_event, /decl/observ/turf_exited, new)
|
||||
name = "Turf Exited"
|
||||
expected_type = /turf
|
||||
|
||||
*/
|
||||
//Deprecated in favor of Comsigs
|
||||
|
||||
/********************
|
||||
* Movement Handling *
|
||||
********************/
|
||||
|
||||
|
||||
/turf/Entered(var/atom/movable/am, var/atom/old_loc)
|
||||
. = ..()
|
||||
GLOB.turf_entered_event.raise_event(src, am, old_loc)
|
||||
SEND_SIGNAL(src, COMSIG_OBSERVER_TURF_ENTERED, am, old_loc)
|
||||
|
||||
/turf/Exited(var/atom/movable/am, var/atom/new_loc)
|
||||
. = ..()
|
||||
GLOB.turf_exited_event.raise_event(src, am, new_loc)
|
||||
SEND_SIGNAL(src, COMSIG_OBSERVER_TURF_EXITED, am, new_loc)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// Arguments that the called proc should expect:
|
||||
// /mob/equipped: The mob that unequipped/dropped the item.
|
||||
// /obj/item/item: The unequipped item.
|
||||
|
||||
/*
|
||||
GLOBAL_DATUM_INIT(mob_unequipped_event, /decl/observ/mob_unequipped, new)
|
||||
|
||||
/decl/observ/mob_unequipped
|
||||
@@ -27,6 +27,8 @@ GLOBAL_DATUM_INIT(item_unequipped_event, /decl/observ/item_unequipped, new)
|
||||
/decl/observ/item_unequipped
|
||||
name = "Item Unequipped"
|
||||
expected_type = /obj/item
|
||||
*/
|
||||
//Deprecated in favor of comsigs
|
||||
|
||||
/**********************
|
||||
* Unequipped Handling *
|
||||
@@ -34,5 +36,10 @@ GLOBAL_DATUM_INIT(item_unequipped_event, /decl/observ/item_unequipped, new)
|
||||
|
||||
/obj/item/dropped(var/mob/user)
|
||||
..()
|
||||
GLOB.mob_unequipped_event.raise_event(user, src)
|
||||
GLOB.item_unequipped_event.raise_event(src, user)
|
||||
//SEND_SIGNAL(user, COMSIG_OBSERVER_MOB_UNEQUIPPED, src)
|
||||
//SEND_SIGNAL(src, COMSIG_OBSERVER_ITEM_UNEQUIPPED, user)
|
||||
if(user) // Cannot always guarantee that user won't be null
|
||||
SEND_SIGNAL(user, COMSIG_OBSERVER_MOB_UNEQUIPPED, src)
|
||||
SEND_SIGNAL(src, COMSIG_OBSERVER_ITEM_UNEQUIPPED, user)
|
||||
else
|
||||
SEND_SIGNAL(src, COMSIG_OBSERVER_ITEM_UNEQUIPPED)
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// Observer Pattern Implementation: Z_Moved
|
||||
// Registration type: /atom/movable
|
||||
//
|
||||
// Raised when: An /atom/movable instance has changed z-levels by any means.
|
||||
//
|
||||
// Arguments that the called proc should expect:
|
||||
// /atom/movable/moving_instance: The instance that moved
|
||||
// old_z: The z number before the move.
|
||||
// new_z: The z number after the move.
|
||||
|
||||
|
||||
GLOBAL_DATUM_INIT(z_moved_event, /decl/observ/z_moved, new)
|
||||
|
||||
/decl/observ/z_moved
|
||||
name = "Z_Moved"
|
||||
expected_type = /atom/movable
|
||||
@@ -1,67 +0,0 @@
|
||||
GLOBAL_LIST_EMPTY(global_listen_count)
|
||||
GLOBAL_LIST_EMPTY(event_sources_count)
|
||||
GLOBAL_LIST_EMPTY(event_listen_count)
|
||||
|
||||
/decl/observ/destroyed/raise_event()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/source = args[1]
|
||||
|
||||
if(GLOB.global_listen_count[source])
|
||||
cleanup_global_listener(source, GLOB.global_listen_count[source])
|
||||
if(GLOB.event_sources_count[source])
|
||||
cleanup_source_listeners(source, GLOB.event_sources_count[source])
|
||||
if(GLOB.event_listen_count[source])
|
||||
cleanup_event_listener(source, GLOB.event_listen_count[source])
|
||||
|
||||
|
||||
/decl/observ/register(var/datum/event_source, var/datum/listener, var/proc_call)
|
||||
. = ..()
|
||||
if(.)
|
||||
GLOB.event_sources_count[event_source] += 1
|
||||
GLOB.event_listen_count[listener] += 1
|
||||
|
||||
/decl/observ/unregister(var/datum/event_source, var/datum/listener, var/proc_call)
|
||||
. = ..()
|
||||
if(.)
|
||||
GLOB.event_sources_count[event_source] -= 1
|
||||
GLOB.event_listen_count[listener] -= 1
|
||||
|
||||
/decl/observ/register_global(var/datum/listener, var/proc_call)
|
||||
. = ..()
|
||||
if(.)
|
||||
GLOB.global_listen_count[listener] += 1
|
||||
|
||||
/decl/observ/unregister_global(var/datum/listener, var/proc_call)
|
||||
. = ..()
|
||||
if(.)
|
||||
GLOB.global_listen_count[listener] -= 1
|
||||
|
||||
/decl/observ/destroyed/proc/cleanup_global_listener(listener, listen_count)
|
||||
GLOB.global_listen_count -= listener
|
||||
for(var/decl/observ/event as anything in GLOB.all_observable_events.events)
|
||||
if(event.unregister_global(listener))
|
||||
// log_debug("[event] - [listener] was deleted while still registered to global events.") // TODO: Apply axe, reimplement with datum component listeners
|
||||
if(!(--listen_count))
|
||||
return
|
||||
|
||||
/decl/observ/destroyed/proc/cleanup_source_listeners(event_source, source_listener_count)
|
||||
GLOB.event_sources_count -= event_source
|
||||
for(var/decl/observ/event as anything in GLOB.all_observable_events.events)
|
||||
var/proc_owners = event.event_sources[event_source]
|
||||
if(proc_owners)
|
||||
for(var/proc_owner in proc_owners)
|
||||
if(event.unregister(event_source, proc_owner))
|
||||
// log_debug("[event] - [event_source] was deleted while still being listened to by [proc_owner].") // TODO: Apply axe, reimplement with datum component listeners
|
||||
if(!(--source_listener_count))
|
||||
return
|
||||
|
||||
/decl/observ/destroyed/proc/cleanup_event_listener(listener, listener_count)
|
||||
GLOB.event_listen_count -= listener
|
||||
for(var/decl/observ/event as anything in GLOB.all_observable_events.events)
|
||||
for(var/event_source in event.event_sources)
|
||||
if(event.unregister(event_source, listener))
|
||||
// log_debug("[event] - [listener] was deleted while still listening to [event_source].") // TODO: Apply axe, reimplement with datum component listeners
|
||||
if(!(--listener_count))
|
||||
return
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
/atom/movable/proc/stop_orbit()
|
||||
SpinAnimation(0,0)
|
||||
qdel(orbiting)
|
||||
QDEL_NULL(orbiting)
|
||||
|
||||
/atom/Destroy(force = FALSE)
|
||||
. = ..()
|
||||
|
||||
@@ -23,4 +23,70 @@
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur
|
||||
id_type = /obj/item/weapon/card/id/civilian/entrepreneur
|
||||
l_hand = /obj/item/device/ticket_printer/train
|
||||
uniform = /obj/item/clothing/under/tropical/pink
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/lawyer
|
||||
uniform = /obj/item/clothing/under/lawyer/red
|
||||
r_hand = /obj/item/weapon/clipboard
|
||||
l_pocket = /obj/item/weapon/pen/fountain3
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/private_eye
|
||||
l_hand = /obj/item/weapon/storage/box/private_investigator
|
||||
suit = /obj/item/clothing/suit/storage/trench
|
||||
head = /obj/item/clothing/head/fedora/brown
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/bodyguard
|
||||
glasses = /obj/item/clothing/glasses/sunglasses
|
||||
l_pocket = /obj/item/weapon/reagent_containers/spray/pepper
|
||||
suit = /obj/item/clothing/accessory/sweater/blackneck
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/personal_physician
|
||||
suit = /obj/item/clothing/suit/storage/toggle/labcoat
|
||||
l_pocket = /obj/item/clothing/accessory/stethoscope
|
||||
r_pocket = /obj/item/device/healthanalyzer
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/dentist
|
||||
l_hand = /obj/item/weapon/storage/box/dentist
|
||||
suit = /obj/item/clothing/suit/storage/toggle/labcoat
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/fitness_instructor
|
||||
l_hand = /obj/item/weapon/storage/box/fitness_trainer
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/yoga_teacher
|
||||
uniform = /obj/item/clothing/under/pants/yogapants
|
||||
l_hand = /obj/item/weapon/storage/box/yoga_teacher
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/masseuse
|
||||
r_hand = /obj/item/roller/massage
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/tradesperson
|
||||
r_hand = /obj/item/weapon/storage/toolbox/brass
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/streamer
|
||||
l_pocket = /obj/item/device/tvcamera/streamer
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/influencer
|
||||
l_pocket = /obj/item/device/camera/selfie
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/paranormal_investigator
|
||||
l_hand = /obj/item/weapon/storage/box/paranormal_investigator
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/stylist
|
||||
l_hand = /obj/item/weapon/storage/box/stylist
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/fisher
|
||||
r_hand = /obj/item/weapon/material/fishing_rod/modern
|
||||
l_pocket = /obj/item/weapon/material/fishing_net
|
||||
head = /obj/item/clothing/head/fishing
|
||||
r_pocket = /obj/item/weapon/storage/box/wormcan
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/personal_secretary
|
||||
uniform = /obj/item/clothing/under/lawyer/blue
|
||||
r_hand = /obj/item/weapon/clipboard
|
||||
l_pocket = /obj/item/weapon/pen/fountain3
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/fortune_teller
|
||||
l_hand = /obj/item/weapon/storage/box/fortune_teller
|
||||
|
||||
/decl/hierarchy/outfit/job/assistant/entrepreneur/spirit_healer
|
||||
l_hand = /obj/item/weapon/storage/box/spirit_healer
|
||||
|
||||
@@ -127,7 +127,8 @@ var/list/outfits_decls_by_type_
|
||||
if(gloves)
|
||||
H.equip_to_slot_or_del(new gloves(H),slot_gloves)
|
||||
if(shoes)
|
||||
H.equip_to_slot_or_del(new shoes(H),slot_shoes)
|
||||
if(!(H.client?.prefs?.shoe_hater)) //RS ADD
|
||||
H.equip_to_slot_or_del(new shoes(H),slot_shoes)
|
||||
if(mask)
|
||||
H.equip_to_slot_or_del(new mask(H),slot_wear_mask)
|
||||
if(head)
|
||||
|
||||
@@ -91,4 +91,4 @@
|
||||
var/obj/structure/largecrate/C = /obj/structure/largecrate
|
||||
icon = image(initial(C.icon), initial(C.icon_state))
|
||||
|
||||
return "\icon[icon][bicon(icon)]"
|
||||
return "[bicon(icon)]"
|
||||
|
||||
@@ -130,7 +130,7 @@ var/datum/uplink/uplink = new()
|
||||
|
||||
/datum/uplink_item/item/log_icon()
|
||||
var/obj/I = path
|
||||
return "\icon[I][bicon(I)]"
|
||||
return "[bicon(I)]"
|
||||
|
||||
/********************************
|
||||
* *
|
||||
@@ -144,7 +144,7 @@ var/datum/uplink/uplink = new()
|
||||
if(!default_abstract_uplink_icon)
|
||||
default_abstract_uplink_icon = image('icons/obj/pda.dmi', "pda-syn")
|
||||
|
||||
return "\icon[default_abstract_uplink_icon][bicon(default_abstract_uplink_icon)]"
|
||||
return "[bicon(default_abstract_uplink_icon)]"
|
||||
|
||||
/*
|
||||
* Crated goods.
|
||||
@@ -174,7 +174,7 @@ var/datum/uplink/uplink = new()
|
||||
|
||||
/datum/uplink_item/crated/log_icon()
|
||||
var/obj/I = crate_path
|
||||
return "\icon[I]"
|
||||
return "[bicon(I)]"
|
||||
|
||||
/****************
|
||||
* Support procs *
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
C.light_disabled = !C.light_disabled
|
||||
|
||||
if(WIRE_CAM_ALARM)
|
||||
C.visible_message("\icon[C][bicon(C)] *beep*", "\icon[C][bicon(C)] *beep*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *beep*", "[icon2html(C,viewers(holder))] *beep*")
|
||||
..()
|
||||
|
||||
/datum/wires/camera/proc/CanDeconstruct()
|
||||
|
||||
@@ -31,16 +31,16 @@
|
||||
var/obj/machinery/media/jukebox/A = holder
|
||||
switch(wire)
|
||||
if(WIRE_MAIN_POWER1)
|
||||
holder.visible_message("<span class='notice'>\icon[holder][bicon(holder)] The power light flickers.</span>")
|
||||
holder.visible_message("<span class='notice'>[icon2html(A,viewers(holder))] The power light flickers.</span>")
|
||||
A.shock(usr, 90)
|
||||
if(WIRE_JUKEBOX_HACK)
|
||||
holder.visible_message("<span class='notice'>\icon[holder][bicon(holder)] The parental guidance light flickers.</span>")
|
||||
holder.visible_message("<span class='notice'>[icon2html(A,viewers(holder))] The parental guidance light flickers.</span>")
|
||||
if(WIRE_REVERSE)
|
||||
holder.visible_message("<span class='notice'>\icon[holder][bicon(holder)] The data light blinks ominously.</span>")
|
||||
holder.visible_message("<span class='notice'>[icon2html(A,viewers(holder))] The data light blinks ominously.</span>")
|
||||
if(WIRE_SPEEDUP)
|
||||
holder.visible_message("<span class='notice'>\icon[holder][bicon(holder)] The speakers squeaks.</span>")
|
||||
holder.visible_message("<span class='notice'>[icon2html(A,viewers(holder))] The speakers squeaks.</span>")
|
||||
if(WIRE_SPEEDDOWN)
|
||||
holder.visible_message("<span class='notice'>\icon[holder][bicon(holder)] The speakers rumble.</span>")
|
||||
holder.visible_message("<span class='notice'>[icon2html(A,viewers(holder))] The speakers rumble.</span>")
|
||||
if(WIRE_START)
|
||||
A.StartPlaying()
|
||||
if(WIRE_STOP)
|
||||
|
||||
+11
-11
@@ -21,15 +21,15 @@
|
||||
|
||||
switch(wire)
|
||||
if(WIRE_EXPLODE)
|
||||
C.visible_message("\icon[C][bicon(C)] *BEEE-*", "\icon[C][bicon(C)] *BEEE-*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *BEEE-*", "[icon2html(C,viewers(holder))] *BEEE-*")
|
||||
C.explode()
|
||||
|
||||
if(WIRE_EXPLODE_DELAY)
|
||||
C.visible_message("\icon[C][bicon(C)] *BEEE-*", "\icon[C][bicon(C)] *BEEE-*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *BEEE-*", "[icon2html(C,viewers(holder))] *BEEE-*")
|
||||
C.explode()
|
||||
|
||||
if(WIRE_DISARM)
|
||||
C.visible_message("\icon[C][bicon(C)] *click!*", "\icon[C][bicon(C)] *click!*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *click!*", "[icon2html(C,viewers(holder))] *click!*")
|
||||
var/obj/effect/mine/MI = new C.mineitemtype(get_turf(C))
|
||||
|
||||
if(C.trap)
|
||||
@@ -41,15 +41,15 @@
|
||||
qdel(C)
|
||||
|
||||
if(WIRE_BADDISARM)
|
||||
C.visible_message("\icon[C][bicon(C)] *BEEPBEEPBEEP*", "\icon[C][bicon(C)] *BEEPBEEPBEEP*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *BEEPBEEPBEEP*", "[icon2html(C,viewers(holder))] *BEEPBEEPBEEP*")
|
||||
spawn(20)
|
||||
C.explode()
|
||||
|
||||
if(WIRE_TRAP)
|
||||
C.visible_message("\icon[C][bicon(C)] *click!*", "\icon[C][bicon(C)] *click!*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *click!*", "[icon2html(C,viewers(holder))] *click!*")
|
||||
|
||||
if(mend)
|
||||
C.visible_message("\icon[C][bicon(C)] - The mine recalibrates[C.camo_net ? ", revealing \the [C.trap] inside." : "."]")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] - The mine recalibrates[C.camo_net ? ", revealing \the [C.trap] inside." : "."]")
|
||||
|
||||
C.alpha = 255
|
||||
|
||||
@@ -61,21 +61,21 @@
|
||||
return
|
||||
switch(wire)
|
||||
if(WIRE_EXPLODE)
|
||||
C.visible_message("\icon[C][bicon(C)] *beep*", "\icon[C][bicon(C)] *beep*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *beep*", "[icon2html(C,viewers(holder))] *beep*")
|
||||
|
||||
if(WIRE_EXPLODE_DELAY)
|
||||
C.visible_message("\icon[C][bicon(C)] *BEEPBEEPBEEP*", "\icon[C][bicon(C)] *BEEPBEEPBEEP*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *BEEPBEEPBEEP*", "[icon2html(C,viewers(holder))] *BEEPBEEPBEEP*")
|
||||
spawn(20)
|
||||
C.explode()
|
||||
|
||||
if(WIRE_DISARM)
|
||||
C.visible_message("\icon[C][bicon(C)] *ping*", "\icon[C][bicon(C)] *ping*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *ping*", "[icon2html(C,viewers(holder))] *ping*")
|
||||
|
||||
if(WIRE_BADDISARM)
|
||||
C.visible_message("\icon[C][bicon(C)] *ping*", "\icon[C][bicon(C)] *ping*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *ping*", "[icon2html(C,viewers(holder))] *ping*")
|
||||
|
||||
if(WIRE_TRAP)
|
||||
C.visible_message("\icon[C][bicon(C)] *ping*", "\icon[C][bicon(C)] *ping*")
|
||||
C.visible_message("[icon2html(C,viewers(holder))] *ping*", "[icon2html(C,viewers(holder))] *ping*")
|
||||
|
||||
..()
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
C.interface_control = !C.interface_control
|
||||
|
||||
if(WIRE_PARTICLE_POWER_LIMIT)
|
||||
C.visible_message("\icon[C][bicon(C)]<b>[C]</b> makes a large whirring noise.")
|
||||
C.visible_message("[icon2html(C,viewers(holder))]<b>[C]</b> makes a large whirring noise.")
|
||||
|
||||
/datum/wires/particle_acc/control_box/on_cut(wire, mend)
|
||||
var/obj/machinery/particle_accelerator/control_box/C = holder
|
||||
|
||||
+4
-4
@@ -160,7 +160,7 @@
|
||||
ASSERT(isturf(loc))
|
||||
var/list/turfs = trange(range, src)
|
||||
for(var/turf/T as anything in turfs)
|
||||
GLOB.turf_entered_event.register(T, src, callback)
|
||||
RegisterSignal(T, COMSIG_OBSERVER_TURF_ENTERED, callback)
|
||||
|
||||
//Unregister from prox listening in a certain range. You should do this BEFORE you move, but if you
|
||||
// really can't, then you can set the center where you moved from.
|
||||
@@ -168,7 +168,7 @@
|
||||
ASSERT(isturf(center) || isturf(loc))
|
||||
var/list/turfs = trange(range, center ? center : src)
|
||||
for(var/turf/T as anything in turfs)
|
||||
GLOB.turf_entered_event.unregister(T, src, callback)
|
||||
UnregisterSignal(T, COMSIG_OBSERVER_TURF_ENTERED)
|
||||
|
||||
|
||||
/atom/proc/emp_act(var/severity)
|
||||
@@ -235,7 +235,7 @@
|
||||
else
|
||||
f_name += "oil-stained [name][infix]."
|
||||
|
||||
var/list/output = list("\icon[src.examine_icon()][bicon(src)] That's [f_name] [suffix]", get_examine_desc())
|
||||
var/list/output = list("[icon2html(src,user.client)] That's [f_name] [suffix]", get_examine_desc())
|
||||
|
||||
if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE)
|
||||
output += description_info
|
||||
@@ -712,7 +712,7 @@
|
||||
|
||||
/atom/Entered(atom/movable/AM, atom/old_loc)
|
||||
. = ..()
|
||||
GLOB.moved_event.raise_event(AM, old_loc, AM.loc)
|
||||
SEND_SIGNAL(AM, COMSIG_OBSERVER_MOVED, old_loc, AM.loc)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, old_loc)
|
||||
SEND_SIGNAL(AM, COMSIG_ATOM_ENTERING, src, old_loc)
|
||||
|
||||
|
||||
@@ -374,7 +374,7 @@
|
||||
return TRUE
|
||||
|
||||
/atom/movable/proc/onTransitZ(old_z,new_z)
|
||||
GLOB.z_moved_event.raise_event(src, old_z, new_z)
|
||||
SEND_SIGNAL(src, COMSIG_OBSERVER_Z_MOVED, old_z, new_z)
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z)
|
||||
for(var/atom/movable/AM as anything in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
|
||||
AM.onTransitZ(old_z,new_z)
|
||||
|
||||
@@ -337,70 +337,84 @@
|
||||
/datum/alt_title/lawyer
|
||||
title = "Lawyer"
|
||||
title_blurb = "A Lawyer is knowledgable in various legal systems, including station's operations. They can try to offer their legal counsel, although nobody is really obliged to listen."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_secretary
|
||||
|
||||
/datum/alt_title/private_eye
|
||||
title = "Private Eye"
|
||||
title_blurb = "A Private Eye is a detective that has no credentials or equipment. But if someone wants something found without security's knowledge, they are the one to go to."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/private_eye
|
||||
|
||||
/datum/alt_title/bodyguard
|
||||
title = "Bodyguard"
|
||||
title_blurb = "A Bodyguard offers service of personal protection. They may not be allowed any weapons, but their own body is weapon enough."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/bodyguard
|
||||
|
||||
/datum/alt_title/personal_physician
|
||||
title = "Personal Physician"
|
||||
title_blurb = "A Personal Physicial is a doctor dedicated less to Hippocratic Oath and more to the moneymaking grind. Their license may be expired, but the grindset never will be."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_physician
|
||||
|
||||
/datum/alt_title/dentist
|
||||
title = "Dentist"
|
||||
title_blurb = "A Dentist is a doctor that specializes in oral care. Company may not recognize them as a proper doctor, but surely their customers will."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/dentist
|
||||
|
||||
/datum/alt_title/fitness_instructor
|
||||
title = "Fitness Instructor"
|
||||
title_blurb = "A Fitness Instructor dedicates themselves to improving the health of the crew through physical activity, and boy, do they need the help."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fitness_instructor
|
||||
|
||||
/datum/alt_title/yoga_teacher
|
||||
title = "Yoga Teacher"
|
||||
title_blurb = "A Yoga Teacher is similar to fitness instructor, but rather than turning the round bodies into firm ones, they focus on helping people find balance and harmony."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/yoga_teacher
|
||||
|
||||
/datum/alt_title/masseuse
|
||||
title = "Masseuse"
|
||||
title_blurb = "A Masseuse is master of physical therapy and working others' bodies with their hands."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/masseuse
|
||||
|
||||
/datum/alt_title/tradesperson
|
||||
title = "Tradesperson"
|
||||
title_blurb = "A Tradesperson is someone attempting to make money via the most obvious act of all - buying and selling. Now if only customs allowed you to bring your goods along..."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/tradesperson
|
||||
|
||||
/datum/alt_title/streamer
|
||||
title = "Streamer"
|
||||
title_blurb = "A Streamer is here to entertain. Not the crew! Their audience across exonet!"
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/streamer
|
||||
|
||||
/datum/alt_title/influencer
|
||||
title = "Influencer"
|
||||
title_blurb = "An Influencer has lucked out with some exonet following, and was given permission to go onstation to provide free exposure. Don't let it go to your head."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/influencer
|
||||
|
||||
/datum/alt_title/paranormal_investigator
|
||||
title = "Paranormal Investigator"
|
||||
title_blurb = "A Paranormal Investigator looks beyond what is accepted by modern science, and searches for the true unknown. Aliens, alternate dimensions, ghosts... The truth is out there!"
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/paranormal_investigator
|
||||
|
||||
/datum/alt_title/personal_secretary
|
||||
title = "Personal Secretary"
|
||||
title_blurb = "A Personal Secretary offers services of general assistance. Although it's doubtful anyone will ever actually need those."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_secretary
|
||||
|
||||
/datum/alt_title/stylist
|
||||
title = "Stylist"
|
||||
title_blurb = "A Stylist offers fashion advice, as well as helps with adjusting appearance of the crew to better suit their beauty standards."
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/stylist
|
||||
|
||||
/datum/alt_title/fisher
|
||||
title = "Fisher"
|
||||
title_blurb = "A Fisher is a capable angler, who is good at obtaining large amounts of marine goods. Whether you generously give them to station or attempt to make a quick thaler by selling, it's up to you!"
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fisher
|
||||
|
||||
/datum/alt_title/fortune_teller
|
||||
title = "Fortune Teller"
|
||||
title_blurb = "A Fortune Teller peers into the future, and offers these visions to others. Occasionally those visions may even come true!"
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fortune_teller
|
||||
|
||||
/datum/alt_title/spirit_healer
|
||||
title = "Spirit Healer"
|
||||
title_blurb = "A Spirit Healer offers alternative forms of medicine. Rituals, magic rocks, seances... It totally works. What's that about placebo?"
|
||||
|
||||
|
||||
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/spirit_healer
|
||||
|
||||
@@ -430,6 +430,8 @@ var/global/datum/controller/occupations/job_master
|
||||
//if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head)
|
||||
// custom_equip_leftovers += thing
|
||||
//else
|
||||
if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater) //RS ADD
|
||||
continue
|
||||
if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
|
||||
to_chat(H, "<span class='notice'>Equipping you with \the [thing]!</span>")
|
||||
if(G.slot != slot_tie)
|
||||
@@ -455,6 +457,8 @@ var/global/datum/controller/occupations/job_master
|
||||
// If some custom items could not be equipped before, try again now.
|
||||
for(var/thing in custom_equip_leftovers)
|
||||
var/datum/gear/G = gear_datums[thing]
|
||||
if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater) //RS ADD
|
||||
continue
|
||||
if(G.slot in custom_equip_slots)
|
||||
spawn_in_storage += thing
|
||||
else
|
||||
|
||||
@@ -27,13 +27,10 @@
|
||||
var/newlevel = round(charging.percent() * 4.0 / 99)
|
||||
//to_world("nl: [newlevel]")
|
||||
|
||||
if(chargelevel != newlevel)
|
||||
|
||||
cut_overlays()
|
||||
add_overlay("ccharger-o[newlevel]")
|
||||
|
||||
chargelevel = newlevel
|
||||
cut_overlays()
|
||||
add_overlay("ccharger-o[newlevel]")
|
||||
|
||||
chargelevel = newlevel
|
||||
add_overlay(image(charging.icon, charging.icon_state))
|
||||
add_overlay("ccharger-[charging.connector_type]-on")
|
||||
|
||||
@@ -126,10 +123,11 @@
|
||||
return
|
||||
|
||||
if(charging && !charging.fully_charged())
|
||||
var/newlevel = round(charging.percent() * 4.0 / 99)
|
||||
charging.give(efficiency*CELLRATE)
|
||||
update_use_power(USE_POWER_ACTIVE)
|
||||
|
||||
update_icon()
|
||||
if(chargelevel != newlevel)
|
||||
update_icon()
|
||||
else
|
||||
update_use_power(USE_POWER_IDLE)
|
||||
|
||||
@@ -137,4 +135,4 @@
|
||||
var/E = 0
|
||||
for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
|
||||
E += C.rating
|
||||
efficiency = active_power_usage * (1+ (E - 1)*0.5)
|
||||
efficiency = active_power_usage * (1+ (E - 1)*0.5)
|
||||
|
||||
@@ -1125,7 +1125,7 @@
|
||||
|
||||
// This is not a status display message, since it's something the character
|
||||
// themselves is meant to see BEFORE putting the money in
|
||||
to_chat(usr, "\icon[cashmoney][bicon(cashmoney)] <span class='warning'>That is not enough money.</span>")
|
||||
to_chat(usr, "[icon2html(cashmoney,user.client)] <span class='warning'>That is not enough money.</span>")
|
||||
return 0
|
||||
|
||||
if(istype(cashmoney, /obj/item/weapon/spacecash))
|
||||
@@ -1338,4 +1338,4 @@
|
||||
to_chat(user, "<span class='notice'>You turn in 2 tickets to the [src] and claim a prize!</span>")
|
||||
return
|
||||
else
|
||||
..() //You can now actually deconstruct these.
|
||||
..() //You can now actually deconstruct these.
|
||||
|
||||
@@ -1141,7 +1141,11 @@ About the new airlock wires panel:
|
||||
if(istype(C, /mob/living))
|
||||
..()
|
||||
return
|
||||
if(!repairing && C.has_tool_quality(TOOL_WELDER) && !( src.operating > 0 ) && src.density)
|
||||
//VOREstation Edit: Removing material cost from repair requirements
|
||||
if(C.has_tool_quality(TOOL_WELDER) && !( src.operating > 0 ) && src.density)
|
||||
if(health < maxhealth && user.a_intent == I_HELP)
|
||||
..()
|
||||
return
|
||||
var/obj/item/weapon/weldingtool/W = C.get_welder()
|
||||
if(W.remove_fuel(0,user))
|
||||
if(!src.welded)
|
||||
@@ -1176,7 +1180,7 @@ About the new airlock wires panel:
|
||||
else if(istype(C, /obj/item/weapon/pai_cable)) // -- TLE
|
||||
var/obj/item/weapon/pai_cable/cable = C
|
||||
cable.plugin(src, user)
|
||||
else if(!repairing && C.has_tool_quality(TOOL_CROWBAR))
|
||||
else if(C.has_tool_quality(TOOL_CROWBAR))
|
||||
if(can_remove_electronics())
|
||||
playsound(src, C.usesound, 75, 1)
|
||||
user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.")
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
var/destroy_hits = 10 //How many strong hits it takes to destroy the door
|
||||
var/min_force = 10 //minimum amount of force needed to damage the door with a melee weapon
|
||||
var/hitsound = 'sound/weapons/smash.ogg' //sound door makes when hit with a weapon
|
||||
var/repairing = 0
|
||||
//var/repairing = 0 //VOREstation Edit: We're not using materials anymore
|
||||
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
|
||||
var/close_door_at = 0 //When to automatically close the door, if possible
|
||||
|
||||
@@ -226,63 +226,21 @@
|
||||
if(istype(I))
|
||||
if(attackby_vr(I, user)) //VOREStation begin: Fireproofing
|
||||
return //VOREStation begin: Fireproofing
|
||||
if(istype(I, /obj/item/stack/material) && I.get_material_name() == src.get_material_name())
|
||||
if(stat & BROKEN)
|
||||
to_chat(user, "<span class='notice'>It looks like \the [src] is pretty busted. It's going to need more than just patching up now.</span>")
|
||||
return
|
||||
if(health >= maxhealth)
|
||||
to_chat(user, "<span class='notice'>Nothing to fix!</span>")
|
||||
return
|
||||
if(!density)
|
||||
to_chat(user, "<span class='warning'>\The [src] must be closed before you can repair it.</span>")
|
||||
return
|
||||
|
||||
//figure out how much metal we need
|
||||
var/amount_needed = (maxhealth - health) / DOOR_REPAIR_AMOUNT
|
||||
amount_needed = (round(amount_needed) == amount_needed)? amount_needed : round(amount_needed) + 1 //Why does BYOND not have a ceiling proc?
|
||||
|
||||
var/obj/item/stack/stack = I
|
||||
var/amount_given = amount_needed - repairing
|
||||
var/mats_given = stack.get_amount()
|
||||
if(repairing && amount_given <= 0)
|
||||
to_chat(user, "<span class='warning'>You must weld or remove \the [get_material_name()] from \the [src] before you can add anything else.</span>")
|
||||
else
|
||||
if(mats_given >= amount_given)
|
||||
if(stack.use(amount_given))
|
||||
repairing += amount_given
|
||||
else
|
||||
if(stack.use(mats_given))
|
||||
repairing += mats_given
|
||||
amount_given = mats_given
|
||||
if(amount_given)
|
||||
to_chat(user, "<span class='notice'>You fit [amount_given] [stack.singular_name]\s to damaged and broken parts on \the [src].</span>")
|
||||
|
||||
return
|
||||
|
||||
if(repairing && I.has_tool_quality(TOOL_WELDER))
|
||||
if(health < maxhealth && I.has_tool_quality(TOOL_WELDER))
|
||||
if(!density)
|
||||
to_chat(user, "<span class='warning'>\The [src] must be closed before you can repair it.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/weapon/weldingtool/welder = I.get_welder()
|
||||
if(welder.remove_fuel(0,user))
|
||||
to_chat(user, "<span class='notice'>You start to fix dents and weld \the [get_material_name()] into place.</span>")
|
||||
to_chat(user, "<span class='notice'>You start to fix dents and repair \the [src].</span>")
|
||||
playsound(src, welder.usesound, 50, 1)
|
||||
if(do_after(user, (5 * repairing) * welder.toolspeed) && welder && welder.isOn())
|
||||
var/repairtime = maxhealth - health //Since we're not using materials anymore... We'll just calculate how much damage there is to repair.
|
||||
if(do_after(user, repairtime * welder.toolspeed) && welder && welder.isOn())
|
||||
to_chat(user, "<span class='notice'>You finish repairing the damage to \the [src].</span>")
|
||||
health = between(health, health + repairing*DOOR_REPAIR_AMOUNT, maxhealth)
|
||||
health = maxhealth
|
||||
update_icon()
|
||||
repairing = 0
|
||||
return
|
||||
|
||||
if(repairing && I.has_tool_quality(TOOL_CROWBAR))
|
||||
var/datum/material/mat = get_material()
|
||||
var/obj/item/stack/material/repairing_sheet = mat.place_sheet(loc, repairing)
|
||||
repairing = 0
|
||||
to_chat(user, "<span class='notice'>You remove \the [repairing_sheet].</span>")
|
||||
playsound(src, I.usesound, 100, 1)
|
||||
return
|
||||
|
||||
//psa to whoever coded this, there are plenty of objects that need to call attack() on doors without bludgeoning them.
|
||||
if(src.density && istype(I, /obj/item/weapon) && user.a_intent == I_HURT && !istype(I, /obj/item/weapon/card))
|
||||
var/obj/item/weapon/W = I
|
||||
|
||||
@@ -248,7 +248,12 @@
|
||||
return //Don't open the door if we're putting tape on it to tell people 'don't open the door'.
|
||||
if(operating)
|
||||
return//Already doing something.
|
||||
if(C.has_tool_quality(TOOL_WELDER) && !repairing)
|
||||
if(C.has_tool_quality(TOOL_WELDER))
|
||||
//VOREstation Edit: Removing Material requirements on repairs
|
||||
if(health < maxhealth)
|
||||
..()
|
||||
return
|
||||
//VOREstation Edit End
|
||||
if(prying)
|
||||
to_chat(user, "<span class='notice'>Someone's busy prying that [density ? "open" : "closed"]!</span>")
|
||||
var/obj/item/weapon/weldingtool/W = C.get_welder()
|
||||
@@ -269,7 +274,7 @@
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(blocked && C.has_tool_quality(TOOL_CROWBAR) && !repairing)
|
||||
if(blocked && C.has_tool_quality(TOOL_CROWBAR))
|
||||
if(!hatch_open)
|
||||
to_chat(user, "<span class='danger'>You must open the maintenance hatch first!</span>")
|
||||
else
|
||||
|
||||
@@ -86,4 +86,14 @@
|
||||
..(severity)
|
||||
return
|
||||
power_change()
|
||||
..(severity)
|
||||
..(severity)
|
||||
|
||||
//Breakers for event maps
|
||||
|
||||
/obj/machinery/light_switch/breaker
|
||||
name = "lights breaker"
|
||||
desc = "A breaker for controlling power to the lights connected to the circuit."
|
||||
icon = 'icons/obj/power_breaker.dmi'
|
||||
icon_state = "light1"
|
||||
on = 0
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ Class Procs:
|
||||
|
||||
/obj/machinery/proc/state(var/msg)
|
||||
for(var/mob/O in hearers(src, null))
|
||||
O.show_message("\icon[src][bicon(src)] <span class = 'notice'>[msg]</span>", 2)
|
||||
O.show_message("[icon2html(src,O.client)] <span class = 'notice'>[msg]</span>", 2)
|
||||
|
||||
/obj/machinery/proc/ping(text=null)
|
||||
if(!text)
|
||||
|
||||
@@ -73,14 +73,18 @@
|
||||
// Do not do power stuff in New/Initialize until after ..()
|
||||
/obj/machinery/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_OBSERVER_MOVED, PROC_REF(update_power_on_move))
|
||||
AddComponent(/datum/component/recursive_move)
|
||||
var/power = POWER_CONSUMPTION
|
||||
REPORT_POWER_CONSUMPTION_CHANGE(0, power)
|
||||
power_init_complete = TRUE
|
||||
|
||||
// Or in Destroy at all, but especially after the ..().
|
||||
/obj/machinery/Destroy()
|
||||
/*
|
||||
if(ismovable(loc))
|
||||
GLOB.moved_event.unregister(loc, src, PROC_REF(update_power_on_move)) // Unregister just in case
|
||||
UnregisterSignal(loc, COMSIG_OBSERVER_MOVED) // Unregister just in case
|
||||
*/
|
||||
var/power = POWER_CONSUMPTION
|
||||
REPORT_POWER_CONSUMPTION_CHANGE(power, 0)
|
||||
. = ..()
|
||||
@@ -90,10 +94,12 @@
|
||||
/obj/machinery/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
. = ..()
|
||||
update_power_on_move(src, old_loc, loc)
|
||||
if(ismovable(loc)) // Register for recursive movement (if the thing we're inside moves)
|
||||
GLOB.moved_event.register(loc, src, PROC_REF(update_power_on_move))
|
||||
/* No
|
||||
if(ismovable(old_loc)) // Unregister recursive movement.
|
||||
GLOB.moved_event.unregister(old_loc, src, PROC_REF(update_power_on_move))
|
||||
UnregisterSignal(old_loc, COMSIG_OBSERVER_MOVED)
|
||||
if(ismovable(loc)) // Register for recursive movement (if the thing we're inside moves)
|
||||
RegisterSignal(loc, COMSIG_OBSERVER_MOVED, PROC_REF(update_power_on_move), override = TRUE)
|
||||
*/
|
||||
|
||||
/obj/machinery/proc/update_power_on_move(atom/movable/mover, atom/old_loc, atom/new_loc)
|
||||
var/area/old_area = get_area(old_loc)
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
var/icon/I = imap[1+(ix + icx*iy)*2]
|
||||
var/icon/I2 = imap[2+(ix + icx*iy)*2]
|
||||
|
||||
//to_world("icon: \icon[I][bicon(I)]")
|
||||
//to_world("icon: [icon2html(I)]")
|
||||
|
||||
I.DrawBox(colour, rx, ry, rx+1, ry+1)
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
|
||||
H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"
|
||||
|
||||
//to_world("\icon[I][bicon(I)] at [H.screen_loc]")
|
||||
//to_world("[icon2html(I)] at [H.screen_loc]")
|
||||
|
||||
H.name = (i==0)?"maprefresh":"map"
|
||||
|
||||
@@ -266,7 +266,7 @@
|
||||
//to_world("trying [ix],[iy] : [ix+icx*iy]")
|
||||
var/icon/I = imap[1+(ix + icx*iy)]
|
||||
|
||||
//to_world("icon: \icon[I][bicon(I)]")
|
||||
//to_world("icon: [icon2html(I)]")
|
||||
|
||||
I.DrawBox(colour, rx, ry, rx, ry)
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
|
||||
H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"
|
||||
|
||||
//to_world("\icon[I][bicon(I)] at [H.screen_loc]")
|
||||
//to_world("[icon2html(I)] at [H.screen_loc]")
|
||||
|
||||
H.name = (i==0)?"maprefresh":"map"
|
||||
|
||||
@@ -332,4 +332,4 @@
|
||||
qdel(O)
|
||||
|
||||
mapobjs = null
|
||||
src.unset_machine()
|
||||
src.unset_machine()
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
removeFromQueue(1)
|
||||
update_icon()
|
||||
else if(busy)
|
||||
visible_message("<span class='notice'>\icon [src] flashes: insufficient materials: [getLackingMaterials(D)].</span>")
|
||||
visible_message("<span class='notice'>[icon2html(src,viewers(src))] flashes: insufficient materials: [getLackingMaterials(D)].</span>")
|
||||
busy = 0
|
||||
update_use_power(USE_POWER_IDLE)
|
||||
update_icon()
|
||||
@@ -279,7 +279,7 @@
|
||||
var/datum/category_item/partslathe/current = queue[1]
|
||||
data["building"] = current.name
|
||||
data["buildPercent"] = (progress / current.time * 100)
|
||||
|
||||
|
||||
data["error"] = null
|
||||
if(queue.len > 0 && !canBuild(queue[1]))
|
||||
data["error"] = getLackingMaterials(queue[1])
|
||||
|
||||
@@ -254,9 +254,6 @@
|
||||
if(get_dist(src, L) > 7) //if it's too far away, why bother?
|
||||
return TURRET_NOT_TARGET
|
||||
|
||||
if(!(L in check_trajectory(L, src))) //check if we have true line of sight
|
||||
return TURRET_NOT_TARGET
|
||||
|
||||
if(L.lying) //Don't need to stun-lock the players
|
||||
return TURRET_NOT_TARGET
|
||||
|
||||
@@ -726,9 +723,6 @@
|
||||
if(get_dist(src, L) > 7) //if it's too far away, why bother?
|
||||
return TURRET_NOT_TARGET
|
||||
|
||||
if(!(L in check_trajectory(L, src))) //check if we have true line of sight
|
||||
return TURRET_NOT_TARGET
|
||||
|
||||
if(emagged) // If emagged not even the dead get a rest
|
||||
return L.stat ? TURRET_SECONDARY_TARGET : TURRET_PRIORITY_TARGET
|
||||
|
||||
@@ -841,13 +835,14 @@
|
||||
if(disabled)
|
||||
return FALSE
|
||||
if(target)
|
||||
last_target = target
|
||||
popUp() //pop the turret up if it's not already up.
|
||||
set_dir(get_dir(src, target)) //even if you can't shoot, follow the target
|
||||
playsound(src, 'sound/machines/turrets/turret_rotate.ogg', 100, 1) // Play rotating sound
|
||||
spawn()
|
||||
shootAt(target)
|
||||
return TRUE
|
||||
if(target in check_trajectory(target, src)) //Finally, check if we can actually hit the target
|
||||
last_target = target
|
||||
popUp() //pop the turret up if it's not already up.
|
||||
set_dir(get_dir(src, target)) //even if you can't shoot, follow the target
|
||||
playsound(src, 'sound/machines/turrets/turret_rotate.ogg', 100, 1) // Play rotating sound
|
||||
spawn()
|
||||
shootAt(target)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/porta_turret/proc/shootAt(var/mob/living/target)
|
||||
|
||||
@@ -198,7 +198,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
|
||||
screen = RCS_SENTPASS
|
||||
message_log += list(list("Message sent to [recipient]", "[message]"))
|
||||
else
|
||||
audible_message(text("\icon[src][bicon(src)] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
|
||||
audible_message(text("[icon2html(src,viewers(src))] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
|
||||
. = TRUE
|
||||
|
||||
//Handle printing
|
||||
|
||||
@@ -477,7 +477,7 @@ GLOBAL_LIST_EMPTY(suit_cycler_typecache)
|
||||
|
||||
/obj/machinery/suit_cycler/proc/finished_job()
|
||||
var/turf/T = get_turf(src)
|
||||
T.visible_message("\icon[src][bicon(src)]<span class='notice'>The [src] beeps several times.</span>")
|
||||
T.visible_message("[icon2html(src,viewers(src))]<span class='notice'>The [src] beeps several times.</span>")
|
||||
icon_state = initial(icon_state)
|
||||
active = 0
|
||||
playsound(src, 'sound/machines/boobeebeep.ogg', 50)
|
||||
@@ -543,5 +543,5 @@ GLOBAL_LIST_EMPTY(suit_cycler_typecache)
|
||||
if(target_species.can_refit_to(helmet, suit, suit?.helmet))
|
||||
target_species.do_refit_to(helmet, suit, suit?.helmet)
|
||||
else
|
||||
visible_message("\icon[src][bicon(src)]<span class='warning'>Unable to apply specified cosmetics with specified species. Please try again with a different species or cosmetic option selected.</span>")
|
||||
visible_message("[icon2html(src,viewers(src))]<span class='warning'>Unable to apply specified cosmetics with specified species. Please try again with a different species or cosmetic option selected.</span>")
|
||||
return
|
||||
|
||||
@@ -455,7 +455,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
if(data == DATA_ANTAG) // intercepted radio message
|
||||
part_b_extra = " <i>(Intercepted)</i>"
|
||||
var/part_a = "<span class='[frequency_span_class(display_freq)]'>"
|
||||
var/part_b = "\icon[radio][bicon(radio)]<b>\[[freq_text]\][part_b_extra]</b> <span class='name'>" // goes in the actual output
|
||||
var/part_b = "[icon2html(radio, heard_masked + heard_normal + heard_voice + heard_garbled + heard_gibberish)]<b>\[[freq_text]\][part_b_extra]</b> <span class='name'>" // goes in the actual output
|
||||
|
||||
// --- Some more pre-message formatting ---
|
||||
var/part_c = "</span> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
@@ -658,7 +658,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
// Create a radio headset for the sole purpose of using its icon
|
||||
var/obj/item/device/radio/headset/radio = new
|
||||
|
||||
var/part_b = "</span><b>\icon[radio][bicon(radio)]\[[freq_text]\][part_b_extra]</b> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
var/part_b = "</span><b>[icon2html(radio, heard_normal + heard_garbled + heard_gibberish)]\[[freq_text]\][part_b_extra]</b> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
var/part_blackbox_b = "</span><b> \[[freq_text]\]</b> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
var/part_c = "</span></span>"
|
||||
|
||||
|
||||
@@ -313,13 +313,13 @@
|
||||
|
||||
|
||||
if("freq")
|
||||
var/newfreq = input(usr, "Specify a new frequency to filter (GHz). Decimals assigned automatically.", src, network) as null|num
|
||||
var/newfreq = tgui_input_number(usr, "Specify a new frequency to filter (GHz). Decimals assigned automatically.", src, max_value=9999)
|
||||
if(newfreq && canAccess(usr))
|
||||
if(findtext(num2text(newfreq), "."))
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
if(!(newfreq in freq_listening) && newfreq < 10000)
|
||||
freq_listening.Add(newfreq)
|
||||
set_temp("-% New frequency filter assigned: \"[newfreq] GHz\" %-", "average")
|
||||
set_temp("-% New frequency filter assigned: \"[newfreq/10] GHz\" %-", "average")
|
||||
. = TRUE
|
||||
|
||||
if("delete")
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/occupant_message(message)
|
||||
if(chassis)
|
||||
chassis.occupant_message("\icon[src][bicon(src)] [message]")
|
||||
chassis.occupant_message("[icon2html(src, chassis.occupant.client)] [message]")
|
||||
return
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/log_message(message)
|
||||
|
||||
@@ -77,7 +77,8 @@
|
||||
/obj/item/shield_projector/rectangle/mecha/Initialize()
|
||||
. = ..()
|
||||
my_mech = loc
|
||||
GLOB.moved_event.register(my_mech, src, /obj/item/shield_projector/proc/update_shield_positions)
|
||||
RegisterSignal(my_mech, COMSIG_OBSERVER_MOVED, /obj/item/shield_projector/proc/update_shield_positions)
|
||||
my_mech.AddComponent(/datum/component/recursive_move)
|
||||
update_shift(my_mech)
|
||||
|
||||
/obj/item/shield_projector/rectangle/mecha/proc/update_shift(atom/movable/mech)
|
||||
@@ -88,7 +89,7 @@
|
||||
shift_y = round(y_dif, 1)
|
||||
|
||||
/obj/item/shield_projector/rectangle/mecha/Destroy()
|
||||
GLOB.moved_event.unregister(my_mech, src, /obj/item/shield_projector/proc/update_shield_positions)
|
||||
UnregisterSignal(my_mech, COMSIG_OBSERVER_MOVED)
|
||||
my_mech = null
|
||||
..()
|
||||
|
||||
|
||||
@@ -664,20 +664,20 @@
|
||||
switch(emagged)
|
||||
if(0)
|
||||
emagged = 0.5
|
||||
visible_message("\icon[src][bicon(src)] <b>[src]</b> beeps: \"DB error \[Code 0x00F1\]\"")
|
||||
visible_message("[icon2html(src,viewers(src))] <b>[src]</b> beeps: \"DB error \[Code 0x00F1\]\"")
|
||||
sleep(10)
|
||||
visible_message("\icon[src][bicon(src)] <b>[src]</b> beeps: \"Attempting auto-repair\"")
|
||||
visible_message("[icon2html(src,viewers(src))] <b>[src]</b> beeps: \"Attempting auto-repair\"")
|
||||
sleep(15)
|
||||
visible_message("\icon[src][bicon(src)] <b>[src]</b> beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
|
||||
visible_message("[icon2html(src,viewers(src))] <b>[src]</b> beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
|
||||
sleep(30)
|
||||
visible_message("\icon[src][bicon(src)] <b>[src]</b> beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"")
|
||||
visible_message("[icon2html(src,viewers(src))] <b>[src]</b> beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"")
|
||||
req_access = null
|
||||
emagged = 1
|
||||
return 1
|
||||
if(0.5)
|
||||
visible_message("\icon[src][bicon(src)] <b>[src]</b> beeps: \"DB not responding \[Code 0x0003\]...\"")
|
||||
visible_message("[icon2html(src,viewers(src))] <b>[src]</b> beeps: \"DB not responding \[Code 0x0003\]...\"")
|
||||
if(1)
|
||||
visible_message("\icon[src][bicon(src)] <b>[src]</b> beeps: \"No records in User DB\"")
|
||||
visible_message("[icon2html(src,viewers(src))] <b>[src]</b> beeps: \"No records in User DB\"")
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
|
||||
var/recursive = amount == -1 ? TRUE : FALSE
|
||||
|
||||
@@ -538,7 +538,7 @@
|
||||
if(equipment?.len)
|
||||
. += "It's equipped with:"
|
||||
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
|
||||
. += "\icon[ME][bicon(ME)] [ME]"
|
||||
. += "[icon2html(ME,user.client)] [ME]"
|
||||
|
||||
/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits.
|
||||
return
|
||||
@@ -2439,7 +2439,7 @@
|
||||
/obj/mecha/proc/occupant_message(message as text)
|
||||
if(message)
|
||||
if(src.occupant && src.occupant.client)
|
||||
to_chat(src.occupant, "\icon[src][bicon(src)] [message]")
|
||||
to_chat(src.occupant, "[icon2html(src, src.occupant.client)] [message]")
|
||||
return
|
||||
|
||||
/obj/mecha/proc/log_message(message as text,red=null)
|
||||
|
||||
@@ -1018,6 +1018,7 @@ var/global/list/semirandom_mob_spawner_decisions = list()
|
||||
overwrite_hostility = 1
|
||||
mob_hostile = 0
|
||||
mob_retaliate = 0
|
||||
mob_ghostjoin = 25 //25% chance to be ghost joinable
|
||||
|
||||
/obj/random/mob/semirandom_mob_spawner/vore/passive/b
|
||||
mob_faction = "pasvoreb"
|
||||
@@ -1030,6 +1031,7 @@ var/global/list/semirandom_mob_spawner_decisions = list()
|
||||
overwrite_hostility = 1
|
||||
mob_hostile = 0
|
||||
mob_retaliate = 1
|
||||
mob_ghostjoin = 25 //25% chance to be ghost joinable
|
||||
|
||||
/obj/random/mob/semirandom_mob_spawner/vore/retaliate/b
|
||||
mob_faction = "retvoreb"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
. = ..()
|
||||
if(randomdir)
|
||||
dir = pick(list(NORTH, SOUTH, EAST, WEST))
|
||||
timerid = QDEL_IN(src, duration)
|
||||
timerid = QDEL_IN_STOPPABLE(src, duration)
|
||||
|
||||
/obj/effect/temp_visual/Destroy()
|
||||
. = ..()
|
||||
@@ -35,4 +35,3 @@
|
||||
if(set_dir)
|
||||
dir = set_dir
|
||||
. = ..()
|
||||
|
||||
|
||||
+20
-12
@@ -703,7 +703,14 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
|
||||
//Looking through a scope or binoculars should /not/ improve your periphereal vision. Still, increase viewsize a tiny bit so that sniping isn't as restricted to NSEW
|
||||
/obj/item/var/ignore_visor_zoom_restriction = FALSE
|
||||
|
||||
/obj/item/proc/zoom(var/tileoffset = 14,var/viewsize = 9) //tileoffset is client view offset in the direction the user is facing. viewsize is how far out this thing zooms. 7 is normal view
|
||||
/obj/item/proc/zoom(var/mob/living/M, var/tileoffset = 14,var/viewsize = 9) //tileoffset is client view offset in the direction the user is facing. viewsize is how far out this thing zooms. 7 is normal view
|
||||
|
||||
if(isliving(usr)) //Always prefer usr if set
|
||||
M = usr
|
||||
|
||||
if(!isliving(M))
|
||||
return 0
|
||||
|
||||
|
||||
var/devicename
|
||||
|
||||
@@ -714,25 +721,26 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
|
||||
|
||||
var/cannotzoom
|
||||
|
||||
if((usr.stat && !zoom) || !(istype(usr,/mob/living/carbon/human)))
|
||||
to_chat(usr, "<span class='filter_notice'>You are unable to focus through the [devicename].</span>")
|
||||
if((M.stat && !zoom) || !(istype(M,/mob/living/carbon/human)))
|
||||
to_chat(M, "<span class='filter_notice'>You are unable to focus through the [devicename].</span>")
|
||||
cannotzoom = 1
|
||||
else if(!zoom && (global_hud.darkMask[1] in usr.client.screen))
|
||||
to_chat(usr, "<span class='filter_notice'>Your visor gets in the way of looking through the [devicename].</span>")
|
||||
else if(!zoom && (global_hud.darkMask[1] in M.client.screen))
|
||||
to_chat(M, "<span class='filter_notice'>Your visor gets in the way of looking through the [devicename].</span>")
|
||||
cannotzoom = 1
|
||||
else if(!zoom && usr.get_active_hand() != src)
|
||||
to_chat(usr, "<span class='filter_notice'>You are too distracted to look through the [devicename], perhaps if it was in your active hand this might work better.</span>")
|
||||
else if(!zoom && M.get_active_hand() != src)
|
||||
to_chat(M, "<span class='filter_notice'>You are too distracted to look through the [devicename], perhaps if it was in your active hand this might work better.</span>")
|
||||
cannotzoom = 1
|
||||
|
||||
//We checked above if they are a human and returned already if they weren't.
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
if(!zoom && !cannotzoom)
|
||||
if(H.hud_used.hud_shown)
|
||||
H.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in
|
||||
H.set_viewsize(viewsize)
|
||||
zoom = 1
|
||||
GLOB.moved_event.register(H, src, PROC_REF(zoom))
|
||||
H.AddComponent(/datum/component/recursive_move)
|
||||
RegisterSignal(H, COMSIG_OBSERVER_MOVED, PROC_REF(zoom), override = TRUE)
|
||||
|
||||
var/tilesize = 32
|
||||
var/viewoffset = tilesize * tileoffset
|
||||
@@ -751,7 +759,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
|
||||
H.client.pixel_x = -viewoffset
|
||||
H.client.pixel_y = 0
|
||||
|
||||
H.visible_message("<span class='filter_notice'>[usr] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].</span>")
|
||||
H.visible_message("<span class='filter_notice'>[M] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].</span>")
|
||||
if(!ignore_visor_zoom_restriction)
|
||||
H.looking_elsewhere = TRUE
|
||||
H.handle_vision()
|
||||
@@ -761,7 +769,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
|
||||
if(!H.hud_used.hud_shown)
|
||||
H.toggle_zoom_hud()
|
||||
zoom = 0
|
||||
GLOB.moved_event.unregister(H, src, PROC_REF(zoom))
|
||||
UnregisterSignal(H, COMSIG_OBSERVER_MOVED)
|
||||
|
||||
H.client.pixel_x = 0
|
||||
H.client.pixel_y = 0
|
||||
@@ -769,7 +777,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
|
||||
H.handle_vision()
|
||||
|
||||
if(!cannotzoom)
|
||||
usr.visible_message("<span class='filter_notice'>[zoomdevicename ? "[usr] looks up from the [src.name]" : "[usr] lowers the [src.name]"].</span>")
|
||||
M.visible_message("<span class='filter_notice'>[zoomdevicename ? "[M] looks up from the [src.name]" : "[M] lowers the [src.name]"].</span>")
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -94,22 +94,22 @@
|
||||
if(new_state != old_state)
|
||||
switch(new_state)
|
||||
if(PROXIMITY_OFF_CAMERANET)
|
||||
to_chat(carrier, "<span class='notice'>\icon[src][bicon(src)] Now outside of camera network.</span>")
|
||||
to_chat(carrier, "<span class='notice'>[icon2html(src, carrier.client)] Now outside of camera network.</span>")
|
||||
carrier << 'sound/machines/defib_failed.ogg'
|
||||
if(PROXIMITY_NONE)
|
||||
to_chat(carrier, "<span class='notice'>\icon[src][bicon(src)] Now within camera network, AI and cameras unfocused.</span>")
|
||||
to_chat(carrier, "<span class='notice'>[icon2html(src, carrier.client)] Now within camera network, AI and cameras unfocused.</span>")
|
||||
carrier << 'sound/machines/defib_safetyOff.ogg'
|
||||
if(PROXIMITY_NEAR)
|
||||
to_chat(carrier, "<span class='warning'>\icon[src][bicon(src)] Warning: AI focus at nearby location.</span>")
|
||||
to_chat(carrier, "<span class='warning'>[icon2html(src, carrier.client)] Warning: AI focus at nearby location.</span>")
|
||||
carrier << 'sound/machines/defib_SafetyOn.ogg'
|
||||
if(PROXIMITY_ON_SCREEN)
|
||||
to_chat(carrier, "<font size='3'><span class='danger'>\icon[src][bicon(src)] Alert: AI or camera focused at current location!</span></font>")
|
||||
to_chat(carrier, "<font size='3'><span class='danger'>[icon2html(src, carrier.client)] Alert: AI or camera focused at current location!</span></font>")
|
||||
carrier <<'sound/machines/defib_ready.ogg'
|
||||
if(PROXIMITY_TRACKING)
|
||||
to_chat(carrier, "<font size='3'><span class='danger'>\icon[src][bicon(src)] Danger: AI is actively tracking you!</span></font>")
|
||||
to_chat(carrier, "<font size='3'><span class='danger'>[icon2html(src, carrier.client)] Danger: AI is actively tracking you!</span></font>")
|
||||
carrier << 'sound/machines/defib_success.ogg'
|
||||
if(PROXIMITY_TRACKING_FAIL)
|
||||
to_chat(carrier, "<font size='3'><span class='danger'>\icon[src][bicon(src)] Danger: AI is attempting to actively track you, but you are outside of the camera network!</span></font>")
|
||||
to_chat(carrier, "<font size='3'><span class='danger'>[icon2html(src, carrier.client)] Danger: AI is attempting to actively track you, but you are outside of the camera network!</span></font>")
|
||||
carrier <<'sound/machines/defib_ready.ogg'
|
||||
|
||||
|
||||
@@ -118,4 +118,4 @@
|
||||
#undef PROXIMITY_NEAR
|
||||
#undef PROXIMITY_ON_SCREEN
|
||||
#undef PROXIMITY_TRACKING
|
||||
#undef PROXIMITY_TRACKING_FAIL
|
||||
#undef PROXIMITY_TRACKING_FAIL
|
||||
|
||||
@@ -382,7 +382,7 @@
|
||||
im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text))
|
||||
log_pda("(COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]", usr)
|
||||
var/obj/item/device/communicator/comm = exonet.get_atom_from_address(their_address)
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
to_chat(usr, "<span class='notice'>[icon2html(src, usr.client)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
|
||||
|
||||
@@ -302,7 +302,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
/obj/item/device/communicator/Destroy()
|
||||
for(var/mob/living/voice/voice in contents)
|
||||
voice_mobs.Remove(voice)
|
||||
to_chat(voice, "<span class='danger'>\icon[src][bicon(src)] Connection timed out with remote host.</span>")
|
||||
to_chat(voice, "<span class='danger'>[icon2html(src, voice.client)] Connection timed out with remote host.</span>")
|
||||
qdel(voice)
|
||||
close_connection(reason = "Connection timed out")
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
if(src in comm.voice_invites)
|
||||
comm.open_connection(src)
|
||||
return
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Receiving communicator request from [origin_atom]. To answer, use the <b>Call Communicator</b> \
|
||||
to_chat(src, "<span class='notice'>[icon2html(origin_atom,src.client)] Receiving communicator request from [origin_atom]. To answer, use the <b>Call Communicator</b> \
|
||||
verb, and select that name to answer the call.</span>")
|
||||
src << 'sound/machines/defib_SafetyOn.ogg'
|
||||
comm.voice_invites |= src
|
||||
@@ -44,7 +44,7 @@
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Received text message from [origin_atom]: <b>\"[text]\"</b></span>")
|
||||
to_chat(src, "<span class='notice'>[icon2html(origin_atom,src.client)] Received text message from [origin_atom]: <b>\"[text]\"</b></span>")
|
||||
src << 'sound/machines/defib_safetyOff.ogg'
|
||||
exonet_messages.Add("<b>From [origin_atom]:</b><br>[text]")
|
||||
return
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
playsound(src, S, 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *[ttone]*"))
|
||||
O.show_message(text("[icon2html(src,O.client)] *[ttone]*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
@@ -95,7 +95,7 @@
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Message from [who]: <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[candidate]'>Reply</a>)</span>")
|
||||
to_chat(L, "<span class='notice'>[icon2html(src,L.client)] Message from [who]: <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[candidate]'>Reply</a>)</span>")
|
||||
|
||||
// This is the only Topic the communicators really uses
|
||||
/obj/item/device/communicator/Topic(href, href_list)
|
||||
@@ -108,7 +108,7 @@
|
||||
exonet.send_message(comm.exonet.address, "text", message)
|
||||
im_list += list(list("address" = exonet.address, "to_address" = comm.exonet.address, "im" = message))
|
||||
log_pda("(COMM: [src]) sent \"[message]\" to [exonet.get_atom_from_address(comm.exonet.address)]", usr)
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[message]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
to_chat(usr, "<span class='notice'>[icon2html(src,usr.client)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[message]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
|
||||
// Verb: text_communicator()
|
||||
// Parameters: None
|
||||
|
||||
@@ -39,15 +39,15 @@
|
||||
comm.voice_requests.Remove(src)
|
||||
|
||||
if(user)
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connecting to [src].</span>")
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [comm].</span>")
|
||||
comm.visible_message("<span class='notice'>[icon2html(src,viewers(src))] Connecting to [src].</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src,user.client)] Attempting to call [comm].</span>")
|
||||
sleep(10)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Dialing internally from [station_name()], [system_name()].</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src,user.client)] Dialing internally from [station_name()], [system_name()].</span>")
|
||||
sleep(20) //If they don't have an exonet something is very wrong and we want a runtime.
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection re-routed to [comm] at [comm.exonet.address].</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src,user.client)] Connection re-routed to [comm] at [comm.exonet.address].</span>")
|
||||
sleep(40)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection to [comm] at [comm.exonet.address] established.</span>")
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connection to [src] at [exonet.address] established.</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src,user.client)] Connection to [comm] at [comm.exonet.address] established.</span>")
|
||||
comm.visible_message("<span class='notice'>[icon2html(src,viewers(src))] Connection to [src] at [exonet.address] established.</span>")
|
||||
sleep(20)
|
||||
|
||||
src.add_communicating(comm)
|
||||
@@ -86,28 +86,28 @@
|
||||
|
||||
//Now for some connection fluff.
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connecting to [candidate].</span>")
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [src].</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src,user.client)] Connecting to [candidate].</span>")
|
||||
to_chat(new_voice, "<span class='notice'>[icon2html(src,new_voice.client)] Attempting to call [src].</span>")
|
||||
sleep(10)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>")
|
||||
to_chat(new_voice, "<span class='notice'>[icon2html(src,new_voice.client)] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>")
|
||||
sleep(20)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connecting to [station_name()] telecommunications array.</span>")
|
||||
to_chat(new_voice, "<span class='notice'>[icon2html(src,new_voice.client)] Connecting to [station_name()] telecommunications array.</span>")
|
||||
sleep(40)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>")
|
||||
to_chat(new_voice, "<span class='notice'>[icon2html(src,new_voice.client)] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>")
|
||||
sleep(20)
|
||||
|
||||
//We're connected, no need to hide everything.
|
||||
new_voice.client.screen.Remove(blackness)
|
||||
qdel(blackness)
|
||||
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [src] established.</span>")
|
||||
to_chat(new_voice, "<span class='notice'>[icon2html(src,new_voice.client)] Connection to [src] established.</span>")
|
||||
to_chat(new_voice, "<b>To talk to the person on the other end of the call, just talk normally.</b>")
|
||||
to_chat(new_voice, "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>")
|
||||
to_chat(new_voice, "<b>Remember, your character does not know anything you've learned from observing!</b>")
|
||||
if(new_voice.mind)
|
||||
new_voice.mind.assigned_role = "Disembodied Voice"
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Your communicator is now connected to [candidate]'s communicator.</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src,new_voice.client)] Your communicator is now connected to [candidate]'s communicator.</span>")
|
||||
|
||||
// Proc: close_connection()
|
||||
// Parameters: 3 (user - the user who initiated the disconnect, target - the mob or device being disconnected, reason - string shown when disconnected)
|
||||
@@ -120,8 +120,8 @@
|
||||
for(var/mob/living/voice/voice in voice_mobs) //Handle ghost-callers
|
||||
if(target && voice != target) //If no target is inputted, it deletes all of them.
|
||||
continue
|
||||
to_chat(voice, "<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
to_chat(voice, "<span class='danger'>[icon2html(src,voice.client)] [reason].</span>")
|
||||
visible_message("<span class='danger'>[icon2html(src,viewers(src))] [reason].</span>")
|
||||
voice_mobs.Remove(voice)
|
||||
qdel(voice)
|
||||
update_icon()
|
||||
@@ -131,8 +131,8 @@
|
||||
continue
|
||||
src.del_communicating(comm)
|
||||
comm.del_communicating(src)
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
comm.visible_message("<span class='danger'>[icon2html(src,viewers(src))] [reason].</span>")
|
||||
visible_message("<span class='danger'>[icon2html(src,viewers(src))] [reason].</span>")
|
||||
if(comm.camera && video_source == comm.camera) //We hung up on the person on video
|
||||
end_video()
|
||||
if(camera && comm.video_source == camera) //We hung up on them while they were watching us
|
||||
@@ -163,7 +163,7 @@
|
||||
if(ringer)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *beep*"))
|
||||
O.show_message(text("[icon2html(src,O.client)] *beep*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
@@ -174,7 +174,7 @@
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Communications request from [who].</span>")
|
||||
to_chat(L, "<span class='notice'>[icon2html(src,L.client)] Communications request from [who].</span>")
|
||||
|
||||
// Proc: del_request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator to be declined)
|
||||
@@ -197,13 +197,13 @@
|
||||
us = loc
|
||||
|
||||
if(us)
|
||||
to_chat(us, "<span class='notice'>\icon[src][bicon(src)] Declined request.</span>")
|
||||
to_chat(us, "<span class='notice'>[icon2html(src,us.client)] Declined request.</span>")
|
||||
|
||||
// Proc: see_emote()
|
||||
// Parameters: 2 (M - the mob the emote originated from, text - the emote's contents)
|
||||
// Description: Relays the emote to all linked communicators.
|
||||
/obj/item/device/communicator/see_emote(mob/living/M, text)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[text]</span>"
|
||||
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
@@ -216,7 +216,7 @@
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
var/rendered = "[icon2html(src,mobs_to_relay)] <span class='message'>[text]</span>"
|
||||
for(var/mob/mob in mobs_to_relay) //We can't use visible_message(), or else we will get an infinite loop if two communicators hear each other.
|
||||
var/dst = get_dist(get_turf(mob),get_turf(comm))
|
||||
if(dst <= video_range)
|
||||
@@ -250,20 +250,20 @@
|
||||
var/message = combined["formatted"]
|
||||
var/name_used = M.GetVoice()
|
||||
var/rendered = null
|
||||
rendered = "<span class='game say'>\icon[src][bicon(src)] <span class='name'>[name_used]</span> [message]</span>"
|
||||
rendered = "<span class='game say'>[icon2html(src,mobs_to_relay)] <span class='name'>[name_used]</span> [message]</span>"
|
||||
mob.show_message(rendered, 2)
|
||||
|
||||
// Proc: show_message()
|
||||
// Parameters: 4 (msg - the message, type - number to determine if message is visible or audible, alt - unknown, alt_type - unknown)
|
||||
// Description: Relays the message to all linked communicators.
|
||||
/obj/item/device/communicator/show_message(msg, type, alt, alt_type)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[msg]</span>"
|
||||
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0)
|
||||
var/list/mobs_to_relay = in_range["mobs"]
|
||||
|
||||
var/rendered = "[icon2html(src, mobs_to_relay)] <span class='message'>[msg]</span>"
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
mob.show_message(rendered)
|
||||
..()
|
||||
@@ -339,28 +339,29 @@
|
||||
return
|
||||
|
||||
if(!(src in comm.communicating) || !comm.camera) //You called someone with a broken communicator or one that's fake or yourself or something
|
||||
to_chat(user, "<span class='danger'>\icon[src][bicon(src)]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning.</span>")
|
||||
to_chat(user, "<span class='danger'>[icon2html(src, user.client)]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning.</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to start video over existing call.</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src, user.client)] Attempting to start video over existing call.</span>")
|
||||
sleep(30)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Please wait...</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src, user.client)] Please wait...</span>")
|
||||
|
||||
video_source = comm.camera
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] New video connection from [comm].</span>")
|
||||
comm.visible_message("<span class='danger'>[icon2html(src,viewers(src))] New video connection from [comm].</span>")
|
||||
update_active_camera_screen()
|
||||
GLOB.moved_event.register(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
RegisterSignal(video_source, COMSIG_OBSERVER_MOVED, PROC_REF(update_active_camera_screen))
|
||||
video_source.AddComponent(/datum/component/recursive_move)
|
||||
update_icon()
|
||||
|
||||
// Proc: end_video()
|
||||
// Parameters: reason - the text reason to print for why it ended
|
||||
// Description: Ends the video call by clearing video_source
|
||||
/obj/item/device/communicator/proc/end_video(var/reason)
|
||||
GLOB.moved_event.unregister(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
UnregisterSignal(video_source, COMSIG_OBSERVER_MOVED)
|
||||
show_static()
|
||||
video_source = null
|
||||
|
||||
. = "<span class='danger'>\icon[src][bicon(src)] [reason ? reason : "Video session ended"].</span>"
|
||||
. = "<span class='danger'>[bicon(src)] [reason ? reason : "Video session ended"].</span>"
|
||||
|
||||
visible_message(.)
|
||||
update_icon()
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
update_sound()
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] You switch [scanning ? "on" : "off"] \the [src].</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src, user.client)] You switch [scanning ? "on" : "off"] \the [src].</span>")
|
||||
|
||||
/obj/item/device/geiger/update_icon()
|
||||
if(!scanning)
|
||||
@@ -120,7 +120,7 @@
|
||||
scanning = !scanning
|
||||
update_icon()
|
||||
update_sound()
|
||||
to_chat(user, "<span class='notice'>\icon[src] You switch [scanning ? "on" : "off"] \the [src].</span>")
|
||||
to_chat(user, "<span class='notice'>[icon2html(src, user.client)] You switch [scanning ? "on" : "off"] \the [src].</span>")
|
||||
|
||||
/obj/item/device/geiger/wall/update_icon()
|
||||
if(!scanning)
|
||||
@@ -165,4 +165,4 @@
|
||||
|
||||
/obj/item/device/geiger/wall/west
|
||||
pixel_x = -28
|
||||
dir = WEST
|
||||
dir = WEST
|
||||
|
||||
@@ -38,15 +38,16 @@ var/list/GPS_list = list()
|
||||
/obj/item/device/gps/proc/update_holder()
|
||||
|
||||
if(holder && loc != holder)
|
||||
GLOB.moved_event.unregister(holder, src)
|
||||
GLOB.dir_set_event.unregister(holder, src)
|
||||
UnregisterSignal(holder, COMSIG_OBSERVER_MOVED)
|
||||
//GLOB.dir_set_event.unregister(holder, src)
|
||||
holder.client?.screen -= compass
|
||||
holder = null
|
||||
|
||||
if(istype(loc, /mob))
|
||||
holder = loc
|
||||
GLOB.moved_event.register(holder, src, PROC_REF(update_compass))
|
||||
GLOB.dir_set_event.register(holder, src, PROC_REF(update_compass))
|
||||
RegisterSignal(holder, COMSIG_OBSERVER_MOVED, PROC_REF(update_compass), override = TRUE)
|
||||
holder.AddComponent(/datum/component/recursive_move)
|
||||
//GLOB.dir_set_event.register(holder, src, PROC_REF(update_compass))
|
||||
|
||||
if(holder && tracking)
|
||||
if(!is_in_processing_list)
|
||||
|
||||
@@ -71,12 +71,12 @@
|
||||
to_chat(user, "<span class='warning'>You are already hacking!</span>")
|
||||
return 0
|
||||
if(!is_type_in_list(target, supported_types))
|
||||
to_chat(user, "\icon[src][bicon(src)] <span class='warning'>Unable to hack this target, invalid target type.</span>")
|
||||
to_chat(user, "[icon2html(src, user.client)] <span class='warning'>Unable to hack this target, invalid target type.</span>")
|
||||
return 0
|
||||
|
||||
var/obj/machinery/door/airlock/D = target
|
||||
if(D.security_level > max_level)
|
||||
to_chat(user, "\icon[src][bicon(src)] <span class='warning'>Target's electronic security is too complex.</span>")
|
||||
to_chat(user, "[icon2html(src, user.client)] <span class='warning'>Target's electronic security is too complex.</span>")
|
||||
return 0
|
||||
|
||||
var/found = known_targets.Find(D)
|
||||
|
||||
@@ -20,13 +20,15 @@
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
GLOB.apc_event.register(A, src, /atom/proc/update_icon)
|
||||
RegisterSignal(A, COMSIG_OBSERVER_APC, /atom/proc/update_icon)
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/radio/intercom/Destroy()
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
GLOB.apc_event.unregister(A, src, /atom/proc/update_icon)
|
||||
UnregisterSignal(A, COMSIG_OBSERVER_APC)
|
||||
if(circuit)
|
||||
QDEL_NULL(circuit)
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/intercom/custom
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user