mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-12 19:22:56 +00:00
Merge branch 'master' of https://github.com/PolarisSS13/Polaris into polaris-sync
# Conflicts: # vorestation.dme
This commit is contained in:
@@ -24,9 +24,6 @@
|
|||||||
/obj/machinery/atmospherics/unary/freezer/New()
|
/obj/machinery/atmospherics/unary/freezer/New()
|
||||||
..()
|
..()
|
||||||
initialize_directions = dir
|
initialize_directions = dir
|
||||||
|
|
||||||
/obj/machinery/atmospherics/unary/freezer/map/New()
|
|
||||||
..()
|
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
/obj/machinery/atmospherics/unary/heater/New()
|
/obj/machinery/atmospherics/unary/heater/New()
|
||||||
..()
|
..()
|
||||||
initialize_directions = dir
|
initialize_directions = dir
|
||||||
|
|
||||||
/obj/machinery/atmospherics/unary/heater/map/New()
|
|
||||||
..()
|
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||||
|
|||||||
18
code/__defines/btime.dm
Normal file
18
code/__defines/btime.dm
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Comment this out if the external btime library is unavailable
|
||||||
|
#define PRECISE_TIMER_AVAILABLE
|
||||||
|
|
||||||
|
#ifdef PRECISE_TIMER_AVAILABLE
|
||||||
|
var/global/__btime__libName = "btime.[world.system_type==MS_WINDOWS?"dll":"so"]"
|
||||||
|
#define TimeOfHour (__extern__timeofhour)
|
||||||
|
#define __extern__timeofhour text2num(call(__btime__libName, "gettime")())
|
||||||
|
/hook/startup/proc/checkbtime()
|
||||||
|
try
|
||||||
|
// This will always return 1 unless the btime library cannot be accessed
|
||||||
|
if(TimeOfHour || 1) return 1
|
||||||
|
catch(var/exception/e)
|
||||||
|
log_to_dd("PRECISE_TIMER_AVAILABLE is defined in btime.dm, but calling the btime library failed: [e]")
|
||||||
|
log_to_dd("This is a fatal error. The world will now shut down.")
|
||||||
|
del(world)
|
||||||
|
#else
|
||||||
|
#define TimeOfHour (world.timeofday % 36000)
|
||||||
|
#endif
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
// Some arbitrary defines to be used by self-pruning global lists. (see master_controller)
|
// Some arbitrary defines to be used by self-pruning global lists. (see master_controller)
|
||||||
#define PROCESS_KILL 26 // Used to trigger removal from a processing list.
|
#define PROCESS_KILL 26 // Used to trigger removal from a processing list.
|
||||||
#define MAX_GEAR_COST 10 // Used in chargen for accessory loadout limit.
|
#define MAX_GEAR_COST 15 // Used in chargen for accessory loadout limit.
|
||||||
|
|
||||||
// For secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list of humans.
|
// For secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list of humans.
|
||||||
#define HEALTH_HUD 1 // A simple line rounding the mob's number health.
|
#define HEALTH_HUD 1 // A simple line rounding the mob's number health.
|
||||||
|
|||||||
@@ -11,7 +11,10 @@
|
|||||||
#define PROCESS_DEFAULT_HANG_ALERT_TIME 600 // 60 seconds
|
#define PROCESS_DEFAULT_HANG_ALERT_TIME 600 // 60 seconds
|
||||||
#define PROCESS_DEFAULT_HANG_RESTART_TIME 900 // 90 seconds
|
#define PROCESS_DEFAULT_HANG_RESTART_TIME 900 // 90 seconds
|
||||||
#define PROCESS_DEFAULT_SCHEDULE_INTERVAL 50 // 50 ticks
|
#define PROCESS_DEFAULT_SCHEDULE_INTERVAL 50 // 50 ticks
|
||||||
#define PROCESS_DEFAULT_SLEEP_INTERVAL 2 // 2 ticks
|
#define PROCESS_DEFAULT_SLEEP_INTERVAL 8 // 2 ticks
|
||||||
#define PROCESS_DEFAULT_CPU_THRESHOLD 90 // 90%
|
#define PROCESS_DEFAULT_CPU_THRESHOLD 90 // 90%
|
||||||
|
|
||||||
//#define UPDATE_QUEUE_DEBUG
|
// SCHECK macros
|
||||||
|
// This references src directly to work around a weird bug with try/catch
|
||||||
|
#define SCHECK_EVERY(this_many_calls) if(++src.calls_since_last_scheck >= this_many_calls) sleepCheck()
|
||||||
|
#define SCHECK SCHECK_EVERY(50)
|
||||||
@@ -74,7 +74,6 @@ var/global/list/GlobalPool = list()
|
|||||||
|
|
||||||
D.Destroy()
|
D.Destroy()
|
||||||
D.ResetVars()
|
D.ResetVars()
|
||||||
D.disposed = 1 //Set to stop processing while pooled
|
|
||||||
|
|
||||||
/proc/IsPooled(var/datum/D)
|
/proc/IsPooled(var/datum/D)
|
||||||
if(isnull(GlobalPool[D.type]))
|
if(isnull(GlobalPool[D.type]))
|
||||||
@@ -86,7 +85,6 @@ var/global/list/GlobalPool = list()
|
|||||||
New(arglist(args))
|
New(arglist(args))
|
||||||
else
|
else
|
||||||
New(args)
|
New(args)
|
||||||
disposed = null
|
|
||||||
|
|
||||||
/atom/movable/Prepare(args)
|
/atom/movable/Prepare(args)
|
||||||
var/list/args_list = args
|
var/list/args_list = args
|
||||||
|
|||||||
@@ -602,13 +602,13 @@ proc/dd_sortedTextList(list/incoming)
|
|||||||
/datum/alarm/dd_SortValue()
|
/datum/alarm/dd_SortValue()
|
||||||
return "[sanitize_old(last_name)]"
|
return "[sanitize_old(last_name)]"
|
||||||
|
|
||||||
/proc/subtypes(prototype)
|
/proc/subtypesof(prototype)
|
||||||
return (typesof(prototype) - prototype)
|
return (typesof(prototype) - prototype)
|
||||||
|
|
||||||
//creates every subtype of prototype (excluding prototype) and adds it to list L.
|
//creates every subtype of prototype (excluding prototype) and adds it to list L.
|
||||||
//if no list/L is provided, one is created.
|
//if no list/L is provided, one is created.
|
||||||
/proc/init_subtypes(prototype, list/L)
|
/proc/init_subtypes(prototype, list/L)
|
||||||
if(!istype(L)) L = list()
|
if(!istype(L)) L = list()
|
||||||
for(var/path in subtypes(prototype))
|
for(var/path in subtypesof(prototype))
|
||||||
L += new path()
|
L += new path()
|
||||||
return L
|
return L
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
if (config.log_admin)
|
if (config.log_admin)
|
||||||
diary << "\[[time_stamp()]]ADMIN: [text][log_end]"
|
diary << "\[[time_stamp()]]ADMIN: [text][log_end]"
|
||||||
|
|
||||||
|
|
||||||
/proc/log_debug(text)
|
/proc/log_debug(text)
|
||||||
if (config.log_debug)
|
if (config.log_debug)
|
||||||
diary << "\[[time_stamp()]]DEBUG: [text][log_end]"
|
diary << "\[[time_stamp()]]DEBUG: [text][log_end]"
|
||||||
@@ -34,7 +33,6 @@
|
|||||||
if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
|
if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
|
||||||
C << "DEBUG: [text]"
|
C << "DEBUG: [text]"
|
||||||
|
|
||||||
|
|
||||||
/proc/log_game(text)
|
/proc/log_game(text)
|
||||||
if (config.log_game)
|
if (config.log_game)
|
||||||
diary << "\[[time_stamp()]]GAME: [text][log_end]"
|
diary << "\[[time_stamp()]]GAME: [text][log_end]"
|
||||||
@@ -79,6 +77,11 @@
|
|||||||
if (config.log_pda)
|
if (config.log_pda)
|
||||||
diary << "\[[time_stamp()]]PDA: [text][log_end]"
|
diary << "\[[time_stamp()]]PDA: [text][log_end]"
|
||||||
|
|
||||||
|
/proc/log_to_dd(text)
|
||||||
|
world.log << text //this comes before the config check because it can't possibly runtime
|
||||||
|
if(config.log_world_output)
|
||||||
|
diary << "\[[time_stamp()]]DD_OUTPUT: [text][log_end]"
|
||||||
|
|
||||||
/proc/log_misc(text)
|
/proc/log_misc(text)
|
||||||
diary << "\[[time_stamp()]]MISC: [text][log_end]"
|
diary << "\[[time_stamp()]]MISC: [text][log_end]"
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
// DM Environment file for ProcessScheduler.dme.
|
|
||||||
// All manual changes should be made outside the BEGIN_ and END_ blocks.
|
|
||||||
// New source code should be placed in .dm files: choose File/New --> Code File.
|
|
||||||
|
|
||||||
// BEGIN_INTERNALS
|
|
||||||
// END_INTERNALS
|
|
||||||
|
|
||||||
// BEGIN_FILE_DIR
|
|
||||||
#define FILE_DIR .
|
|
||||||
// END_FILE_DIR
|
|
||||||
|
|
||||||
// BEGIN_PREFERENCES
|
|
||||||
// END_PREFERENCES
|
|
||||||
|
|
||||||
// BEGIN_INCLUDE
|
|
||||||
#include "core\_define.dm"
|
|
||||||
#include "core\_stubs.dm"
|
|
||||||
#include "core\process.dm"
|
|
||||||
#include "core\processScheduler.dm"
|
|
||||||
#include "core\updateQueue.dm"
|
|
||||||
#include "core\updateQueueWorker.dm"
|
|
||||||
#include "test\processSchedulerView.dm"
|
|
||||||
#include "test\testDyingUpdateQueueProcess.dm"
|
|
||||||
#include "test\testHarness.dm"
|
|
||||||
#include "test\testHungProcess.dm"
|
|
||||||
#include "test\testNiceProcess.dm"
|
|
||||||
#include "test\testSlowProcess.dm"
|
|
||||||
#include "test\testUpdateQueue.dm"
|
|
||||||
#include "test\testUpdateQueueProcess.dm"
|
|
||||||
#include "test\testZombieProcess.dm"
|
|
||||||
// END_INCLUDE
|
|
||||||
|
|
||||||
@@ -4,15 +4,7 @@
|
|||||||
* This file contains constructs that the process scheduler expects to exist
|
* This file contains constructs that the process scheduler expects to exist
|
||||||
* in a standard ss13 fork.
|
* in a standard ss13 fork.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
/**
|
|
||||||
* message_admins
|
|
||||||
*
|
|
||||||
* sends a message to admins
|
|
||||||
*/
|
|
||||||
/proc/message_admins(msg)
|
|
||||||
world << msg
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* logTheThing
|
* logTheThing
|
||||||
*
|
*
|
||||||
@@ -25,14 +17,3 @@
|
|||||||
world << "Diary: \[[diaryType]:[type]] [text]"
|
world << "Diary: \[[diaryType]:[type]] [text]"
|
||||||
else
|
else
|
||||||
world << "Log: \[[type]] [text]"
|
world << "Log: \[[type]] [text]"
|
||||||
|
|
||||||
/**
|
|
||||||
* var/disposed
|
|
||||||
*
|
|
||||||
* In goonstation, disposed is set to 1 after an object enters the delete queue
|
|
||||||
* or the object is placed in an object pool (effectively out-of-play so to speak)
|
|
||||||
*/
|
|
||||||
/datum/var/disposed
|
|
||||||
// Garbage collection (controller).
|
|
||||||
/datum/var/gcDestroyed
|
|
||||||
/datum/var/timeDestroyed
|
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
// This controls how often the process will yield (call sleep(0)) while it is running.
|
// This controls how often the process will yield (call sleep(0)) while it is running.
|
||||||
// Every concurrent process should sleep periodically while running in order to allow other
|
// Every concurrent process should sleep periodically while running in order to allow other
|
||||||
// processes to execute concurrently.
|
// processes to execute concurrently.
|
||||||
var/tmp/sleep_interval = PROCESS_DEFAULT_SLEEP_INTERVAL
|
var/tmp/sleep_interval
|
||||||
|
|
||||||
// hang_warning_time - this is the time (in 1/10 seconds) after which the server will begin to show "maybe hung" in the context window
|
// hang_warning_time - this is the time (in 1/10 seconds) after which the server will begin to show "maybe hung" in the context window
|
||||||
var/tmp/hang_warning_time = PROCESS_DEFAULT_HANG_WARNING_TIME
|
var/tmp/hang_warning_time = PROCESS_DEFAULT_HANG_WARNING_TIME
|
||||||
@@ -59,20 +59,20 @@
|
|||||||
// hang_restart_time - After this much time(in 1/10 seconds), the server will automatically kill and restart the process.
|
// hang_restart_time - After this much time(in 1/10 seconds), the server will automatically kill and restart the process.
|
||||||
var/tmp/hang_restart_time = PROCESS_DEFAULT_HANG_RESTART_TIME
|
var/tmp/hang_restart_time = PROCESS_DEFAULT_HANG_RESTART_TIME
|
||||||
|
|
||||||
// cpu_threshold - if world.cpu >= cpu_threshold, scheck() will call sleep(1) to defer further work until the next tick. This keeps a process from driving a tick into overtime (causing perceptible lag)
|
|
||||||
var/tmp/cpu_threshold = PROCESS_DEFAULT_CPU_THRESHOLD
|
|
||||||
|
|
||||||
// How many times in the current run has the process deferred work till the next tick?
|
// How many times in the current run has the process deferred work till the next tick?
|
||||||
var/tmp/cpu_defer_count = 0
|
var/tmp/cpu_defer_count = 0
|
||||||
|
|
||||||
|
// How many SCHECKs have been skipped (to limit btime calls)
|
||||||
|
var/tmp/calls_since_last_scheck = 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* recordkeeping vars
|
* recordkeeping vars
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Records the time (server ticks) at which the process last finished sleeping
|
// Records the time (1/10s timeofday) at which the process last finished sleeping
|
||||||
var/tmp/last_slept = 0
|
var/tmp/last_slept = 0
|
||||||
|
|
||||||
// Records the time (s-ticks) at which the process last began running
|
// Records the time (1/10s timeofday) at which the process last began running
|
||||||
var/tmp/run_start = 0
|
var/tmp/run_start = 0
|
||||||
|
|
||||||
// Records the number of times this process has been killed and restarted
|
// Records the number of times this process has been killed and restarted
|
||||||
@@ -85,26 +85,33 @@
|
|||||||
|
|
||||||
var/tmp/last_object
|
var/tmp/last_object
|
||||||
|
|
||||||
datum/controller/process/New(var/datum/controller/processScheduler/scheduler)
|
// Counts the number of times an exception has occurred; gets reset after 10
|
||||||
|
var/tmp/list/exceptions = list()
|
||||||
|
|
||||||
|
// Number of deciseconds to delay before starting the process
|
||||||
|
var/start_delay = 0
|
||||||
|
|
||||||
|
/datum/controller/process/New(var/datum/controller/processScheduler/scheduler)
|
||||||
..()
|
..()
|
||||||
main = scheduler
|
main = scheduler
|
||||||
previousStatus = "idle"
|
previousStatus = "idle"
|
||||||
idle()
|
idle()
|
||||||
name = "process"
|
name = "process"
|
||||||
schedule_interval = 50
|
schedule_interval = 50
|
||||||
sleep_interval = 2
|
sleep_interval = world.tick_lag / PROCESS_DEFAULT_SLEEP_INTERVAL
|
||||||
last_slept = 0
|
last_slept = 0
|
||||||
run_start = 0
|
run_start = 0
|
||||||
ticks = 0
|
ticks = 0
|
||||||
last_task = 0
|
last_task = 0
|
||||||
last_object = null
|
last_object = null
|
||||||
|
|
||||||
datum/controller/process/proc/started()
|
/datum/controller/process/proc/started()
|
||||||
|
var/timeofhour = TimeOfHour
|
||||||
// Initialize last_slept so we can know when to sleep
|
// Initialize last_slept so we can know when to sleep
|
||||||
last_slept = world.timeofday
|
last_slept = timeofhour
|
||||||
|
|
||||||
// Initialize run_start so we can detect hung processes.
|
// Initialize run_start so we can detect hung processes.
|
||||||
run_start = world.timeofday
|
run_start = timeofhour
|
||||||
|
|
||||||
// Initialize defer count
|
// Initialize defer count
|
||||||
cpu_defer_count = 0
|
cpu_defer_count = 0
|
||||||
@@ -114,65 +121,65 @@ datum/controller/process/proc/started()
|
|||||||
|
|
||||||
onStart()
|
onStart()
|
||||||
|
|
||||||
datum/controller/process/proc/finished()
|
/datum/controller/process/proc/finished()
|
||||||
ticks++
|
ticks++
|
||||||
idle()
|
idle()
|
||||||
main.processFinished(src)
|
main.processFinished(src)
|
||||||
|
|
||||||
onFinish()
|
onFinish()
|
||||||
|
|
||||||
datum/controller/process/proc/doWork()
|
/datum/controller/process/proc/doWork()
|
||||||
|
|
||||||
datum/controller/process/proc/setup()
|
/datum/controller/process/proc/setup()
|
||||||
|
|
||||||
datum/controller/process/proc/process()
|
/datum/controller/process/proc/process()
|
||||||
started()
|
started()
|
||||||
doWork()
|
doWork()
|
||||||
finished()
|
finished()
|
||||||
|
|
||||||
datum/controller/process/proc/running()
|
/datum/controller/process/proc/running()
|
||||||
idle = 0
|
idle = 0
|
||||||
queued = 0
|
queued = 0
|
||||||
running = 1
|
running = 1
|
||||||
hung = 0
|
hung = 0
|
||||||
setStatus(PROCESS_STATUS_RUNNING)
|
setStatus(PROCESS_STATUS_RUNNING)
|
||||||
|
|
||||||
datum/controller/process/proc/idle()
|
/datum/controller/process/proc/idle()
|
||||||
queued = 0
|
queued = 0
|
||||||
running = 0
|
running = 0
|
||||||
idle = 1
|
idle = 1
|
||||||
hung = 0
|
hung = 0
|
||||||
setStatus(PROCESS_STATUS_IDLE)
|
setStatus(PROCESS_STATUS_IDLE)
|
||||||
|
|
||||||
datum/controller/process/proc/queued()
|
/datum/controller/process/proc/queued()
|
||||||
idle = 0
|
idle = 0
|
||||||
running = 0
|
running = 0
|
||||||
queued = 1
|
queued = 1
|
||||||
hung = 0
|
hung = 0
|
||||||
setStatus(PROCESS_STATUS_QUEUED)
|
setStatus(PROCESS_STATUS_QUEUED)
|
||||||
|
|
||||||
datum/controller/process/proc/hung()
|
/datum/controller/process/proc/hung()
|
||||||
hung = 1
|
hung = 1
|
||||||
setStatus(PROCESS_STATUS_HUNG)
|
setStatus(PROCESS_STATUS_HUNG)
|
||||||
|
|
||||||
datum/controller/process/proc/handleHung()
|
/datum/controller/process/proc/handleHung()
|
||||||
|
var/timeofhour = TimeOfHour
|
||||||
var/datum/lastObj = last_object
|
var/datum/lastObj = last_object
|
||||||
var/lastObjType = "null"
|
var/lastObjType = "null"
|
||||||
if(istype(lastObj))
|
if(istype(lastObj))
|
||||||
lastObjType = lastObj.type
|
lastObjType = lastObj.type
|
||||||
|
|
||||||
// If world.timeofday has rolled over, then we need to adjust.
|
// If timeofhour has rolled over, then we need to adjust.
|
||||||
if (world.timeofday < run_start)
|
if (timeofhour < run_start)
|
||||||
run_start -= 864000
|
run_start -= 36000
|
||||||
|
var/msg = "[name] process hung at tick #[ticks]. Process was unresponsive for [(timeofhour - run_start) / 10] seconds and was restarted. Last task: [last_task]. Last Object Type: [lastObjType]"
|
||||||
var/msg = "[name] process hung at tick #[ticks]. Process was unresponsive for [(world.timeofday - run_start) / 10] seconds and was restarted. Last task: [last_task]. Last Object Type: [lastObjType]"
|
|
||||||
logTheThing("debug", null, null, msg)
|
logTheThing("debug", null, null, msg)
|
||||||
logTheThing("diary", null, null, msg, "debug")
|
logTheThing("diary", null, null, msg, "debug")
|
||||||
message_admins(msg)
|
message_admins(msg)
|
||||||
|
|
||||||
main.restartProcess(src.name)
|
main.restartProcess(src.name)
|
||||||
|
|
||||||
datum/controller/process/proc/kill()
|
/datum/controller/process/proc/kill()
|
||||||
if (!killed)
|
if (!killed)
|
||||||
var/msg = "[name] process was killed at tick #[ticks]."
|
var/msg = "[name] process was killed at tick #[ticks]."
|
||||||
logTheThing("debug", null, null, msg)
|
logTheThing("debug", null, null, msg)
|
||||||
@@ -182,59 +189,68 @@ datum/controller/process/proc/kill()
|
|||||||
// Allow inheritors to clean up if needed
|
// Allow inheritors to clean up if needed
|
||||||
onKill()
|
onKill()
|
||||||
|
|
||||||
killed = TRUE
|
// This should del
|
||||||
|
del(src)
|
||||||
|
|
||||||
del(src) // This should del
|
// Do not call this directly - use SHECK or SCHECK_EVERY
|
||||||
|
/datum/controller/process/proc/sleepCheck(var/tickId = 0)
|
||||||
datum/controller/process/proc/scheck(var/tickId = 0)
|
calls_since_last_scheck = 0
|
||||||
if (killed)
|
if (killed)
|
||||||
// The kill proc is the only place where killed is set.
|
// The kill proc is the only place where killed is set.
|
||||||
// The kill proc should have deleted this datum, and all sleeping procs that are
|
// The kill proc should have deleted this datum, and all sleeping procs that are
|
||||||
// owned by it.
|
// owned by it.
|
||||||
CRASH("A killed process is still running somehow...")
|
CRASH("A killed process is still running somehow...")
|
||||||
|
if (hung)
|
||||||
|
// This will only really help if the doWork proc ends up in an infinite loop.
|
||||||
|
handleHung()
|
||||||
|
CRASH("Process [name] hung and was restarted.")
|
||||||
|
|
||||||
// For each tick the process defers, it increments the cpu_defer_count so we don't
|
if (main.getCurrentTickElapsedTime() > main.timeAllowance)
|
||||||
// defer indefinitely
|
sleep(world.tick_lag)
|
||||||
if (world.cpu >= cpu_threshold + cpu_defer_count * 10)
|
|
||||||
sleep(1)
|
|
||||||
cpu_defer_count++
|
cpu_defer_count++
|
||||||
last_slept = world.timeofday
|
last_slept = TimeOfHour
|
||||||
else
|
else
|
||||||
// If world.timeofday has rolled over, then we need to adjust.
|
var/timeofhour = TimeOfHour
|
||||||
if (world.timeofday < last_slept)
|
// If timeofhour has rolled over, then we need to adjust.
|
||||||
last_slept -= 864000
|
if (timeofhour < last_slept)
|
||||||
|
last_slept -= 36000
|
||||||
|
|
||||||
if (world.timeofday > last_slept + sleep_interval)
|
if (timeofhour > last_slept + sleep_interval)
|
||||||
// If we haven't slept in sleep_interval ticks, sleep to allow other work to proceed.
|
// If we haven't slept in sleep_interval deciseconds, sleep to allow other work to proceed.
|
||||||
sleep(0)
|
sleep(0)
|
||||||
last_slept = world.timeofday
|
last_slept = TimeOfHour
|
||||||
|
|
||||||
datum/controller/process/proc/update()
|
/datum/controller/process/proc/update()
|
||||||
// Clear delta
|
// Clear delta
|
||||||
if(previousStatus != status)
|
if(previousStatus != status)
|
||||||
setStatus(status)
|
setStatus(status)
|
||||||
|
|
||||||
var/elapsedTime = getElapsedTime()
|
var/elapsedTime = getElapsedTime()
|
||||||
|
|
||||||
if (elapsedTime > hang_restart_time)
|
if (hung)
|
||||||
|
handleHung()
|
||||||
|
return
|
||||||
|
else if (elapsedTime > hang_restart_time)
|
||||||
hung()
|
hung()
|
||||||
else if (elapsedTime > hang_alert_time)
|
else if (elapsedTime > hang_alert_time)
|
||||||
setStatus(PROCESS_STATUS_PROBABLY_HUNG)
|
setStatus(PROCESS_STATUS_PROBABLY_HUNG)
|
||||||
else if (elapsedTime > hang_warning_time)
|
else if (elapsedTime > hang_warning_time)
|
||||||
setStatus(PROCESS_STATUS_MAYBE_HUNG)
|
setStatus(PROCESS_STATUS_MAYBE_HUNG)
|
||||||
|
|
||||||
datum/controller/process/proc/getElapsedTime()
|
|
||||||
if (world.timeofday < run_start)
|
|
||||||
return world.timeofday - (run_start - 864000)
|
|
||||||
return world.timeofday - run_start
|
|
||||||
|
|
||||||
datum/controller/process/proc/tickDetail()
|
/datum/controller/process/proc/getElapsedTime()
|
||||||
|
var/timeofhour = TimeOfHour
|
||||||
|
if (timeofhour < run_start)
|
||||||
|
return timeofhour - (run_start - 36000)
|
||||||
|
return timeofhour - run_start
|
||||||
|
|
||||||
|
/datum/controller/process/proc/tickDetail()
|
||||||
return
|
return
|
||||||
|
|
||||||
datum/controller/process/proc/getContext()
|
/datum/controller/process/proc/getContext()
|
||||||
return "<tr><td>[name]</td><td>[main.averageRunTime(src)]</td><td>[main.last_run_time[src]]</td><td>[main.highest_run_time[src]]</td><td>[ticks]</td></tr>\n"
|
return "<tr><td>[name]</td><td>[main.averageRunTime(src)]</td><td>[main.last_run_time[src]]</td><td>[main.highest_run_time[src]]</td><td>[ticks]</td></tr>\n"
|
||||||
|
|
||||||
datum/controller/process/proc/getContextData()
|
/datum/controller/process/proc/getContextData()
|
||||||
return list(
|
return list(
|
||||||
"name" = name,
|
"name" = name,
|
||||||
"averageRunTime" = main.averageRunTime(src),
|
"averageRunTime" = main.averageRunTime(src),
|
||||||
@@ -246,10 +262,10 @@ datum/controller/process/proc/getContextData()
|
|||||||
"disabled" = disabled
|
"disabled" = disabled
|
||||||
)
|
)
|
||||||
|
|
||||||
datum/controller/process/proc/getStatus()
|
/datum/controller/process/proc/getStatus()
|
||||||
return status
|
return status
|
||||||
|
|
||||||
datum/controller/process/proc/getStatusText(var/s = 0)
|
/datum/controller/process/proc/getStatusText(var/s = 0)
|
||||||
if(!s)
|
if(!s)
|
||||||
s = status
|
s = status
|
||||||
switch(s)
|
switch(s)
|
||||||
@@ -268,21 +284,21 @@ datum/controller/process/proc/getStatusText(var/s = 0)
|
|||||||
else
|
else
|
||||||
return "UNKNOWN"
|
return "UNKNOWN"
|
||||||
|
|
||||||
datum/controller/process/proc/getPreviousStatus()
|
/datum/controller/process/proc/getPreviousStatus()
|
||||||
return previousStatus
|
return previousStatus
|
||||||
|
|
||||||
datum/controller/process/proc/getPreviousStatusText()
|
/datum/controller/process/proc/getPreviousStatusText()
|
||||||
return getStatusText(previousStatus)
|
return getStatusText(previousStatus)
|
||||||
|
|
||||||
datum/controller/process/proc/setStatus(var/newStatus)
|
/datum/controller/process/proc/setStatus(var/newStatus)
|
||||||
previousStatus = status
|
previousStatus = status
|
||||||
status = newStatus
|
status = newStatus
|
||||||
|
|
||||||
datum/controller/process/proc/setLastTask(var/task, var/object)
|
/datum/controller/process/proc/setLastTask(var/task, var/object)
|
||||||
last_task = task
|
last_task = task
|
||||||
last_object = object
|
last_object = object
|
||||||
|
|
||||||
datum/controller/process/proc/_copyStateFrom(var/datum/controller/process/target)
|
/datum/controller/process/proc/_copyStateFrom(var/datum/controller/process/target)
|
||||||
main = target.main
|
main = target.main
|
||||||
name = target.name
|
name = target.name
|
||||||
schedule_interval = target.schedule_interval
|
schedule_interval = target.schedule_interval
|
||||||
@@ -295,28 +311,62 @@ datum/controller/process/proc/_copyStateFrom(var/datum/controller/process/target
|
|||||||
last_object = target.last_object
|
last_object = target.last_object
|
||||||
copyStateFrom(target)
|
copyStateFrom(target)
|
||||||
|
|
||||||
datum/controller/process/proc/copyStateFrom(var/datum/controller/process/target)
|
/datum/controller/process/proc/copyStateFrom(var/datum/controller/process/target)
|
||||||
|
|
||||||
datum/controller/process/proc/onKill()
|
/datum/controller/process/proc/onKill()
|
||||||
|
|
||||||
datum/controller/process/proc/onStart()
|
/datum/controller/process/proc/onStart()
|
||||||
|
|
||||||
datum/controller/process/proc/onFinish()
|
/datum/controller/process/proc/onFinish()
|
||||||
|
|
||||||
datum/controller/process/proc/disable()
|
/datum/controller/process/proc/disable()
|
||||||
disabled = 1
|
disabled = 1
|
||||||
|
|
||||||
datum/controller/process/proc/enable()
|
/datum/controller/process/proc/enable()
|
||||||
disabled = 0
|
disabled = 0
|
||||||
|
|
||||||
|
/datum/controller/process/proc/getAverageRunTime()
|
||||||
|
return main.averageRunTime(src)
|
||||||
/datum/controller/process/proc/getLastRunTime()
|
/datum/controller/process/proc/getLastRunTime()
|
||||||
return main.getProcessLastRunTime(src)
|
return main.getProcessLastRunTime(src)
|
||||||
|
|
||||||
|
/datum/controller/process/proc/getHighestRunTime()
|
||||||
|
return main.getProcessHighestRunTime(src)
|
||||||
|
|
||||||
/datum/controller/process/proc/getTicks()
|
/datum/controller/process/proc/getTicks()
|
||||||
return ticks
|
return ticks
|
||||||
|
|
||||||
/datum/controller/process/proc/getStatName()
|
/datum/controller/process/proc/statProcess()
|
||||||
return name
|
var/averageRunTime = round(getAverageRunTime(), 0.1)/10
|
||||||
|
var/lastRunTime = round(getLastRunTime(), 0.1)/10
|
||||||
|
var/highestRunTime = round(getHighestRunTime(), 0.1)/10
|
||||||
|
stat("[name]", "T#[getTicks()] | AR [averageRunTime] | LR [lastRunTime] | HR [highestRunTime] | D [cpu_defer_count]")
|
||||||
|
|
||||||
/datum/controller/process/proc/getTickTime()
|
/datum/controller/process/proc/catchException(var/exception/e, var/thrower)
|
||||||
return "#[getTicks()]\t- [getLastRunTime()]"
|
var/etext = "[e]"
|
||||||
|
var/eid = "[e]" // Exception ID, for tracking repeated exceptions
|
||||||
|
var/ptext = "" // "processing..." text, for what was being processed (if known)
|
||||||
|
if(istype(e))
|
||||||
|
etext += " in [e.file], line [e.line]"
|
||||||
|
eid = "[e.file]:[e.line]"
|
||||||
|
if(eid in exceptions)
|
||||||
|
if(exceptions[eid]++ >= 10)
|
||||||
|
return
|
||||||
|
else
|
||||||
|
exceptions[eid] = 1
|
||||||
|
if(istype(thrower, /datum))
|
||||||
|
var/datum/D = thrower
|
||||||
|
ptext = " processing [D.type]"
|
||||||
|
if(istype(thrower, /atom))
|
||||||
|
var/atom/A = thrower
|
||||||
|
ptext += " ([A]) ([A.x],[A.y],[A.z])"
|
||||||
|
log_to_dd("\[[time_stamp()]\] Process [name] caught exception[ptext]: [etext]")
|
||||||
|
if(exceptions[eid] >= 10)
|
||||||
|
log_to_dd("This exception will now be ignored for ten minutes.")
|
||||||
|
spawn(6000)
|
||||||
|
exceptions[eid] = 0
|
||||||
|
|
||||||
|
/datum/controller/process/proc/catchBadType(var/datum/caught)
|
||||||
|
if(isnull(caught) || !istype(caught) || !isnull(caught.gcDestroyed))
|
||||||
|
return // Only bother with types we can identify and that don't belong
|
||||||
|
catchException("Type [caught.type] does not belong in process' queue")
|
||||||
@@ -17,7 +17,10 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
// Process name -> process object map
|
// Process name -> process object map
|
||||||
var/tmp/datum/controller/process/list/nameToProcessMap = new
|
var/tmp/datum/controller/process/list/nameToProcessMap = new
|
||||||
|
|
||||||
// Process last start times
|
// Process last queued times (world time)
|
||||||
|
var/tmp/datum/controller/process/list/last_queued = new
|
||||||
|
|
||||||
|
// Process last start times (real time)
|
||||||
var/tmp/datum/controller/process/list/last_start = new
|
var/tmp/datum/controller/process/list/last_start = new
|
||||||
|
|
||||||
// Process last run durations
|
// Process last run durations
|
||||||
@@ -29,8 +32,8 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
// Process highest run time
|
// Process highest run time
|
||||||
var/tmp/datum/controller/process/list/highest_run_time = new
|
var/tmp/datum/controller/process/list/highest_run_time = new
|
||||||
|
|
||||||
// Sleep 1 tick -- This may be too aggressive.
|
// How long to sleep between runs (set to tick_lag in New)
|
||||||
var/tmp/scheduler_sleep_interval = 1
|
var/tmp/scheduler_sleep_interval
|
||||||
|
|
||||||
// Controls whether the scheduler is running or not
|
// Controls whether the scheduler is running or not
|
||||||
var/tmp/isRunning = 0
|
var/tmp/isRunning = 0
|
||||||
@@ -38,6 +41,25 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
// Setup for these processes will be deferred until all the other processes are set up.
|
// Setup for these processes will be deferred until all the other processes are set up.
|
||||||
var/tmp/list/deferredSetupList = new
|
var/tmp/list/deferredSetupList = new
|
||||||
|
|
||||||
|
var/tmp/currentTick = 0
|
||||||
|
|
||||||
|
var/tmp/currentTickStart = 0
|
||||||
|
|
||||||
|
var/tmp/timeAllowance = 0
|
||||||
|
|
||||||
|
var/tmp/cpuAverage = 0
|
||||||
|
|
||||||
|
var/tmp/timeAllowanceMax = 0
|
||||||
|
|
||||||
|
/datum/controller/processScheduler/New()
|
||||||
|
..()
|
||||||
|
// When the process scheduler is first new'd, tick_lag may be wrong, so these
|
||||||
|
// get re-initialized when the process scheduler is started.
|
||||||
|
// (These are kept here for any processes that decide to process before round start)
|
||||||
|
scheduler_sleep_interval = world.tick_lag
|
||||||
|
timeAllowance = world.tick_lag * 0.5
|
||||||
|
timeAllowanceMax = world.tick_lag
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* deferSetupFor
|
* deferSetupFor
|
||||||
* @param path processPath
|
* @param path processPath
|
||||||
@@ -57,7 +79,7 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
|
|
||||||
var/process
|
var/process
|
||||||
// Add all the processes we can find, except for the ticker
|
// Add all the processes we can find, except for the ticker
|
||||||
for (process in typesof(/datum/controller/process) - /datum/controller/process)
|
for (process in subtypesof(/datum/controller/process))
|
||||||
if (!(process in deferredSetupList))
|
if (!(process in deferredSetupList))
|
||||||
addProcess(new process(src))
|
addProcess(new process(src))
|
||||||
|
|
||||||
@@ -66,11 +88,22 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
|
|
||||||
/datum/controller/processScheduler/proc/start()
|
/datum/controller/processScheduler/proc/start()
|
||||||
isRunning = 1
|
isRunning = 1
|
||||||
|
// tick_lag will have been set by now, so re-initialize these
|
||||||
|
scheduler_sleep_interval = world.tick_lag
|
||||||
|
timeAllowance = world.tick_lag * 0.5
|
||||||
|
timeAllowanceMax = world.tick_lag
|
||||||
|
updateStartDelays()
|
||||||
spawn(0)
|
spawn(0)
|
||||||
process()
|
process()
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/process()
|
/datum/controller/processScheduler/proc/process()
|
||||||
|
updateCurrentTickData()
|
||||||
|
|
||||||
|
for(var/i=world.tick_lag,i<world.tick_lag*50,i+=world.tick_lag)
|
||||||
|
spawn(i) updateCurrentTickData()
|
||||||
while(isRunning)
|
while(isRunning)
|
||||||
|
// Hopefully spawning this for 50 ticks in the future will make it the first thing in the queue.
|
||||||
|
spawn(world.tick_lag*50) updateCurrentTickData()
|
||||||
checkRunningProcesses()
|
checkRunningProcesses()
|
||||||
queueProcesses()
|
queueProcesses()
|
||||||
runQueuedProcesses()
|
runQueuedProcesses()
|
||||||
@@ -92,15 +125,11 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
// Check status changes
|
// Check status changes
|
||||||
if(status != previousStatus)
|
if(status != previousStatus)
|
||||||
//Status changed.
|
//Status changed.
|
||||||
|
|
||||||
switch(status)
|
switch(status)
|
||||||
if(PROCESS_STATUS_MAYBE_HUNG)
|
|
||||||
message_admins("Process '[p.name]' is [p.getStatusText(status)].")
|
|
||||||
if(PROCESS_STATUS_PROBABLY_HUNG)
|
if(PROCESS_STATUS_PROBABLY_HUNG)
|
||||||
message_admins("Process '[p.name]' is [p.getStatusText(status)].")
|
message_admins("Process '[p.name]' may be hung.")
|
||||||
if(PROCESS_STATUS_HUNG)
|
if(PROCESS_STATUS_HUNG)
|
||||||
message_admins("Process '[p.name]' is [p.getStatusText(status)].")
|
message_admins("Process '[p.name]' is hung and will be restarted.")
|
||||||
p.handleHung()
|
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/queueProcesses()
|
/datum/controller/processScheduler/proc/queueProcesses()
|
||||||
for(var/datum/controller/process/p in processes)
|
for(var/datum/controller/process/p in processes)
|
||||||
@@ -108,12 +137,8 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
if (p.disabled || p.running || p.queued || !p.idle)
|
if (p.disabled || p.running || p.queued || !p.idle)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
// If world.timeofday has rolled over, then we need to adjust.
|
|
||||||
if (world.timeofday < last_start[p])
|
|
||||||
last_start[p] -= 864000
|
|
||||||
|
|
||||||
// If the process should be running by now, go ahead and queue it
|
// If the process should be running by now, go ahead and queue it
|
||||||
if (world.timeofday > last_start[p] + p.schedule_interval)
|
if (world.time >= last_queued[p] + p.schedule_interval)
|
||||||
setQueuedProcessState(p)
|
setQueuedProcessState(p)
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/runQueuedProcesses()
|
/datum/controller/processScheduler/proc/runQueuedProcesses()
|
||||||
@@ -176,6 +201,10 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
|
|
||||||
nameToProcessMap[newProcess.name] = newProcess
|
nameToProcessMap[newProcess.name] = newProcess
|
||||||
|
|
||||||
|
/datum/controller/processScheduler/proc/updateStartDelays()
|
||||||
|
for(var/datum/controller/process/p in processes)
|
||||||
|
if(p.start_delay)
|
||||||
|
last_queued[p] = world.time - p.start_delay
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/runProcess(var/datum/controller/process/process)
|
/datum/controller/processScheduler/proc/runProcess(var/datum/controller/process/process)
|
||||||
spawn(0)
|
spawn(0)
|
||||||
@@ -197,8 +226,6 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
if (!(process in idle))
|
if (!(process in idle))
|
||||||
idle += process
|
idle += process
|
||||||
|
|
||||||
process.idle()
|
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/setQueuedProcessState(var/datum/controller/process/process)
|
/datum/controller/processScheduler/proc/setQueuedProcessState(var/datum/controller/process/process)
|
||||||
if (process in running)
|
if (process in running)
|
||||||
running -= process
|
running -= process
|
||||||
@@ -218,21 +245,22 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
if (!(process in running))
|
if (!(process in running))
|
||||||
running += process
|
running += process
|
||||||
|
|
||||||
process.running()
|
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/recordStart(var/datum/controller/process/process, var/time = null)
|
/datum/controller/processScheduler/proc/recordStart(var/datum/controller/process/process, var/time = null)
|
||||||
if (isnull(time))
|
if (isnull(time))
|
||||||
time = world.timeofday
|
time = TimeOfHour
|
||||||
|
last_queued[process] = world.time
|
||||||
last_start[process] = time
|
last_start[process] = time
|
||||||
|
else
|
||||||
|
last_queued[process] = (time == 0 ? 0 : world.time)
|
||||||
|
last_start[process] = time
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/recordEnd(var/datum/controller/process/process, var/time = null)
|
/datum/controller/processScheduler/proc/recordEnd(var/datum/controller/process/process, var/time = null)
|
||||||
if (isnull(time))
|
if (isnull(time))
|
||||||
time = world.timeofday
|
time = TimeOfHour
|
||||||
|
|
||||||
// If world.timeofday has rolled over, then we need to adjust.
|
// If world.timeofday has rolled over, then we need to adjust.
|
||||||
if (time < last_start[process])
|
if (time < last_start[process])
|
||||||
last_start[process] -= 864000
|
last_start[process] -= 36000
|
||||||
|
|
||||||
var/lastRunTime = time - last_start[process]
|
var/lastRunTime = time - last_start[process]
|
||||||
|
|
||||||
@@ -273,6 +301,12 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
return t / c
|
return t / c
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
/datum/controller/processScheduler/proc/getProcessLastRunTime(var/datum/controller/process/process)
|
||||||
|
return last_run_time[process]
|
||||||
|
|
||||||
|
/datum/controller/processScheduler/proc/getProcessHighestRunTime(var/datum/controller/process/process)
|
||||||
|
return highest_run_time[process]
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/getStatusData()
|
/datum/controller/processScheduler/proc/getStatusData()
|
||||||
var/list/data = new
|
var/list/data = new
|
||||||
|
|
||||||
@@ -310,11 +344,39 @@ var/global/datum/controller/processScheduler/processScheduler
|
|||||||
var/datum/controller/process/process = nameToProcessMap[processName]
|
var/datum/controller/process/process = nameToProcessMap[processName]
|
||||||
process.disable()
|
process.disable()
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/getProcess(var/name)
|
/datum/controller/processScheduler/proc/getCurrentTickElapsedTime()
|
||||||
return nameToProcessMap[name]
|
if (world.time > currentTick)
|
||||||
|
updateCurrentTickData()
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return TimeOfHour - currentTickStart
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/getProcessLastRunTime(var/datum/controller/process/process)
|
/datum/controller/processScheduler/proc/updateCurrentTickData()
|
||||||
return last_run_time[process]
|
if (world.time > currentTick)
|
||||||
|
// New tick!
|
||||||
|
currentTick = world.time
|
||||||
|
currentTickStart = TimeOfHour
|
||||||
|
updateTimeAllowance()
|
||||||
|
cpuAverage = (world.cpu + cpuAverage + cpuAverage) / 3
|
||||||
|
|
||||||
/datum/controller/processScheduler/proc/getIsRunning()
|
/datum/controller/processScheduler/proc/updateTimeAllowance()
|
||||||
return isRunning
|
// Time allowance goes down linearly with world.cpu.
|
||||||
|
var/tmp/error = cpuAverage - 100
|
||||||
|
var/tmp/timeAllowanceDelta = sign(error) * -0.5 * world.tick_lag * max(0, 0.001 * abs(error))
|
||||||
|
|
||||||
|
//timeAllowance = world.tick_lag * min(1, 0.5 * ((200/max(1,cpuAverage)) - 1))
|
||||||
|
timeAllowance = min(timeAllowanceMax, max(0, timeAllowance + timeAllowanceDelta))
|
||||||
|
|
||||||
|
/datum/controller/processScheduler/proc/sign(var/x)
|
||||||
|
if (x == 0)
|
||||||
|
return 1
|
||||||
|
return x / abs(x)
|
||||||
|
|
||||||
|
/datum/controller/processScheduler/proc/statProcesses()
|
||||||
|
if(!isRunning)
|
||||||
|
stat("Processes", "Scheduler not running")
|
||||||
|
return
|
||||||
|
stat("Processes", "[processes.len] (R [running.len] / Q [queued.len] / I [idle.len])")
|
||||||
|
stat(null, "[round(cpuAverage, 0.1)] CPU, [round(timeAllowance, 0.1)/10] TA")
|
||||||
|
for(var/datum/controller/process/p in processes)
|
||||||
|
p.statProcess()
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
/**
|
|
||||||
* updateQueue.dm
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef UPDATE_QUEUE_DEBUG
|
|
||||||
#define uq_dbg(text) world << text
|
|
||||||
#else
|
|
||||||
#define uq_dbg(text)
|
|
||||||
#endif
|
|
||||||
/datum/updateQueue
|
|
||||||
var/tmp/list/objects
|
|
||||||
var/tmp/previousStart
|
|
||||||
var/tmp/procName
|
|
||||||
var/tmp/list/arguments
|
|
||||||
var/tmp/datum/updateQueueWorker/currentWorker
|
|
||||||
var/tmp/workerTimeout
|
|
||||||
var/tmp/adjustedWorkerTimeout
|
|
||||||
var/tmp/currentKillCount
|
|
||||||
var/tmp/totalKillCount
|
|
||||||
|
|
||||||
/datum/updateQueue/New(list/objects = list(), procName = "update", list/arguments = list(), workerTimeout = 2, inplace = 0)
|
|
||||||
..()
|
|
||||||
|
|
||||||
uq_dbg("Update queue created.")
|
|
||||||
|
|
||||||
// Init proc allows for recycling the worker.
|
|
||||||
init(objects = objects, procName = procName, arguments = arguments, workerTimeout = workerTimeout, inplace = inplace)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* init
|
|
||||||
* @param list objects objects to update
|
|
||||||
* @param text procName the proc to call on each item in the object list
|
|
||||||
* @param list arguments optional arguments to pass to the update proc
|
|
||||||
* @param number workerTimeout number of ticks to wait for an update to
|
|
||||||
finish before forking a new update worker
|
|
||||||
* @param bool inplace whether the updateQueue should make a copy of objects.
|
|
||||||
the internal list will be modified, so it is usually
|
|
||||||
a good idea to leave this alone. Default behavior is to
|
|
||||||
copy.
|
|
||||||
*/
|
|
||||||
/datum/updateQueue/proc/init(list/objects = list(), procName = "update", list/arguments = list(), workerTimeout = 2, inplace = 0)
|
|
||||||
uq_dbg("Update queue initialization started.")
|
|
||||||
|
|
||||||
if (!inplace)
|
|
||||||
// Make an internal copy of the list so we're not modifying the original.
|
|
||||||
initList(objects)
|
|
||||||
else
|
|
||||||
src.objects = objects
|
|
||||||
|
|
||||||
// Init vars
|
|
||||||
src.procName = procName
|
|
||||||
src.arguments = arguments
|
|
||||||
src.workerTimeout = workerTimeout
|
|
||||||
|
|
||||||
adjustedWorkerTimeout = workerTimeout
|
|
||||||
currentKillCount = 0
|
|
||||||
totalKillCount = 0
|
|
||||||
|
|
||||||
uq_dbg("Update queue initialization finished. procName = '[procName]'")
|
|
||||||
|
|
||||||
/datum/updateQueue/proc/initList(list/toCopy)
|
|
||||||
/**
|
|
||||||
* We will copy the list in reverse order, as our doWork proc
|
|
||||||
* will access them by popping an element off the end of the list.
|
|
||||||
* This ends up being quite a lot faster than taking elements off
|
|
||||||
* the head of the list.
|
|
||||||
*/
|
|
||||||
objects = new
|
|
||||||
|
|
||||||
uq_dbg("Copying [toCopy.len] items for processing.")
|
|
||||||
|
|
||||||
for(var/i=toCopy.len,i>0,)
|
|
||||||
objects.len++
|
|
||||||
objects[objects.len] = toCopy[i--]
|
|
||||||
|
|
||||||
/datum/updateQueue/proc/Run()
|
|
||||||
uq_dbg("Starting run...")
|
|
||||||
|
|
||||||
startWorker()
|
|
||||||
while (istype(currentWorker) && !currentWorker.finished)
|
|
||||||
sleep(2)
|
|
||||||
checkWorker()
|
|
||||||
|
|
||||||
uq_dbg("UpdateQueue completed run.")
|
|
||||||
|
|
||||||
/datum/updateQueue/proc/checkWorker()
|
|
||||||
if(istype(currentWorker))
|
|
||||||
// If world.timeofday has rolled over, then we need to adjust.
|
|
||||||
if(world.timeofday < currentWorker.lastStart)
|
|
||||||
currentWorker.lastStart -= 864000
|
|
||||||
|
|
||||||
if(world.timeofday - currentWorker.lastStart > adjustedWorkerTimeout)
|
|
||||||
// This worker is a bit slow, let's spawn a new one and kill the old one.
|
|
||||||
uq_dbg("Current worker is lagging... starting a new one.")
|
|
||||||
killWorker()
|
|
||||||
startWorker()
|
|
||||||
else // No worker!
|
|
||||||
uq_dbg("update queue ended up without a worker... starting a new one...")
|
|
||||||
startWorker()
|
|
||||||
|
|
||||||
/datum/updateQueue/proc/startWorker()
|
|
||||||
// only run the worker if we have objects to work on
|
|
||||||
if(objects.len)
|
|
||||||
uq_dbg("Starting worker process.")
|
|
||||||
|
|
||||||
// No need to create a fresh worker if we already have one...
|
|
||||||
if (istype(currentWorker))
|
|
||||||
currentWorker.init(objects, procName, arguments)
|
|
||||||
else
|
|
||||||
currentWorker = new(objects, procName, arguments)
|
|
||||||
currentWorker.start()
|
|
||||||
else
|
|
||||||
uq_dbg("Queue is empty. No worker was started.")
|
|
||||||
currentWorker = null
|
|
||||||
|
|
||||||
/datum/updateQueue/proc/killWorker()
|
|
||||||
// Kill the worker
|
|
||||||
currentWorker.kill()
|
|
||||||
currentWorker = null
|
|
||||||
// After we kill a worker, yield so that if the worker's been tying up the cpu, other stuff can immediately resume
|
|
||||||
sleep(-1)
|
|
||||||
currentKillCount++
|
|
||||||
totalKillCount++
|
|
||||||
if (currentKillCount >= 3)
|
|
||||||
uq_dbg("[currentKillCount] workers have been killed with a timeout of [adjustedWorkerTimeout]. Increasing worker timeout to compensate.")
|
|
||||||
adjustedWorkerTimeout++
|
|
||||||
currentKillCount = 0
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
datum/updateQueueWorker
|
|
||||||
var/tmp/list/objects
|
|
||||||
var/tmp/killed
|
|
||||||
var/tmp/finished
|
|
||||||
var/tmp/procName
|
|
||||||
var/tmp/list/arguments
|
|
||||||
var/tmp/lastStart
|
|
||||||
var/tmp/cpuThreshold
|
|
||||||
|
|
||||||
datum/updateQueueWorker/New(var/list/objects, var/procName, var/list/arguments, var/cpuThreshold = 90)
|
|
||||||
..()
|
|
||||||
uq_dbg("updateQueueWorker created.")
|
|
||||||
|
|
||||||
init(objects, procName, arguments, cpuThreshold)
|
|
||||||
|
|
||||||
datum/updateQueueWorker/proc/init(var/list/objects, var/procName, var/list/arguments, var/cpuThreshold = 90)
|
|
||||||
src.objects = objects
|
|
||||||
src.procName = procName
|
|
||||||
src.arguments = arguments
|
|
||||||
src.cpuThreshold = cpuThreshold
|
|
||||||
|
|
||||||
killed = 0
|
|
||||||
finished = 0
|
|
||||||
|
|
||||||
datum/updateQueueWorker/proc/doWork()
|
|
||||||
// If there's nothing left to execute or we were killed, mark finished and return.
|
|
||||||
if (!objects || !objects.len) return finished()
|
|
||||||
|
|
||||||
lastStart = world.timeofday // Absolute number of ticks since the world started up
|
|
||||||
|
|
||||||
var/datum/object = objects[objects.len] // Pull out the object
|
|
||||||
objects.len-- // Remove the object from the list
|
|
||||||
|
|
||||||
if (istype(object) && !isturf(object) && !object.disposed && isnull(object.gcDestroyed)) // We only work with real objects
|
|
||||||
call(object, procName)(arglist(arguments))
|
|
||||||
|
|
||||||
// If there's nothing left to execute
|
|
||||||
// or we were killed while running the above code, mark finished and return.
|
|
||||||
if (!objects || !objects.len) return finished()
|
|
||||||
|
|
||||||
if (world.cpu > cpuThreshold)
|
|
||||||
// We don't want to force a tick into overtime!
|
|
||||||
// If the tick is about to go overtime, spawn the next update to go
|
|
||||||
// in the next tick.
|
|
||||||
uq_dbg("tick went into overtime with world.cpu = [world.cpu], deferred next update to next tick [1+(world.time / world.tick_lag)]")
|
|
||||||
|
|
||||||
spawn(1)
|
|
||||||
doWork()
|
|
||||||
else
|
|
||||||
spawn(0) // Execute anonymous function immediately as if we were in a while loop...
|
|
||||||
doWork()
|
|
||||||
|
|
||||||
datum/updateQueueWorker/proc/finished()
|
|
||||||
uq_dbg("updateQueueWorker finished.")
|
|
||||||
/**
|
|
||||||
* If the worker was killed while it was working on something, it
|
|
||||||
* should delete itself when it finally finishes working on it.
|
|
||||||
* Meanwhile, the updateQueue will have proceeded on with the rest of
|
|
||||||
* the queue. This will also terminate the spawned function that was
|
|
||||||
* created in the kill() proc.
|
|
||||||
*/
|
|
||||||
if(killed)
|
|
||||||
del(src)
|
|
||||||
|
|
||||||
finished = 1
|
|
||||||
|
|
||||||
datum/updateQueueWorker/proc/kill()
|
|
||||||
uq_dbg("updateQueueWorker killed.")
|
|
||||||
killed = 1
|
|
||||||
objects = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the worker is not done in 30 seconds after it's killed,
|
|
||||||
* we'll forcibly delete it, causing the anonymous function it was
|
|
||||||
* running to be terminated. Hasta la vista, baby.
|
|
||||||
*/
|
|
||||||
spawn(300)
|
|
||||||
del(src)
|
|
||||||
|
|
||||||
datum/updateQueueWorker/proc/start()
|
|
||||||
uq_dbg("updateQueueWorker started.")
|
|
||||||
spawn(0)
|
|
||||||
doWork()
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
/datum/processSchedulerView
|
|
||||||
|
|
||||||
/datum/processSchedulerView/Topic(href, href_list)
|
|
||||||
if (!href_list["action"])
|
|
||||||
return
|
|
||||||
|
|
||||||
switch (href_list["action"])
|
|
||||||
if ("kill")
|
|
||||||
var/toKill = href_list["name"]
|
|
||||||
processScheduler.killProcess(toKill)
|
|
||||||
refreshProcessTable()
|
|
||||||
if ("enable")
|
|
||||||
var/toEnable = href_list["name"]
|
|
||||||
processScheduler.enableProcess(toEnable)
|
|
||||||
refreshProcessTable()
|
|
||||||
if ("disable")
|
|
||||||
var/toDisable = href_list["name"]
|
|
||||||
processScheduler.disableProcess(toDisable)
|
|
||||||
refreshProcessTable()
|
|
||||||
if ("refresh")
|
|
||||||
refreshProcessTable()
|
|
||||||
|
|
||||||
/datum/processSchedulerView/proc/refreshProcessTable()
|
|
||||||
windowCall("handleRefresh", getProcessTable())
|
|
||||||
|
|
||||||
/datum/processSchedulerView/proc/windowCall(var/function, var/data = null)
|
|
||||||
usr << output(data, "processSchedulerContext.browser:[function]")
|
|
||||||
|
|
||||||
/datum/processSchedulerView/proc/getProcessTable()
|
|
||||||
var/text = "<table class=\"table table-striped\"><thead><tr><td>Name</td><td>Avg(s)</td><td>Last(s)</td><td>Highest(s)</td><td>Tickcount</td><td>Tickrate</td><td>State</td><td>Action</td></tr></thead><tbody>"
|
|
||||||
// and the context of each
|
|
||||||
for (var/list/data in processScheduler.getStatusData())
|
|
||||||
text += "<tr>"
|
|
||||||
text += "<td>[data["name"]]</td>"
|
|
||||||
text += "<td>[num2text(data["averageRunTime"]/10,3)]</td>"
|
|
||||||
text += "<td>[num2text(data["lastRunTime"]/10,3)]</td>"
|
|
||||||
text += "<td>[num2text(data["highestRunTime"]/10,3)]</td>"
|
|
||||||
text += "<td>[num2text(data["ticks"],4)]</td>"
|
|
||||||
text += "<td>[data["schedule"]]</td>"
|
|
||||||
text += "<td>[data["status"]]</td>"
|
|
||||||
text += "<td><button class=\"btn kill-btn\" data-process-name=\"[data["name"]]\" id=\"kill-[data["name"]]\">Kill</button>"
|
|
||||||
if (data["disabled"])
|
|
||||||
text += "<button class=\"btn enable-btn\" data-process-name=\"[data["name"]]\" id=\"enable-[data["name"]]\">Enable</button>"
|
|
||||||
else
|
|
||||||
text += "<button class=\"btn disable-btn\" data-process-name=\"[data["name"]]\" id=\"disable-[data["name"]]\">Disable</button>"
|
|
||||||
text += "</td>"
|
|
||||||
text += "</tr>"
|
|
||||||
|
|
||||||
text += "</tbody></table>"
|
|
||||||
return text
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getContext
|
|
||||||
* Outputs an interface showing stats for all processes.
|
|
||||||
*/
|
|
||||||
/datum/processSchedulerView/proc/getContext()
|
|
||||||
bootstrap_browse()
|
|
||||||
usr << browse('processScheduler.js', "file=processScheduler.js;display=0")
|
|
||||||
|
|
||||||
var/text = {"<html><head>
|
|
||||||
<title>Process Scheduler Detail</title>
|
|
||||||
<script type="text/javascript">var ref = '\ref[src]';</script>
|
|
||||||
[bootstrap_includes()]
|
|
||||||
<script type="text/javascript" src="processScheduler.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>Process Scheduler</h2>
|
|
||||||
<div class="btn-group">
|
|
||||||
<button id="btn-refresh" class="btn">Refresh</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>The process scheduler controls [processScheduler.getProcessCount()] loops.<h3>"}
|
|
||||||
|
|
||||||
text += "<div id=\"processTable\">"
|
|
||||||
text += getProcessTable()
|
|
||||||
text += "</div></body></html>"
|
|
||||||
|
|
||||||
usr << browse(text, "window=processSchedulerContext;size=800x600")
|
|
||||||
|
|
||||||
/datum/processSchedulerView/proc/bootstrap_browse()
|
|
||||||
usr << browse('bower_components/jquery/dist/jquery.min.js', "file=jquery.min.js;display=0")
|
|
||||||
usr << browse('bower_components/bootstrap2.3.2/bootstrap/js/bootstrap.min.js', "file=bootstrap.min.js;display=0")
|
|
||||||
usr << browse('bower_components/bootstrap2.3.2/bootstrap/css/bootstrap.min.css', "file=bootstrap.min.css;display=0")
|
|
||||||
usr << browse('bower_components/bootstrap2.3.2/bootstrap/img/glyphicons-halflings-white.png', "file=glyphicons-halflings-white.png;display=0")
|
|
||||||
usr << browse('bower_components/bootstrap2.3.2/bootstrap/img/glyphicons-halflings.png', "file=glyphicons-halflings.png;display=0")
|
|
||||||
usr << browse('bower_components/json2/json2.js', "file=json2.js;display=0")
|
|
||||||
|
|
||||||
/datum/processSchedulerView/proc/bootstrap_includes()
|
|
||||||
return {"
|
|
||||||
<link rel="stylesheet" href="bootstrap.min.css" />
|
|
||||||
<script type="text/javascript" src="json2.js"></script>
|
|
||||||
<script type="text/javascript" src="jquery.min.js"></script>
|
|
||||||
<script type="text/javascript" src="bootstrap.js"></script>
|
|
||||||
"}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/**
|
|
||||||
* testDyingUpdateQueueProcess
|
|
||||||
* This process is an example of a process using an updateQueue.
|
|
||||||
* The datums updated by this process behave badly and block the update loop
|
|
||||||
* by sleeping. If you #define UPDATE_QUEUE_DEBUG, you will see the updateQueue
|
|
||||||
* killing off its worker processes and spawning new ones to work around slow
|
|
||||||
* updates. This means that if you have a code path that sleeps for a long time
|
|
||||||
* in mob.Life once in a blue moon, the mob update loop will not hang.
|
|
||||||
*/
|
|
||||||
/datum/slowTestDatum/proc/wackyUpdateProcessName()
|
|
||||||
sleep(rand(0,20)) // Randomly REALLY slow :|
|
|
||||||
|
|
||||||
/datum/controller/process/testDyingUpdateQueueProcess
|
|
||||||
var/tmp/datum/updateQueue/updateQueueInstance
|
|
||||||
var/tmp/list/testDatums = list()
|
|
||||||
|
|
||||||
/datum/controller/process/testDyingUpdateQueueProcess/setup()
|
|
||||||
name = "Dying UpdateQueue Process"
|
|
||||||
schedule_interval = 30 // every 3 seconds
|
|
||||||
updateQueueInstance = new
|
|
||||||
for(var/i = 1, i < 30, i++)
|
|
||||||
testDatums.Add(new /datum/slowTestDatum)
|
|
||||||
|
|
||||||
/datum/controller/process/testDyingUpdateQueueProcess/doWork()
|
|
||||||
updateQueueInstance.init(testDatums, "wackyUpdateProcessName")
|
|
||||||
updateQueueInstance.Run()
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
These are simple defaults for your project.
|
|
||||||
*/
|
|
||||||
#define DEBUG
|
|
||||||
|
|
||||||
var/global/datum/processSchedulerView/processSchedulerView
|
|
||||||
|
|
||||||
world
|
|
||||||
loop_checks = 0
|
|
||||||
New()
|
|
||||||
..()
|
|
||||||
processScheduler = new
|
|
||||||
processSchedulerView = new
|
|
||||||
|
|
||||||
mob
|
|
||||||
step_size = 8
|
|
||||||
|
|
||||||
New()
|
|
||||||
..()
|
|
||||||
|
|
||||||
|
|
||||||
verb
|
|
||||||
startProcessScheduler()
|
|
||||||
set name = "Start Process Scheduler"
|
|
||||||
processScheduler.setup()
|
|
||||||
processScheduler.start()
|
|
||||||
|
|
||||||
getProcessSchedulerContext()
|
|
||||||
set name = "Get Process Scheduler Status Panel"
|
|
||||||
processSchedulerView.getContext()
|
|
||||||
|
|
||||||
runUpdateQueueTests()
|
|
||||||
set name = "Run Update Queue Testsuite"
|
|
||||||
var/datum/updateQueueTests/t = new
|
|
||||||
t.runTests()
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
/**
|
|
||||||
* testHungProcess
|
|
||||||
* This process is an example of a simple update loop process that hangs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/datum/controller/process/testHungProcess/setup()
|
|
||||||
name = "Hung Process"
|
|
||||||
schedule_interval = 30 // every 3 seconds
|
|
||||||
|
|
||||||
/datum/controller/process/testHungProcess/doWork()
|
|
||||||
sleep(1000) // FUCK
|
|
||||||
// scheck is also responsible for handling hung processes. If a process
|
|
||||||
// hangs, and later resumes, but has already been killed by the scheduler,
|
|
||||||
// scheck will force the process to bail out.
|
|
||||||
scheck()
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
/**
|
|
||||||
* testNiceProcess
|
|
||||||
* This process is an example of a simple update loop process that is
|
|
||||||
* relatively fast.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/datum/controller/process/testNiceProcess/setup()
|
|
||||||
name = "Nice Process"
|
|
||||||
schedule_interval = 10 // every second
|
|
||||||
|
|
||||||
/datum/controller/process/testNiceProcess/doWork()
|
|
||||||
sleep(rand(1,5)) // Just to pretend we're doing something
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
* testSlowProcess
|
|
||||||
* This process is an example of a simple update loop process that is slow.
|
|
||||||
* The update loop here sleeps inside to provide an example, but if you had
|
|
||||||
* a computationally intensive loop process that is simply slow, you can use
|
|
||||||
* scheck() inside the loop to force it to yield periodically according to
|
|
||||||
* the sleep_interval var. By default, scheck will cause a loop to sleep every
|
|
||||||
* 2 ticks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/datum/controller/process/testSlowProcess/setup()
|
|
||||||
name = "Slow Process"
|
|
||||||
schedule_interval = 30 // every 3 seconds
|
|
||||||
|
|
||||||
/datum/controller/process/testSlowProcess/doWork()
|
|
||||||
// set background = 1 will cause loop constructs to sleep periodically,
|
|
||||||
// whenever the BYOND scheduler deems it productive to do so.
|
|
||||||
// This behavior is not always sufficient, nor is it always consistent.
|
|
||||||
// Rather than leaving it up to the BYOND scheduler, we can control it
|
|
||||||
// ourselves and leave nothing to the black box.
|
|
||||||
set background = 1
|
|
||||||
|
|
||||||
for(var/i=1,i<30,i++)
|
|
||||||
// Just to pretend we're doing something here
|
|
||||||
sleep(rand(3, 5))
|
|
||||||
|
|
||||||
// Forces this loop to yield(sleep) periodically.
|
|
||||||
scheck()
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
var/global/list/updateQueueTestCount = list()
|
|
||||||
|
|
||||||
/datum/updateQueueTests
|
|
||||||
var/start
|
|
||||||
proc
|
|
||||||
runTests()
|
|
||||||
world << "<b>Running 9 tests...</b>"
|
|
||||||
testUpdateQueuePerformance()
|
|
||||||
sleep(1)
|
|
||||||
testInplace()
|
|
||||||
sleep(1)
|
|
||||||
testInplaceUpdateQueuePerformance()
|
|
||||||
sleep(1)
|
|
||||||
testUpdateQueueReinit()
|
|
||||||
sleep(1)
|
|
||||||
testCrashingQueue()
|
|
||||||
sleep(1)
|
|
||||||
testEmptyQueue()
|
|
||||||
sleep(1)
|
|
||||||
testManySlowItemsInQueue()
|
|
||||||
sleep(1)
|
|
||||||
testVariableWorkerTimeout()
|
|
||||||
sleep(1)
|
|
||||||
testReallySlowItemInQueue()
|
|
||||||
sleep(1)
|
|
||||||
world << "<b>Finished!</b>"
|
|
||||||
|
|
||||||
beginTiming()
|
|
||||||
start = world.time
|
|
||||||
|
|
||||||
endTiming(text)
|
|
||||||
var/time = (world.time - start) / world.tick_lag
|
|
||||||
world << {"<b><font color="blue">Performance - [text] - <font color="green">[time]</font> ticks</font></b>"}
|
|
||||||
|
|
||||||
getCount()
|
|
||||||
return updateQueueTestCount[updateQueueTestCount.len]
|
|
||||||
|
|
||||||
incrementTestCount()
|
|
||||||
updateQueueTestCount.len++
|
|
||||||
updateQueueTestCount[updateQueueTestCount.len] = 0
|
|
||||||
|
|
||||||
assertCountEquals(count, text)
|
|
||||||
assertThat(getCount() == count, text)
|
|
||||||
|
|
||||||
assertCountLessThan(count, text)
|
|
||||||
assertThat(getCount() < count, text)
|
|
||||||
|
|
||||||
assertCountGreaterThan(count, text)
|
|
||||||
assertThat(getCount() > count, text)
|
|
||||||
|
|
||||||
assertThat(condition, text)
|
|
||||||
if (condition)
|
|
||||||
world << {"<font color="green"><b>PASS</b></font>: [text]"}
|
|
||||||
else
|
|
||||||
world << {"<b><font color="red">FAIL</font>: [text]</b>"}
|
|
||||||
|
|
||||||
testUpdateQueuePerformance()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
for(var/i=1,i<=100000,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
|
|
||||||
var/datum/updateQueue/uq = new(objs)
|
|
||||||
|
|
||||||
beginTiming()
|
|
||||||
uq.Run()
|
|
||||||
endTiming("updating 100000 simple objects")
|
|
||||||
|
|
||||||
assertCountEquals(100000, "test that update queue updates all objects expected")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
testUpdateQueueReinit()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
for(var/i=1,i<=100,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
|
|
||||||
var/datum/updateQueue/uq = new(objs)
|
|
||||||
uq.Run()
|
|
||||||
objs = new
|
|
||||||
|
|
||||||
for(var/i=1,i<=100,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
uq.init(objs)
|
|
||||||
uq.Run()
|
|
||||||
assertCountEquals(200, "test that update queue reinitializes properly and updates all objects as expected.")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
testInplace()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
for(var/i=1,i<=100,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
var/datum/updateQueue/uq = new(objects = objs, inplace = 1)
|
|
||||||
uq.Run()
|
|
||||||
assertThat(objs.len == 0, "test that update queue inplace option really works inplace")
|
|
||||||
assertCountEquals(100, "test that inplace update queue updates the right number of objects")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
testInplaceUpdateQueuePerformance()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
for(var/i=1,i<=100000,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
|
|
||||||
var/datum/updateQueue/uq = new(objs)
|
|
||||||
|
|
||||||
beginTiming()
|
|
||||||
uq.Run()
|
|
||||||
endTiming("updating 100000 simple objects in place")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
testCrashingQueue()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
for(var/i=1,i<=10,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
objs.Add(new /datum/uqTestDatum/crasher(updateQueueTestCount.len))
|
|
||||||
for(var/i=1,i<=10,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
|
|
||||||
var/datum/updateQueue/uq = new(objs)
|
|
||||||
uq.Run()
|
|
||||||
assertCountEquals(20, "test that update queue handles crashed update procs OK")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
testEmptyQueue()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
var/datum/updateQueue/uq = new(objs)
|
|
||||||
uq.Run()
|
|
||||||
assertCountEquals(0, "test that update queue doesn't barf on empty lists")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
testManySlowItemsInQueue()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
for(var/i=1,i<=30,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/slow(updateQueueTestCount.len))
|
|
||||||
var/datum/updateQueue/uq = new(objs)
|
|
||||||
uq.Run()
|
|
||||||
assertCountEquals(30, "test that update queue slows down execution if too many objects are slow to update")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
testVariableWorkerTimeout()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
for(var/i=1,i<=20,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/slow(updateQueueTestCount.len))
|
|
||||||
var/datum/updateQueue/uq = new(objs, workerTimeout=6)
|
|
||||||
uq.Run()
|
|
||||||
assertCountEquals(20, "test that variable worker timeout works properly")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
testReallySlowItemInQueue()
|
|
||||||
incrementTestCount()
|
|
||||||
var/list/objs = new
|
|
||||||
for(var/i=1,i<=10,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
objs.Add(new /datum/uqTestDatum/reallySlow(updateQueueTestCount.len))
|
|
||||||
for(var/i=1,i<=10,i++)
|
|
||||||
objs.Add(new /datum/uqTestDatum/fast(updateQueueTestCount.len))
|
|
||||||
var/datum/updateQueue/uq = new(objs)
|
|
||||||
uq.Run()
|
|
||||||
assertCountEquals(20, "test that update queue skips objects that are too slow to update")
|
|
||||||
del(objs)
|
|
||||||
del(uq)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
datum/uqTestDatum
|
|
||||||
var/testNum
|
|
||||||
New(testNum)
|
|
||||||
..()
|
|
||||||
src.testNum = testNum
|
|
||||||
proc/update()
|
|
||||||
updateQueueTestCount[testNum]++
|
|
||||||
proc/lag(cycles)
|
|
||||||
set background = 1
|
|
||||||
for(var/i=0,i<cycles,)
|
|
||||||
i++
|
|
||||||
datum/uqTestDatum/fast
|
|
||||||
|
|
||||||
datum/uqTestDatum/slow
|
|
||||||
update()
|
|
||||||
set background = 1
|
|
||||||
var/start = world.timeofday
|
|
||||||
while(world.timeofday - start < 5) // lag 4 deciseconds
|
|
||||||
..()
|
|
||||||
|
|
||||||
datum/uqTestDatum/reallySlow
|
|
||||||
update()
|
|
||||||
set background = 1
|
|
||||||
var/start = world.timeofday
|
|
||||||
while(world.timeofday - start < 300) // lag 30 seconds
|
|
||||||
..()
|
|
||||||
|
|
||||||
datum/uqTestDatum/crasher
|
|
||||||
update()
|
|
||||||
CRASH("I crashed! (I am supposed to crash XD)")
|
|
||||||
..() // This should do nothing lol
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/**
|
|
||||||
* testUpdateQueueProcess
|
|
||||||
* This process is an example of a process using an updateQueue.
|
|
||||||
* The datums updated by this process behave nicely and do not block.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/datum/fastTestDatum/proc/wackyUpdateProcessName()
|
|
||||||
sleep(prob(10)) // Pretty quick, usually instant
|
|
||||||
|
|
||||||
/datum/controller/process/testUpdateQueueProcess
|
|
||||||
var/tmp/datum/updateQueue/updateQueueInstance
|
|
||||||
var/tmp/list/testDatums = list()
|
|
||||||
|
|
||||||
/datum/controller/process/testUpdateQueueProcess/setup()
|
|
||||||
name = "UpdateQueue Process"
|
|
||||||
schedule_interval = 20 // every 2 seconds
|
|
||||||
updateQueueInstance = new
|
|
||||||
for(var/i = 1, i < 30, i++)
|
|
||||||
testDatums.Add(new /datum/fastTestDatum)
|
|
||||||
|
|
||||||
/datum/controller/process/testUpdateQueueProcess/doWork()
|
|
||||||
updateQueueInstance.init(testDatums, "wackyUpdateProcessName")
|
|
||||||
updateQueueInstance.Run()
|
|
||||||
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
/**
|
|
||||||
* testBadZombieProcess
|
|
||||||
* This process is an example of a simple update loop process that hangs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/datum/controller/process/testZombieProcess/setup()
|
|
||||||
name = "Zombie Process"
|
|
||||||
schedule_interval = 30 // every 3 seconds
|
|
||||||
|
|
||||||
/datum/controller/process/testZombieProcess/doWork()
|
|
||||||
for (var/i = 0, i < 1000, i++)
|
|
||||||
sleep(1)
|
|
||||||
scheck()
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
/datum/controller/process/air/setup()
|
/datum/controller/process/air/setup()
|
||||||
name = "air"
|
name = "air"
|
||||||
schedule_interval = 20 // every 2 seconds
|
schedule_interval = 20 // every 2 seconds
|
||||||
|
start_delay = 4
|
||||||
|
|
||||||
if(!air_master)
|
if(!air_master)
|
||||||
air_master = new
|
air_master = new
|
||||||
|
|||||||
@@ -1,10 +1,42 @@
|
|||||||
|
|
||||||
|
// We manually initialize the alarm handlers instead of looping over all existing types
|
||||||
|
// to make it possible to write: camera.triggerAlarm() rather than alarm_manager.managers[datum/alarm_handler/camera].triggerAlarm() or a variant thereof.
|
||||||
|
/var/global/datum/alarm_handler/atmosphere/atmosphere_alarm = new()
|
||||||
|
/var/global/datum/alarm_handler/camera/camera_alarm = new()
|
||||||
|
/var/global/datum/alarm_handler/fire/fire_alarm = new()
|
||||||
|
/var/global/datum/alarm_handler/motion/motion_alarm = new()
|
||||||
|
/var/global/datum/alarm_handler/power/power_alarm = new()
|
||||||
|
|
||||||
|
// Alarm Manager, the manager for alarms.
|
||||||
|
var/datum/controller/process/alarm/alarm_manager
|
||||||
|
|
||||||
|
/datum/controller/process/alarm
|
||||||
|
var/list/datum/alarm/all_handlers
|
||||||
|
|
||||||
/datum/controller/process/alarm/setup()
|
/datum/controller/process/alarm/setup()
|
||||||
name = "alarm"
|
name = "alarm"
|
||||||
schedule_interval = 20 // every 2 seconds
|
schedule_interval = 20 // every 2 seconds
|
||||||
|
all_handlers = list(atmosphere_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
|
||||||
|
alarm_manager = src
|
||||||
|
|
||||||
/datum/controller/process/alarm/doWork()
|
/datum/controller/process/alarm/doWork()
|
||||||
alarm_manager.fire()
|
for(last_object in all_handlers)
|
||||||
|
var/datum/alarm_handler/AH = last_object
|
||||||
|
AH.process()
|
||||||
|
SCHECK
|
||||||
|
|
||||||
/datum/controller/process/alarm/getStatName()
|
/datum/controller/process/alarm/proc/active_alarms()
|
||||||
var/list/alarms = alarm_manager.active_alarms()
|
var/list/all_alarms = new
|
||||||
return ..()+"([alarms.len])"
|
for(var/datum/alarm_handler/AH in all_handlers)
|
||||||
|
var/list/alarms = AH.alarms
|
||||||
|
all_alarms += alarms
|
||||||
|
|
||||||
|
return all_alarms
|
||||||
|
|
||||||
|
/datum/controller/process/alarm/proc/number_of_active_alarms()
|
||||||
|
var/list/alarms = active_alarms()
|
||||||
|
return alarms.len
|
||||||
|
|
||||||
|
/datum/controller/process/alarm/statProcess()
|
||||||
|
..()
|
||||||
|
stat(null, "[number_of_active_alarms()] alarm\s")
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
var/datum/controller/process/chemistry/chemistryProcess
|
var/datum/controller/process/chemistry/chemistryProcess
|
||||||
|
|
||||||
/datum/controller/process/chemistry
|
/datum/controller/process/chemistry
|
||||||
var/tmp/datum/updateQueue/updateQueueInstance
|
|
||||||
var/list/active_holders
|
var/list/active_holders
|
||||||
var/list/chemical_reactions
|
var/list/chemical_reactions
|
||||||
var/list/chemical_reagents
|
var/list/chemical_reagents
|
||||||
@@ -9,23 +8,24 @@ var/datum/controller/process/chemistry/chemistryProcess
|
|||||||
/datum/controller/process/chemistry/setup()
|
/datum/controller/process/chemistry/setup()
|
||||||
name = "chemistry"
|
name = "chemistry"
|
||||||
schedule_interval = 20 // every 2 seconds
|
schedule_interval = 20 // every 2 seconds
|
||||||
updateQueueInstance = new
|
|
||||||
chemistryProcess = src
|
chemistryProcess = src
|
||||||
active_holders = list()
|
active_holders = list()
|
||||||
chemical_reactions = chemical_reactions_list
|
chemical_reactions = chemical_reactions_list
|
||||||
chemical_reagents = chemical_reagents_list
|
chemical_reagents = chemical_reagents_list
|
||||||
|
|
||||||
/datum/controller/process/chemistry/getStatName()
|
/datum/controller/process/chemistry/statProcess()
|
||||||
return ..()+"([active_holders.len])"
|
..()
|
||||||
|
stat(null, "[active_holders.len] reagent holder\s")
|
||||||
|
|
||||||
/datum/controller/process/chemistry/doWork()
|
/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())
|
if(!holder.process_reactions())
|
||||||
active_holders -= holder
|
active_holders -= holder
|
||||||
scheck()
|
SCHECK
|
||||||
|
|
||||||
/datum/controller/process/chemistry/proc/mark_for_update(var/datum/reagents/holder)
|
/datum/controller/process/chemistry/proc/mark_for_update(var/datum/reagents/holder)
|
||||||
if(holder in active_holders)
|
if(holder in active_holders)
|
||||||
return
|
return
|
||||||
|
|
||||||
//Process once, right away. If we still need to continue then add to the active_holders list and continue later
|
//Process once, right away. If we still need to continue then add to the active_holders list and continue later
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
/datum/controller/process/disease
|
|
||||||
var/tmp/datum/updateQueue/updateQueueInstance
|
|
||||||
|
|
||||||
/datum/controller/process/disease/setup()
|
|
||||||
name = "disease"
|
|
||||||
schedule_interval = 20 // every 2 seconds
|
|
||||||
updateQueueInstance = new
|
|
||||||
|
|
||||||
/datum/controller/process/disease/doWork()
|
|
||||||
updateQueueInstance.init(active_diseases, "process")
|
|
||||||
updateQueueInstance.Run()
|
|
||||||
|
|
||||||
/datum/controller/process/disease/getStatName()
|
|
||||||
return ..()+"([active_diseases.len])"
|
|
||||||
@@ -1,13 +1,18 @@
|
|||||||
|
// The time a datum was destroyed by the GC, or null if it hasn't been
|
||||||
|
/datum/var/gcDestroyed
|
||||||
|
|
||||||
|
#define GC_COLLECTIONS_PER_RUN 300
|
||||||
|
#define GC_COLLECTION_TIMEOUT (30 SECONDS)
|
||||||
|
#define GC_FORCE_DEL_PER_RUN 30
|
||||||
|
|
||||||
var/datum/controller/process/garbage_collector/garbage_collector
|
var/datum/controller/process/garbage_collector/garbage_collector
|
||||||
var/list/delayed_garbage = list()
|
var/list/delayed_garbage = list()
|
||||||
|
|
||||||
/datum/controller/process/garbage_collector
|
/datum/controller/process/garbage_collector
|
||||||
var/garbage_collect = 1 // Whether or not to actually do work
|
var/garbage_collect = 1 // Whether or not to actually do work
|
||||||
var/collection_timeout = 300 //deciseconds to wait to let running procs finish before we just say fuck it and force del() the object
|
var/total_dels = 0 // number of total del()'s
|
||||||
var/max_checks_multiplier = 5 //multiplier (per-decisecond) for calculating max number of tests per tick. These tests check if our GC'd objects are actually GC'd
|
var/tick_dels = 0 // number of del()'s we've done this tick
|
||||||
var/max_forcedel_multiplier = 1 //multiplier (per-decisecond) for calculating max number of force del() calls per tick.
|
var/soft_dels = 0
|
||||||
|
|
||||||
var/dels = 0 // number of del()'s we've done this tick
|
|
||||||
var/hard_dels = 0 // number of hard dels in total
|
var/hard_dels = 0 // number of hard dels in total
|
||||||
var/list/destroyed = list() // list of refID's of things that should be garbage collected
|
var/list/destroyed = list() // list of refID's of things that should be garbage collected
|
||||||
// refID's are associated with the time at which they time out and need to be manually del()
|
// refID's are associated with the time at which they time out and need to be manually del()
|
||||||
@@ -18,7 +23,8 @@ var/list/delayed_garbage = list()
|
|||||||
|
|
||||||
/datum/controller/process/garbage_collector/setup()
|
/datum/controller/process/garbage_collector/setup()
|
||||||
name = "garbage"
|
name = "garbage"
|
||||||
schedule_interval = 2 SECONDS
|
schedule_interval = 5 SECONDS
|
||||||
|
start_delay = 3
|
||||||
|
|
||||||
if(!garbage_collector)
|
if(!garbage_collector)
|
||||||
garbage_collector = src
|
garbage_collector = src
|
||||||
@@ -36,38 +42,14 @@ world/loop_checks = 0
|
|||||||
if(!garbage_collect)
|
if(!garbage_collect)
|
||||||
return
|
return
|
||||||
|
|
||||||
dels = 0
|
tick_dels = 0
|
||||||
var/time_to_kill = world.time - collection_timeout // Anything qdel() but not GC'd BEFORE this time needs to be manually del()
|
var/time_to_kill = world.time - GC_COLLECTION_TIMEOUT
|
||||||
var/checkRemain = max_checks_multiplier * schedule_interval
|
var/checkRemain = GC_COLLECTIONS_PER_RUN
|
||||||
var/maxDels = max_forcedel_multiplier * schedule_interval
|
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: [jointext(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)
|
while(destroyed.len && --checkRemain >= 0)
|
||||||
if(dels >= maxDels)
|
if(remaining_force_dels <= 0)
|
||||||
#ifdef GC_DEBUG
|
#ifdef GC_DEBUG
|
||||||
testing("GC: Reached max force dels per tick [dels] vs [maxDels]")
|
testing("GC: Reached max force dels per tick [dels] vs [maxDels]")
|
||||||
#endif
|
#endif
|
||||||
@@ -88,13 +70,22 @@ world/loop_checks = 0
|
|||||||
testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --")
|
testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --")
|
||||||
logging["[A.type]"]++
|
logging["[A.type]"]++
|
||||||
del(A)
|
del(A)
|
||||||
++dels
|
|
||||||
++hard_dels
|
hard_dels++
|
||||||
#ifdef GC_DEBUG
|
remaining_force_dels--
|
||||||
else
|
else
|
||||||
|
#ifdef GC_DEBUG
|
||||||
testing("GC: [refID] properly GC'd at [world.time] with timeout [GCd_at_time]")
|
testing("GC: [refID] properly GC'd at [world.time] with timeout [GCd_at_time]")
|
||||||
#endif
|
#endif
|
||||||
|
soft_dels++
|
||||||
|
tick_dels++
|
||||||
|
total_dels++
|
||||||
destroyed.Cut(1, 2)
|
destroyed.Cut(1, 2)
|
||||||
|
SCHECK
|
||||||
|
|
||||||
|
#undef GC_FORCE_DEL_PER_TICK
|
||||||
|
#undef GC_COLLECTION_TIMEOUT
|
||||||
|
#undef GC_COLLECTIONS_PER_TICK
|
||||||
|
|
||||||
#ifdef GC_FINDREF
|
#ifdef GC_FINDREF
|
||||||
/datum/controller/process/garbage_collector/proc/LookForRefs(var/datum/D, var/list/targ)
|
/datum/controller/process/garbage_collector/proc/LookForRefs(var/datum/D, var/list/targ)
|
||||||
@@ -132,8 +123,11 @@ world/loop_checks = 0
|
|||||||
destroyed -= "\ref[A]" // Removing any previous references that were GC'd so that the current object will be at the end of the list.
|
destroyed -= "\ref[A]" // Removing any previous references that were GC'd so that the current object will be at the end of the list.
|
||||||
destroyed["\ref[A]"] = world.time
|
destroyed["\ref[A]"] = world.time
|
||||||
|
|
||||||
/datum/controller/process/garbage_collector/getStatName()
|
/datum/controller/process/garbage_collector/statProcess()
|
||||||
return ..()+"([garbage_collector.destroyed.len]/[garbage_collector.dels]/[garbage_collector.hard_dels])"
|
..()
|
||||||
|
stat(null, "[garbage_collect ? "On" : "Off"], [destroyed.len] queued")
|
||||||
|
stat(null, "Dels: [total_dels], [soft_dels] soft, [hard_dels] hard, [tick_dels] last run")
|
||||||
|
|
||||||
|
|
||||||
// Tests if an atom has been deleted.
|
// Tests if an atom has been deleted.
|
||||||
/proc/deleted(atom/A)
|
/proc/deleted(atom/A)
|
||||||
@@ -149,7 +143,7 @@ world/loop_checks = 0
|
|||||||
crash_with("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
|
crash_with("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
|
||||||
del(A)
|
del(A)
|
||||||
if(garbage_collector)
|
if(garbage_collector)
|
||||||
garbage_collector.dels++
|
garbage_collector.total_dels++
|
||||||
garbage_collector.hard_dels++
|
garbage_collector.hard_dels++
|
||||||
else if(isnull(A.gcDestroyed))
|
else if(isnull(A.gcDestroyed))
|
||||||
// Let our friend know they're about to get collected
|
// Let our friend know they're about to get collected
|
||||||
@@ -263,4 +257,4 @@ world/loop_checks = 0
|
|||||||
|
|
||||||
#ifdef GC_FINDREF
|
#ifdef GC_FINDREF
|
||||||
#undef GC_FINDREF
|
#undef GC_FINDREF
|
||||||
#endif
|
#endif
|
||||||
@@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
/datum/controller/process/inactivity/doWork()
|
/datum/controller/process/inactivity/doWork()
|
||||||
if(config.kick_inactive)
|
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(!C.holder && C.is_afk(config.kick_inactive MINUTES))
|
||||||
if(!istype(C.mob, /mob/observer/dead))
|
if(!istype(C.mob, /mob/observer/dead))
|
||||||
log_access("AFK: [key_name(C)]")
|
log_access("AFK: [key_name(C)]")
|
||||||
C << "<SPAN CLASS='warning'>You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.</SPAN>"
|
C << "<SPAN CLASS='warning'>You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.</SPAN>"
|
||||||
del(C) // Don't qdel, cannot override finalize_qdel behaviour for clients.
|
del(C) // Don't qdel, cannot override finalize_qdel behaviour for clients.
|
||||||
scheck()
|
SCHECK
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
/datum/controller/process/machinery/setup()
|
/datum/controller/process/machinery/setup()
|
||||||
name = "machinery"
|
name = "machinery"
|
||||||
schedule_interval = 20 // every 2 seconds
|
schedule_interval = 20 // every 2 seconds
|
||||||
|
start_delay = 12
|
||||||
|
|
||||||
/datum/controller/process/machinery/doWork()
|
/datum/controller/process/machinery/doWork()
|
||||||
internal_sort()
|
internal_sort()
|
||||||
@@ -17,12 +18,9 @@
|
|||||||
machines = dd_sortedObjectList(machines)
|
machines = dd_sortedObjectList(machines)
|
||||||
|
|
||||||
/datum/controller/process/machinery/proc/internal_process_machinery()
|
/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 && !M.gcDestroyed)
|
||||||
#ifdef PROFILE_MACHINES
|
|
||||||
var/time_start = world.timeofday
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(M.process() == PROCESS_KILL)
|
if(M.process() == PROCESS_KILL)
|
||||||
//M.inMachineList = 0 We don't use this debugging function
|
//M.inMachineList = 0 We don't use this debugging function
|
||||||
machines.Remove(M)
|
machines.Remove(M)
|
||||||
@@ -31,41 +29,39 @@
|
|||||||
if(M && M.use_power)
|
if(M && M.use_power)
|
||||||
M.auto_use_power()
|
M.auto_use_power()
|
||||||
|
|
||||||
#ifdef PROFILE_MACHINES
|
SCHECK
|
||||||
var/time_end = world.timeofday
|
|
||||||
|
|
||||||
if(!(M.type in machine_profiling))
|
|
||||||
machine_profiling[M.type] = 0
|
|
||||||
|
|
||||||
machine_profiling[M.type] += (time_end - time_start)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
scheck()
|
|
||||||
|
|
||||||
/datum/controller/process/machinery/proc/internal_process_power()
|
/datum/controller/process/machinery/proc/internal_process_power()
|
||||||
for(var/datum/powernet/powerNetwork in powernets)
|
for(last_object in powernets)
|
||||||
if(istype(powerNetwork) && !powerNetwork.disposed)
|
var/datum/powernet/powerNetwork = last_object
|
||||||
|
if(istype(powerNetwork) && isnull(powerNetwork.gcDestroyed))
|
||||||
powerNetwork.reset()
|
powerNetwork.reset()
|
||||||
scheck()
|
SCHECK
|
||||||
continue
|
continue
|
||||||
|
|
||||||
powernets.Remove(powerNetwork)
|
powernets.Remove(powerNetwork)
|
||||||
|
|
||||||
/datum/controller/process/machinery/proc/internal_process_power_drain()
|
/datum/controller/process/machinery/proc/internal_process_power_drain()
|
||||||
// Currently only used by powersinks. These items get priority processed before machinery
|
// 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.
|
if(!I.pwr_drain()) // 0 = Process Kill, remove from processing list.
|
||||||
processing_power_items.Remove(I)
|
processing_power_items.Remove(I)
|
||||||
scheck()
|
SCHECK
|
||||||
|
|
||||||
/datum/controller/process/machinery/proc/internal_process_pipenets()
|
/datum/controller/process/machinery/proc/internal_process_pipenets()
|
||||||
for(var/datum/pipe_network/pipeNetwork in pipe_networks)
|
for(last_object in pipe_networks)
|
||||||
if(istype(pipeNetwork) && !pipeNetwork.disposed)
|
var/datum/pipe_network/pipeNetwork = last_object
|
||||||
|
if(istype(pipeNetwork) && isnull(pipeNetwork.gcDestroyed))
|
||||||
pipeNetwork.process()
|
pipeNetwork.process()
|
||||||
scheck()
|
SCHECK
|
||||||
continue
|
continue
|
||||||
|
|
||||||
pipe_networks.Remove(pipeNetwork)
|
pipe_networks.Remove(pipeNetwork)
|
||||||
|
|
||||||
/datum/controller/process/machinery/getStatName()
|
/datum/controller/process/machinery/statProcess()
|
||||||
return ..()+"(MCH:[machines.len] PWR:[powernets.len] PIP:[pipe_networks.len])"
|
..()
|
||||||
|
stat(null, "[machines.len] machines")
|
||||||
|
stat(null, "[powernets.len] powernets")
|
||||||
|
stat(null, "[pipe_networks.len] pipenets")
|
||||||
|
stat(null, "[processing_power_items.len] power item\s")
|
||||||
@@ -4,20 +4,26 @@
|
|||||||
/datum/controller/process/mob/setup()
|
/datum/controller/process/mob/setup()
|
||||||
name = "mob"
|
name = "mob"
|
||||||
schedule_interval = 20 // every 2 seconds
|
schedule_interval = 20 // every 2 seconds
|
||||||
updateQueueInstance = new
|
start_delay = 16
|
||||||
|
|
||||||
/datum/controller/process/mob/started()
|
/datum/controller/process/mob/started()
|
||||||
..()
|
..()
|
||||||
if(!updateQueueInstance)
|
if(!mob_list)
|
||||||
if(!mob_list)
|
mob_list = list()
|
||||||
mob_list = list()
|
|
||||||
else if(mob_list.len)
|
|
||||||
updateQueueInstance = new
|
|
||||||
|
|
||||||
/datum/controller/process/mob/doWork()
|
/datum/controller/process/mob/doWork()
|
||||||
if(updateQueueInstance)
|
for(last_object in mob_list)
|
||||||
updateQueueInstance.init(mob_list, "Life")
|
var/mob/M = last_object
|
||||||
updateQueueInstance.Run()
|
if(isnull(M.gcDestroyed))
|
||||||
|
try
|
||||||
|
M.Life()
|
||||||
|
catch(var/exception/e)
|
||||||
|
catchException(e, M)
|
||||||
|
SCHECK
|
||||||
|
else
|
||||||
|
catchBadType(M)
|
||||||
|
mob_list -= M
|
||||||
|
|
||||||
/datum/controller/process/mob/getStatName()
|
/datum/controller/process/mob/statProcess()
|
||||||
return ..()+"([mob_list.len])"
|
..()
|
||||||
|
stat(null, "[mob_list.len] mobs")
|
||||||
@@ -1,14 +1,19 @@
|
|||||||
/datum/controller/process/nanoui
|
|
||||||
var/tmp/datum/updateQueue/updateQueueInstance
|
|
||||||
|
|
||||||
/datum/controller/process/nanoui/setup()
|
/datum/controller/process/nanoui/setup()
|
||||||
name = "nanoui"
|
name = "nanoui"
|
||||||
schedule_interval = 10 // every 1 second
|
schedule_interval = 20 // every 2 seconds
|
||||||
updateQueueInstance = new
|
|
||||||
|
/datum/controller/process/nanoui/statProcess()
|
||||||
|
..()
|
||||||
|
stat(null, "[nanomanager.processing_uis.len] UIs")
|
||||||
|
|
||||||
/datum/controller/process/nanoui/doWork()
|
/datum/controller/process/nanoui/doWork()
|
||||||
updateQueueInstance.init(nanomanager.processing_uis, "process")
|
for(last_object in nanomanager.processing_uis)
|
||||||
updateQueueInstance.Run()
|
var/datum/nanoui/NUI = last_object
|
||||||
|
if(istype(NUI) && isnull(NUI.gcDestroyed))
|
||||||
/datum/controller/process/nanoui/getStatName()
|
try
|
||||||
return ..()+"([nanomanager.processing_uis.len])"
|
NUI.process()
|
||||||
|
catch(var/exception/e)
|
||||||
|
catchException(e, NUI)
|
||||||
|
else
|
||||||
|
catchBadType(NUI)
|
||||||
|
nanomanager.processing_uis -= NUI
|
||||||
@@ -1,24 +1,26 @@
|
|||||||
var/global/list/object_profiling = list()
|
|
||||||
/datum/controller/process/obj
|
|
||||||
var/tmp/datum/updateQueue/updateQueueInstance
|
|
||||||
|
|
||||||
/datum/controller/process/obj/setup()
|
/datum/controller/process/obj/setup()
|
||||||
name = "obj"
|
name = "obj"
|
||||||
schedule_interval = 20 // every 2 seconds
|
schedule_interval = 20 // every 2 seconds
|
||||||
updateQueueInstance = new
|
start_delay = 8
|
||||||
|
|
||||||
/datum/controller/process/obj/started()
|
/datum/controller/process/obj/started()
|
||||||
..()
|
..()
|
||||||
if(!updateQueueInstance)
|
if(!processing_objects)
|
||||||
if(!processing_objects)
|
processing_objects = list()
|
||||||
processing_objects = list()
|
|
||||||
else if(processing_objects.len)
|
|
||||||
updateQueueInstance = new
|
|
||||||
|
|
||||||
/datum/controller/process/obj/doWork()
|
/datum/controller/process/obj/doWork()
|
||||||
if(updateQueueInstance)
|
for(last_object in processing_objects)
|
||||||
updateQueueInstance.init(processing_objects, "process")
|
var/datum/O = last_object
|
||||||
updateQueueInstance.Run()
|
if(isnull(O.gcDestroyed))
|
||||||
|
try
|
||||||
|
O:process()
|
||||||
|
catch(var/exception/e)
|
||||||
|
catchException(e, O)
|
||||||
|
SCHECK
|
||||||
|
else
|
||||||
|
catchBadType(O)
|
||||||
|
processing_objects -= O
|
||||||
|
|
||||||
/datum/controller/process/obj/getStatName()
|
/datum/controller/process/obj/statProcess()
|
||||||
return ..()+"([processing_objects.len])"
|
..()
|
||||||
|
stat(null, "[processing_objects.len] objects")
|
||||||
133
code/controllers/Processes/scheduler.dm
Normal file
133
code/controllers/Processes/scheduler.dm
Normal file
@@ -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)
|
||||||
@@ -5,10 +5,12 @@ var/global/list/turf/processing_turfs = list()
|
|||||||
schedule_interval = 20 // every 2 seconds
|
schedule_interval = 20 // every 2 seconds
|
||||||
|
|
||||||
/datum/controller/process/turf/doWork()
|
/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)
|
if(T.process() == PROCESS_KILL)
|
||||||
processing_turfs.Remove(T)
|
processing_turfs.Remove(T)
|
||||||
scheck()
|
SCHECK
|
||||||
|
|
||||||
/datum/controller/process/turf/getStatName()
|
/datum/controller/process/turf/statProcess()
|
||||||
return ..()+"([processing_turfs.len])"
|
..()
|
||||||
|
stat(null, "[processing_turfs.len] turf\s")
|
||||||
@@ -21,6 +21,7 @@ var/list/gamemode_cache = list()
|
|||||||
var/log_pda = 0 // log pda messages
|
var/log_pda = 0 // log pda messages
|
||||||
var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
|
var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
|
||||||
var/log_runtime = 0 // logs world.log to a file
|
var/log_runtime = 0 // logs world.log to a file
|
||||||
|
var/log_world_output = 0 // log world.log << messages
|
||||||
var/sql_enabled = 0 // for sql switching
|
var/sql_enabled = 0 // for sql switching
|
||||||
var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
|
var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
|
||||||
var/allow_vote_restart = 0 // allow votes to restart
|
var/allow_vote_restart = 0 // allow votes to restart
|
||||||
@@ -327,6 +328,9 @@ var/list/gamemode_cache = list()
|
|||||||
if ("log_pda")
|
if ("log_pda")
|
||||||
config.log_pda = 1
|
config.log_pda = 1
|
||||||
|
|
||||||
|
if ("log_world_output")
|
||||||
|
config.log_world_output = 1
|
||||||
|
|
||||||
if ("log_hrefs")
|
if ("log_hrefs")
|
||||||
config.log_hrefs = 1
|
config.log_hrefs = 1
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ datum/controller/game_controller/proc/setup_objects()
|
|||||||
admin_notice("<span class='danger'>Initializing objects</span>", R_DEBUG)
|
admin_notice("<span class='danger'>Initializing objects</span>", R_DEBUG)
|
||||||
sleep(-1)
|
sleep(-1)
|
||||||
for(var/atom/movable/object in world)
|
for(var/atom/movable/object in world)
|
||||||
object.initialize()
|
if(isnull(object.gcDestroyed))
|
||||||
|
object.initialize()
|
||||||
|
|
||||||
admin_notice("<span class='danger'>Initializing areas</span>", R_DEBUG)
|
admin_notice("<span class='danger'>Initializing areas</span>", R_DEBUG)
|
||||||
sleep(-1)
|
sleep(-1)
|
||||||
|
|||||||
@@ -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
|
|
||||||
*/
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// We manually initialize the alarm handlers instead of looping over all existing types
|
|
||||||
// to make it possible to write: camera.triggerAlarm() rather than alarm_manager.managers[datum/alarm_handler/camera].triggerAlarm() or a variant thereof.
|
|
||||||
/var/global/datum/alarm_handler/atmosphere/atmosphere_alarm = new()
|
|
||||||
/var/global/datum/alarm_handler/camera/camera_alarm = new()
|
|
||||||
/var/global/datum/alarm_handler/fire/fire_alarm = new()
|
|
||||||
/var/global/datum/alarm_handler/motion/motion_alarm = new()
|
|
||||||
/var/global/datum/alarm_handler/power/power_alarm = new()
|
|
||||||
|
|
||||||
/datum/subsystem/alarm
|
|
||||||
name = "Alarm"
|
|
||||||
var/list/datum/alarm/all_handlers
|
|
||||||
|
|
||||||
/datum/subsystem/alarm/New()
|
|
||||||
all_handlers = list(atmosphere_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
|
|
||||||
|
|
||||||
/datum/subsystem/alarm/fire()
|
|
||||||
for(var/datum/alarm_handler/AH in all_handlers)
|
|
||||||
AH.process()
|
|
||||||
|
|
||||||
/datum/subsystem/alarm/proc/active_alarms()
|
|
||||||
var/list/all_alarms = new
|
|
||||||
for(var/datum/alarm_handler/AH in all_handlers)
|
|
||||||
var/list/alarms = AH.alarms
|
|
||||||
all_alarms += alarms
|
|
||||||
|
|
||||||
return all_alarms
|
|
||||||
|
|
||||||
/datum/subsystem/alarm/proc/number_of_active_alarms()
|
|
||||||
var/list/alarms = active_alarms()
|
|
||||||
return alarms.len
|
|
||||||
@@ -28,7 +28,6 @@ var/global/datum/getrev/revdata = new()
|
|||||||
world.log << branch
|
world.log << branch
|
||||||
world.log << date
|
world.log << date
|
||||||
world.log << revision
|
world.log << revision
|
||||||
return
|
|
||||||
|
|
||||||
client/verb/showrevinfo()
|
client/verb/showrevinfo()
|
||||||
set category = "OOC"
|
set category = "OOC"
|
||||||
@@ -43,4 +42,3 @@ client/verb/showrevinfo()
|
|||||||
src << revdata.revision
|
src << revdata.revision
|
||||||
else
|
else
|
||||||
src << "Revision unknown"
|
src << "Revision unknown"
|
||||||
return
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
/datum/mind/New(var/key)
|
/datum/mind/New(var/key)
|
||||||
src.key = key
|
src.key = key
|
||||||
|
|
||||||
|
..()
|
||||||
|
|
||||||
/datum/mind/proc/transfer_to(mob/living/new_character)
|
/datum/mind/proc/transfer_to(mob/living/new_character)
|
||||||
if(!istype(new_character))
|
if(!istype(new_character))
|
||||||
|
|||||||
11
code/datums/observation/_debug.dm
Normal file
11
code/datums/observation/_debug.dm
Normal file
@@ -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()
|
||||||
|
..()
|
||||||
1
code/datums/observation/_defines.dm
Normal file
1
code/datums/observation/_defines.dm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#define CANCEL_MOVE_EVENT -55
|
||||||
15
code/datums/observation/destroyed.dm
Normal file
15
code/datums/observation/destroyed.dm
Normal file
@@ -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)
|
||||||
|
. = ..()
|
||||||
35
code/datums/observation/dir_set.dm
Normal file
35
code/datums/observation/dir_set.dm
Normal file
@@ -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)
|
||||||
38
code/datums/observation/equipped.dm
Normal file
38
code/datums/observation/equipped.dm
Normal file
@@ -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)
|
||||||
18
code/datums/observation/helpers.dm
Normal file
18
code/datums/observation/helpers.dm
Normal file
@@ -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)
|
||||||
21
code/datums/observation/logged_in.dm
Normal file
21
code/datums/observation/logged_in.dm
Normal file
@@ -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)
|
||||||
52
code/datums/observation/moved.dm
Normal file
52
code/datums/observation/moved.dm
Normal file
@@ -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)
|
||||||
238
code/datums/observation/observation.dm
Normal file
238
code/datums/observation/observation.dm
Normal file
@@ -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
|
||||||
13
code/datums/observation/task_triggered.dm
Normal file
13
code/datums/observation/task_triggered.dm
Normal file
@@ -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
|
||||||
38
code/datums/observation/unequipped.dm
Normal file
38
code/datums/observation/unequipped.dm
Normal file
@@ -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)
|
||||||
70
code/datums/observation/~cleanup.dm
Normal file
70
code/datums/observation/~cleanup.dm
Normal file
@@ -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
|
||||||
@@ -1834,6 +1834,35 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
|||||||
access = access_security
|
access = access_security
|
||||||
group = "Security"
|
group = "Security"
|
||||||
|
|
||||||
|
/datum/supply_packs/bolt_rifles_competitive
|
||||||
|
name = "Competitive shooting crate"
|
||||||
|
contains = list(
|
||||||
|
/obj/item/device/assembly/timer,
|
||||||
|
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/practice = 2,
|
||||||
|
/obj/item/ammo_magazine/clip/a762/practice = 4,
|
||||||
|
/obj/item/target = 2,
|
||||||
|
/obj/item/target/alien = 2,
|
||||||
|
/obj/item/target/syndicate = 2
|
||||||
|
)
|
||||||
|
cost = 40
|
||||||
|
containertype = /obj/structure/closet/crate/secure/weapon
|
||||||
|
containername = "Weapons crate"
|
||||||
|
access = access_security
|
||||||
|
group = "Security"
|
||||||
|
|
||||||
|
/datum/supply_packs/bolt_rifles_mosin
|
||||||
|
name = "Surplus militia rifles"
|
||||||
|
contains = list(
|
||||||
|
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin = 3,
|
||||||
|
/obj/item/ammo_magazine/clip/a762 = 6
|
||||||
|
)
|
||||||
|
cost = 50
|
||||||
|
hidden = 1
|
||||||
|
containertype = /obj/structure/closet/crate/secure/weapon
|
||||||
|
containername = "Weapons crate"
|
||||||
|
access = access_security
|
||||||
|
group = "Security"
|
||||||
|
|
||||||
/datum/supply_packs/medicalextragear
|
/datum/supply_packs/medicalextragear
|
||||||
name = "Medical surplus equipment"
|
name = "Medical surplus equipment"
|
||||||
contains = list(
|
contains = list(
|
||||||
@@ -2108,4 +2137,4 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
|||||||
cost = 10
|
cost = 10
|
||||||
containertype = "/obj/structure/closet/crate"
|
containertype = "/obj/structure/closet/crate"
|
||||||
containername = "Chaplain equipment crate"
|
containername = "Chaplain equipment crate"
|
||||||
group = "Miscellaneous"
|
group = "Miscellaneous"
|
||||||
|
|||||||
@@ -6,62 +6,98 @@
|
|||||||
category = /datum/uplink_category/ammunition
|
category = /datum/uplink_category/ammunition
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/a357
|
/datum/uplink_item/item/ammo/a357
|
||||||
name = ".357"
|
name = ".357 Speedloader"
|
||||||
path = /obj/item/ammo_magazine/a357
|
path = /obj/item/ammo_magazine/a357
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/mc9mm
|
/datum/uplink_item/item/ammo/mc9mm
|
||||||
name = "9mm"
|
name = "Pistol Magazine (9mm)"
|
||||||
path = /obj/item/ammo_magazine/mc9mm
|
path = /obj/item/ammo_magazine/mc9mm
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/c45m
|
/datum/uplink_item/item/ammo/c45m
|
||||||
name = ".45"
|
name = "Pistol Magazine (.45)"
|
||||||
path = /obj/item/ammo_magazine/c45m
|
path = /obj/item/ammo_magazine/c45m
|
||||||
|
|
||||||
|
/datum/uplink_item/item/ammo/tommymag
|
||||||
|
name = "Tommygun Magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/tommymag
|
||||||
|
|
||||||
|
/datum/uplink_item/item/ammo/tommydrum
|
||||||
|
name = "Tommygun Drum Magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/tommydrum
|
||||||
|
item_cost = 4 // Buy 40 bullets, get 10 free!
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/darts
|
/datum/uplink_item/item/ammo/darts
|
||||||
name = "Darts"
|
name = "Darts"
|
||||||
path = /obj/item/ammo_magazine/chemdart
|
path = /obj/item/ammo_magazine/chemdart
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/sniperammo
|
/datum/uplink_item/item/ammo/sniperammo
|
||||||
name = "14.5mm"
|
name = "Anti-Materiel Rifle ammo box (14.5mm)"
|
||||||
path = /obj/item/weapon/storage/box/sniperammo
|
path = /obj/item/weapon/storage/box/sniperammo
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/a556
|
/datum/uplink_item/item/ammo/a556
|
||||||
name = "5.56mm"
|
name = "10rnd Rifle Magazine (5.56mm)"
|
||||||
path = /obj/item/ammo_magazine/a556
|
path = /obj/item/ammo_magazine/a556
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/a556/ap
|
/datum/uplink_item/item/ammo/a556/ap
|
||||||
name = "5.56mm AP"
|
name = "10rnd Rifle Magazine (5.56mm AP)"
|
||||||
path = /obj/item/ammo_magazine/a556/ap
|
path = /obj/item/ammo_magazine/a556/ap
|
||||||
|
|
||||||
|
/datum/uplink_item/item/ammo/a556m
|
||||||
|
name = "20rnd Rifle Magazine (5.56mm)"
|
||||||
|
path = /obj/item/ammo_magazine/a556m
|
||||||
|
item_cost = 4
|
||||||
|
|
||||||
|
/datum/uplink_item/item/ammo/a556m/ap
|
||||||
|
name = "20rnd Rifle Magazine (5.56mm AP)"
|
||||||
|
path = /obj/item/ammo_magazine/a556m/ap
|
||||||
|
item_cost = 4
|
||||||
|
|
||||||
|
/datum/uplink_item/item/ammo/c762
|
||||||
|
name = "20rnd Rifle Magazine (7.62mm)"
|
||||||
|
path = /obj/item/ammo_magazine/c762
|
||||||
|
|
||||||
|
/datum/uplink_item/item/ammo/c762/ap
|
||||||
|
name = "20rnd Rifle Magazine (7.62mm AP)"
|
||||||
|
path = /obj/item/ammo_magazine/c762/ap
|
||||||
|
|
||||||
|
/datum/uplink_item/item/ammo/s762
|
||||||
|
name = "10rnd Rifle Magazine (7.62mm)"
|
||||||
|
path = /obj/item/ammo_magazine/s762
|
||||||
|
item_cost = 1 // Half the capacity.
|
||||||
|
|
||||||
|
/datum/uplink_item/item/ammo/s762/ap
|
||||||
|
name = "10rnd Rifle Magazine (7.62mm AP)"
|
||||||
|
path = /obj/item/ammo_magazine/s762/ap
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/a10mm
|
/datum/uplink_item/item/ammo/a10mm
|
||||||
name = "10mm"
|
name = "SMG Magazine (10mm)"
|
||||||
path = /obj/item/ammo_magazine/a10mm
|
path = /obj/item/ammo_magazine/a10mm
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/a762
|
/datum/uplink_item/item/ammo/a762
|
||||||
name = "7.62mm"
|
name = "Machinegun Magazine (7.62mm)"
|
||||||
path = /obj/item/ammo_magazine/a762
|
path = /obj/item/ammo_magazine/a762
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/a762/ap
|
/datum/uplink_item/item/ammo/a762/ap
|
||||||
name = "7.62mm AP"
|
name = "Machinegun Magazine (7.62mm AP)"
|
||||||
path = /obj/item/ammo_magazine/a762/ap
|
path = /obj/item/ammo_magazine/a762/ap
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/g12
|
/datum/uplink_item/item/ammo/g12
|
||||||
name = "12 gauge"
|
name = "12g Auto-Shotgun Magazine (Slug)"
|
||||||
path = /obj/item/ammo_magazine/g12
|
path = /obj/item/ammo_magazine/g12
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/g12/beanbag
|
/datum/uplink_item/item/ammo/g12/beanbag
|
||||||
name = "12 gauge beanbag"
|
name = "12g Auto-Shotgun Magazine (Beanbag)"
|
||||||
path = /obj/item/ammo_magazine/g12/beanbag
|
path = /obj/item/ammo_magazine/g12/beanbag
|
||||||
item_cost = 1 // Discount due to it being LTL.
|
item_cost = 1 // Discount due to it being LTL.
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/g12/pellet
|
/datum/uplink_item/item/ammo/g12/pellet
|
||||||
name = "12 gauge pellet"
|
name = "12g Auto-Shotgun Magazine (Pellet)"
|
||||||
path = /obj/item/ammo_magazine/g12/pellet
|
path = /obj/item/ammo_magazine/g12/pellet
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/g12/stun
|
/datum/uplink_item/item/ammo/g12/stun
|
||||||
name = "12 gauge stun"
|
name = "12g Auto-Shotgun Magazine (Stun)"
|
||||||
path = /obj/item/weapon/storage/box/stunshells
|
path = /obj/item/weapon/storage/box/stunshells
|
||||||
|
|
||||||
/datum/uplink_item/item/ammo/g12/flash
|
/datum/uplink_item/item/ammo/g12/flash
|
||||||
name = "12 gauge flash"
|
name = "12g Auto-Shotgun Magazine (Flash)"
|
||||||
path = /obj/item/weapon/storage/box/flashshells
|
path = /obj/item/weapon/storage/box/flashshells
|
||||||
@@ -34,22 +34,37 @@
|
|||||||
item_cost = 6
|
item_cost = 6
|
||||||
path = /obj/item/weapon/gun/projectile/revolver
|
path = /obj/item/weapon/gun/projectile/revolver
|
||||||
|
|
||||||
|
/datum/uplink_item/item/visible_weapons/Derringer
|
||||||
|
name = ".357 Derringer Pistol"
|
||||||
|
item_cost = 5
|
||||||
|
path = /obj/item/weapon/gun/projectile/derringer
|
||||||
|
|
||||||
/datum/uplink_item/item/visible_weapons/heavysniper
|
/datum/uplink_item/item/visible_weapons/heavysniper
|
||||||
name = "Anti-materiel Rifle"
|
name = "Anti-Materiel Rifle (14.5mm)"
|
||||||
item_cost = DEFAULT_TELECRYSTAL_AMOUNT
|
item_cost = DEFAULT_TELECRYSTAL_AMOUNT
|
||||||
path = /obj/item/weapon/gun/projectile/heavysniper
|
path = /obj/item/weapon/gun/projectile/heavysniper
|
||||||
|
|
||||||
|
/datum/uplink_item/item/visible_weapons/tommygun
|
||||||
|
name = "Tommygun (.45)" // We're keeping this because it's CLASSY. -Spades
|
||||||
|
item_cost = 7
|
||||||
|
path = /obj/item/weapon/gun/projectile/automatic/tommygun
|
||||||
|
|
||||||
//These are for traitors (or other antags, perhaps) to have the option of purchasing some merc gear.
|
//These are for traitors (or other antags, perhaps) to have the option of purchasing some merc gear.
|
||||||
/datum/uplink_item/item/visible_weapons/submachinegun
|
/datum/uplink_item/item/visible_weapons/submachinegun
|
||||||
name = "Submachine Gun"
|
name = "Submachine Gun (10mm)"
|
||||||
item_cost = 6
|
item_cost = 6
|
||||||
path = /obj/item/weapon/gun/projectile/automatic/c20r
|
path = /obj/item/weapon/gun/projectile/automatic/c20r
|
||||||
|
|
||||||
/datum/uplink_item/item/visible_weapons/assaultrifle
|
/datum/uplink_item/item/visible_weapons/assaultrifle
|
||||||
name = "Assault Rifle"
|
name = "Assault Rifle (7.62mm)"
|
||||||
item_cost = 7
|
item_cost = 7
|
||||||
path = /obj/item/weapon/gun/projectile/automatic/sts35
|
path = /obj/item/weapon/gun/projectile/automatic/sts35
|
||||||
|
|
||||||
|
/datum/uplink_item/item/visible_weapons/bullpuprifle
|
||||||
|
name = "Assault Rifle (5.56mm)"
|
||||||
|
item_cost = 7
|
||||||
|
path = /obj/item/weapon/gun/projectile/automatic/carbine
|
||||||
|
|
||||||
/datum/uplink_item/item/visible_weapons/combatshotgun
|
/datum/uplink_item/item/visible_weapons/combatshotgun
|
||||||
name = "Combat Shotgun"
|
name = "Combat Shotgun"
|
||||||
item_cost = 7
|
item_cost = 7
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
/obj/item/weapon/soap/deluxe/New()
|
/obj/item/weapon/soap/deluxe/New()
|
||||||
desc = "A deluxe Waffle Co. brand bar of soap. Smells of [pick("lavender", "vanilla", "strawberry", "chocolate" ,"space")]."
|
desc = "A deluxe Waffle Co. brand bar of soap. Smells of [pick("lavender", "vanilla", "strawberry", "chocolate" ,"space")]."
|
||||||
|
..()
|
||||||
|
|
||||||
/obj/item/weapon/soap/syndie
|
/obj/item/weapon/soap/syndie
|
||||||
desc = "An untrustworthy bar of soap. Smells of fear."
|
desc = "An untrustworthy bar of soap. Smells of fear."
|
||||||
@@ -398,9 +399,11 @@
|
|||||||
icon = 'icons/obj/stock_parts.dmi'
|
icon = 'icons/obj/stock_parts.dmi'
|
||||||
w_class = 2.0
|
w_class = 2.0
|
||||||
var/rating = 1
|
var/rating = 1
|
||||||
New()
|
|
||||||
src.pixel_x = rand(-5.0, 5)
|
/obj/item/weapon/stock_parts/New()
|
||||||
src.pixel_y = rand(-5.0, 5)
|
src.pixel_x = rand(-5.0, 5)
|
||||||
|
src.pixel_y = rand(-5.0, 5)
|
||||||
|
..()
|
||||||
|
|
||||||
//Rank 1
|
//Rank 1
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ var/datum/antagonist/deathsquad/mercenary/commandos
|
|||||||
player.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(player), slot_glasses)
|
player.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(player), slot_glasses)
|
||||||
player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(player), slot_wear_mask)
|
player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(player), slot_wear_mask)
|
||||||
player.equip_to_slot_or_del(new /obj/item/weapon/storage/box(player), slot_in_backpack)
|
player.equip_to_slot_or_del(new /obj/item/weapon/storage/box(player), slot_in_backpack)
|
||||||
player.equip_to_slot_or_del(new /obj/item/ammo_magazine/c45(player), slot_in_backpack)
|
player.equip_to_slot_or_del(new /obj/item/ammo_magazine/clip/c45(player), slot_in_backpack)
|
||||||
player.equip_to_slot_or_del(new /obj/item/weapon/rig/merc(player), slot_back)
|
player.equip_to_slot_or_del(new /obj/item/weapon/rig/merc(player), slot_back)
|
||||||
player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand)
|
player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand)
|
||||||
|
|
||||||
|
|||||||
@@ -80,16 +80,22 @@ var/datum/antagonist/raider/raiders
|
|||||||
/obj/item/weapon/gun/projectile/automatic/c20r,
|
/obj/item/weapon/gun/projectile/automatic/c20r,
|
||||||
/obj/item/weapon/gun/projectile/automatic/wt550,
|
/obj/item/weapon/gun/projectile/automatic/wt550,
|
||||||
/obj/item/weapon/gun/projectile/automatic/sts35,
|
/obj/item/weapon/gun/projectile/automatic/sts35,
|
||||||
|
/obj/item/weapon/gun/projectile/automatic/carbine,
|
||||||
|
/obj/item/weapon/gun/projectile/automatic/tommygun,
|
||||||
/obj/item/weapon/gun/projectile/silenced,
|
/obj/item/weapon/gun/projectile/silenced,
|
||||||
/obj/item/weapon/gun/projectile/shotgun/pump,
|
/obj/item/weapon/gun/projectile/shotgun/pump,
|
||||||
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
|
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
|
||||||
|
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin,
|
||||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
|
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
|
||||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet,
|
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet,
|
||||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn,
|
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn,
|
||||||
/obj/item/weapon/gun/projectile/colt/detective,
|
/obj/item/weapon/gun/projectile/colt/detective,
|
||||||
/obj/item/weapon/gun/projectile/pistol,
|
/obj/item/weapon/gun/projectile/pistol,
|
||||||
/obj/item/weapon/gun/projectile/revolver,
|
/obj/item/weapon/gun/projectile/revolver,
|
||||||
/obj/item/weapon/gun/projectile/pirate
|
/obj/item/weapon/gun/projectile/pirate,
|
||||||
|
/obj/item/weapon/gun/projectile/revolver/judge,
|
||||||
|
list(/obj/item/weapon/gun/projectile/luger,/obj/item/weapon/gun/projectile/luger/brown),
|
||||||
|
list(/obj/item/weapon/gun/projectile/deagle, /obj/item/weapon/gun/projectile/deagle/gold, /obj/item/weapon/gun/projectile/deagle/camo)
|
||||||
)
|
)
|
||||||
|
|
||||||
var/list/raider_holster = list(
|
var/list/raider_holster = list(
|
||||||
|
|||||||
@@ -37,19 +37,25 @@ var/datum/antagonist/renegade/renegades
|
|||||||
/obj/item/weapon/gun/projectile/automatic/mini_uzi,
|
/obj/item/weapon/gun/projectile/automatic/mini_uzi,
|
||||||
/obj/item/weapon/gun/projectile/automatic/c20r,
|
/obj/item/weapon/gun/projectile/automatic/c20r,
|
||||||
/obj/item/weapon/gun/projectile/automatic/sts35,
|
/obj/item/weapon/gun/projectile/automatic/sts35,
|
||||||
|
/obj/item/weapon/gun/projectile/automatic/carbine,
|
||||||
/obj/item/weapon/gun/projectile/automatic/wt550,
|
/obj/item/weapon/gun/projectile/automatic/wt550,
|
||||||
/obj/item/weapon/gun/projectile/automatic/z8,
|
/obj/item/weapon/gun/projectile/automatic/z8,
|
||||||
|
/obj/item/weapon/gun/projectile/automatic/tommygun,
|
||||||
/obj/item/weapon/gun/projectile/colt/detective,
|
/obj/item/weapon/gun/projectile/colt/detective,
|
||||||
/obj/item/weapon/gun/projectile/sec/wood,
|
/obj/item/weapon/gun/projectile/sec/wood,
|
||||||
/obj/item/weapon/gun/projectile/silenced,
|
/obj/item/weapon/gun/projectile/silenced,
|
||||||
/obj/item/weapon/gun/projectile/pistol,
|
/obj/item/weapon/gun/projectile/pistol,
|
||||||
/obj/item/weapon/gun/projectile/revolver,
|
/obj/item/weapon/gun/projectile/revolver,
|
||||||
|
/obj/item/weapon/gun/projectile/derringer,
|
||||||
/obj/item/weapon/gun/projectile/shotgun/pump,
|
/obj/item/weapon/gun/projectile/shotgun/pump,
|
||||||
|
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin,
|
||||||
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
|
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
|
||||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
|
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
|
||||||
|
/obj/item/weapon/gun/projectile/revolver/judge,
|
||||||
list(/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet, /obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn),
|
list(/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet, /obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn),
|
||||||
list(/obj/item/weapon/gun/projectile/deagle, /obj/item/weapon/gun/projectile/deagle/gold, /obj/item/weapon/gun/projectile/deagle/camo),
|
list(/obj/item/weapon/gun/projectile/deagle, /obj/item/weapon/gun/projectile/deagle/gold, /obj/item/weapon/gun/projectile/deagle/camo),
|
||||||
list(/obj/item/weapon/gun/projectile/revolver/detective, /obj/item/weapon/gun/projectile/revolver/deckard)
|
list(/obj/item/weapon/gun/projectile/revolver/detective, /obj/item/weapon/gun/projectile/revolver/deckard),
|
||||||
|
list(/obj/item/weapon/gun/projectile/luger,/obj/item/weapon/gun/projectile/luger/brown)
|
||||||
)
|
)
|
||||||
|
|
||||||
/datum/antagonist/renegade/New()
|
/datum/antagonist/renegade/New()
|
||||||
|
|||||||
@@ -46,7 +46,8 @@
|
|||||||
pulledby = null
|
pulledby = null
|
||||||
|
|
||||||
/atom/movable/proc/initialize()
|
/atom/movable/proc/initialize()
|
||||||
return
|
if(!isnull(gcDestroyed))
|
||||||
|
crash_with("GC: -- [type] had initialize() called after qdel() --")
|
||||||
|
|
||||||
/atom/movable/Bump(var/atom/A, yes)
|
/atom/movable/Bump(var/atom/A, yes)
|
||||||
if(src.throwing)
|
if(src.throwing)
|
||||||
@@ -211,7 +212,7 @@
|
|||||||
/atom/movable/overlay/New()
|
/atom/movable/overlay/New()
|
||||||
for(var/x in src.verbs)
|
for(var/x in src.verbs)
|
||||||
src.verbs -= x
|
src.verbs -= x
|
||||||
return
|
..()
|
||||||
|
|
||||||
/atom/movable/overlay/attackby(a, b)
|
/atom/movable/overlay/attackby(a, b)
|
||||||
if (src.master)
|
if (src.master)
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ The "dust" will damage the hull of the station causin minor hull breaches.
|
|||||||
|
|
||||||
|
|
||||||
New()
|
New()
|
||||||
|
..()
|
||||||
var/startx = 0
|
var/startx = 0
|
||||||
var/starty = 0
|
var/starty = 0
|
||||||
var/endy = 0
|
var/endy = 0
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ datum/objective
|
|||||||
all_objectives |= src
|
all_objectives |= src
|
||||||
if(text)
|
if(text)
|
||||||
explanation_text = text
|
explanation_text = text
|
||||||
|
..()
|
||||||
|
|
||||||
Destroy()
|
Destroy()
|
||||||
all_objectives -= src
|
all_objectives -= src
|
||||||
|
|||||||
@@ -92,16 +92,6 @@
|
|||||||
active_power_usage = 200 //builtin health analyzer, dialysis machine, injectors.
|
active_power_usage = 200 //builtin health analyzer, dialysis machine, injectors.
|
||||||
|
|
||||||
/obj/machinery/sleeper/New()
|
/obj/machinery/sleeper/New()
|
||||||
..()
|
|
||||||
spawn(5)
|
|
||||||
//src.machine = locate(/obj/machinery/mineral/processing_unit, get_step(src, machinedir))
|
|
||||||
var/obj/machinery/sleep_console/C = locate(/obj/machinery/sleep_console) in range(2,src)
|
|
||||||
if(C)
|
|
||||||
C.connected = src
|
|
||||||
return
|
|
||||||
return
|
|
||||||
|
|
||||||
/obj/machinery/sleeper/map/New()
|
|
||||||
..()
|
..()
|
||||||
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
|
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
@@ -114,6 +104,14 @@
|
|||||||
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
|
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
|
||||||
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
|
component_parts += new /obj/item/weapon/reagent_containers/syringe(src)
|
||||||
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
|
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
|
||||||
|
|
||||||
|
spawn(5)
|
||||||
|
//src.machine = locate(/obj/machinery/mineral/processing_unit, get_step(src, machinedir))
|
||||||
|
var/obj/machinery/sleep_console/C = locate(/obj/machinery/sleep_console) in range(2,src)
|
||||||
|
if(C)
|
||||||
|
C.connected = src
|
||||||
|
return
|
||||||
|
|
||||||
RefreshParts()
|
RefreshParts()
|
||||||
|
|
||||||
/obj/machinery/sleeper/initialize()
|
/obj/machinery/sleeper/initialize()
|
||||||
|
|||||||
@@ -16,15 +16,6 @@
|
|||||||
active_power_usage = 10000 //10 kW. It's a big all-body scanner.
|
active_power_usage = 10000 //10 kW. It's a big all-body scanner.
|
||||||
|
|
||||||
/obj/machinery/bodyscanner/New()
|
/obj/machinery/bodyscanner/New()
|
||||||
..()
|
|
||||||
spawn( 5 )
|
|
||||||
var/obj/machinery/body_scanconsole/C = locate(/obj/machinery/body_scanconsole) in range(2,src)
|
|
||||||
if(C)
|
|
||||||
C.connected = src
|
|
||||||
return
|
|
||||||
return
|
|
||||||
|
|
||||||
/obj/machinery/bodyscanner/map/New()
|
|
||||||
..()
|
..()
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
@@ -32,6 +23,13 @@
|
|||||||
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
||||||
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
||||||
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
|
component_parts += new /obj/item/stack/material/glass/reinforced(src, 2)
|
||||||
|
|
||||||
|
spawn( 5 )
|
||||||
|
var/obj/machinery/body_scanconsole/C = locate(/obj/machinery/body_scanconsole) in range(2,src)
|
||||||
|
if(C)
|
||||||
|
C.connected = src
|
||||||
|
return
|
||||||
|
|
||||||
RefreshParts()
|
RefreshParts()
|
||||||
|
|
||||||
/obj/machinery/bodyscanner/relaymove(mob/user as mob)
|
/obj/machinery/bodyscanner/relaymove(mob/user as mob)
|
||||||
|
|||||||
@@ -26,10 +26,6 @@
|
|||||||
/obj/machinery/autolathe/New()
|
/obj/machinery/autolathe/New()
|
||||||
..()
|
..()
|
||||||
wires = new(src)
|
wires = new(src)
|
||||||
|
|
||||||
/obj/machinery/autolathe/map/New()
|
|
||||||
..()
|
|
||||||
//Create parts for lathe.
|
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||||
@@ -150,6 +146,22 @@
|
|||||||
if(is_robot_module(O))
|
if(is_robot_module(O))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
if(istype(O,/obj/item/ammo_magazine/clip) || istype(O,/obj/item/ammo_magazine/a357) || istype(O,/obj/item/ammo_magazine/c38)) // Prevents ammo recycling exploit with speedloaders.
|
||||||
|
user << "\The [O] is too hazardous to recycle with the autolathe!"
|
||||||
|
return
|
||||||
|
/* ToDo: Make this actually check for ammo and change the value of the magazine if it's empty. -Spades
|
||||||
|
var/obj/item/ammo_magazine/speedloader = O
|
||||||
|
if(speedloader.stored_ammo)
|
||||||
|
user << "\The [speedloader] is too hazardous to put back into the autolathe while there's ammunition inside of it!"
|
||||||
|
return
|
||||||
|
else
|
||||||
|
speedloader.matter = list(DEFAULT_WALL_MATERIAL = 75) // It's just a hunk of scrap metal now.
|
||||||
|
if(istype(O,/obj/item/ammo_magazine)) // This was just for immersion consistency with above.
|
||||||
|
var/obj/item/ammo_magazine/mag = O
|
||||||
|
if(mag.stored_ammo)
|
||||||
|
user << "\The [mag] is too hazardous to put back into the autolathe while there's ammunition inside of it!"
|
||||||
|
return*/
|
||||||
|
|
||||||
//Resources are being loaded.
|
//Resources are being loaded.
|
||||||
var/obj/item/eating = O
|
var/obj/item/eating = O
|
||||||
if(!eating.matter)
|
if(!eating.matter)
|
||||||
|
|||||||
@@ -330,36 +330,415 @@
|
|||||||
path = /obj/item/weapon/syringe_cartridge
|
path = /obj/item/weapon/syringe_cartridge
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
////////////////
|
||||||
|
/*Ammo casings*/
|
||||||
|
////////////////
|
||||||
|
|
||||||
/datum/autolathe/recipe/shotgun_blanks
|
/datum/autolathe/recipe/shotgun_blanks
|
||||||
name = "ammunition (shotgun, blank)"
|
name = "ammunition (12g, blank)"
|
||||||
path = /obj/item/ammo_casing/shotgun/blank
|
path = /obj/item/ammo_casing/shotgun/blank
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
/datum/autolathe/recipe/shotgun_beanbag
|
/datum/autolathe/recipe/shotgun_beanbag
|
||||||
name = "ammunition (shotgun, beanbag)"
|
name = "ammunition (12g, beanbag)"
|
||||||
path = /obj/item/ammo_casing/shotgun/beanbag
|
path = /obj/item/ammo_casing/shotgun/beanbag
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
/datum/autolathe/recipe/shotgun_flash
|
/datum/autolathe/recipe/shotgun_flash
|
||||||
name = "ammunition (shotgun, flash)"
|
name = "ammunition (12g, flash)"
|
||||||
path = /obj/item/ammo_casing/shotgun/flash
|
path = /obj/item/ammo_casing/shotgun/flash
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_rubber
|
/datum/autolathe/recipe/shotgun
|
||||||
name = "ammunition (.45, rubber)"
|
name = "ammunition (12g, slug)"
|
||||||
|
path = /obj/item/ammo_casing/shotgun
|
||||||
|
hidden = 1
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/shotgun_pellet
|
||||||
|
name = "ammunition (12g, pellet)"
|
||||||
|
path = /obj/item/ammo_casing/shotgun/pellet
|
||||||
|
hidden = 1
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/stunshell
|
||||||
|
name = "ammunition (stun cartridge, shotgun)"
|
||||||
|
path = /obj/item/ammo_casing/shotgun/stunshell
|
||||||
|
hidden = 1
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
/*Ammo magazines*/
|
||||||
|
//////////////////
|
||||||
|
|
||||||
|
/////// 5mm
|
||||||
|
/*
|
||||||
|
/datum/autolathe/recipe/pistol_5mm
|
||||||
|
name = "pistol magazine (5mm)"
|
||||||
|
path = /obj/item/ammo_magazine/c5mm
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/////// .45
|
||||||
|
/datum/autolathe/recipe/pistol_45
|
||||||
|
name = "pistol magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/c45m
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_45p
|
||||||
|
name = "pistol magazine (.45 practice)"
|
||||||
|
path = /obj/item/ammo_magazine/c45m/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_45r
|
||||||
|
name = "pistol magazine (.45 rubber)"
|
||||||
path = /obj/item/ammo_magazine/c45m/rubber
|
path = /obj/item/ammo_magazine/c45m/rubber
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_flash
|
/datum/autolathe/recipe/pistol_45f
|
||||||
name = "ammunition (.45, flash)"
|
name = "pistol magazine (.45 flash)"
|
||||||
path = /obj/item/ammo_magazine/c45m/flash
|
path = /obj/item/ammo_magazine/c45m/flash
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_smg_rubber
|
/datum/autolathe/recipe/pistol_45uzi
|
||||||
name = "ammunition (9mm rubber top mounted)"
|
name = "uzi magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/c45uzi
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/tommymag
|
||||||
|
name = "Tommygun magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/tommymag
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/tommydrum
|
||||||
|
name = "Tommygun drum magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/tommydrum
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/////// 9mm
|
||||||
|
|
||||||
|
/obj/item/ammo_magazine/mc9mm/flash
|
||||||
|
ammo_type = /obj/item/ammo_casing/c9mmf
|
||||||
|
|
||||||
|
/obj/item/ammo_magazine/mc9mm/rubber
|
||||||
|
name = "magazine (9mm rubber)"
|
||||||
|
ammo_type = /obj/item/ammo_casing/c9mmr
|
||||||
|
|
||||||
|
/obj/item/ammo_magazine/mc9mm/practice
|
||||||
|
name = "magazine (9mm practice)"
|
||||||
|
ammo_type = /obj/item/ammo_casing/c9mmp
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_9mm
|
||||||
|
name = "pistol magazine (9mm)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mm
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_9mmr
|
||||||
|
name = "pistol magazine (9mm rubber)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mm/rubber
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_9mmp
|
||||||
|
name = "pistol magazine (9mm practice)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mm/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_9mmf
|
||||||
|
name = "pistol magazine (9mm flash)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mm/flash
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/smg_9mm
|
||||||
|
name = "top-mounted SMG magazine (9mm)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mmt
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/smg_9mmr
|
||||||
|
name = "top-mounted SMG magazine (9mm rubber)"
|
||||||
path = /obj/item/ammo_magazine/mc9mmt/rubber
|
path = /obj/item/ammo_magazine/mc9mmt/rubber
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/smg_9mmp
|
||||||
|
name = "top-mounted SMG magazine (9mm practice)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mmt/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/smg_9mmf
|
||||||
|
name = "top-mounted SMG magazine (9mm flash)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mmt/flash
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/////// 10mm
|
||||||
|
/datum/autolathe/recipe/smg_10mm
|
||||||
|
name = "SMG magazine (10mm)"
|
||||||
|
path = /obj/item/ammo_magazine/a10mm
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_50
|
||||||
|
name = "pistol magazine (.50AE)"
|
||||||
|
path = /obj/item/ammo_magazine/a50
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/////// 5.56mm
|
||||||
|
/datum/autolathe/recipe/rifle_556
|
||||||
|
name = "10rnd rifle magazine (5.56mm)"
|
||||||
|
path = /obj/item/ammo_magazine/a556
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_556p
|
||||||
|
name = "10rnd rifle magazine (5.56mm practice)"
|
||||||
|
path = /obj/item/ammo_magazine/a556/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_556m
|
||||||
|
name = "20rnd rifle magazine (5.56mm)"
|
||||||
|
path = /obj/item/ammo_magazine/a556m
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_556mp
|
||||||
|
name = "20rnd rifle magazine (5.56mm practice)"
|
||||||
|
path = /obj/item/ammo_magazine/a556m/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/////// 7.62
|
||||||
|
/datum/autolathe/recipe/rifle_small_762
|
||||||
|
name = "10rnd rifle magazine (7.62mm)"
|
||||||
|
path = /obj/item/ammo_magazine/s762
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_762
|
||||||
|
name = "20rnd rifle magazine (7.62mm)"
|
||||||
|
path = /obj/item/ammo_magazine/c762
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/machinegun_762
|
||||||
|
name = "machinegun box magazine (7.62)"
|
||||||
|
path = /obj/item/ammo_magazine/a762
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/shotgun_magazine
|
||||||
|
name = "24rnd shotgun magazine (12g)"
|
||||||
|
path = /obj/item/ammo_magazine/g12
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/* Commented out until autolathe stuff is decided/fixed. Will probably remove these entirely. -Spades
|
||||||
|
// These should always be /empty! The idea is to fill them up manually with ammo clips.
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_5mm
|
||||||
|
name = "pistol magazine (5mm)"
|
||||||
|
path = /obj/item/ammo_magazine/c5mm/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/smg_5mm
|
||||||
|
name = "top-mounted SMG magazine (5mm)"
|
||||||
|
path = /obj/item/ammo_magazine/c5mmt/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_45
|
||||||
|
name = "pistol magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/c45m/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_45uzi
|
||||||
|
name = "uzi magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/c45uzi/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/tommymag
|
||||||
|
name = "Tommygun magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/tommymag/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/tommydrum
|
||||||
|
name = "Tommygun drum magazine (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/tommydrum/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_9mm
|
||||||
|
name = "pistol magazine (9mm)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mm/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/smg_9mm
|
||||||
|
name = "top-mounted SMG magazine (9mm)"
|
||||||
|
path = /obj/item/ammo_magazine/mc9mmt/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/smg_10mm
|
||||||
|
name = "SMG magazine (10mm)"
|
||||||
|
path = /obj/item/ammo_magazine/a10mm/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_50
|
||||||
|
name = "pistol magazine (.50AE)"
|
||||||
|
path = /obj/item/ammo_magazine/a50/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_556
|
||||||
|
name = "10rnd rifle magazine (5.56mm)"
|
||||||
|
path = /obj/item/ammo_magazine/a556/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_556m
|
||||||
|
name = "20rnd rifle magazine (5.56mm)"
|
||||||
|
path = /obj/item/ammo_magazine/a556m/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_SVD
|
||||||
|
name = "10rnd rifle magazine (7.62mm)"
|
||||||
|
path = /obj/item/ammo_magazine/SVD/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_762
|
||||||
|
name = "20rnd rifle magazine (7.62mm)"
|
||||||
|
path = /obj/item/ammo_magazine/c762/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/machinegun_762
|
||||||
|
name = "machinegun box magazine (7.62)"
|
||||||
|
path = /obj/item/ammo_magazine/a762/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/shotgun_magazine
|
||||||
|
name = "24rnd shotgun magazine (12g)"
|
||||||
|
path = /obj/item/ammo_magazine/g12/empty
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1*/
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
/*Ammo clips and Speedloaders*/
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/speedloader_357
|
||||||
|
name = "speedloader (.357)"
|
||||||
|
path = /obj/item/ammo_magazine/a357
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/speedloader_38
|
||||||
|
name = "speedloader (.38)"
|
||||||
|
path = /obj/item/ammo_magazine/c38
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/speedloader_38r
|
||||||
|
name = "speedloader (.38 rubber)"
|
||||||
|
path = /obj/item/ammo_magazine/c38/rubber
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
// Commented out until metal exploits with autolathe is fixed.
|
||||||
|
/*/datum/autolathe/recipe/pistol_clip_45
|
||||||
|
name = "ammo clip (.45)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c45
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_45r
|
||||||
|
name = "ammo clip (.45 rubber)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c45/rubber
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_45f
|
||||||
|
name = "ammo clip (.45 flash)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c45/flash
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_45p
|
||||||
|
name = "ammo clip (.45 practice)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c45/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_9mm
|
||||||
|
name = "ammo clip (9mm)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c9mm
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_9mmr
|
||||||
|
name = "ammo clip (9mm rubber)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c9mm/rubber
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_9mmp
|
||||||
|
name = "ammo clip (9mm practice)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c9mm/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_9mmf
|
||||||
|
name = "ammo clip (9mm flash)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c9mm/flash
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_5mm
|
||||||
|
name = "ammo clip (5mm)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/c5mm
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_10mm
|
||||||
|
name = "ammo clip (10mm)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/a10mm
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/pistol_clip_50
|
||||||
|
name = "ammo clip (.50AE)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/a50
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_clip_556
|
||||||
|
name = "ammo clip (5.56mm)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/a556
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_clip_556_practice
|
||||||
|
name = "ammo clip (5.56mm practice)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/a556/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
*/
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_clip_762
|
||||||
|
name = "ammo clip (7.62mm)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/a762
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
hidden = 1
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/rifle_clip_762_practice
|
||||||
|
name = "ammo clip (7.62mm practice)"
|
||||||
|
path = /obj/item/ammo_magazine/clip/a762/practice
|
||||||
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
|
||||||
/datum/autolathe/recipe/consolescreen
|
/datum/autolathe/recipe/consolescreen
|
||||||
name = "console screen"
|
name = "console screen"
|
||||||
path = /obj/item/weapon/stock_parts/console_screen
|
path = /obj/item/weapon/stock_parts/console_screen
|
||||||
@@ -427,78 +806,6 @@
|
|||||||
hidden = 1
|
hidden = 1
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_revolver_1
|
|
||||||
name = "ammunition (.357)"
|
|
||||||
path = /obj/item/ammo_magazine/a357
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_revolver_2
|
|
||||||
name = "ammunition (.45)"
|
|
||||||
path = /obj/item/ammo_magazine/c45m
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_stetchkin
|
|
||||||
name = "ammunition (9mm)"
|
|
||||||
path = /obj/item/ammo_magazine/mc9mm
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_stetchkin_flash
|
|
||||||
name = "ammunition (9mm, flash)"
|
|
||||||
path = /obj/item/ammo_magazine/mc9mm/flash
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_c20r
|
|
||||||
name = "ammunition (10mm)"
|
|
||||||
path = /obj/item/ammo_magazine/a10mm
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_arifle
|
|
||||||
name = "ammunition (7.62mm)"
|
|
||||||
path = /obj/item/ammo_magazine/c762
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_smg
|
|
||||||
name = "ammunition (9mm top mounted)"
|
|
||||||
path = /obj/item/ammo_magazine/mc9mmt
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/magazine_carbine
|
|
||||||
name = "ammunition (5.56mm)"
|
|
||||||
path = /obj/item/ammo_magazine/a556
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/shotgun
|
|
||||||
name = "ammunition (slug, shotgun)"
|
|
||||||
path = /obj/item/ammo_casing/shotgun
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/shotgun_pellet
|
|
||||||
name = "ammunition (shell, shotgun)"
|
|
||||||
path = /obj/item/ammo_casing/shotgun/pellet
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/tacknife
|
|
||||||
name = "tactical knife"
|
|
||||||
path = /obj/item/weapon/material/hatchet/tacknife
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/stunshell
|
|
||||||
name = "ammunition (stun cartridge, shotgun)"
|
|
||||||
path = /obj/item/ammo_casing/shotgun/stunshell
|
|
||||||
hidden = 1
|
|
||||||
category = "Arms and Ammunition"
|
|
||||||
|
|
||||||
/datum/autolathe/recipe/rcd
|
/datum/autolathe/recipe/rcd
|
||||||
name = "rapid construction device"
|
name = "rapid construction device"
|
||||||
path = /obj/item/weapon/rcd
|
path = /obj/item/weapon/rcd
|
||||||
@@ -534,3 +841,9 @@
|
|||||||
path = /obj/item/weapon/material/knuckledusters
|
path = /obj/item/weapon/material/knuckledusters
|
||||||
hidden = 1
|
hidden = 1
|
||||||
category = "Arms and Ammunition"
|
category = "Arms and Ammunition"
|
||||||
|
|
||||||
|
/datum/autolathe/recipe/tacknife
|
||||||
|
name = "tactical knife"
|
||||||
|
path = /obj/item/weapon/material/hatchet/tacknife
|
||||||
|
hidden = 1
|
||||||
|
category = "Arms and Ammunition"
|
||||||
@@ -22,8 +22,6 @@
|
|||||||
reagents = R
|
reagents = R
|
||||||
R.my_atom = src
|
R.my_atom = src
|
||||||
|
|
||||||
/obj/machinery/biogenerator/map/New()
|
|
||||||
..()
|
|
||||||
beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
|
beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
var/eject_wait = 0 //Don't eject them as soon as they are created fuckkk
|
var/eject_wait = 0 //Don't eject them as soon as they are created fuckkk
|
||||||
var/biomass = CLONE_BIOMASS * 3
|
var/biomass = CLONE_BIOMASS * 3
|
||||||
|
|
||||||
/obj/machinery/clonepod/map/New()
|
/obj/machinery/clonepod/New()
|
||||||
..()
|
..()
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
@@ -424,6 +424,7 @@
|
|||||||
read_only = 1
|
read_only = 1
|
||||||
|
|
||||||
New()
|
New()
|
||||||
|
..()
|
||||||
initializeDisk()
|
initializeDisk()
|
||||||
buf.types=DNA2_BUF_SE
|
buf.types=DNA2_BUF_SE
|
||||||
var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4)
|
var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
name = "\improper RCON console"
|
name = "\improper RCON console"
|
||||||
desc = "Console used to remotely control machinery on the station."
|
desc = "Console used to remotely control machinery on the station."
|
||||||
icon_keyboard = "power_key"
|
icon_keyboard = "power_key"
|
||||||
icon_screen = "power_screen"
|
icon_screen = "power:0"
|
||||||
light_color = "#a97faa"
|
light_color = "#a97faa"
|
||||||
circuit = /obj/item/weapon/circuitboard/rcon_console
|
circuit = /obj/item/weapon/circuitboard/rcon_console
|
||||||
req_one_access = list(access_engine)
|
req_one_access = list(access_engine)
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ var/global/list/minor_air_alarms = list()
|
|||||||
|
|
||||||
/obj/machinery/computer/atmos_alert/New()
|
/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()
|
/obj/machinery/computer/atmos_alert/Destroy()
|
||||||
atmosphere_alarm.unregister(src)
|
atmosphere_alarm.unregister_alarm(src)
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/obj/machinery/computer/atmos_alert/attack_hand(mob/user)
|
/obj/machinery/computer/atmos_alert/attack_hand(mob/user)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
possibleNets["Cargo"] = access_qm
|
possibleNets["Cargo"] = access_qm
|
||||||
possibleNets["Research"] = access_rd
|
possibleNets["Research"] = access_rd
|
||||||
possibleNets["Medbay"] = access_cmo
|
possibleNets["Medbay"] = access_cmo
|
||||||
|
..()
|
||||||
|
|
||||||
proc/updateBuildPath()
|
proc/updateBuildPath()
|
||||||
build_path = null
|
build_path = null
|
||||||
|
|||||||
@@ -17,13 +17,13 @@
|
|||||||
monitor_type = /datum/nano_module/alarm_monitor/all
|
monitor_type = /datum/nano_module/alarm_monitor/all
|
||||||
circuit = /obj/item/weapon/circuitboard/stationalert_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 = 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()
|
/obj/machinery/computer/station_alert/Destroy()
|
||||||
alarm_monitor.unregister(src)
|
alarm_monitor.unregister_alarm(src)
|
||||||
qdel(alarm_monitor)
|
qdel(alarm_monitor)
|
||||||
..()
|
..()
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
/obj/machinery/computer/station_alert/update_icon()
|
/obj/machinery/computer/station_alert/update_icon()
|
||||||
if(!(stat & (BROKEN|NOPOWER)))
|
if(!(stat & (BROKEN|NOPOWER)))
|
||||||
var/list/alarms = alarm_monitor.major_alarms()
|
var/list/alarms = alarm_monitor ? alarm_monitor.major_alarms() : list()
|
||||||
if(alarms.len)
|
if(alarms.len)
|
||||||
icon_screen = "alert:2"
|
icon_screen = "alert:2"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -100,6 +100,7 @@
|
|||||||
if(content)
|
if(content)
|
||||||
if(file_increment > 1)
|
if(file_increment > 1)
|
||||||
volume = round(file_increment * length(content))
|
volume = round(file_increment * length(content))
|
||||||
|
..()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A generic file that contains text
|
A generic file that contains text
|
||||||
|
|||||||
@@ -30,14 +30,11 @@
|
|||||||
reagents = new/datum/reagents(100)
|
reagents = new/datum/reagents(100)
|
||||||
reagents.my_atom = src
|
reagents.my_atom = src
|
||||||
|
|
||||||
/obj/machinery/microwave/map/New()
|
|
||||||
..()
|
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
|
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
|
||||||
component_parts += new /obj/item/weapon/stock_parts/motor(src)
|
component_parts += new /obj/item/weapon/stock_parts/motor(src)
|
||||||
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
|
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
|
||||||
RefreshParts()
|
|
||||||
|
|
||||||
if (!available_recipes)
|
if (!available_recipes)
|
||||||
available_recipes = new
|
available_recipes = new
|
||||||
@@ -58,6 +55,8 @@
|
|||||||
acceptable_items |= /obj/item/weapon/holder
|
acceptable_items |= /obj/item/weapon/holder
|
||||||
acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown
|
acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown
|
||||||
|
|
||||||
|
RefreshParts()
|
||||||
|
|
||||||
/*******************
|
/*******************
|
||||||
* Item Adding
|
* Item Adding
|
||||||
********************/
|
********************/
|
||||||
|
|||||||
@@ -1,3 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Datum that holds the instances and information about the items in the smartfridge.
|
||||||
|
*/
|
||||||
|
/datum/data/stored_item
|
||||||
|
var/item_name = "name" //Name of the item(s) displayed
|
||||||
|
var/item_path = null
|
||||||
|
var/amount = 0
|
||||||
|
var/list/instances //What items are actually stored
|
||||||
|
var/fridge //The attatched fridge
|
||||||
|
|
||||||
|
/datum/data/stored_item/New(var/fridge, var/path, var/name = null, var/amount = 0)
|
||||||
|
..()
|
||||||
|
|
||||||
|
src.item_path = path
|
||||||
|
|
||||||
|
if(!name)
|
||||||
|
var/atom/tmp = path
|
||||||
|
src.item_name = initial(tmp.name)
|
||||||
|
else
|
||||||
|
src.item_name = name
|
||||||
|
|
||||||
|
src.amount = amount
|
||||||
|
src.fridge = fridge
|
||||||
|
|
||||||
|
/datum/data/stored_item/Destroy()
|
||||||
|
fridge = null
|
||||||
|
if(instances)
|
||||||
|
for(var/product in instances)
|
||||||
|
qdel(product)
|
||||||
|
instances.Cut()
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/datum/data/stored_item/proc/get_amount()
|
||||||
|
return instances ? instances.len : amount
|
||||||
|
|
||||||
|
/datum/data/stored_item/proc/get_product(var/product_location)
|
||||||
|
if(!get_amount() || !product_location)
|
||||||
|
return
|
||||||
|
init_products()
|
||||||
|
|
||||||
|
var/atom/movable/product = instances[instances.len] // Remove the last added product
|
||||||
|
instances -= product
|
||||||
|
product.forceMove(product_location)
|
||||||
|
|
||||||
|
/datum/data/stored_item/proc/add_product(var/atom/movable/product)
|
||||||
|
if(product.type != item_path)
|
||||||
|
return 0
|
||||||
|
init_products()
|
||||||
|
product.forceMove(fridge)
|
||||||
|
instances += product
|
||||||
|
|
||||||
|
/datum/data/stored_item/proc/init_products()
|
||||||
|
if(instances)
|
||||||
|
return
|
||||||
|
instances = list()
|
||||||
|
for(var/i = 1 to amount)
|
||||||
|
var/new_product = new item_path(fridge)
|
||||||
|
instances += new_product
|
||||||
|
|
||||||
|
|
||||||
/* SmartFridge. Much todo
|
/* SmartFridge. Much todo
|
||||||
*/
|
*/
|
||||||
/obj/machinery/smartfridge
|
/obj/machinery/smartfridge
|
||||||
@@ -15,7 +75,8 @@
|
|||||||
var/icon_on = "smartfridge"
|
var/icon_on = "smartfridge"
|
||||||
var/icon_off = "smartfridge-off"
|
var/icon_off = "smartfridge-off"
|
||||||
var/icon_panel = "smartfridge-panel"
|
var/icon_panel = "smartfridge-panel"
|
||||||
var/item_quants = list()
|
var/list/item_records = list()
|
||||||
|
var/datum/data/stored_item/currently_vending = null //What we're putting out of the machine.
|
||||||
var/seconds_electrified = 0;
|
var/seconds_electrified = 0;
|
||||||
var/shoot_inventory = 0
|
var/shoot_inventory = 0
|
||||||
var/locked = 0
|
var/locked = 0
|
||||||
@@ -68,11 +129,14 @@
|
|||||||
|
|
||||||
/obj/machinery/smartfridge/secure/extract/New()
|
/obj/machinery/smartfridge/secure/extract/New()
|
||||||
..()
|
..()
|
||||||
|
var/datum/data/stored_item/I = new(src, /obj/item/xenoproduct/slime/core)
|
||||||
|
item_records.Add(I)
|
||||||
for(var/i=1 to 5)
|
for(var/i=1 to 5)
|
||||||
var/obj/item/xenoproduct/slime/core/C = new(src)
|
var/obj/item/xenoproduct/slime/core/C = new(src)
|
||||||
C.traits = new()
|
C.traits = new()
|
||||||
C.nameVar = "grey"
|
C.nameVar = "grey"
|
||||||
item_quants[C.name]++
|
I.add_product(C)
|
||||||
|
|
||||||
|
|
||||||
/obj/machinery/smartfridge/secure/medbay
|
/obj/machinery/smartfridge/secure/medbay
|
||||||
name = "\improper Refrigerated Medicine Storage"
|
name = "\improper Refrigerated Medicine Storage"
|
||||||
@@ -162,20 +226,19 @@
|
|||||||
overlays += "drying_rack_drying"
|
overlays += "drying_rack_drying"
|
||||||
|
|
||||||
/obj/machinery/smartfridge/drying_rack/proc/dry()
|
/obj/machinery/smartfridge/drying_rack/proc/dry()
|
||||||
for(var/obj/item/weapon/reagent_containers/food/snacks/S in contents)
|
for(var/datum/data/stored_item/I in item_records)
|
||||||
if(S.dry) continue
|
for(var/obj/item/weapon/reagent_containers/food/snacks/S in I.instances)
|
||||||
if(S.dried_type == S.type)
|
if(S.dry) continue
|
||||||
S.dry = 1
|
if(S.dried_type == S.type)
|
||||||
item_quants[S.name]--
|
S.dry = 1
|
||||||
S.name = "dried [S.name]"
|
S.name = "dried [S.name]"
|
||||||
S.color = "#AAAAAA"
|
S.color = "#AAAAAA"
|
||||||
S.loc = loc
|
I.get_product(loc)
|
||||||
else
|
else
|
||||||
var/D = S.dried_type
|
var/D = S.dried_type
|
||||||
new D(loc)
|
new D(loc)
|
||||||
item_quants[S.name]--
|
qdel(S)
|
||||||
qdel(S)
|
return
|
||||||
return
|
|
||||||
return
|
return
|
||||||
|
|
||||||
/obj/machinery/smartfridge/process()
|
/obj/machinery/smartfridge/process()
|
||||||
@@ -222,35 +285,39 @@
|
|||||||
return
|
return
|
||||||
|
|
||||||
if(accept_check(O))
|
if(accept_check(O))
|
||||||
if(contents.len >= max_n_of_items)
|
user.remove_from_mob(O)
|
||||||
user << "<span class='notice'>\The [src] is full.</span>"
|
var/hasRecord = FALSE //Check to see if this passes or not.
|
||||||
return 1
|
for(var/datum/data/stored_item/I in item_records)
|
||||||
else
|
if(istype(O, I.item_path))
|
||||||
user.remove_from_mob(O)
|
stock(O, I)
|
||||||
O.loc = src
|
qdel(O)
|
||||||
if(item_quants[O.name])
|
return
|
||||||
item_quants[O.name]++
|
if(!hasRecord)
|
||||||
else
|
var/datum/data/stored_item/item = new/datum/data/stored_item(src, O.type)
|
||||||
item_quants[O.name] = 1
|
stock(O, item)
|
||||||
user.visible_message("<span class='notice'>[user] has added \the [O] to \the [src].</span>", "<span class='notice'>You add \the [O] to \the [src].</span>")
|
item_records.Add(item)
|
||||||
|
|
||||||
|
user.visible_message("<span class='notice'>[user] has added \the [O] to \the [src].</span>", "<span class='notice'>You add \the [O] to \the [src].</span>")
|
||||||
|
|
||||||
nanomanager.update_uis(src)
|
nanomanager.update_uis(src)
|
||||||
|
|
||||||
else if(istype(O, /obj/item/weapon/storage/bag))
|
else if(istype(O, /obj/item/weapon/storage/bag))
|
||||||
var/obj/item/weapon/storage/bag/P = O
|
var/obj/item/weapon/storage/bag/P = O
|
||||||
var/plants_loaded = 0
|
var/plants_loaded = 0
|
||||||
for(var/obj/G in P.contents)
|
for(var/obj/G in P.contents)
|
||||||
if(accept_check(G))
|
if(accept_check(G))
|
||||||
if(contents.len >= max_n_of_items)
|
plants_loaded++
|
||||||
user << "<span class='notice'>\The [src] is full.</span>"
|
var/hasRecord = FALSE //Check to see if this passes or not.
|
||||||
return 1
|
for(var/datum/data/stored_item/I in item_records)
|
||||||
else
|
if(istype(G, I.item_path))
|
||||||
P.remove_from_storage(G,src)
|
if(G.name == I.item_name)
|
||||||
if(item_quants[G.name])
|
stock(G, I)
|
||||||
item_quants[G.name]++
|
hasRecord = TRUE
|
||||||
else
|
if(!hasRecord)
|
||||||
item_quants[G.name] = 1
|
var/datum/data/stored_item/item = new/datum/data/stored_item(src, G.type, G.name)
|
||||||
plants_loaded++
|
stock(G, item)
|
||||||
|
item_records.Add(item)
|
||||||
|
|
||||||
if(plants_loaded)
|
if(plants_loaded)
|
||||||
|
|
||||||
user.visible_message("<span class='notice'>[user] loads \the [src] with \the [P].</span>", "<span class='notice'>You load \the [src] with \the [P].</span>")
|
user.visible_message("<span class='notice'>[user] loads \the [src] with \the [P].</span>", "<span class='notice'>You load \the [src] with \the [P].</span>")
|
||||||
@@ -269,6 +336,14 @@
|
|||||||
locked = -1
|
locked = -1
|
||||||
user << "You short out the product lock on [src]."
|
user << "You short out the product lock on [src]."
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
/obj/machinery/smartfridge/proc/stock(obj/item/O, var/datum/data/stored_item/I)
|
||||||
|
I.add_product(O)
|
||||||
|
nanomanager.update_uis(src)
|
||||||
|
|
||||||
|
/obj/machinery/smartfridge/proc/vend(datum/data/stored_item/I)
|
||||||
|
I.get_product(get_turf(src))
|
||||||
|
nanomanager.update_uis(src)
|
||||||
|
|
||||||
/obj/machinery/smartfridge/attack_ai(mob/user as mob)
|
/obj/machinery/smartfridge/attack_ai(mob/user as mob)
|
||||||
attack_hand(user)
|
attack_hand(user)
|
||||||
@@ -294,11 +369,11 @@
|
|||||||
data["secure"] = is_secure
|
data["secure"] = is_secure
|
||||||
|
|
||||||
var/list/items[0]
|
var/list/items[0]
|
||||||
for (var/i=1 to length(item_quants))
|
for (var/i=1 to length(item_records))
|
||||||
var/K = item_quants[i]
|
var/datum/data/stored_item/I = item_records[i]
|
||||||
var/count = item_quants[K]
|
var/count = I.get_amount()
|
||||||
if(count > 0)
|
if(count > 0)
|
||||||
items.Add(list(list("display_name" = html_encode(capitalize(K)), "vend" = i, "quantity" = count)))
|
items.Add(list(list("display_name" = html_encode(capitalize(I.item_name)), "vend" = i, "quantity" = count)))
|
||||||
|
|
||||||
if(items.len > 0)
|
if(items.len > 0)
|
||||||
data["contents"] = items
|
data["contents"] = items
|
||||||
@@ -325,20 +400,15 @@
|
|||||||
if(href_list["vend"])
|
if(href_list["vend"])
|
||||||
var/index = text2num(href_list["vend"])
|
var/index = text2num(href_list["vend"])
|
||||||
var/amount = text2num(href_list["amount"])
|
var/amount = text2num(href_list["amount"])
|
||||||
var/K = item_quants[index]
|
var/datum/data/stored_item/I = item_records[index]
|
||||||
var/count = item_quants[K]
|
var/count = I.get_amount()
|
||||||
|
|
||||||
// Sanity check, there are probably ways to press the button when it shouldn't be possible.
|
// Sanity check, there are probably ways to press the button when it shouldn't be possible.
|
||||||
if(count > 0)
|
if(count > 0)
|
||||||
item_quants[K] = max(count - amount, 0)
|
if((count - amount) < 0)
|
||||||
|
amount = count
|
||||||
var/i = amount
|
for(var/i = 1 to amount)
|
||||||
for(var/obj/O in contents)
|
vend(I)
|
||||||
if(O.name == K)
|
|
||||||
O.loc = loc
|
|
||||||
i--
|
|
||||||
if(i <= 0)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
return 0
|
return 0
|
||||||
@@ -349,17 +419,12 @@
|
|||||||
if(!target)
|
if(!target)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
for (var/O in item_quants)
|
for(var/datum/data/stored_item/I in src.item_records)
|
||||||
if(item_quants[O] <= 0) //Try to use a record that actually has something to dump.
|
throw_item = I.get_product(loc)
|
||||||
|
if (!throw_item)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
item_quants[O]--
|
|
||||||
for(var/obj/T in contents)
|
|
||||||
if(T.name == O)
|
|
||||||
T.loc = src.loc
|
|
||||||
throw_item = T
|
|
||||||
break
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if(!throw_item)
|
if(!throw_item)
|
||||||
return 0
|
return 0
|
||||||
spawn(0)
|
spawn(0)
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ Class Procs:
|
|||||||
if(contents) // The same for contents.
|
if(contents) // The same for contents.
|
||||||
for(var/atom/A in contents)
|
for(var/atom/A in contents)
|
||||||
qdel(A)
|
qdel(A)
|
||||||
..()
|
return ..()
|
||||||
|
|
||||||
/obj/machinery/process()//If you dont use process or power why are you here
|
/obj/machinery/process()//If you dont use process or power why are you here
|
||||||
if(!(use_power || idle_power_usage || active_power_usage))
|
if(!(use_power || idle_power_usage || active_power_usage))
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
var/id = 1.0
|
var/id = 1.0
|
||||||
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
|
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
|
||||||
|
|
||||||
/obj/machinery/mass_driver/map/New()
|
/obj/machinery/mass_driver/New()
|
||||||
..()
|
..()
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ obj/machinery/recharger
|
|||||||
var/portable = 1
|
var/portable = 1
|
||||||
circuit = /obj/item/weapon/circuitboard/recharger
|
circuit = /obj/item/weapon/circuitboard/recharger
|
||||||
|
|
||||||
obj/machinery/recharger/map/New()
|
obj/machinery/recharger/New()
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
|
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
|
||||||
@@ -172,12 +172,3 @@ obj/machinery/recharger/wallcharger
|
|||||||
portable = 0
|
portable = 0
|
||||||
circuit = /obj/item/weapon/circuitboard/recharger/wrecharger
|
circuit = /obj/item/weapon/circuitboard/recharger/wrecharger
|
||||||
frame_type = "wrecharger"
|
frame_type = "wrecharger"
|
||||||
|
|
||||||
obj/machinery/recharger/wallcharger/map/New()
|
|
||||||
circuit = new circuit(src)
|
|
||||||
component_parts = list()
|
|
||||||
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
|
|
||||||
component_parts += new /obj/item/stack/cable_coil(src, 5)
|
|
||||||
RefreshParts()
|
|
||||||
..()
|
|
||||||
return
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
var/weld_power_use = 2300 // power used per point of brute damage repaired. 2.3 kW ~ about the same power usage of a handheld arc welder
|
var/weld_power_use = 2300 // power used per point of brute damage repaired. 2.3 kW ~ about the same power usage of a handheld arc welder
|
||||||
var/wire_power_use = 500 // power used per point of burn damage repaired.
|
var/wire_power_use = 500 // power used per point of burn damage repaired.
|
||||||
|
|
||||||
/obj/machinery/recharge_station/map/New()
|
/obj/machinery/recharge_station/New()
|
||||||
..()
|
..()
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
|
|||||||
@@ -179,8 +179,6 @@
|
|||||||
underlays.Cut()
|
underlays.Cut()
|
||||||
underlays += image('icons/obj/stationobjs.dmi', icon_state = "tele-wires")
|
underlays += image('icons/obj/stationobjs.dmi', icon_state = "tele-wires")
|
||||||
|
|
||||||
/obj/machinery/teleport/hub/map/New()
|
|
||||||
..()
|
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
|
||||||
@@ -331,8 +329,6 @@
|
|||||||
overlays.Cut()
|
overlays.Cut()
|
||||||
overlays += image('icons/obj/stationobjs.dmi', icon_state = "controller-wires")
|
overlays += image('icons/obj/stationobjs.dmi', icon_state = "controller-wires")
|
||||||
|
|
||||||
/obj/machinery/teleport/station/map/New()
|
|
||||||
..()
|
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
|
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
var/obj/crayon
|
var/obj/crayon
|
||||||
var/list/washing = list()
|
var/list/washing = list()
|
||||||
|
|
||||||
/obj/machinery/washing_machine/map/New()
|
/obj/machinery/washing_machine/New()
|
||||||
circuit = new circuit(src)
|
circuit = new circuit(src)
|
||||||
component_parts = list()
|
component_parts = list()
|
||||||
component_parts += new /obj/item/weapon/stock_parts/motor(src)
|
component_parts += new /obj/item/weapon/stock_parts/motor(src)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
/obj/item/mecha_parts/mecha_equipment/weapon/proc/Fire(atom/A, atom/target)
|
/obj/item/mecha_parts/mecha_equipment/weapon/proc/Fire(atom/A, atom/target)
|
||||||
var/obj/item/projectile/P = A
|
var/obj/item/projectile/P = A
|
||||||
P.launch(target)
|
P.launch(target)
|
||||||
|
|
||||||
/obj/item/mecha_parts/mecha_equipment/weapon/energy
|
/obj/item/mecha_parts/mecha_equipment/weapon/energy
|
||||||
name = "general energy weapon"
|
name = "general energy weapon"
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
energy_drain = 120
|
energy_drain = 120
|
||||||
origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 6, TECH_POWER = 4)
|
origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 6, TECH_POWER = 4)
|
||||||
projectile = /obj/item/projectile/beam/pulse/heavy
|
projectile = /obj/item/projectile/beam/pulse/heavy
|
||||||
fire_sound = 'sound/weapons/marauder.ogg'
|
fire_sound = 'sound/weapons/gauss_shoot.ogg'
|
||||||
|
|
||||||
/obj/item/projectile/beam/pulse/heavy
|
/obj/item/projectile/beam/pulse/heavy
|
||||||
name = "heavy pulse laser"
|
name = "heavy pulse laser"
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
icon_state = "mecha_uac2"
|
icon_state = "mecha_uac2"
|
||||||
equip_cooldown = 10
|
equip_cooldown = 10
|
||||||
projectile = /obj/item/projectile/bullet/pistol/medium
|
projectile = /obj/item/projectile/bullet/pistol/medium
|
||||||
fire_sound = 'sound/weapons/Gunshot.ogg'
|
fire_sound = 'sound/weapons/machinegun.ogg'
|
||||||
projectiles = 300
|
projectiles = 300
|
||||||
projectiles_per_shot = 3
|
projectiles_per_shot = 3
|
||||||
deviation = 0.3
|
deviation = 0.3
|
||||||
@@ -218,7 +218,7 @@
|
|||||||
|
|
||||||
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
|
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
|
||||||
AM.throw_at(target,missile_range, missile_speed, chassis)
|
AM.throw_at(target,missile_range, missile_speed, chassis)
|
||||||
|
|
||||||
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare
|
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare
|
||||||
name = "\improper BNI Flare Launcher"
|
name = "\improper BNI Flare Launcher"
|
||||||
icon_state = "mecha_flaregun"
|
icon_state = "mecha_flaregun"
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
missile_speed = 1
|
missile_speed = 1
|
||||||
missile_range = 15
|
missile_range = 15
|
||||||
required_type = /obj/mecha //Why restrict it to just mining or combat mechs?
|
required_type = /obj/mecha //Why restrict it to just mining or combat mechs?
|
||||||
|
|
||||||
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare/Fire(atom/movable/AM, atom/target, turf/aimloc)
|
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare/Fire(atom/movable/AM, atom/target, turf/aimloc)
|
||||||
var/obj/item/device/flashlight/flare/fired = AM
|
var/obj/item/device/flashlight/flare/fired = AM
|
||||||
fired.ignite()
|
fired.ignite()
|
||||||
@@ -241,7 +241,7 @@
|
|||||||
name = "\improper SRM-8 missile rack"
|
name = "\improper SRM-8 missile rack"
|
||||||
icon_state = "mecha_missilerack"
|
icon_state = "mecha_missilerack"
|
||||||
projectile = /obj/item/missile
|
projectile = /obj/item/missile
|
||||||
fire_sound = 'sound/effects/bang.ogg'
|
fire_sound = 'sound/weapons/rpg.ogg'
|
||||||
projectiles = 8
|
projectiles = 8
|
||||||
projectile_energy_cost = 1000
|
projectile_energy_cost = 1000
|
||||||
equip_cooldown = 60
|
equip_cooldown = 60
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/obj/machinery/pros_fabricator
|
/obj/machinery/pros_fabricator
|
||||||
icon = 'icons/obj/robotics.dmi'
|
icon = 'icons/obj/robotics.dmi'
|
||||||
icon_state = "pros-idle"
|
icon_state = "fab-idle"
|
||||||
name = "Prosthetics Fabricator"
|
name = "Prosthetics Fabricator"
|
||||||
desc = "A machine used for construction of prosthetics."
|
desc = "A machine used for construction of prosthetics."
|
||||||
density = 1
|
density = 1
|
||||||
@@ -59,11 +59,11 @@
|
|||||||
/obj/machinery/pros_fabricator/update_icon()
|
/obj/machinery/pros_fabricator/update_icon()
|
||||||
overlays.Cut()
|
overlays.Cut()
|
||||||
if(panel_open)
|
if(panel_open)
|
||||||
icon_state = "pros-o"
|
icon_state = "fab-o"
|
||||||
else
|
else
|
||||||
icon_state = "pros-idle"
|
icon_state = "fab-idle"
|
||||||
if(busy)
|
if(busy)
|
||||||
overlays += "pros-active"
|
overlays += "fab-active"
|
||||||
|
|
||||||
/obj/machinery/pros_fabricator/dismantle()
|
/obj/machinery/pros_fabricator/dismantle()
|
||||||
for(var/f in materials)
|
for(var/f in materials)
|
||||||
|
|||||||
@@ -29,12 +29,16 @@
|
|||||||
/obj/proc/buckle_mob(mob/living/M)
|
/obj/proc/buckle_mob(mob/living/M)
|
||||||
if(!can_buckle || !istype(M) || (M.loc != loc) || M.buckled || M.pinned.len || (buckle_require_restraints && !M.restrained()))
|
if(!can_buckle || !istype(M) || (M.loc != loc) || M.buckled || M.pinned.len || (buckle_require_restraints && !M.restrained()))
|
||||||
return 0
|
return 0
|
||||||
|
if(buckled_mob) //Handles trying to buckle yourself to the chair when someone is on it
|
||||||
|
M << "<span class='notice'>\The [src] already has someone buckled to it.</span>"
|
||||||
|
return 0
|
||||||
|
|
||||||
M.buckled = src
|
M.buckled = src
|
||||||
M.facing_dir = null
|
M.facing_dir = null
|
||||||
M.set_dir(buckle_dir ? buckle_dir : dir)
|
M.set_dir(buckle_dir ? buckle_dir : dir)
|
||||||
M.update_canmove()
|
M.update_canmove()
|
||||||
buckled_mob = M
|
buckled_mob = M
|
||||||
|
|
||||||
post_buckle_mob(M)
|
post_buckle_mob(M)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|||||||
@@ -107,9 +107,10 @@ steam.start() -- spawns the effect
|
|||||||
var/turf/T = src.loc
|
var/turf/T = src.loc
|
||||||
if (istype(T, /turf))
|
if (istype(T, /turf))
|
||||||
T.hotspot_expose(1000,100)
|
T.hotspot_expose(1000,100)
|
||||||
spawn (20)
|
|
||||||
qdel(src)
|
/obj/effect/effect/sparks/initialize()
|
||||||
return
|
..()
|
||||||
|
schedule_task_in(5 SECONDS, /proc/qdel, list(src))
|
||||||
|
|
||||||
/obj/effect/effect/sparks/Destroy()
|
/obj/effect/effect/sparks/Destroy()
|
||||||
var/turf/T = src.loc
|
var/turf/T = src.loc
|
||||||
@@ -185,7 +186,6 @@ steam.start() -- spawns the effect
|
|||||||
..()
|
..()
|
||||||
spawn (time_to_live)
|
spawn (time_to_live)
|
||||||
qdel(src)
|
qdel(src)
|
||||||
return
|
|
||||||
|
|
||||||
/obj/effect/effect/smoke/Crossed(mob/living/carbon/M as mob )
|
/obj/effect/effect/smoke/Crossed(mob/living/carbon/M as mob )
|
||||||
..()
|
..()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
anchored = 1.0
|
anchored = 1.0
|
||||||
unacidable = 1
|
unacidable = 1
|
||||||
simulated = 0
|
simulated = 0
|
||||||
|
var/delete_me = 0
|
||||||
|
|
||||||
/obj/effect/landmark/New()
|
/obj/effect/landmark/New()
|
||||||
..()
|
..()
|
||||||
@@ -14,33 +15,35 @@
|
|||||||
switch(name) //some of these are probably obsolete
|
switch(name) //some of these are probably obsolete
|
||||||
if("monkey")
|
if("monkey")
|
||||||
monkeystart += loc
|
monkeystart += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("start")
|
if("start")
|
||||||
newplayer_start += loc
|
newplayer_start += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
return
|
||||||
if("JoinLate")
|
if("JoinLate")
|
||||||
latejoin += loc
|
latejoin += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
return
|
||||||
if("JoinLateGateway")
|
if("JoinLateGateway")
|
||||||
latejoin_gateway += loc
|
latejoin_gateway += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("JoinLateElevator")
|
if("JoinLateElevator")
|
||||||
latejoin_elevator += loc
|
latejoin_elevator += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("JoinLateCryo")
|
if("JoinLateCryo")
|
||||||
latejoin_cryo += loc
|
latejoin_cryo += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("JoinLateCyborg")
|
if("JoinLateCyborg")
|
||||||
latejoin_cyborg += loc
|
latejoin_cyborg += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("prisonwarp")
|
if("prisonwarp")
|
||||||
prisonwarp += loc
|
prisonwarp += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("Holding Facility")
|
if("Holding Facility")
|
||||||
holdingfacility += loc
|
holdingfacility += loc
|
||||||
@@ -54,28 +57,36 @@
|
|||||||
tdomeobserve += loc
|
tdomeobserve += loc
|
||||||
if("prisonsecuritywarp")
|
if("prisonsecuritywarp")
|
||||||
prisonsecuritywarp += loc
|
prisonsecuritywarp += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("blobstart")
|
if("blobstart")
|
||||||
blobstart += loc
|
blobstart += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("xeno_spawn")
|
if("xeno_spawn")
|
||||||
xeno_spawn += loc
|
xeno_spawn += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("endgame_exit")
|
if("endgame_exit")
|
||||||
endgame_safespawns += loc
|
endgame_safespawns += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
if("bluespacerift")
|
if("bluespacerift")
|
||||||
endgame_exits += loc
|
endgame_exits += loc
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
return
|
return
|
||||||
|
|
||||||
landmarks_list += src
|
landmarks_list += src
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
/obj/effect/landmark/proc/delete()
|
||||||
|
delete_me = 1
|
||||||
|
|
||||||
|
/obj/effect/landmark/initialize()
|
||||||
|
..()
|
||||||
|
if(delete_me)
|
||||||
|
qdel(src)
|
||||||
|
|
||||||
/obj/effect/landmark/Destroy()
|
/obj/effect/landmark/Destroy()
|
||||||
landmarks_list -= src
|
landmarks_list -= src
|
||||||
return ..()
|
return ..()
|
||||||
@@ -99,14 +110,14 @@
|
|||||||
var/list/options = typesof(/obj/effect/landmark/costume)
|
var/list/options = typesof(/obj/effect/landmark/costume)
|
||||||
var/PICK= options[rand(1,options.len)]
|
var/PICK= options[rand(1,options.len)]
|
||||||
new PICK(src.loc)
|
new PICK(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
//SUBCLASSES. Spawn a bunch of items and disappear likewise
|
//SUBCLASSES. Spawn a bunch of items and disappear likewise
|
||||||
/obj/effect/landmark/costume/chicken/New()
|
/obj/effect/landmark/costume/chicken/New()
|
||||||
new /obj/item/clothing/suit/chickensuit(src.loc)
|
new /obj/item/clothing/suit/chickensuit(src.loc)
|
||||||
new /obj/item/clothing/head/chicken(src.loc)
|
new /obj/item/clothing/head/chicken(src.loc)
|
||||||
new /obj/item/weapon/reagent_containers/food/snacks/egg(src.loc)
|
new /obj/item/weapon/reagent_containers/food/snacks/egg(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/gladiator/New()
|
/obj/effect/landmark/costume/gladiator/New()
|
||||||
new /obj/item/clothing/under/gladiator(src.loc)
|
new /obj/item/clothing/under/gladiator(src.loc)
|
||||||
@@ -118,32 +129,32 @@
|
|||||||
new /obj/item/clothing/head/flatcap(src.loc)
|
new /obj/item/clothing/head/flatcap(src.loc)
|
||||||
new /obj/item/clothing/suit/storage/toggle/labcoat/mad(src.loc)
|
new /obj/item/clothing/suit/storage/toggle/labcoat/mad(src.loc)
|
||||||
new /obj/item/clothing/glasses/gglasses(src.loc)
|
new /obj/item/clothing/glasses/gglasses(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/elpresidente/New()
|
/obj/effect/landmark/costume/elpresidente/New()
|
||||||
new /obj/item/clothing/under/gimmick/rank/captain/suit(src.loc)
|
new /obj/item/clothing/under/gimmick/rank/captain/suit(src.loc)
|
||||||
new /obj/item/clothing/head/flatcap(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/mask/smokable/cigarette/cigar/havana(src.loc)
|
||||||
new /obj/item/clothing/shoes/jackboots(src.loc)
|
new /obj/item/clothing/shoes/jackboots(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/nyangirl/New()
|
/obj/effect/landmark/costume/nyangirl/New()
|
||||||
new /obj/item/clothing/under/schoolgirl(src.loc)
|
new /obj/item/clothing/under/schoolgirl(src.loc)
|
||||||
new /obj/item/clothing/head/kitty(src.loc)
|
new /obj/item/clothing/head/kitty(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/maid/New()
|
/obj/effect/landmark/costume/maid/New()
|
||||||
new /obj/item/clothing/under/skirt(src.loc)
|
new /obj/item/clothing/under/skirt(src.loc)
|
||||||
var/CHOICE = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears )
|
var/CHOICE = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears )
|
||||||
new CHOICE(src.loc)
|
new CHOICE(src.loc)
|
||||||
new /obj/item/clothing/glasses/sunglasses/blindfold(src.loc)
|
new /obj/item/clothing/glasses/sunglasses/blindfold(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/butler/New()
|
/obj/effect/landmark/costume/butler/New()
|
||||||
new /obj/item/clothing/suit/wcoat(src.loc)
|
new /obj/item/clothing/suit/wcoat(src.loc)
|
||||||
new /obj/item/clothing/under/suit_jacket(src.loc)
|
new /obj/item/clothing/under/suit_jacket(src.loc)
|
||||||
new /obj/item/clothing/head/that(src.loc)
|
new /obj/item/clothing/head/that(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/scratch/New()
|
/obj/effect/landmark/costume/scratch/New()
|
||||||
new /obj/item/clothing/gloves/white(src.loc)
|
new /obj/item/clothing/gloves/white(src.loc)
|
||||||
@@ -151,12 +162,12 @@
|
|||||||
new /obj/item/clothing/under/scratch(src.loc)
|
new /obj/item/clothing/under/scratch(src.loc)
|
||||||
if (prob(30))
|
if (prob(30))
|
||||||
new /obj/item/clothing/head/cueball(src.loc)
|
new /obj/item/clothing/head/cueball(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/highlander/New()
|
/obj/effect/landmark/costume/highlander/New()
|
||||||
new /obj/item/clothing/under/kilt(src.loc)
|
new /obj/item/clothing/under/kilt(src.loc)
|
||||||
new /obj/item/clothing/head/beret(src.loc)
|
new /obj/item/clothing/head/beret(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/prig/New()
|
/obj/effect/landmark/costume/prig/New()
|
||||||
new /obj/item/clothing/suit/wcoat(src.loc)
|
new /obj/item/clothing/suit/wcoat(src.loc)
|
||||||
@@ -167,24 +178,24 @@
|
|||||||
new /obj/item/weapon/cane(src.loc)
|
new /obj/item/weapon/cane(src.loc)
|
||||||
new /obj/item/clothing/under/sl_suit(src.loc)
|
new /obj/item/clothing/under/sl_suit(src.loc)
|
||||||
new /obj/item/clothing/mask/fakemoustache(src.loc)
|
new /obj/item/clothing/mask/fakemoustache(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/plaguedoctor/New()
|
/obj/effect/landmark/costume/plaguedoctor/New()
|
||||||
new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(src.loc)
|
new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(src.loc)
|
||||||
new /obj/item/clothing/head/plaguedoctorhat(src.loc)
|
new /obj/item/clothing/head/plaguedoctorhat(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/nightowl/New()
|
/obj/effect/landmark/costume/nightowl/New()
|
||||||
new /obj/item/clothing/under/owl(src.loc)
|
new /obj/item/clothing/under/owl(src.loc)
|
||||||
new /obj/item/clothing/mask/gas/owl_mask(src.loc)
|
new /obj/item/clothing/mask/gas/owl_mask(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/waiter/New()
|
/obj/effect/landmark/costume/waiter/New()
|
||||||
new /obj/item/clothing/under/waiter(src.loc)
|
new /obj/item/clothing/under/waiter(src.loc)
|
||||||
var/CHOICE= pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears)
|
var/CHOICE= pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears)
|
||||||
new CHOICE(src.loc)
|
new CHOICE(src.loc)
|
||||||
new /obj/item/clothing/suit/apron(src.loc)
|
new /obj/item/clothing/suit/apron(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/pirate/New()
|
/obj/effect/landmark/costume/pirate/New()
|
||||||
new /obj/item/clothing/under/pirate(src.loc)
|
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 )
|
var/CHOICE = pick( /obj/item/clothing/head/pirate , /obj/item/clothing/head/bandana )
|
||||||
new CHOICE(src.loc)
|
new CHOICE(src.loc)
|
||||||
new /obj/item/clothing/glasses/eyepatch(src.loc)
|
new /obj/item/clothing/glasses/eyepatch(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/commie/New()
|
/obj/effect/landmark/costume/commie/New()
|
||||||
new /obj/item/clothing/under/soviet(src.loc)
|
new /obj/item/clothing/under/soviet(src.loc)
|
||||||
new /obj/item/clothing/head/ushanka(src.loc)
|
new /obj/item/clothing/head/ushanka(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/imperium_monk/New()
|
/obj/effect/landmark/costume/imperium_monk/New()
|
||||||
new /obj/item/clothing/suit/imperium_monk(src.loc)
|
new /obj/item/clothing/suit/imperium_monk(src.loc)
|
||||||
if (prob(25))
|
if (prob(25))
|
||||||
new /obj/item/clothing/mask/gas/cyborg(src.loc)
|
new /obj/item/clothing/mask/gas/cyborg(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/holiday_priest/New()
|
/obj/effect/landmark/costume/holiday_priest/New()
|
||||||
new /obj/item/clothing/suit/holidaypriest(src.loc)
|
new /obj/item/clothing/suit/holidaypriest(src.loc)
|
||||||
@@ -212,26 +223,26 @@
|
|||||||
/obj/effect/landmark/costume/marisawizard/fake/New()
|
/obj/effect/landmark/costume/marisawizard/fake/New()
|
||||||
new /obj/item/clothing/head/wizard/marisa/fake(src.loc)
|
new /obj/item/clothing/head/wizard/marisa/fake(src.loc)
|
||||||
new/obj/item/clothing/suit/wizrobe/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()
|
/obj/effect/landmark/costume/cutewitch/New()
|
||||||
new /obj/item/clothing/under/sundress(src.loc)
|
new /obj/item/clothing/under/sundress(src.loc)
|
||||||
new /obj/item/clothing/head/witchwig(src.loc)
|
new /obj/item/clothing/head/witchwig(src.loc)
|
||||||
new /obj/item/weapon/staff/broom(src.loc)
|
new /obj/item/weapon/staff/broom(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/fakewizard/New()
|
/obj/effect/landmark/costume/fakewizard/New()
|
||||||
new /obj/item/clothing/suit/wizrobe/fake(src.loc)
|
new /obj/item/clothing/suit/wizrobe/fake(src.loc)
|
||||||
new /obj/item/clothing/head/wizard/fake(src.loc)
|
new /obj/item/clothing/head/wizard/fake(src.loc)
|
||||||
new /obj/item/weapon/staff/(src.loc)
|
new /obj/item/weapon/staff/(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/sexyclown/New()
|
/obj/effect/landmark/costume/sexyclown/New()
|
||||||
new /obj/item/clothing/mask/gas/sexyclown(src.loc)
|
new /obj/item/clothing/mask/gas/sexyclown(src.loc)
|
||||||
new /obj/item/clothing/under/sexyclown(src.loc)
|
new /obj/item/clothing/under/sexyclown(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|
||||||
/obj/effect/landmark/costume/sexymime/New()
|
/obj/effect/landmark/costume/sexymime/New()
|
||||||
new /obj/item/clothing/mask/gas/sexymime(src.loc)
|
new /obj/item/clothing/mask/gas/sexymime(src.loc)
|
||||||
new /obj/item/clothing/under/sexymime(src.loc)
|
new /obj/item/clothing/under/sexymime(src.loc)
|
||||||
qdel(src)
|
delete_me = 1
|
||||||
|
|||||||
@@ -52,3 +52,48 @@
|
|||||||
..()
|
..()
|
||||||
pixel_x += rand(-10, 10)
|
pixel_x += rand(-10, 10)
|
||||||
pixel_y += rand(-10, 10)
|
pixel_y += rand(-10, 10)
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow
|
||||||
|
name = "snow"
|
||||||
|
icon = 'icons/turf/overlays.dmi'
|
||||||
|
icon_state = "snow"
|
||||||
|
anchored = 1
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/floor
|
||||||
|
icon_state = "snowfloor"
|
||||||
|
layer = 2.01 //Just above floor
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/floor/edges
|
||||||
|
icon_state = "snow_edges"
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/floor/surround
|
||||||
|
icon_state = "snow_surround"
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/airlock
|
||||||
|
icon_state = "snowairlock"
|
||||||
|
layer = 3.2 //Just above airlocks
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/floor/north
|
||||||
|
icon_state = "snowfloor_n"
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/floor/south
|
||||||
|
icon_state = "snowfloor_s"
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/floor/east
|
||||||
|
icon_state = "snowfloor_e"
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/floor/west
|
||||||
|
icon_state = "snowfloor_w"
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/wall/north
|
||||||
|
icon_state = "snowwall_n"
|
||||||
|
layer = 5 //Same as lights so humans can stand under it
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/wall/south
|
||||||
|
icon_state = "snowwall_s"
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/wall/east
|
||||||
|
icon_state = "snowwall_e"
|
||||||
|
|
||||||
|
/obj/effect/overlay/snow/wall/west
|
||||||
|
icon_state = "snowwall_w"
|
||||||
@@ -12,9 +12,6 @@
|
|||||||
var/syndie = 0
|
var/syndie = 0
|
||||||
var/list/channels = list()
|
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/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||||
|
|
||||||
/obj/item/device/encryptionkey/syndicate
|
/obj/item/device/encryptionkey/syndicate
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
/obj/item/weapon/extinguisher/New()
|
/obj/item/weapon/extinguisher/New()
|
||||||
create_reagents(max_water)
|
create_reagents(max_water)
|
||||||
reagents.add_reagent("water", max_water)
|
reagents.add_reagent("water", max_water)
|
||||||
|
..()
|
||||||
|
|
||||||
/obj/item/weapon/extinguisher/examine(mob/user)
|
/obj/item/weapon/extinguisher/examine(mob/user)
|
||||||
if(..(user, 0))
|
if(..(user, 0))
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
/obj/item/weapon/material/wirerod/attackby(var/obj/item/I, mob/user as mob)
|
/obj/item/weapon/material/wirerod/attackby(var/obj/item/I, mob/user as mob)
|
||||||
..()
|
..()
|
||||||
var/obj/item/finished
|
var/obj/item/finished
|
||||||
if(istype(I, /obj/item/weapon/material/shard))
|
if(istype(I, /obj/item/weapon/material/shard) || istype(I, /obj/item/weapon/material/butterflyblade))
|
||||||
var/obj/item/weapon/material/tmp_shard = I
|
var/obj/item/weapon/material/tmp_shard = I
|
||||||
finished = new /obj/item/weapon/material/twohanded/spear(get_turf(user), tmp_shard.material.name)
|
finished = new /obj/item/weapon/material/twohanded/spear(get_turf(user), tmp_shard.material.name)
|
||||||
user << "<span class='notice'>You fasten \the [I] to the top of the rod with the cable.</span>"
|
user << "<span class='notice'>You fasten \the [I] to the top of the rod with the cable.</span>"
|
||||||
|
|||||||
@@ -225,7 +225,7 @@
|
|||||||
/obj/item/weapon/storage/box/emps/New()
|
/obj/item/weapon/storage/box/emps/New()
|
||||||
..()
|
..()
|
||||||
for(var/i = 1 to 5)
|
for(var/i = 1 to 5)
|
||||||
new /obj/item/weapon/grenade/empgrenade(src)
|
new /obj/item/weapon/grenade/empgrenade(src)
|
||||||
|
|
||||||
/obj/item/weapon/storage/box/empslite
|
/obj/item/weapon/storage/box/empslite
|
||||||
name = "box of low yield emp grenades"
|
name = "box of low yield emp grenades"
|
||||||
@@ -275,7 +275,7 @@
|
|||||||
/obj/item/weapon/storage/box/metalfoam/New()
|
/obj/item/weapon/storage/box/metalfoam/New()
|
||||||
..()
|
..()
|
||||||
for(var/i = 1 to 7)
|
for(var/i = 1 to 7)
|
||||||
new /obj/item/weapon/grenade/chem_grenade/metalfoam
|
new /obj/item/weapon/grenade/chem_grenade/metalfoam(src)
|
||||||
|
|
||||||
/obj/item/weapon/storage/box/trackimp
|
/obj/item/weapon/storage/box/trackimp
|
||||||
name = "boxed tracking implant kit"
|
name = "boxed tracking implant kit"
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
if (prob(75))
|
if (prob(75))
|
||||||
src.pixel_y = rand(0, 16)
|
src.pixel_y = rand(0, 16)
|
||||||
return
|
..()
|
||||||
|
|
||||||
/obj/item/weapon/screwdriver/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
|
/obj/item/weapon/screwdriver/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
|
||||||
if(!istype(M) || user.a_intent == "help")
|
if(!istype(M) || user.a_intent == "help")
|
||||||
@@ -114,6 +114,7 @@
|
|||||||
if(prob(50))
|
if(prob(50))
|
||||||
icon_state = "cutters-y"
|
icon_state = "cutters-y"
|
||||||
item_state = "cutters_yellow"
|
item_state = "cutters_yellow"
|
||||||
|
..()
|
||||||
|
|
||||||
/obj/item/weapon/wirecutters/attack(mob/living/carbon/C as mob, mob/user as mob)
|
/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)))
|
if(user.a_intent == I_HELP && (C.handcuffed) && (istype(C.handcuffed, /obj/item/weapon/handcuffs/cable)))
|
||||||
@@ -162,12 +163,12 @@
|
|||||||
reagents = R
|
reagents = R
|
||||||
R.my_atom = src
|
R.my_atom = src
|
||||||
R.add_reagent("fuel", max_fuel)
|
R.add_reagent("fuel", max_fuel)
|
||||||
return
|
..()
|
||||||
|
|
||||||
/obj/item/weapon/weldingtool/Destroy()
|
/obj/item/weapon/weldingtool/Destroy()
|
||||||
if(welding)
|
if(welding)
|
||||||
processing_objects -= src
|
processing_objects -= src
|
||||||
..()
|
return ..()
|
||||||
|
|
||||||
/obj/item/weapon/weldingtool/examine(mob/user)
|
/obj/item/weapon/weldingtool/examine(mob/user)
|
||||||
if(..(user, 0))
|
if(..(user, 0))
|
||||||
|
|||||||
@@ -11,8 +11,10 @@
|
|||||||
..()
|
..()
|
||||||
if (!prob(spawn_nothing_percentage))
|
if (!prob(spawn_nothing_percentage))
|
||||||
spawn_item()
|
spawn_item()
|
||||||
qdel(src)
|
|
||||||
|
|
||||||
|
/obj/random/initialize()
|
||||||
|
..()
|
||||||
|
qdel(src)
|
||||||
|
|
||||||
// this function should return a specific item to spawn
|
// this function should return a specific item to spawn
|
||||||
/obj/random/proc/item_to_spawn()
|
/obj/random/proc/item_to_spawn()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
/obj/structure/closet/emcloset/New()
|
/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")
|
if ("small")
|
||||||
new /obj/item/weapon/tank/emergency_oxygen(src)
|
new /obj/item/weapon/tank/emergency_oxygen(src)
|
||||||
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/suit/space/emergency(src)
|
||||||
new /obj/item/clothing/head/helmet/space/emergency(src)
|
new /obj/item/clothing/head/helmet/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()
|
/obj/structure/closet/emcloset/legacy/New()
|
||||||
..()
|
..()
|
||||||
|
|||||||
@@ -5,6 +5,13 @@
|
|||||||
icon_state = "densecrate"
|
icon_state = "densecrate"
|
||||||
density = 1
|
density = 1
|
||||||
|
|
||||||
|
/obj/structure/largecrate/initialize()
|
||||||
|
..()
|
||||||
|
for(var/obj/I in src.loc)
|
||||||
|
if(I.density || I.anchored || I == src || !I.simulated)
|
||||||
|
continue
|
||||||
|
I.forceMove(src)
|
||||||
|
|
||||||
/obj/structure/largecrate/attack_hand(mob/user as mob)
|
/obj/structure/largecrate/attack_hand(mob/user as mob)
|
||||||
user << "<span class='notice'>You need a crowbar to pry this open!</span>"
|
user << "<span class='notice'>You need a crowbar to pry this open!</span>"
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
layer = 2.3 //under pipes
|
layer = 2.3 //under pipes
|
||||||
// flags = CONDUCT
|
// 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)))
|
if(!(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open) || istype(src.loc, /turf/simulated/mineral)))
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
/obj/structure/mopbucket/New()
|
/obj/structure/mopbucket/New()
|
||||||
create_reagents(100)
|
create_reagents(100)
|
||||||
|
..()
|
||||||
|
|
||||||
/obj/structure/mopbucket/examine(mob/user)
|
/obj/structure/mopbucket/examine(mob/user)
|
||||||
if(..(user, 1))
|
if(..(user, 1))
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user