diff --git a/code/controllers/Processes/alarm.dm b/code/controllers/Processes/alarm.dm index ed948276f8..47f311efea 100644 --- a/code/controllers/Processes/alarm.dm +++ b/code/controllers/Processes/alarm.dm @@ -20,7 +20,8 @@ var/datum/controller/process/alarm/alarm_manager alarm_manager = src /datum/controller/process/alarm/doWork() - for(var/datum/alarm_handler/AH in all_handlers) + for(last_object in all_handlers) + var/datum/alarm_handler/AH = last_object AH.process() SCHECK diff --git a/code/controllers/Processes/chemistry.dm b/code/controllers/Processes/chemistry.dm index 282dd61c9f..084de83e28 100644 --- a/code/controllers/Processes/chemistry.dm +++ b/code/controllers/Processes/chemistry.dm @@ -18,7 +18,8 @@ var/datum/controller/process/chemistry/chemistryProcess stat(null, "[active_holders.len] reagent holder\s") /datum/controller/process/chemistry/doWork() - for(var/datum/reagents/holder in active_holders) + for(last_object in active_holders) + var/datum/reagents/holder = last_object if(!holder.process_reactions()) active_holders -= holder SCHECK diff --git a/code/controllers/Processes/garbage.dm b/code/controllers/Processes/garbage.dm index ce6842ac3b..2d56dde1a2 100644 --- a/code/controllers/Processes/garbage.dm +++ b/code/controllers/Processes/garbage.dm @@ -1,7 +1,7 @@ // The time a datum was destroyed by the GC, or null if it hasn't been /datum/var/gcDestroyed -#define GC_COLLECTIONS_PER_RUN 150 +#define GC_COLLECTIONS_PER_RUN 300 #define GC_COLLECTION_TIMEOUT (30 SECONDS) #define GC_FORCE_DEL_PER_RUN 30 @@ -23,7 +23,7 @@ var/list/delayed_garbage = list() /datum/controller/process/garbage_collector/setup() name = "garbage" - schedule_interval = 10 SECONDS + schedule_interval = 5 SECONDS start_delay = 3 if(!garbage_collector) @@ -47,30 +47,6 @@ world/loop_checks = 0 var/checkRemain = GC_COLLECTIONS_PER_RUN var/remaining_force_dels = GC_FORCE_DEL_PER_RUN - #ifdef GC_FINDREF - var/list/searching = list() - for(var/refID in destroyed) // Reference search - before all deletions and for all at once - var/GCd_at_time = destroyed[refID] - if(GCd_at_time > time_to_kill) - break - var/atom/A = locate(refID) - if(A && A.gcDestroyed == GCd_at_time) - searching += A - if(searching.len >= checkRemain) - break - - for(var/atom/A in searching) - testing("GC: Searching references for [A] | [A.type]") - if(A.loc != null) - testing("GC: [A] | [A.type] is located in [A.loc] instead of null") - if(A.contents.len) - testing("GC: [A] | [A.type] has contents: [list2text(A.contents)]") - if(searching.len) - for(var/atom/D in world) - LookForRefs(D, searching) - for(var/datum/D) - LookForRefs(D, searching) - #endif while(destroyed.len && --checkRemain >= 0) if(remaining_force_dels <= 0) diff --git a/code/controllers/Processes/inactivity.dm b/code/controllers/Processes/inactivity.dm index f12c0d4e3c..26cc136ccc 100644 --- a/code/controllers/Processes/inactivity.dm +++ b/code/controllers/Processes/inactivity.dm @@ -4,7 +4,8 @@ /datum/controller/process/inactivity/doWork() if(config.kick_inactive) - for(var/client/C in clients) + for(last_object in clients) + var/client/C = last_object if(!C.holder && C.is_afk(config.kick_inactive MINUTES)) if(!istype(C.mob, /mob/observer/dead)) log_access("AFK: [key_name(C)]") diff --git a/code/controllers/Processes/machinery.dm b/code/controllers/Processes/machinery.dm index d046974489..405615dc1f 100644 --- a/code/controllers/Processes/machinery.dm +++ b/code/controllers/Processes/machinery.dm @@ -18,7 +18,8 @@ machines = dd_sortedObjectList(machines) /datum/controller/process/machinery/proc/internal_process_machinery() - for(var/obj/machinery/M in machines) + for(last_object in machines) + var/obj/machinery/M = last_object if(M && !M.gcDestroyed) if(M.process() == PROCESS_KILL) //M.inMachineList = 0 We don't use this debugging function @@ -31,7 +32,8 @@ SCHECK /datum/controller/process/machinery/proc/internal_process_power() - for(var/datum/powernet/powerNetwork in powernets) + for(last_object in powernets) + var/datum/powernet/powerNetwork = last_object if(istype(powerNetwork) && isnull(powerNetwork.gcDestroyed)) powerNetwork.reset() SCHECK @@ -41,13 +43,15 @@ /datum/controller/process/machinery/proc/internal_process_power_drain() // Currently only used by powersinks. These items get priority processed before machinery - for(var/obj/item/I in processing_power_items) + for(last_object in processing_power_items) + var/obj/item/I = last_object if(!I.pwr_drain()) // 0 = Process Kill, remove from processing list. processing_power_items.Remove(I) SCHECK /datum/controller/process/machinery/proc/internal_process_pipenets() - for(var/datum/pipe_network/pipeNetwork in pipe_networks) + for(last_object in pipe_networks) + var/datum/pipe_network/pipeNetwork = last_object if(istype(pipeNetwork) && isnull(pipeNetwork.gcDestroyed)) pipeNetwork.process() SCHECK diff --git a/code/controllers/Processes/scheduler.dm b/code/controllers/Processes/scheduler.dm new file mode 100644 index 0000000000..fdbe55faed --- /dev/null +++ b/code/controllers/Processes/scheduler.dm @@ -0,0 +1,133 @@ +/var/datum/controller/process/scheduler/scheduler + +/************ +* Scheduler * +************/ +/datum/controller/process/scheduler + var/list/scheduled_tasks + +/datum/controller/process/scheduler/setup() + name = "scheduler" + schedule_interval = 3 SECONDS + scheduled_tasks = list() + scheduler = src + +/datum/controller/process/scheduler/doWork() + for(last_object in scheduled_tasks) + var/datum/scheduled_task/scheduled_task = last_object + try + if(world.time > scheduled_task.trigger_time) + unschedule(scheduled_task) + scheduled_task.pre_process() + scheduled_task.process() + scheduled_task.post_process() + catch(var/exception/e) + catchException(e, last_object) + SCHECK + +/datum/controller/process/scheduler/statProcess() + ..() + stat(null, "[scheduled_tasks.len] task\s") + +/datum/controller/process/scheduler/proc/schedule(var/datum/scheduled_task/st) + scheduled_tasks += st + destroyed_event.register(st, src, /datum/controller/process/scheduler/proc/unschedule) + +/datum/controller/process/scheduler/proc/unschedule(var/datum/scheduled_task/st) + if(st in scheduled_tasks) + scheduled_tasks -= st + destroyed_event.unregister(st, src) + +/********** +* Helpers * +**********/ +/proc/schedule_task_in(var/in_time, var/procedure, var/list/arguments = list()) + return schedule_task(world.time + in_time, procedure, arguments) + +/proc/schedule_task_with_source_in(var/in_time, var/source, var/procedure, var/list/arguments = list()) + return schedule_task_with_source(world.time + in_time, source, procedure, arguments) + +/proc/schedule_task(var/trigger_time, var/procedure, var/list/arguments) + var/datum/scheduled_task/st = new/datum/scheduled_task(trigger_time, procedure, arguments, /proc/destroy_scheduled_task, list()) + scheduler.schedule(st) + return st + +/proc/schedule_task_with_source(var/trigger_time, var/source, var/procedure, var/list/arguments) + var/datum/scheduled_task/st = new/datum/scheduled_task/source(trigger_time, source, procedure, arguments, /proc/destroy_scheduled_task, list()) + scheduler.schedule(st) + return st + +/proc/schedule_repeating_task(var/trigger_time, var/repeat_interval, var/procedure, var/list/arguments) + var/datum/scheduled_task/st = new/datum/scheduled_task(trigger_time, procedure, arguments, /proc/repeat_scheduled_task, list(repeat_interval)) + scheduler.schedule(st) + return st + +/proc/schedule_repeating_task_with_source(var/trigger_time, var/repeat_interval, var/source, var/procedure, var/list/arguments) + var/datum/scheduled_task/st = new/datum/scheduled_task/source(trigger_time, source, procedure, arguments, /proc/repeat_scheduled_task, list(repeat_interval)) + scheduler.schedule(st) + return st + +/************* +* Task Datum * +*************/ +/datum/scheduled_task + var/trigger_time + var/procedure + var/list/arguments + var/task_after_process + var/list/task_after_process_args + +/datum/scheduled_task/New(var/trigger_time, var/procedure, var/list/arguments, var/proc/task_after_process, var/list/task_after_process_args) + ..() + src.trigger_time = trigger_time + src.procedure = procedure + src.arguments = arguments ? arguments : list() + src.task_after_process = task_after_process ? task_after_process : /proc/destroy_scheduled_task + src.task_after_process_args = istype(task_after_process_args) ? task_after_process_args : list() + task_after_process_args += src + +/datum/scheduled_task/Destroy() + procedure = null + arguments.Cut() + task_after_process = null + task_after_process_args.Cut() + return ..() + +/datum/scheduled_task/proc/pre_process() + task_triggered_event.raise_event(list(src)) + +/datum/scheduled_task/proc/process() + if(procedure) + call(procedure)(arglist(arguments)) + +/datum/scheduled_task/proc/post_process() + call(task_after_process)(arglist(task_after_process_args)) + +// Resets the trigger time, has no effect if the task has already triggered +/datum/scheduled_task/proc/trigger_task_in(var/trigger_in) + src.trigger_time = world.time + trigger_in + +/datum/scheduled_task/source + var/datum/source + +/datum/scheduled_task/source/New(var/trigger_time, var/datum/source, var/procedure, var/list/arguments, var/proc/task_after_process, var/list/task_after_process_args) + src.source = source + destroyed_event.register(src.source, src, /datum/scheduled_task/source/proc/source_destroyed) + ..(trigger_time, procedure, arguments, task_after_process, task_after_process_args) + +/datum/scheduled_task/source/Destroy() + source = null + return ..() + +/datum/scheduled_task/source/process() + call(source, procedure)(arglist(arguments)) + +/datum/scheduled_task/source/proc/source_destroyed() + qdel(src) + +/proc/destroy_scheduled_task(var/datum/scheduled_task/st) + qdel(st) + +/proc/repeat_scheduled_task(var/trigger_delay, var/datum/scheduled_task/st) + st.trigger_time = world.time + trigger_delay + scheduler.schedule(st) \ No newline at end of file diff --git a/code/controllers/Processes/turf.dm b/code/controllers/Processes/turf.dm index 3396774497..bfced8f93b 100644 --- a/code/controllers/Processes/turf.dm +++ b/code/controllers/Processes/turf.dm @@ -5,7 +5,8 @@ var/global/list/turf/processing_turfs = list() schedule_interval = 20 // every 2 seconds /datum/controller/process/turf/doWork() - for(var/turf/T in processing_turfs) + for(last_object in processing_turfs) + var/turf/T = last_object if(T.process() == PROCESS_KILL) processing_turfs.Remove(T) SCHECK diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 5263e1af79..682b0fb3d0 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -47,7 +47,8 @@ datum/controller/game_controller/proc/setup_objects() admin_notice("Initializing objects", R_DEBUG) sleep(-1) for(var/atom/movable/object in world) - object.initialize() + if(isnull(object.gcDestroyed)) + object.initialize() admin_notice("Initializing areas", R_DEBUG) sleep(-1) diff --git a/code/controllers/observer_listener/datum/observer.dm b/code/controllers/observer_listener/datum/observer.dm deleted file mode 100644 index 61f6fbf180..0000000000 --- a/code/controllers/observer_listener/datum/observer.dm +++ /dev/null @@ -1,28 +0,0 @@ -/* -#define OBSERVER_EVENT_DESTROY "OnDestroy" - -/datum - var/list/observer_events - -/datum/Destroy() - for(var/list/listeners in observer_events) - listeners.Cut() - - return ..() - -/datum/proc/register(var/event, var/procOwner, var/proc_call) - var/list/listeners = get_listener_list_from_event(event) - listeners[procOwner] = proc_call - -/datum/proc/unregister(var/event, var/procOwner) - var/list/listeners = get_listener_list_from_event(event) - listeners -= procOwner - -/datum/proc/get_listener_list_from_event(var/observer_event) - if(!observer_events) observer_events = list() - var/list/listeners = observer_events[observer_event] - if(!listeners) - listeners = list() - observer_events[observer_event] = listeners - return listeners -*/ diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index 34082d12ba..aef0fd0ac2 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -28,7 +28,6 @@ var/global/datum/getrev/revdata = new() world.log << branch world.log << date world.log << revision - return client/verb/showrevinfo() set category = "OOC" @@ -43,4 +42,3 @@ client/verb/showrevinfo() src << revdata.revision else src << "Revision unknown" - return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 824b52a2fe..11d622b255 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -71,6 +71,7 @@ /datum/mind/New(var/key) src.key = key + ..() /datum/mind/proc/transfer_to(mob/living/new_character) if(!istype(new_character)) diff --git a/code/datums/observation/_debug.dm b/code/datums/observation/_debug.dm new file mode 100644 index 0000000000..2f882929cf --- /dev/null +++ b/code/datums/observation/_debug.dm @@ -0,0 +1,11 @@ +/**************** +* Debug Support * +****************/ +var/datum/all_observable_events/all_observable_events = new() + +/datum/all_observable_events + var/list/events + +/datum/all_observable_events/New() + events = list() + ..() diff --git a/code/datums/observation/_defines.dm b/code/datums/observation/_defines.dm new file mode 100644 index 0000000000..902d655870 --- /dev/null +++ b/code/datums/observation/_defines.dm @@ -0,0 +1 @@ +#define CANCEL_MOVE_EVENT -55 diff --git a/code/datums/observation/destroyed.dm b/code/datums/observation/destroyed.dm new file mode 100644 index 0000000000..6a65300a25 --- /dev/null +++ b/code/datums/observation/destroyed.dm @@ -0,0 +1,15 @@ +// Observer Pattern Implementation: Destroyed +// Registration type: /datum +// +// Raised when: A /datum instance is destroyed. +// +// Arguments that the called proc should expect: +// /datum/destroyed_instance: The instance that was destroyed. +var/decl/observ/destroyed/destroyed_event = new() + +/decl/observ/destroyed + name = "Destroyed" + +/datum/Destroy() + destroyed_event.raise_event(src) + . = ..() diff --git a/code/datums/observation/dir_set.dm b/code/datums/observation/dir_set.dm new file mode 100644 index 0000000000..1f4c8e251e --- /dev/null +++ b/code/datums/observation/dir_set.dm @@ -0,0 +1,35 @@ +// 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. + +var/decl/observ/dir_set/dir_set_event = 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 && dir_set_event.has_listeners(am)) + dir_set_event.register(src, am, /atom/proc/recursive_dir_set) + +/atom/movable/Exited(var/atom/movable/am, atom/old_loc) + . = ..() + dir_set_event.unregister(src, am, /atom/proc/recursive_dir_set) diff --git a/code/datums/observation/equipped.dm b/code/datums/observation/equipped.dm new file mode 100644 index 0000000000..de07a74355 --- /dev/null +++ b/code/datums/observation/equipped.dm @@ -0,0 +1,38 @@ +// Observer Pattern Implementation: Equipped +// Registration type: /mob +// +// Raised when: A mob equips an item. +// +// Arguments that the called proc should expect: +// /mob/equipper: The mob that equipped the item. +// /obj/item/item: The equipped item. +// slot: The slot equipped to. +var/decl/observ/mob_equipped/mob_equipped_event = new() + +/decl/observ/mob_equipped + name = "Mob Equipped" + expected_type = /mob + +// Observer Pattern Implementation: Equipped +// Registration type: /obj/item +// +// Raised when: A mob equips an item. +// +// Arguments that the called proc should expect: +// /obj/item/item: The equipped item. +// /mob/equipper: The mob that equipped the item. +// slot: The slot equipped to. +var/decl/observ/item_equipped/item_equipped_event = new() + +/decl/observ/item_equipped + name = "Item Equipped" + expected_type = /obj/item + +/******************** +* Equipped Handling * +********************/ + +/obj/item/equipped(var/mob/user, var/slot) + . = ..() + mob_equipped_event.raise_event(user, src, slot) + item_equipped_event.raise_event(src, user, slot) diff --git a/code/datums/observation/helpers.dm b/code/datums/observation/helpers.dm new file mode 100644 index 0000000000..79ee8eb08d --- /dev/null +++ b/code/datums/observation/helpers.dm @@ -0,0 +1,18 @@ +/atom/movable/proc/recursive_move(var/atom/movable/am, var/old_loc, var/new_loc) + moved_event.raise_event(src, 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) + forceMove(T) + +/atom/proc/recursive_dir_set(var/atom/a, var/old_dir, var/new_dir) + set_dir(new_dir) + +/proc/register_all_movement(var/event_source, var/listener) + moved_event.register(event_source, listener, /atom/movable/proc/recursive_move) + dir_set_event.register(event_source, listener, /atom/proc/recursive_dir_set) + +/proc/unregister_all_movement(var/event_source, var/listener) + moved_event.unregister(event_source, listener, /atom/movable/proc/recursive_move) + dir_set_event.unregister(event_source, listener, /atom/proc/recursive_dir_set) diff --git a/code/datums/observation/logged_in.dm b/code/datums/observation/logged_in.dm new file mode 100644 index 0000000000..311ff8acb6 --- /dev/null +++ b/code/datums/observation/logged_in.dm @@ -0,0 +1,21 @@ +// 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 + +var/decl/observ/logged_in/logged_in_event = new() + +/decl/observ/logged_in + name = "Logged In" + expected_type = /mob + +/***************** +* Login Handling * +*****************/ + +/mob/Login() + ..() + logged_in_event.raise_event(src) diff --git a/code/datums/observation/moved.dm b/code/datums/observation/moved.dm new file mode 100644 index 0000000000..86a6b793ac --- /dev/null +++ b/code/datums/observation/moved.dm @@ -0,0 +1,52 @@ +// Observer Pattern Implementation: Moved +// Registration type: /atom/movable +// +// Raised when: An /atom/movable instance has moved using Move() or forceMove(). +// +// Arguments that the called proc should expect: +// /atom/movable/moving_instance: The instance that moved +// /atom/old_loc: The loc before the move. +// /atom/new_loc: The loc after the move. + +var/decl/observ/moved/moved_event = new() + +/decl/observ/moved + name = "Moved" + expected_type = /atom/movable + +/decl/observ/moved/register(var/atom/movable/mover, var/datum/listener, var/proc_call) + . = ..() + + // Listen to the parent if possible. + if(. && istype(mover.loc, expected_type)) + register(mover.loc, mover, /atom/movable/proc/recursive_move) + +/******************** +* Movement Handling * +********************/ + +/atom/Entered(var/atom/movable/am, var/atom/old_loc) + . = ..() + moved_event.raise_event(am, old_loc, am.loc) + +/atom/movable/Entered(var/atom/movable/am, atom/old_loc) + . = ..() + if(moved_event.has_listeners(am)) + moved_event.register(src, am, /atom/movable/proc/recursive_move) + +/atom/movable/Exited(var/atom/movable/am, atom/old_loc) + . = ..() + moved_event.unregister(src, am, /atom/movable/proc/recursive_move) + +// 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) + moved_event.raise_event(src, old_loc, null) + +/atom/movable/forceMove(atom/destination) + var/old_loc = loc + . = ..() + if(. && !loc) + moved_event.raise_event(src, old_loc, null) diff --git a/code/datums/observation/observation.dm b/code/datums/observation/observation.dm new file mode 100644 index 0000000000..32a96871e6 --- /dev/null +++ b/code/datums/observation/observation.dm @@ -0,0 +1,238 @@ +// +// 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() + 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 diff --git a/code/datums/observation/task_triggered.dm b/code/datums/observation/task_triggered.dm new file mode 100644 index 0000000000..0c04ef2ead --- /dev/null +++ b/code/datums/observation/task_triggered.dm @@ -0,0 +1,13 @@ +// +// Observer Pattern Implementation: Scheduled task triggered +// Registration type: /datum/scheduled_task +// +// Raised when: When a scheduled task reaches its trigger time. +// +// Arguments that the called proc should expect: +// /datum/scheduled_task/task: The task that reached its trigger time. +var/decl/observ/task_triggered/task_triggered_event = new() + +/decl/observ/task_triggered + name = "Task Triggered" + expected_type = /datum/scheduled_task diff --git a/code/datums/observation/unequipped.dm b/code/datums/observation/unequipped.dm new file mode 100644 index 0000000000..3287c0a3b5 --- /dev/null +++ b/code/datums/observation/unequipped.dm @@ -0,0 +1,38 @@ +// Observer Pattern Implementation: Unequipped (dropped) +// Registration type: /mob +// +// Raised when: A mob unequips/drops an item. +// +// Arguments that the called proc should expect: +// /mob/equipped: The mob that unequipped/dropped the item. +// /obj/item/item: The unequipped item. + +var/decl/observ/mob_unequipped/mob_unequipped_event = new() + +/decl/observ/mob_unequipped + name = "Mob Unequipped" + expected_type = /mob + +// Observer Pattern Implementation: Unequipped (dropped) +// Registration type: /obj/item +// +// Raised when: A mob unequips/drops an item. +// +// Arguments that the called proc should expect: +// /obj/item/item: The unequipped item. +// /mob/equipped: The mob that unequipped/dropped the item. + +var/decl/observ/item_unequipped/item_unequipped_event = new() + +/decl/observ/item_unequipped + name = "Item Unequipped" + expected_type = /obj/item + +/********************** +* Unequipped Handling * +**********************/ + +/obj/item/dropped(var/mob/user) + ..() + mob_unequipped_event.raise_event(user, src) + item_unequipped_event.raise_event(src, user) diff --git a/code/datums/observation/~cleanup.dm b/code/datums/observation/~cleanup.dm new file mode 100644 index 0000000000..eb6ccceef8 --- /dev/null +++ b/code/datums/observation/~cleanup.dm @@ -0,0 +1,70 @@ +var/list/global_listen_count = list() +var/list/event_sources_count = list() +var/list/event_listen_count = list() + +/decl/observ/destroyed/raise_event() + . = ..() + if(!.) + return + var/source = args[1] + + if(global_listen_count[source]) + cleanup_global_listener(source, global_listen_count[source]) + if(event_sources_count[source]) + cleanup_source_listeners(source, event_sources_count[source]) + if(event_listen_count[source]) + cleanup_event_listener(source, event_listen_count[source]) + + +/decl/observ/register(var/datum/event_source, var/datum/listener, var/proc_call) + . = ..() + if(.) + event_sources_count[event_source] += 1 + event_listen_count[listener] += 1 + +/decl/observ/unregister(var/datum/event_source, var/datum/listener, var/proc_call) + . = ..() + if(.) + event_sources_count[event_source] -= 1 + event_listen_count[listener] -= 1 + +/decl/observ/register_global(var/datum/listener, var/proc_call) + . = ..() + if(.) + global_listen_count[listener] += 1 + +/decl/observ/unregister_global(var/datum/listener, var/proc_call) + . = ..() + if(.) + global_listen_count[listener] -= 1 + +/decl/observ/destroyed/proc/cleanup_global_listener(listener, listen_count) + global_listen_count -= listener + for(var/entry in all_observable_events.events) + var/decl/observ/event = entry + if(event.unregister_global(listener)) + log_debug("[event] - [listener] was deleted while still registered to global events.") + if(!(--listen_count)) + return + +/decl/observ/destroyed/proc/cleanup_source_listeners(event_source, source_listener_count) + event_sources_count -= event_source + for(var/entry in all_observable_events.events) + var/decl/observ/event = entry + 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].") + if(!(--source_listener_count)) + return + +/decl/observ/destroyed/proc/cleanup_event_listener(listener, listener_count) + event_listen_count -= listener + for(var/entry in all_observable_events.events) + var/decl/observ/event = entry + 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].") + if(!(--listener_count)) + return diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 39c91afbed..77779bafcf 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -44,6 +44,7 @@ /obj/item/weapon/soap/deluxe/New() desc = "A deluxe Waffle Co. brand bar of soap. Smells of [pick("lavender", "vanilla", "strawberry", "chocolate" ,"space")]." + ..() /obj/item/weapon/soap/syndie desc = "An untrustworthy bar of soap. Smells of fear." @@ -398,9 +399,11 @@ icon = 'icons/obj/stock_parts.dmi' w_class = 2.0 var/rating = 1 - New() - src.pixel_x = rand(-5.0, 5) - src.pixel_y = rand(-5.0, 5) + +/obj/item/weapon/stock_parts/New() + src.pixel_x = rand(-5.0, 5) + src.pixel_y = rand(-5.0, 5) + ..() //Rank 1 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 7639084918..e45be4bb6a 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -46,7 +46,8 @@ pulledby = null /atom/movable/proc/initialize() - return + if(!isnull(gcDestroyed)) + crash_with("GC: -- [type] had initialize() called after qdel() --") /atom/movable/Bump(var/atom/A, yes) if(src.throwing) @@ -211,7 +212,7 @@ /atom/movable/overlay/New() for(var/x in src.verbs) src.verbs -= x - return + ..() /atom/movable/overlay/attackby(a, b) if (src.master) diff --git a/code/game/gamemodes/events/dust.dm b/code/game/gamemodes/events/dust.dm index 492b932e46..bb8e34364c 100644 --- a/code/game/gamemodes/events/dust.dm +++ b/code/game/gamemodes/events/dust.dm @@ -53,6 +53,7 @@ The "dust" will damage the hull of the station causin minor hull breaches. New() + ..() var/startx = 0 var/starty = 0 var/endy = 0 diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 6b373953b1..f5dd1efe5f 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -12,6 +12,7 @@ datum/objective all_objectives |= src if(text) explanation_text = text + ..() Destroy() all_objectives -= src diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index eed2d4d031..25b38e3b20 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -424,6 +424,7 @@ read_only = 1 New() + ..() initializeDisk() buf.types=DNA2_BUF_SE var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4) diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index f4b06aff1c..eef148a830 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -14,10 +14,10 @@ var/global/list/minor_air_alarms = list() /obj/machinery/computer/atmos_alert/New() ..() - atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/update_icon) + atmosphere_alarm.register_alarm(src, /obj/machinery/computer/station_alert/update_icon) /obj/machinery/computer/atmos_alert/Destroy() - atmosphere_alarm.unregister(src) + atmosphere_alarm.unregister_alarm(src) ..() /obj/machinery/computer/atmos_alert/attack_hand(mob/user) diff --git a/code/game/machinery/computer/camera_circuit.dm b/code/game/machinery/computer/camera_circuit.dm index 4680bb57d1..8db87c36ae 100644 --- a/code/game/machinery/computer/camera_circuit.dm +++ b/code/game/machinery/computer/camera_circuit.dm @@ -17,6 +17,7 @@ possibleNets["Cargo"] = access_qm possibleNets["Research"] = access_rd possibleNets["Medbay"] = access_cmo + ..() proc/updateBuildPath() build_path = null diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 22c97a955a..d1c66b500d 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -17,13 +17,13 @@ monitor_type = /datum/nano_module/alarm_monitor/all circuit = /obj/item/weapon/circuitboard/stationalert_all -/obj/machinery/computer/station_alert/New() - ..() +/obj/machinery/computer/station_alert/initialize() alarm_monitor = new monitor_type(src) - alarm_monitor.register(src, /obj/machinery/computer/station_alert/update_icon) + alarm_monitor.register_alarm(src, /obj/machinery/computer/station_alert/update_icon) + ..() /obj/machinery/computer/station_alert/Destroy() - alarm_monitor.unregister(src) + alarm_monitor.unregister_alarm(src) qdel(alarm_monitor) ..() @@ -46,7 +46,7 @@ /obj/machinery/computer/station_alert/update_icon() if(!(stat & (BROKEN|NOPOWER))) - var/list/alarms = alarm_monitor.major_alarms() + var/list/alarms = alarm_monitor ? alarm_monitor.major_alarms() : list() if(alarms.len) icon_screen = "alert:2" else diff --git a/code/game/machinery/computer3/file.dm b/code/game/machinery/computer3/file.dm index b1fbe0ddbe..be4285b3e1 100644 --- a/code/game/machinery/computer3/file.dm +++ b/code/game/machinery/computer3/file.dm @@ -100,6 +100,7 @@ if(content) if(file_increment > 1) volume = round(file_increment * length(content)) + ..() /* A generic file that contains text diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 3681d1e798..30a9b8548b 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -136,7 +136,7 @@ Class Procs: if(contents) // The same for contents. for(var/atom/A in contents) qdel(A) - ..() + return ..() /obj/machinery/process()//If you dont use process or power why are you here if(!(use_power || idle_power_usage || active_power_usage)) diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 01fc592690..8b349959b5 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -107,9 +107,6 @@ steam.start() -- spawns the effect var/turf/T = src.loc if (istype(T, /turf)) T.hotspot_expose(1000,100) - spawn (20) - qdel(src) - return /obj/effect/effect/sparks/Destroy() var/turf/T = src.loc @@ -185,7 +182,6 @@ steam.start() -- spawns the effect ..() spawn (time_to_live) qdel(src) - return /obj/effect/effect/smoke/Crossed(mob/living/carbon/M as mob ) ..() diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 15cb670a8c..d08d45d5ce 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -5,6 +5,7 @@ anchored = 1.0 unacidable = 1 simulated = 0 + var/delete_me = 0 /obj/effect/landmark/New() ..() @@ -14,33 +15,35 @@ switch(name) //some of these are probably obsolete if("monkey") monkeystart += loc - qdel(src) + delete_me = 1 return if("start") newplayer_start += loc - qdel(src) + delete_me = 1 + return if("JoinLate") latejoin += loc - qdel(src) + delete_me = 1 + return if("JoinLateGateway") latejoin_gateway += loc - qdel(src) + delete_me = 1 return if("JoinLateElevator") latejoin_elevator += loc - qdel(src) + delete_me = 1 return if("JoinLateCryo") latejoin_cryo += loc - qdel(src) + delete_me = 1 return if("JoinLateCyborg") latejoin_cyborg += loc - qdel(src) + delete_me = 1 return if("prisonwarp") prisonwarp += loc - qdel(src) + delete_me = 1 return if("Holding Facility") holdingfacility += loc @@ -54,28 +57,36 @@ tdomeobserve += loc if("prisonsecuritywarp") prisonsecuritywarp += loc - qdel(src) + delete_me = 1 return if("blobstart") blobstart += loc - qdel(src) + delete_me = 1 return if("xeno_spawn") xeno_spawn += loc - qdel(src) + delete_me = 1 return if("endgame_exit") endgame_safespawns += loc - qdel(src) + delete_me = 1 return if("bluespacerift") endgame_exits += loc - qdel(src) + delete_me = 1 return landmarks_list += src return 1 +/obj/effect/landmark/proc/delete() + delete_me = 1 + +/obj/effect/landmark/initialize() + ..() + if(delete_me) + qdel(src) + /obj/effect/landmark/Destroy() landmarks_list -= src return ..() @@ -99,14 +110,14 @@ var/list/options = typesof(/obj/effect/landmark/costume) var/PICK= options[rand(1,options.len)] new PICK(src.loc) - qdel(src) + delete_me = 1 //SUBCLASSES. Spawn a bunch of items and disappear likewise /obj/effect/landmark/costume/chicken/New() new /obj/item/clothing/suit/chickensuit(src.loc) new /obj/item/clothing/head/chicken(src.loc) new /obj/item/weapon/reagent_containers/food/snacks/egg(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/gladiator/New() new /obj/item/clothing/under/gladiator(src.loc) @@ -118,32 +129,32 @@ new /obj/item/clothing/head/flatcap(src.loc) new /obj/item/clothing/suit/storage/toggle/labcoat/mad(src.loc) new /obj/item/clothing/glasses/gglasses(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/elpresidente/New() new /obj/item/clothing/under/gimmick/rank/captain/suit(src.loc) new /obj/item/clothing/head/flatcap(src.loc) new /obj/item/clothing/mask/smokable/cigarette/cigar/havana(src.loc) new /obj/item/clothing/shoes/jackboots(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/nyangirl/New() new /obj/item/clothing/under/schoolgirl(src.loc) new /obj/item/clothing/head/kitty(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/maid/New() new /obj/item/clothing/under/skirt(src.loc) var/CHOICE = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears ) new CHOICE(src.loc) new /obj/item/clothing/glasses/sunglasses/blindfold(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/butler/New() new /obj/item/clothing/suit/wcoat(src.loc) new /obj/item/clothing/under/suit_jacket(src.loc) new /obj/item/clothing/head/that(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/scratch/New() new /obj/item/clothing/gloves/white(src.loc) @@ -151,12 +162,12 @@ new /obj/item/clothing/under/scratch(src.loc) if (prob(30)) new /obj/item/clothing/head/cueball(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/highlander/New() new /obj/item/clothing/under/kilt(src.loc) new /obj/item/clothing/head/beret(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/prig/New() new /obj/item/clothing/suit/wcoat(src.loc) @@ -167,24 +178,24 @@ new /obj/item/weapon/cane(src.loc) new /obj/item/clothing/under/sl_suit(src.loc) new /obj/item/clothing/mask/fakemoustache(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/plaguedoctor/New() new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(src.loc) new /obj/item/clothing/head/plaguedoctorhat(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/nightowl/New() new /obj/item/clothing/under/owl(src.loc) new /obj/item/clothing/mask/gas/owl_mask(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/waiter/New() new /obj/item/clothing/under/waiter(src.loc) var/CHOICE= pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears) new CHOICE(src.loc) new /obj/item/clothing/suit/apron(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/pirate/New() new /obj/item/clothing/under/pirate(src.loc) @@ -192,18 +203,18 @@ var/CHOICE = pick( /obj/item/clothing/head/pirate , /obj/item/clothing/head/bandana ) new CHOICE(src.loc) new /obj/item/clothing/glasses/eyepatch(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/commie/New() new /obj/item/clothing/under/soviet(src.loc) new /obj/item/clothing/head/ushanka(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/imperium_monk/New() new /obj/item/clothing/suit/imperium_monk(src.loc) if (prob(25)) new /obj/item/clothing/mask/gas/cyborg(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/holiday_priest/New() new /obj/item/clothing/suit/holidaypriest(src.loc) @@ -212,26 +223,26 @@ /obj/effect/landmark/costume/marisawizard/fake/New() new /obj/item/clothing/head/wizard/marisa/fake(src.loc) new/obj/item/clothing/suit/wizrobe/marisa/fake(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/cutewitch/New() new /obj/item/clothing/under/sundress(src.loc) new /obj/item/clothing/head/witchwig(src.loc) new /obj/item/weapon/staff/broom(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/fakewizard/New() new /obj/item/clothing/suit/wizrobe/fake(src.loc) new /obj/item/clothing/head/wizard/fake(src.loc) new /obj/item/weapon/staff/(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/sexyclown/New() new /obj/item/clothing/mask/gas/sexyclown(src.loc) new /obj/item/clothing/under/sexyclown(src.loc) - qdel(src) + delete_me = 1 /obj/effect/landmark/costume/sexymime/New() new /obj/item/clothing/mask/gas/sexymime(src.loc) new /obj/item/clothing/under/sexymime(src.loc) - qdel(src) \ No newline at end of file + delete_me = 1 diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index 9a54fa1829..9b5dffdd37 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -12,9 +12,6 @@ var/syndie = 0 var/list/channels = list() - -/obj/item/device/encryptionkey/New() - /obj/item/device/encryptionkey/attackby(obj/item/weapon/W as obj, mob/user as mob) /obj/item/device/encryptionkey/syndicate diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index e2ec23be7c..2a85fbdfc9 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -37,6 +37,7 @@ /obj/item/weapon/extinguisher/New() create_reagents(max_water) reagents.add_reagent("water", max_water) + ..() /obj/item/weapon/extinguisher/examine(mob/user) if(..(user, 0)) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index b39fc0dd27..b7868cf7e0 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -79,7 +79,7 @@ if (prob(75)) src.pixel_y = rand(0, 16) - return + ..() /obj/item/weapon/screwdriver/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) if(!istype(M) || user.a_intent == "help") @@ -114,6 +114,7 @@ if(prob(50)) icon_state = "cutters-y" item_state = "cutters_yellow" + ..() /obj/item/weapon/wirecutters/attack(mob/living/carbon/C as mob, mob/user as mob) if(user.a_intent == I_HELP && (C.handcuffed) && (istype(C.handcuffed, /obj/item/weapon/handcuffs/cable))) @@ -162,12 +163,12 @@ reagents = R R.my_atom = src R.add_reagent("fuel", max_fuel) - return + ..() /obj/item/weapon/weldingtool/Destroy() if(welding) processing_objects -= src - ..() + return ..() /obj/item/weapon/weldingtool/examine(mob/user) if(..(user, 0)) diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm index 1127bf7510..fc6615fcf0 100644 --- a/code/game/objects/random/random.dm +++ b/code/game/objects/random/random.dm @@ -11,8 +11,10 @@ ..() if (!prob(spawn_nothing_percentage)) spawn_item() - qdel(src) +/obj/random/initialize() + ..() + qdel(src) // this function should return a specific item to spawn /obj/random/proc/item_to_spawn() diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index 31f8115b91..714be281b8 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -22,7 +22,7 @@ /obj/structure/closet/emcloset/New() ..() - switch (pickweight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 0, "delete" = 0))) + switch (pickweight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10))) if ("small") new /obj/item/weapon/tank/emergency_oxygen(src) new /obj/item/weapon/tank/emergency_oxygen(src) @@ -51,17 +51,6 @@ new /obj/item/clothing/suit/space/emergency(src) new /obj/item/clothing/head/helmet/space/emergency(src) new /obj/item/clothing/head/helmet/space/emergency(src) - if ("nothing") - // doot - - // teehee - Ah, tg coders... - if ("delete") - qdel(src) - - //If you want to re-add fire, just add "fire" = 15 to the pick list. - /*if ("fire") - new /obj/structure/closet/firecloset(src.loc) - qdel(src)*/ /obj/structure/closet/emcloset/legacy/New() ..() diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 2b8396c554..eff0de4b48 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -9,7 +9,7 @@ layer = 2.3 //under pipes // flags = CONDUCT -/obj/structure/lattice/New() //turf/simulated/floor/asteroid +/obj/structure/lattice/initialize() ..() if(!(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open) || istype(src.loc, /turf/simulated/mineral))) diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index 1624a4bbde..c76ca1802d 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -12,7 +12,7 @@ /obj/structure/mopbucket/New() create_reagents(100) - + ..() /obj/structure/mopbucket/examine(mob/user) if(..(user, 1)) diff --git a/code/modules/alarm/alarm_handler.dm b/code/modules/alarm/alarm_handler.dm index 47b7f7b571..afa45d7649 100644 --- a/code/modules/alarm/alarm_handler.dm +++ b/code/modules/alarm/alarm_handler.dm @@ -86,10 +86,10 @@ /turf/get_alarm_origin() return get_area(src) -/datum/alarm_handler/proc/register(var/object, var/procName) +/datum/alarm_handler/proc/register_alarm(var/object, var/procName) listeners[object] = procName -/datum/alarm_handler/proc/unregister(var/object) +/datum/alarm_handler/proc/unregister_alarm(var/object) listeners -= object /datum/alarm_handler/proc/notify_listeners(var/alarm, var/was_raised) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index d670e17ee3..5a13c7bb79 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -40,7 +40,7 @@ /mob/living/silicon/Destroy() silicon_mob_list -= src for(var/datum/alarm_handler/AH in alarm_manager.all_handlers) - AH.unregister(src) + AH.unregister_alarm(src) ..() /mob/living/silicon/proc/init_id() diff --git a/code/modules/mob/living/silicon/subystems.dm b/code/modules/mob/living/silicon/subystems.dm index fa1363203b..1dae0026aa 100644 --- a/code/modules/mob/living/silicon/subystems.dm +++ b/code/modules/mob/living/silicon/subystems.dm @@ -39,7 +39,7 @@ return for(var/datum/alarm_handler/AH in alarm_manager.all_handlers) - AH.register(src, /mob/living/silicon/proc/receive_alarm) + AH.register_alarm(src, /mob/living/silicon/proc/receive_alarm) queued_alarms[AH] = list() // Makes sure alarms remain listed in consistent order /******************** diff --git a/code/modules/nano/modules/alarm_monitor.dm b/code/modules/nano/modules/alarm_monitor.dm index 29ae55b04a..f3fca46d43 100644 --- a/code/modules/nano/modules/alarm_monitor.dm +++ b/code/modules/nano/modules/alarm_monitor.dm @@ -15,13 +15,13 @@ ..() alarm_handlers = list(camera_alarm, motion_alarm) -/datum/nano_module/alarm_monitor/proc/register(var/object, var/procName) +/datum/nano_module/alarm_monitor/proc/register_alarm(var/object, var/procName) for(var/datum/alarm_handler/AH in alarm_handlers) - AH.register(object, procName) + AH.register_alarm(object, procName) -/datum/nano_module/alarm_monitor/proc/unregister(var/object) +/datum/nano_module/alarm_monitor/proc/unregister_alarm(var/object) for(var/datum/alarm_handler/AH in alarm_handlers) - AH.unregister(object) + AH.unregister_alarm(object) /datum/nano_module/alarm_monitor/proc/all_alarms() var/list/all_alarms = new() diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index 219ebff141..3f5598f647 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -88,6 +88,7 @@ var/list/ammo_states = list() //values /obj/item/ammo_magazine/New() + ..() if(multiple_sprites) initialize_magazine_icondata(src) diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index b9560be615..af53188190 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -726,17 +726,13 @@ CIRCUITS BELOW /datum/design/circuit/AssembleDesignName() ..() if(build_path) - var/obj/item/weapon/circuitboard/C = new build_path() - if(C && istype(C)) - if(C.board_type == "machine") - name = "Machine circuit design ([item_name])" - qdel(C) - return - else if(C.board_type == "computer") - name = "Computer circuit design ([item_name])" - qdel(C) - return - name = "Circuit design ([item_name])" + var/obj/item/weapon/circuitboard/C = build_path + if(initial(C.board_type) == "machine") + name = "Machine circuit design ([item_name])" + else if(initial(C.board_type) == "computer") + name = "Computer circuit design ([item_name])" + else + name = "Circuit design ([item_name])" /datum/design/circuit/AssembleDesignDesc() if(!desc) diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm index 1c6a9ca06d..12b9e26b48 100644 --- a/code/modules/tables/tables.dm +++ b/code/modules/tables/tables.dm @@ -51,8 +51,9 @@ visible_message("\The [src] breaks down!") return break_to_parts() // if we break and form shards, return them to the caller to do !FUN! things with -/obj/structure/table/New() +/obj/structure/table/initialize() ..() + // One table per turf. for(var/obj/structure/table/T in loc) if(T != src) @@ -61,8 +62,6 @@ break_to_parts(full_return = 1) return -/obj/structure/table/initialize() - ..() // reset color/alpha, since they're set for nice map previews color = "#ffffff" alpha = 255 diff --git a/code/world.dm b/code/world.dm index 66edcd00d2..a6d27a8850 100644 --- a/code/world.dm +++ b/code/world.dm @@ -73,7 +73,7 @@ var/global/datum/global_init/init = new () // Set up roundstart seed list. plant_controller = new() - + // Set up roundstart gene masking xenobio_controller = new() diff --git a/polaris.dme b/polaris.dme index 7360a87a99..a83e390b23 100644 --- a/polaris.dme +++ b/polaris.dme @@ -131,7 +131,6 @@ #include "code\controllers\verbs.dm" #include "code\controllers\voting.dm" #include "code\controllers\observer_listener\atom\observer.dm" -#include "code\controllers\observer_listener\datum\observer.dm" #include "code\controllers\Processes\air.dm" #include "code\controllers\Processes\alarm.dm" #include "code\controllers\Processes\chemistry.dm" @@ -143,6 +142,7 @@ #include "code\controllers\Processes\mob.dm" #include "code\controllers\Processes\nanoui.dm" #include "code\controllers\Processes\obj.dm" +#include "code\controllers\Processes\scheduler.dm" #include "code\controllers\Processes\Shuttle.dm" #include "code\controllers\Processes\sun.dm" #include "code\controllers\Processes\supply.dm" @@ -181,6 +181,18 @@ #include "code\datums\locations\tau_ceti.dm" #include "code\datums\locations\uueoa_esa.dm" #include "code\datums\locations\vir.dm" +#include "code\datums\observation\_debug.dm" +#include "code\datums\observation\_defines.dm" +#include "code\datums\observation\destroyed.dm" +#include "code\datums\observation\dir_set.dm" +#include "code\datums\observation\equipped.dm" +#include "code\datums\observation\helpers.dm" +#include "code\datums\observation\logged_in.dm" +#include "code\datums\observation\moved.dm" +#include "code\datums\observation\observation.dm" +#include "code\datums\observation\task_triggered.dm" +#include "code\datums\observation\unequipped.dm" +#include "code\datums\observation\~cleanup.dm" #include "code\datums\repositories\cameras.dm" #include "code\datums\repositories\crew.dm" #include "code\datums\repositories\repository.dm"