mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-14 08:34:16 +01:00
Merge remote-tracking branch 'upstream/master' into mechastuff
# Conflicts: # icons/mob/screen_alert.dmi
This commit is contained in:
@@ -26,15 +26,18 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
|
||||
### Defines
|
||||
|
||||
1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned.
|
||||
|
||||
1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned. This will be noted in the runtime logs
|
||||
|
||||
### Vars
|
||||
|
||||
1. `/datum/var/list/datum_components` (private)
|
||||
* Lazy associated list of type -> component/list of components.
|
||||
1. `/datum/component/var/enabled` (protected, boolean)
|
||||
* If the component is enabled. If not, it will not react to signals
|
||||
1. `/datum/var/list/comp_lookup` (private)
|
||||
* Lazy associated list of signal -> registree/list of registrees
|
||||
1. `/datum/var/list/signal_procs` (private)
|
||||
* Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal
|
||||
1. `/datum/var/signal_enabled` (protected, boolean)
|
||||
* If the datum is signal enabled. If not, it will not react to signals
|
||||
* `FALSE` by default, set to `TRUE` when a signal is registered
|
||||
1. `/datum/component/var/dupe_mode` (protected, enum)
|
||||
* How duplicate component types are handled when added to the datum.
|
||||
@@ -46,11 +49,12 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* Definition of a duplicate component type
|
||||
* `null` means exact match on `type` (default)
|
||||
* Any other type means that and all subtypes
|
||||
1. `/datum/component/var/list/signal_procs` (private)
|
||||
* Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum recieves that signal
|
||||
1. `/datum/component/var/datum/parent` (protected, read-only)
|
||||
* The datum this component belongs to
|
||||
* Never `null` in child procs
|
||||
1. `report_signal_origin` (protected, boolean)
|
||||
* If `TRUE`, will invoke the callback when signalled with the signal type as the first argument.
|
||||
* `FALSE` by default.
|
||||
|
||||
### Procs
|
||||
|
||||
@@ -77,7 +81,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final)
|
||||
* Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead
|
||||
1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async)
|
||||
* Called on a component's `parent` after a signal recieved causes it to activate. `src` is the parameter
|
||||
* Called on a component's `parent` after a signal received causes it to activate. `src` is the parameter
|
||||
* Will only be called if a component's callback returns `TRUE`
|
||||
1. `/datum/proc/TakeComponent(datum/component/C)` (public, final)
|
||||
* Properly transfers ownership of a component from one datum to another
|
||||
@@ -86,13 +90,21 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
1. `/datum/proc/_SendSignal(signal, list/arguments)` (private, final)
|
||||
* Handles most of the actual signaling procedure
|
||||
* Will runtime if used on datums with an empty component list
|
||||
1. `/datum/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final)
|
||||
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
|
||||
* Makes the datum listen for the specified `signal` on it's `parent` datum.
|
||||
* When that signal is received `proc_ref` will be called on the component, along with associated arguments
|
||||
* Example proc ref: `.proc/OnEvent`
|
||||
* If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this
|
||||
* These callbacks run asyncronously
|
||||
* Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it
|
||||
1. `/datum/component/New(datum/parent, ...)` (private, final)
|
||||
* Runs internal setup for the component
|
||||
* Extra arguments are passed to `Initialize()`
|
||||
1. `/datum/component/Initialize(...)` (abstract, no-sleep)
|
||||
* Called by `New()` with the same argments excluding `parent`
|
||||
* Component does not exist in `parent`'s `datum_components` list yet, although `parent` is set and may be used
|
||||
* Signals will not be recieved while this function is running
|
||||
* Signals will not be received while this function is running
|
||||
* Component may be deleted after this function completes without being attached
|
||||
* Do not call `qdel(src)` from this function
|
||||
1. `/datum/component/Destroy(force(bool), silent(bool))` (virtual, no-sleep)
|
||||
@@ -113,13 +125,11 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* Clears `parent` and removes the component from it's component list
|
||||
1. `/datum/component/proc/_JoinParent` (private, final)
|
||||
* Tries to add the component to it's `parent`s `datum_components` list
|
||||
1. `/datum/component/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final)
|
||||
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
|
||||
* Makes a component listen for the specified `signal` on it's `parent` datum.
|
||||
* When that signal is recieved `proc_ref` will be called on the component, along with associated arguments
|
||||
* Example proc ref: `.proc/OnEvent`
|
||||
* If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this
|
||||
* These callbacks run asyncronously
|
||||
* Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `_SendSignal()` that initiated it
|
||||
1. `/datum/component/proc/RegisterWithParent` (abstract, no-sleep)
|
||||
* Used to register the signals that should be on the `parent` object
|
||||
* Use this if you plan on the component transfering between parents
|
||||
1. `/datum/component/proc/UnregisterFromParent` (abstract, no-sleep)
|
||||
* Counterpart to `RegisterWithParent()`
|
||||
* Used to unregister the signals that should only be on the `parent` object
|
||||
|
||||
### See/Define signals and their arguments in __DEFINES\components.dm
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/datum/component
|
||||
var/enabled = FALSE
|
||||
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
|
||||
var/dupe_type
|
||||
var/list/signal_procs
|
||||
var/datum/parent
|
||||
|
||||
/datum/component/New(datum/P, ...)
|
||||
@@ -10,7 +8,7 @@
|
||||
var/list/arguments = args.Copy(2)
|
||||
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
|
||||
qdel(src, TRUE, TRUE)
|
||||
CRASH("Incompatible [type] assigned to a [P]!")
|
||||
CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]")
|
||||
|
||||
_JoinParent(P)
|
||||
|
||||
@@ -47,19 +45,21 @@
|
||||
else //only component of this type, no list
|
||||
dc[I] = src
|
||||
|
||||
RegisterWithParent()
|
||||
|
||||
// If you want/expect to be moving the component around between parents, use this to register on the parent for signals
|
||||
/datum/component/proc/RegisterWithParent()
|
||||
return
|
||||
|
||||
/datum/component/proc/Initialize(...)
|
||||
return
|
||||
|
||||
/datum/component/Destroy(force=FALSE, silent=FALSE)
|
||||
enabled = FALSE
|
||||
var/datum/P = parent
|
||||
if(!force)
|
||||
if(!force && parent)
|
||||
_RemoveFromParent()
|
||||
if(!silent)
|
||||
SEND_SIGNAL(P, COMSIG_COMPONENT_REMOVING, src)
|
||||
SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src)
|
||||
parent = null
|
||||
for(var/target in signal_procs)
|
||||
UnregisterSignal(target, signal_procs[target])
|
||||
return ..()
|
||||
|
||||
/datum/component/proc/_RemoveFromParent()
|
||||
@@ -78,7 +78,12 @@
|
||||
if(!dc.len)
|
||||
P.datum_components = null
|
||||
|
||||
/datum/component/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE)
|
||||
UnregisterFromParent()
|
||||
|
||||
/datum/component/proc/UnregisterFromParent()
|
||||
return
|
||||
|
||||
/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE)
|
||||
if(QDELETED(src) || QDELETED(target))
|
||||
return
|
||||
|
||||
@@ -100,6 +105,7 @@
|
||||
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
|
||||
|
||||
procs[target][sig_type] = proc_or_callback
|
||||
|
||||
if(!lookup[sig_type]) // Nothing has registered here yet
|
||||
lookup[sig_type] = src
|
||||
else if(lookup[sig_type] == src) // We already registered here
|
||||
@@ -110,8 +116,9 @@
|
||||
else // Many other things have registered here
|
||||
lookup[sig_type][src] = TRUE
|
||||
|
||||
enabled = TRUE
|
||||
/datum/component/proc/UnregisterSignal(datum/target, sig_type_or_types)
|
||||
signal_enabled = TRUE
|
||||
|
||||
/datum/proc/UnregisterSignal(datum/target, sig_type_or_types)
|
||||
var/list/lookup = target.comp_lookup
|
||||
if(!signal_procs || !signal_procs[target] || !lookup)
|
||||
return
|
||||
@@ -137,24 +144,19 @@
|
||||
lookup[sig] -= src
|
||||
|
||||
signal_procs[target] -= sig_type_or_types
|
||||
if(length(signal_procs[target]))
|
||||
if(!signal_procs[target].len)
|
||||
signal_procs -= target
|
||||
|
||||
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
|
||||
return
|
||||
|
||||
/datum/component/proc/OnTransfer(datum/new_parent)
|
||||
/datum/component/proc/PreTransfer()
|
||||
return
|
||||
|
||||
/datum/component/proc/PostTransfer()
|
||||
return
|
||||
|
||||
/datum/component/proc/_GetInverseTypeList(our_type = type)
|
||||
#if DM_VERSION >= 513
|
||||
#warn 512 is definitely stable now, remove the old code
|
||||
#endif
|
||||
|
||||
#if DM_VERSION < 512
|
||||
//remove this when we use 512 full time
|
||||
set invisibility = 101
|
||||
#endif
|
||||
//we can do this one simple trick
|
||||
var/current_type = parent_type
|
||||
. = list(our_type, current_type)
|
||||
@@ -166,15 +168,15 @@
|
||||
/datum/proc/_SendSignal(sigtype, list/arguments)
|
||||
var/target = comp_lookup[sigtype]
|
||||
if(!length(target))
|
||||
var/datum/component/C = target
|
||||
if(!C.enabled)
|
||||
var/datum/C = target
|
||||
if(!C.signal_enabled)
|
||||
return NONE
|
||||
var/datum/callback/CB = C.signal_procs[src][sigtype]
|
||||
return CB.InvokeAsync(arglist(arguments))
|
||||
. = NONE
|
||||
for(var/I in target)
|
||||
var/datum/component/C = I
|
||||
if(!C.enabled)
|
||||
var/datum/C = I
|
||||
if(!C.signal_enabled)
|
||||
continue
|
||||
var/datum/callback/CB = C.signal_procs[src][sigtype]
|
||||
. |= CB.InvokeAsync(arglist(arguments))
|
||||
@@ -218,12 +220,9 @@
|
||||
if(ispath(nt))
|
||||
if(nt == /datum/component)
|
||||
CRASH("[nt] attempted instantiation!")
|
||||
if(!isnum(dm))
|
||||
CRASH("[nt]: Invalid dupe_mode ([dm])!")
|
||||
if(dt && !ispath(dt))
|
||||
CRASH("[nt]: Invalid dupe_type ([dt])!")
|
||||
else
|
||||
new_comp = nt
|
||||
nt = new_comp.type
|
||||
|
||||
args[1] = src
|
||||
|
||||
@@ -267,21 +266,27 @@
|
||||
if(!.)
|
||||
return AddComponent(arglist(args))
|
||||
|
||||
/datum/proc/TakeComponent(datum/component/C)
|
||||
if(!C)
|
||||
/datum/component/proc/RemoveComponent()
|
||||
if(!parent)
|
||||
return
|
||||
var/datum/helicopter = C.parent
|
||||
if(helicopter == src)
|
||||
//if we're taking to the same thing no need for anything
|
||||
var/datum/old_parent = parent
|
||||
PreTransfer()
|
||||
_RemoveFromParent()
|
||||
parent = null
|
||||
SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src)
|
||||
|
||||
/datum/proc/TakeComponent(datum/component/target)
|
||||
if(!target || target.parent == src)
|
||||
return
|
||||
if(C.OnTransfer(src) == COMPONENT_INCOMPATIBLE)
|
||||
qdel(C)
|
||||
return
|
||||
C._RemoveFromParent()
|
||||
SEND_SIGNAL(helicopter, COMSIG_COMPONENT_REMOVING, C)
|
||||
C.parent = src
|
||||
if(C == AddComponent(C))
|
||||
C._JoinParent()
|
||||
if(target.parent)
|
||||
target.RemoveComponent()
|
||||
target.parent = src
|
||||
if(target.PostTransfer() == COMPONENT_INCOMPATIBLE)
|
||||
var/c_type = target.type
|
||||
qdel(target)
|
||||
CRASH("Incompatible [c_type] transfer attempt to a [type]!")
|
||||
if(target == AddComponent(target))
|
||||
target._JoinParent()
|
||||
|
||||
/datum/proc/TransferComponents(datum/target)
|
||||
var/list/dc = datum_components
|
||||
@@ -295,4 +300,4 @@
|
||||
target.TakeComponent(comps)
|
||||
|
||||
/datum/component/nano_host()
|
||||
return parent
|
||||
return parent
|
||||
@@ -15,18 +15,25 @@
|
||||
var/sheet_type
|
||||
var/list/materials
|
||||
var/show_on_examine
|
||||
var/disable_attackby
|
||||
var/list/allowed_typecache
|
||||
var/last_inserted_id
|
||||
var/precise_insertion = FALSE
|
||||
var/datum/callback/precondition
|
||||
var/datum/callback/after_insert
|
||||
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert)
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert, _disable_attackby)
|
||||
materials = list()
|
||||
max_amount = max(0, max_amt)
|
||||
show_on_examine = _show_on_examine
|
||||
disable_attackby = _disable_attackby
|
||||
|
||||
if(allowed_types)
|
||||
allowed_typecache = typecacheof(allowed_types)
|
||||
if(ispath(allowed_types) && allowed_types == /obj/item/stack)
|
||||
allowed_typecache = GLOB.typecache_stack
|
||||
else
|
||||
allowed_typecache = typecacheof(allowed_types)
|
||||
|
||||
precondition = _precondition
|
||||
after_insert = _after_insert
|
||||
|
||||
@@ -43,16 +50,21 @@
|
||||
materials[id] = new mat_path()
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = materials[I]
|
||||
var/amt = amount(M.id)
|
||||
if(amt)
|
||||
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
|
||||
if(show_on_examine)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = materials[I]
|
||||
var/amt = amount(M.id)
|
||||
if(amt)
|
||||
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
|
||||
|
||||
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
|
||||
var/list/tc = allowed_typecache
|
||||
if(disable_attackby)
|
||||
return
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return
|
||||
if(I.flags & ABSTRACT)
|
||||
return
|
||||
if((I.flags_2 & (HOLOGRAM_2 | NO_MAT_REDEMPTION_2)) || (tc && !is_type_in_typecache(I, tc)))
|
||||
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
|
||||
return
|
||||
@@ -88,10 +100,9 @@
|
||||
if(istype(I, /obj/item/stack))
|
||||
var/obj/item/stack/S = I
|
||||
to_chat(user, "<span class='notice'>You insert [inserted] [S.singular_name][inserted>1 ? "s" : ""] into [parent].</span>")
|
||||
if(!QDELETED(I))
|
||||
if(!user.put_in_hands(I))
|
||||
stack_trace("Warning: User could not put object back in hand during material container insertion, line [__LINE__]! This can lead to issues.")
|
||||
I.forceMove(user.loc)
|
||||
if(!QDELETED(I) && !user.put_in_hands(I))
|
||||
stack_trace("Warning: User could not put object back in hand during material container insertion, line [__LINE__]! This can lead to issues.")
|
||||
I.forceMove(user.drop_location())
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
|
||||
qdel(I)
|
||||
@@ -235,24 +246,25 @@
|
||||
//For spawning mineral sheets; internal use only
|
||||
/datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null)
|
||||
if(!M.sheet_type)
|
||||
return FALSE
|
||||
if(sheet_amt > 0)
|
||||
if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
|
||||
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
|
||||
var/count = 0
|
||||
while(sheet_amt > MAX_STACK_SIZE)
|
||||
new M.sheet_type(get_turf(parent), MAX_STACK_SIZE)
|
||||
count += MAX_STACK_SIZE
|
||||
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
|
||||
sheet_amt -= MAX_STACK_SIZE
|
||||
if(round((sheet_amt * MINERAL_MATERIAL_AMOUNT) / MINERAL_MATERIAL_AMOUNT))
|
||||
var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(parent), sheet_amt)
|
||||
if(target)
|
||||
s.forceMove(target)
|
||||
count += sheet_amt
|
||||
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
|
||||
return count
|
||||
return FALSE
|
||||
return 0
|
||||
if(sheet_amt <= 0)
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
target = get_turf(parent)
|
||||
if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
|
||||
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
|
||||
var/count = 0
|
||||
while(sheet_amt > MAX_STACK_SIZE)
|
||||
new M.sheet_type(target, MAX_STACK_SIZE)
|
||||
count += MAX_STACK_SIZE
|
||||
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
|
||||
sheet_amt -= MAX_STACK_SIZE
|
||||
if(sheet_amt >= 1)
|
||||
new M.sheet_type(target, sheet_amt)
|
||||
count += sheet_amt
|
||||
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
|
||||
return count
|
||||
|
||||
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null)
|
||||
if(materials[id])
|
||||
@@ -386,4 +398,4 @@
|
||||
/datum/material/plastic
|
||||
name = "Plastic"
|
||||
id = MAT_PLASTIC
|
||||
sheet_type = /obj/item/stack/sheet/plastic
|
||||
sheet_type = /obj/item/stack/sheet/plastic
|
||||
@@ -324,6 +324,7 @@ var/record_id_num = 1001
|
||||
S.fields["notes"] = H.sec_record
|
||||
else
|
||||
S.fields["notes"] = "No notes."
|
||||
LAZYINITLIST(S.fields["comments"])
|
||||
security += S
|
||||
|
||||
//Locked Record
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
var/list/active_timers //for SStimer
|
||||
var/list/datum_components //for /datum/components
|
||||
var/list/comp_lookup
|
||||
var/list/signal_procs
|
||||
var/signal_enabled = FALSE
|
||||
var/var_edited = FALSE //Warranty void if seal is broken
|
||||
|
||||
var/tmp/unique_datum_id = null
|
||||
@@ -26,6 +28,9 @@
|
||||
continue
|
||||
qdel(timer)
|
||||
|
||||
//BEGIN: ECS SHIT
|
||||
signal_enabled = FALSE
|
||||
|
||||
var/list/dc = datum_components
|
||||
if(dc)
|
||||
var/all_components = dc[/datum/component]
|
||||
@@ -51,6 +56,10 @@
|
||||
comp.UnregisterSignal(src, sig)
|
||||
comp_lookup = lookup = null
|
||||
|
||||
for(var/target in signal_procs)
|
||||
UnregisterSignal(target, signal_procs[target])
|
||||
//END: ECS SHIT
|
||||
|
||||
return QDEL_HINT_QUEUE
|
||||
|
||||
|
||||
|
||||
@@ -167,3 +167,11 @@
|
||||
suffix = "way_home.dmm"
|
||||
name = "Salvation"
|
||||
description = "In the darkest times, we will find our way home."
|
||||
|
||||
/datum/map_template/ruin/space/oldstation
|
||||
id = "oldstation"
|
||||
suffix = "oldstation.dmm"
|
||||
name = "Ancient Space Station"
|
||||
description = "The crew of a space station awaken one hundred years after a crisis. Awaking to a derelict space station on the verge of collapse, and a hostile force of invading \
|
||||
hivebots. Can the surviving crew overcome the odds and survive and rebuild, or will the cold embrace of the stars become their new home?"
|
||||
cost = 2
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/datum/spawners_menu
|
||||
var/mob/dead/observer/owner
|
||||
|
||||
/datum/spawners_menu/New(mob/dead/observer/new_owner)
|
||||
if(!istype(new_owner))
|
||||
qdel(src)
|
||||
owner = new_owner
|
||||
|
||||
/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = FALSE, datum/nanoui/master_ui = null)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "spawners_menu.tmpl", "Spawners Menu", 700, 600, master_ui)
|
||||
ui.open()
|
||||
|
||||
/datum/spawners_menu/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["spawners"] = list()
|
||||
for(var/spawner in GLOB.mob_spawners)
|
||||
var/list/this = list()
|
||||
this["name"] = spawner
|
||||
this["desc"] = ""
|
||||
this["uids"] = list()
|
||||
for(var/spawner_obj in GLOB.mob_spawners[spawner])
|
||||
this["uids"] += "\ref[spawner_obj]"
|
||||
if(!this["desc"])
|
||||
if(istype(spawner_obj, /obj/effect/mob_spawn))
|
||||
var/obj/effect/mob_spawn/MS = spawner_obj
|
||||
this["desc"] = MS.flavour_text
|
||||
else
|
||||
var/obj/O = spawner_obj
|
||||
this["desc"] = O.desc
|
||||
this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner])
|
||||
data["spawners"] += list(this)
|
||||
|
||||
return data
|
||||
|
||||
/datum/spawners_menu/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
var/spawners = replacetext(href_list["uid"], ",", ";")
|
||||
var/list/possible_spawners = params2list(spawners)
|
||||
var/obj/effect/mob_spawn/MS = locate(pick(possible_spawners))
|
||||
if(!MS || !istype(MS))
|
||||
log_runtime(EXCEPTION("A ghost tried to interact with an invalid spawner, or the spawner didn't exist."))
|
||||
return
|
||||
switch(href_list["action"])
|
||||
if("jump")
|
||||
owner.forceMove(get_turf(MS))
|
||||
. = TRUE
|
||||
if("spawn")
|
||||
MS.attack_ghost(owner)
|
||||
. = TRUE
|
||||
@@ -992,6 +992,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
item = /obj/item/card/emag
|
||||
cost = 6
|
||||
|
||||
/datum/uplink_item/device_tools/access_tuner
|
||||
name = "Access Tuner"
|
||||
desc = "The access tuner is a small device that can interface with airlocks from range. It takes a few seconds to connect and can change the bolt state, open the door, or toggle emergency access."
|
||||
reference = "HACK"
|
||||
item = /obj/item/door_remote/omni/access_tuner
|
||||
cost = 6
|
||||
|
||||
/datum/uplink_item/device_tools/toolbox
|
||||
name = "Fully Loaded Toolbox"
|
||||
desc = "The syndicate toolbox is a suspicious black and red. Aside from tools, it comes with insulated gloves and a multitool."
|
||||
|
||||
Reference in New Issue
Block a user