Merge pull request #1454 from Yawn-Wider/voreupdate-515

Voreupdate 515 [MDB IGNORE] [IDB IGNORE]
This commit is contained in:
Izac Joof Forsgren
2024-04-26 05:54:19 +02:00
committed by GitHub
381 changed files with 53770 additions and 2279 deletions
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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)
+4 -1
View File
@@ -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
-5
View File
@@ -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)
+2
View File
@@ -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"
+17
View File
@@ -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"
+3 -2
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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)
+6
View File
@@ -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>")
+1
View File
@@ -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
+3 -3
View File
@@ -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, "&nbsp;&nbsp;&nbsp;&nbsp;")
GLOBAL_VAR_INIT(TAB, "&nbsp;&nbsp;&nbsp;&nbsp;")
+1 -1
View File
@@ -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)]&nbsp;"
item_str += "[bicon(A)]&nbsp;"
switch(determiners)
if(DET_NONE) item_str += A.name
if(DET_DEFINITE) item_str += "\the [A]"
+29
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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 -4
View File
@@ -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
+16 -16
View File
@@ -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]
+2 -2
View File
@@ -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)))
+6
View File
@@ -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>"}
+6 -4
View File
@@ -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"
+8 -1
View File
@@ -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
+2
View File
@@ -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
+39 -2
View File
@@ -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
+13
View File
@@ -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))
+5 -4
View File
@@ -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
+32
View File
@@ -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]'")
+2
View File
@@ -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()
+1 -1
View File
@@ -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
+32 -10
View File
@@ -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
+192 -121
View File
@@ -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)
+23 -15
View File
@@ -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()
+3 -3
View File
@@ -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 = "*&nbsp;[text]&nbsp;*"
+119
View File
@@ -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))
-10
View File
@@ -1,10 +0,0 @@
/****************
* Debug Support *
****************/
/datum/all_observable_events
var/list/events
/datum/all_observable_events/New()
events = list()
..()
-1
View File
@@ -1 +0,0 @@
#define CANCEL_MOVE_EVENT -55
+4 -3
View File
@@ -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)
. = ..()
-35
View File
@@ -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)
+5 -3
View File
@@ -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)
+11 -8
View File
@@ -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)
*/
-21
View File
@@ -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)
+10 -7
View File
@@ -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)
-238
View File
@@ -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
+4 -2
View File
@@ -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)
+4 -2
View File
@@ -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,.)
-38
View File
@@ -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()
+5 -3
View File
@@ -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
-28
View File
@@ -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)
+7 -3
View File
@@ -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)
+10 -3
View File
@@ -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)
-16
View File
@@ -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
-67
View File
@@ -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
+1 -1
View File
@@ -105,7 +105,7 @@
/atom/movable/proc/stop_orbit()
SpinAnimation(0,0)
qdel(orbiting)
QDEL_NULL(orbiting)
/atom/Destroy(force = FALSE)
. = ..()
+66
View File
@@ -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
+2 -1
View File
@@ -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)
+1 -1
View File
@@ -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)]"
+3 -3
View File
@@ -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 *
+1 -1
View File
@@ -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()
+5 -5
View File
@@ -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
View File
@@ -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*")
..()
+1 -1
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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)
+17 -3
View File
@@ -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
+4
View File
@@ -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
+7 -9
View File
@@ -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)
+2 -2
View File
@@ -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.
+6 -2
View File
@@ -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.")
+6 -48
View File
@@ -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
+7 -2
View File
@@ -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
+11 -1
View File
@@ -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
+1 -1
View File
@@ -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)
+10 -4
View File
@@ -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)
+5 -5
View File
@@ -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()
+2 -2
View File
@@ -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])
+8 -13
View File
@@ -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)
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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")
+1 -1
View File
@@ -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
..()
+6 -6
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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()
+3 -3
View File
@@ -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
+5 -4
View File
@@ -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)
+2 -2
View File
@@ -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