diff --git a/code/controllers/ProcessScheduler/core/process.dm b/code/controllers/ProcessScheduler/core/process.dm
new file mode 100644
index 0000000000..7e5478d30d
--- /dev/null
+++ b/code/controllers/ProcessScheduler/core/process.dm
@@ -0,0 +1,388 @@
+// Process
+
+/datum/controller/process
+ /**
+ * State vars
+ */
+ // Main controller ref
+ var/tmp/datum/controller/processScheduler/main
+
+ // 1 if process is not running or queued
+ var/tmp/idle = 1
+
+ // 1 if process is queued
+ var/tmp/queued = 0
+
+ // 1 if process is running
+ var/tmp/running = 0
+
+ // 1 if process is blocked up
+ var/tmp/hung = 0
+
+ // 1 if process was killed
+ var/tmp/killed = 0
+
+ // Status text var
+ var/tmp/status
+
+ // Previous status text var
+ var/tmp/previousStatus
+
+ // 1 if process is disabled
+ var/tmp/disabled = 0
+
+ /**
+ * Config vars
+ */
+ // Process name
+
+ // Process schedule interval
+ // This controls how often the process would run under ideal conditions.
+ // If the process scheduler sees that the process has finished, it will wait until
+ // this amount of time has elapsed from the start of the previous run to start the
+ // process running again.
+ var/tmp/schedule_interval = PROCESS_DEFAULT_SCHEDULE_INTERVAL // run every 50 ticks
+
+ // Process sleep interval
+ // 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
+ // processes to execute concurrently.
+ var/tmp/sleep_interval = PROCESS_DEFAULT_SLEEP_INTERVAL
+
+ // Defer usage; the tick usage at which this process will defer until the next tick
+ var/tmp/defer_usage = PROCESS_DEFAULT_DEFER_USAGE
+
+ // 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
+
+ // hang_alert_time - After this much time(in 1/10 seconds), the server will send an admin debug message saying the process may be hung
+ var/tmp/hang_alert_time = PROCESS_DEFAULT_HANG_ALERT_TIME
+
+ // 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
+
+ // Number of deciseconds to delay before starting the process
+ var/start_delay = 0
+
+ /**
+ * recordkeeping vars
+ */
+
+ // Records the time (1/10s timeofgame) at which the process last began running
+ var/tmp/run_start = 0
+
+ // Records the number of times this process has been killed and restarted
+ var/tmp/times_killed
+
+ // Tick count
+ var/tmp/ticks = 0
+
+ var/tmp/last_task = ""
+
+ var/tmp/last_object
+
+ // How many times in the current run has the process deferred work till the next tick?
+ var/tmp/cpu_defer_count = 0
+
+ // Counts the number of times an exception has occurred; gets reset after 10
+ var/tmp/list/exceptions = list()
+
+ // The next tick_usage the process will sleep at
+ var/tmp/next_sleep_usage
+
+ // Last run duration, in seconds
+ var/tmp/last_run_time = 0
+
+ // Last 20 run durations
+ var/tmp/list/last_twenty_run_times = list()
+
+ // Highest run duration, in seconds
+ var/tmp/highest_run_time = 0
+
+ // Tick usage at start of current run (updates upon deferring)
+ var/tmp/tick_usage_start
+
+ // Accumulated tick usage from before each deferral
+ var/tmp/tick_usage_accumulated = 0
+
+/datum/controller/process/New(var/datum/controller/processScheduler/scheduler)
+ ..()
+ main = scheduler
+ previousStatus = "idle"
+ idle()
+ name = "process"
+ run_start = 0
+ ticks = 0
+ last_task = 0
+ last_object = null
+
+/datum/controller/process/proc/started()
+ // Initialize run_start so we can detect hung processes.
+ run_start = TimeOfGame
+
+ // Initialize defer count
+ cpu_defer_count = 0
+
+ // Prepare usage tracking (defer() updates these)
+ tick_usage_start = TICK_USAGE
+ tick_usage_accumulated = 0
+
+ running()
+ main.processStarted(src)
+
+ onStart()
+
+/datum/controller/process/proc/finished()
+ ticks++
+ recordRunTime()
+ idle()
+ main.processFinished(src)
+
+ onFinish()
+
+/datum/controller/process/proc/recordRunTime()
+ // Convert from tick usage (100/tick) to seconds of CPU time used
+ var/total_usage = (tick_usage_accumulated + (TICK_USAGE - tick_usage_start)) / 1000 * world.tick_lag
+
+ last_run_time = total_usage
+ if(total_usage > highest_run_time)
+ highest_run_time = total_usage
+ if(last_twenty_run_times.len == 20)
+ last_twenty_run_times.Cut(1, 2)
+ last_twenty_run_times += total_usage
+
+/datum/controller/process/proc/doWork()
+
+/datum/controller/process/proc/setup()
+
+/datum/controller/process/process()
+ started()
+ doWork()
+ finished()
+
+/datum/controller/process/proc/running()
+ idle = 0
+ queued = 0
+ running = 1
+ hung = 0
+ setStatus(PROCESS_STATUS_RUNNING)
+
+/datum/controller/process/proc/idle()
+ queued = 0
+ running = 0
+ idle = 1
+ hung = 0
+ setStatus(PROCESS_STATUS_IDLE)
+
+/datum/controller/process/proc/queued()
+ idle = 0
+ running = 0
+ queued = 1
+ hung = 0
+ setStatus(PROCESS_STATUS_QUEUED)
+
+/datum/controller/process/proc/hung()
+ hung = 1
+ setStatus(PROCESS_STATUS_HUNG)
+
+/datum/controller/process/proc/handleHung()
+ var/datum/lastObj = last_object
+ var/lastObjType = "null"
+ if(istype(lastObj))
+ lastObjType = lastObj.type
+
+ var/msg = "[name] process hung at tick #[ticks]. Process was unresponsive for [(TimeOfGame - run_start) / 10] seconds and was restarted. Last task: [last_task]. Last Object Type: [lastObjType]"
+ log_debug(msg)
+ message_admins(msg)
+
+ main.restartProcess(src.name)
+
+/datum/controller/process/proc/kill()
+ if (!killed)
+ var/msg = "[name] process was killed at tick #[ticks]."
+ log_debug(msg)
+ message_admins(msg)
+ // Allow inheritors to clean up if needed
+ onKill()
+ qdel(src)
+
+// Do not call this directly - use SHECK
+/datum/controller/process/proc/defer()
+ if(killed)
+ // 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
+ // owned by it.
+ 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.")
+
+ tick_usage_accumulated += (TICK_USAGE - tick_usage_start)
+ if(TICK_USAGE < defer_usage)
+ sleep(0)
+ else
+ sleep(world.tick_lag)
+ cpu_defer_count++
+ tick_usage_start = TICK_USAGE
+ next_sleep_usage = min(TICK_USAGE + sleep_interval, defer_usage)
+
+/datum/controller/process/proc/update()
+ // Clear delta
+ if(previousStatus != status)
+ setStatus(status)
+
+ var/elapsedTime = getElapsedTime()
+
+ if (hung)
+ handleHung()
+ return
+ else if (elapsedTime > hang_restart_time)
+ hung()
+ else if (elapsedTime > hang_alert_time)
+ setStatus(PROCESS_STATUS_PROBABLY_HUNG)
+ else if (elapsedTime > hang_warning_time)
+ setStatus(PROCESS_STATUS_MAYBE_HUNG)
+
+
+/datum/controller/process/proc/getElapsedTime()
+ return TimeOfGame - run_start
+
+/datum/controller/process/proc/tickDetail()
+ return
+
+/datum/controller/process/proc/getContext()
+ return "
[name]
[getAverageRunTime()]
[last_run_time]
[highest_run_time]
[ticks]
\n"
+
+/datum/controller/process/proc/getContextData()
+ return list(
+ "name" = name,
+ "averageRunTime" = getAverageRunTime(),
+ "lastRunTime" = last_run_time,
+ "highestRunTime" = highest_run_time,
+ "ticks" = ticks,
+ "schedule" = schedule_interval,
+ "status" = getStatusText(),
+ "disabled" = disabled
+ )
+
+/datum/controller/process/proc/getStatus()
+ return status
+
+/datum/controller/process/proc/getStatusText(var/s = 0)
+ if(!s)
+ s = status
+ switch(s)
+ if(PROCESS_STATUS_IDLE)
+ return "idle"
+ if(PROCESS_STATUS_QUEUED)
+ return "queued"
+ if(PROCESS_STATUS_RUNNING)
+ return "running"
+ if(PROCESS_STATUS_MAYBE_HUNG)
+ return "maybe hung"
+ if(PROCESS_STATUS_PROBABLY_HUNG)
+ return "probably hung"
+ if(PROCESS_STATUS_HUNG)
+ return "HUNG"
+ else
+ return "UNKNOWN"
+
+/datum/controller/process/proc/getPreviousStatus()
+ return previousStatus
+
+/datum/controller/process/proc/getPreviousStatusText()
+ return getStatusText(previousStatus)
+
+/datum/controller/process/proc/setStatus(var/newStatus)
+ previousStatus = status
+ status = newStatus
+
+/datum/controller/process/proc/setLastTask(var/task, var/object)
+ last_task = task
+ last_object = object
+
+/datum/controller/process/proc/_copyStateFrom(var/datum/controller/process/target)
+ main = target.main
+ name = target.name
+ schedule_interval = target.schedule_interval
+ sleep_interval = target.sleep_interval
+ run_start = 0
+ times_killed = target.times_killed
+ ticks = target.ticks
+ last_task = target.last_task
+ last_object = target.last_object
+ copyStateFrom(target)
+
+/datum/controller/process/proc/copyStateFrom(var/datum/controller/process/target)
+
+/datum/controller/process/proc/onKill()
+
+/datum/controller/process/proc/onStart()
+
+/datum/controller/process/proc/onFinish()
+
+/datum/controller/process/proc/disable()
+ disabled = 1
+
+/datum/controller/process/proc/enable()
+ disabled = 0
+
+/datum/controller/process/proc/getAverageRunTime()
+ var/t = 0
+ var/c = 0
+ for(var/time in last_twenty_run_times)
+ t += time
+ c++
+
+ if(c > 0)
+ return t / c
+ return c
+
+/datum/controller/process/proc/getLastRunTime()
+ return last_run_time
+
+/datum/controller/process/proc/getHighestRunTime()
+ return highest_run_time
+
+/datum/controller/process/proc/getTicks()
+ return ticks
+
+/datum/controller/process/proc/statProcess()
+ var/averageRunTime = round(getAverageRunTime(), 0.001)
+ var/lastRunTime = round(last_run_time, 0.001)
+ var/highestRunTime = round(highest_run_time, 0.001)
+ var/deferTime = round(cpu_defer_count / 10 * world.tick_lag, 0.01)
+ stat("[name]", "T#[getTicks()] | AR [averageRunTime] | LR [lastRunTime] | HR [highestRunTime] | D [deferTime]")
+
+/datum/controller/process/proc/catchException(var/exception/e, var/thrower)
+ if(istype(e)) // Real runtimes go to the real error handler
+ log_runtime(e, thrower, "Caught by process: [name]")
+ return
+ 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) || QDELETED(caught))
+ return // Only bother with types we can identify and that don't belong
+ catchException("Type [caught.type] does not belong in process' queue")
diff --git a/code/controllers/ProcessScheduler/core/processScheduler.dm b/code/controllers/ProcessScheduler/core/processScheduler.dm
new file mode 100644
index 0000000000..96fae6db91
--- /dev/null
+++ b/code/controllers/ProcessScheduler/core/processScheduler.dm
@@ -0,0 +1,234 @@
+// Singleton instance of game_controller_new, setup in world.New()
+var/global/datum/controller/processScheduler/processScheduler
+
+/datum/controller/processScheduler
+ // Processes known by the scheduler
+ var/tmp/datum/controller/process/list/processes = new
+
+ // Processes that are currently running
+ var/tmp/datum/controller/process/list/running = new
+
+ // Processes that are idle
+ var/tmp/datum/controller/process/list/idle = new
+
+ // Processes that are queued to run
+ var/tmp/datum/controller/process/list/queued = new
+
+ // Process name -> process object map
+ var/tmp/datum/controller/process/list/nameToProcessMap = new
+
+ // Process last queued times (world time)
+ var/tmp/datum/controller/process/list/last_queued = new
+
+ // How long to sleep between runs (set to tick_lag in New)
+ var/tmp/scheduler_sleep_interval
+
+ // Controls whether the scheduler is running or not
+ var/tmp/isRunning = 0
+
+ // Setup for these processes will be deferred until all the other processes are set up.
+ var/tmp/list/deferredSetupList = new
+
+/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
+
+/**
+ * deferSetupFor
+ * @param path processPath
+ * If a process needs to be initialized after everything else, add it to
+ * the deferred setup list. On goonstation, only the ticker needs to have
+ * this treatment.
+ */
+/datum/controller/processScheduler/proc/deferSetupFor(var/processPath)
+ if (!(processPath in deferredSetupList))
+ deferredSetupList += processPath
+
+/datum/controller/processScheduler/proc/setup()
+ // There can be only one
+ if(processScheduler && (processScheduler != src))
+ qdel(src)
+ return 0
+
+ var/process
+ // Add all the processes we can find, except for the ticker
+ for (process in subtypesof(/datum/controller/process))
+ if (!(process in deferredSetupList))
+ addProcess(new process(src))
+
+ for (process in deferredSetupList)
+ addProcess(new process(src))
+
+/datum/controller/processScheduler/proc/start()
+ isRunning = 1
+ // tick_lag will have been set by now, so re-initialize these
+ scheduler_sleep_interval = world.tick_lag
+ updateStartDelays()
+ spawn(0)
+ process()
+
+/datum/controller/processScheduler/process()
+ while(isRunning)
+ checkRunningProcesses()
+ queueProcesses()
+ runQueuedProcesses()
+ sleep(scheduler_sleep_interval)
+
+/datum/controller/processScheduler/proc/stop()
+ isRunning = 0
+
+/datum/controller/processScheduler/proc/checkRunningProcesses()
+ for(var/datum/controller/process/p in running)
+ p.update()
+
+ if (isnull(p)) // Process was killed
+ continue
+
+ var/status = p.getStatus()
+ var/previousStatus = p.getPreviousStatus()
+
+ // Check status changes
+ if(status != previousStatus)
+ //Status changed.
+ switch(status)
+ if(PROCESS_STATUS_PROBABLY_HUNG)
+ message_admins("Process '[p.name]' may be hung.")
+ if(PROCESS_STATUS_HUNG)
+ message_admins("Process '[p.name]' is hung and will be restarted.")
+
+/datum/controller/processScheduler/proc/queueProcesses()
+ for(var/datum/controller/process/p in processes)
+ // Don't double-queue, don't queue running processes
+ if (p.disabled || p.running || p.queued || !p.idle)
+ continue
+
+ // If the process should be running by now, go ahead and queue it
+ if (world.time >= last_queued[p] + p.schedule_interval)
+ setQueuedProcessState(p)
+
+/datum/controller/processScheduler/proc/runQueuedProcesses()
+ for(var/datum/controller/process/p in queued)
+ runProcess(p)
+
+/datum/controller/processScheduler/proc/addProcess(var/datum/controller/process/process)
+ processes.Add(process)
+ process.idle()
+ idle.Add(process)
+
+ // Set up process
+ process.setup()
+
+ // Save process in the name -> process map
+ nameToProcessMap[process.name] = process
+
+/datum/controller/processScheduler/proc/replaceProcess(var/datum/controller/process/oldProcess, var/datum/controller/process/newProcess)
+ processes.Remove(oldProcess)
+ processes.Add(newProcess)
+
+ newProcess.idle()
+ idle.Remove(oldProcess)
+ running.Remove(oldProcess)
+ queued.Remove(oldProcess)
+ idle.Add(newProcess)
+
+ newProcess.last_run_time = oldProcess.last_run_time
+ newProcess.last_twenty_run_times = oldProcess.last_twenty_run_times
+ newProcess.highest_run_time = oldProcess.highest_run_time
+
+ 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)
+ spawn(0)
+ process.process()
+
+/datum/controller/processScheduler/proc/processStarted(var/datum/controller/process/process)
+ setRunningProcessState(process)
+ last_queued[process] = world.time
+
+/datum/controller/processScheduler/proc/processFinished(var/datum/controller/process/process)
+ setIdleProcessState(process)
+
+/datum/controller/processScheduler/proc/setIdleProcessState(var/datum/controller/process/process)
+ if (process in running)
+ running -= process
+ if (process in queued)
+ queued -= process
+ if (!(process in idle))
+ idle += process
+
+/datum/controller/processScheduler/proc/setQueuedProcessState(var/datum/controller/process/process)
+ if (process in running)
+ running -= process
+ if (process in idle)
+ idle -= process
+ if (!(process in queued))
+ queued += process
+
+ // The other state transitions are handled internally by the process.
+ process.queued()
+
+/datum/controller/processScheduler/proc/setRunningProcessState(var/datum/controller/process/process)
+ if (process in queued)
+ queued -= process
+ if (process in idle)
+ idle -= process
+ if (!(process in running))
+ running += process
+
+
+/datum/controller/processScheduler/proc/getStatusData()
+ var/list/data = new
+
+ for (var/datum/controller/process/p in processes)
+ data.len++
+ data[data.len] = p.getContextData()
+
+ return data
+
+/datum/controller/processScheduler/proc/getProcessCount()
+ return processes.len
+
+/datum/controller/processScheduler/proc/hasProcess(var/processName as text)
+ if (nameToProcessMap[processName])
+ return 1
+
+/datum/controller/processScheduler/proc/killProcess(var/processName as text)
+ restartProcess(processName)
+
+/datum/controller/processScheduler/proc/restartProcess(var/processName as text)
+ if (hasProcess(processName))
+ var/datum/controller/process/oldInstance = nameToProcessMap[processName]
+ var/datum/controller/process/newInstance = new oldInstance.type(src)
+ newInstance._copyStateFrom(oldInstance)
+ replaceProcess(oldInstance, newInstance)
+ oldInstance.kill()
+
+/datum/controller/processScheduler/proc/enableProcess(var/processName as text)
+ if (hasProcess(processName))
+ var/datum/controller/process/process = nameToProcessMap[processName]
+ process.enable()
+
+/datum/controller/processScheduler/proc/disableProcess(var/processName as text)
+ if (hasProcess(processName))
+ var/datum/controller/process/process = nameToProcessMap[processName]
+ process.disable()
+
+
+/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])")
+ for(var/datum/controller/process/p in processes)
+ p.statProcess()
+
+/datum/controller/processScheduler/proc/getProcess(var/process_name)
+ return nameToProcessMap[process_name]
diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm
index 60b08c71d2..77c9d3ab94 100644
--- a/code/controllers/subsystems/overlays.dm
+++ b/code/controllers/subsystems/overlays.dm
@@ -5,7 +5,6 @@ SUBSYSTEM_DEF(overlays)
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY
- var/initialized = FALSE
var/list/queue // Queue of atoms needing overlay compiling (TODO-VERIFY!)
var/list/stats
var/list/overlay_icon_state_caches // Cache thing
@@ -22,7 +21,6 @@ var/global/image/appearance_bro = new() // Temporarily super-global because of B
stats = list()
/datum/controller/subsystem/overlays/Initialize()
- initialized = TRUE
fire(mc_check = FALSE)
..()
diff --git a/code/controllers/subsystems/processing/chemistry.dm b/code/controllers/subsystems/processing/chemistry.dm
index 7f4fd9c42b..b4641ba7e0 100644
--- a/code/controllers/subsystems/processing/chemistry.dm
+++ b/code/controllers/subsystems/processing/chemistry.dm
@@ -22,6 +22,7 @@ PROCESSING_SUBSYSTEM_DEF(chemistry)
/datum/controller/subsystem/processing/chemistry/Initialize()
initialize_chemical_reactions()
initialize_chemical_reagents()
+ ..()
//Chemical Reactions - Initialises all /datum/chemical_reaction into a list
// It is filtered into multiple lists within a list.
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 157a3f113f..f2da6f644a 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -513,8 +513,14 @@
//HUMAN
/mob/living/carbon/human/mind_initialize()
+<<<<<<< HEAD
..()
if(!mind.assigned_role) mind.assigned_role = USELESS_JOB //defualt //VOREStation Edit - Visitor not Assistant
+=======
+ . = ..()
+ if(!mind.assigned_role)
+ mind.assigned_role = "Assistant" //defualt
+>>>>>>> b22a056... Sideports a couple of init unit tests from Neb. (#7893)
//slime
/mob/living/simple_mob/slime/mind_initialize()
diff --git a/code/datums/roundstats/departmentgoal.dm b/code/datums/roundstats/departmentgoal.dm
index b0aa69784c..333e6c0396 100644
--- a/code/datums/roundstats/departmentgoal.dm
+++ b/code/datums/roundstats/departmentgoal.dm
@@ -35,6 +35,7 @@ GLOBAL_LIST(active_department_goals)
cat_goals -= G
GLOB.active_department_goals[category] |= G
+ return 1
/hook/roundend/proc/checkDepartmentGoals()
for(var/category in GLOB.active_department_goals)
@@ -50,6 +51,7 @@ GLOBAL_LIST(active_department_goals)
var/success = G.check_completion()
to_world("[success ? "[G.name]" : "[G.name]"]")
to_world("[G.goal_text]")
+ return 1
/datum/goal
var/name = "goal"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index b5f9ac3a2f..9c8bbccc79 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -54,10 +54,8 @@
/area/Initialize()
. = ..()
-
luminosity = !(dynamic_lighting)
icon_state = ""
-
return INITIALIZE_HINT_LATELOAD // Areas tradiationally are initialized AFTER other atoms.
/area/LateInitialize()
@@ -68,7 +66,6 @@
power_change() // all machines set to current power level, also updates lighting icon
if(no_spoilers)
set_spoiler_obfuscation(TRUE)
- return INITIALIZE_HINT_LATELOAD
// Changes the area of T to A. Do not do this manually.
// Area is expected to be a non-null instance.
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index bbf4bfb343..241d613275 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -34,7 +34,7 @@
var/last_activation = 0
/obj/structure/cult/pylon/Initialize()
- ..()
+ . = ..()
START_PROCESSING(SSobj, src)
/obj/structure/cult/pylon/attack_hand(mob/M as mob)
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index a97fbf986f..e0ff3a6086 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -529,5 +529,5 @@
stasis_level = 100 //Just one setting
/obj/machinery/sleeper/survival_pod/Initialize()
- ..()
+ . = ..()
RefreshParts(1)
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 7ff97c83e8..25299dcda8 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -1,4 +1,4 @@
-/obj/machinery/computer/arcade/
+/obj/machinery/computer/arcade
name = "random arcade"
desc = "random arcade machine"
icon_state = "arcade"
@@ -25,15 +25,15 @@
/obj/item/toy/stickhorse = 2
)
-/obj/machinery/computer/arcade/New()
- ..()
+/obj/machinery/computer/arcade/Initialize()
+ . = ..()
// If it's a generic arcade machine, pick a random arcade
// circuit board for it and make the new machine
if(!circuit)
var/choice = pick(subtypesof(/obj/item/weapon/circuitboard/arcade) - /obj/item/weapon/circuitboard/arcade/clawmachine)
var/obj/item/weapon/circuitboard/CB = new choice()
new CB.build_path(loc, CB)
- qdel(src)
+ return INITIALIZE_HINT_QDEL
/obj/machinery/computer/arcade/proc/prizevend()
if(!(contents-circuit).len)
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index cc05d63217..8d4202d421 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -26,7 +26,7 @@
light_color = "#315ab4"
/obj/machinery/computer/cloning/Initialize()
- ..()
+ . = ..()
pods = list()
records = list()
set_scan_temp("Scanner ready.", "good")
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index adf53c80a8..680ce44345 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -29,7 +29,7 @@
/obj/machinery/computer/med_data/Initialize()
- ..()
+ . = ..()
field_edit_questions = list(
// General
"sex" = "Please select new sex:",
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index 1caa7b61a4..430b42591c 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -335,7 +335,7 @@
name = "Monitor Decryption Key"
/obj/item/weapon/paper/monitorkey/Initialize()
- ..() //Late init
+ ..()
return INITIALIZE_HINT_LATELOAD
/obj/item/weapon/paper/monitorkey/LateInitialize()
diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm
index dbd5ba8383..5eae5e82d0 100644
--- a/code/game/machinery/computer/pod.dm
+++ b/code/game/machinery/computer/pod.dm
@@ -13,7 +13,7 @@
var/title = "Mass Driver Controls"
/obj/machinery/computer/pod/Initialize()
- ..() //Not returning parent because lateload
+ ..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/pod/LateInitialize()
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 1fbd897113..40a4d594cb 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -25,7 +25,7 @@
var/static/list/field_edit_choices
/obj/machinery/computer/secure_data/Initialize()
- ..()
+ . = ..()
field_edit_questions = list(
// General
"name" = "Please enter new name:",
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index 47b9e8ce25..e11f404b16 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -30,7 +30,7 @@
var/static/list/field_edit_choices
/obj/machinery/computer/skills/Initialize()
- ..()
+ . = ..()
field_edit_questions = list(
// General
"name" = "Please input new name:",
diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm
index f4d9c900ed..fdd526039b 100644
--- a/code/game/machinery/doors/brigdoors.dm
+++ b/code/game/machinery/doors/brigdoors.dm
@@ -40,7 +40,6 @@
/obj/machinery/door_timer/Initialize()
..()
- //Doors need to go first, and can't rely on init order, so come back to me.
return INITIALIZE_HINT_LATELOAD
/obj/machinery/door_timer/LateInitialize()
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index c23d02f4d0..a1798ea5e4 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -164,7 +164,7 @@ GLOBAL_LIST_BOILERPLATE(allCasters, /obj/machinery/newscaster)
securityCaster = 1
/obj/machinery/newscaster/Initialize()
- ..() //Not returning . because lateload below
+ ..()
allCasters += src
unit_no = ++unit_no_cur
paper_remaining = 15
diff --git a/code/game/machinery/transportpod.dm b/code/game/machinery/transportpod.dm
index 0b499096fe..4a43cb1890 100644
--- a/code/game/machinery/transportpod.dm
+++ b/code/game/machinery/transportpod.dm
@@ -32,7 +32,7 @@
sleep(2)
go_out()
sleep(2)
- del(src)
+ qdel(src)
/obj/machinery/transportpod/relaymove(mob/user as mob)
if(user.stat)
diff --git a/code/game/mecha/combat/gorilla.dm b/code/game/mecha/combat/gorilla.dm
index 4052afe8e6..fecb361f1a 100644
--- a/code/game/mecha/combat/gorilla.dm
+++ b/code/game/mecha/combat/gorilla.dm
@@ -31,7 +31,7 @@
thrusters_possible = 1
/obj/mecha/combat/gorilla/Initialize()
- ..()
+ . = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src) // This thing basically cannot function without an external power supply.
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/cannon(src)
diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm
index 3ae3e41e13..a1ea2ab451 100644
--- a/code/game/mecha/combat/phazon.dm
+++ b/code/game/mecha/combat/phazon.dm
@@ -40,7 +40,7 @@
switch_dmg_type_possible = TRUE
/obj/mecha/combat/phazon/equipped/Initialize()
- ..()
+ . = ..()
starting_equipment = list(
/obj/item/mecha_parts/mecha_equipment/tool/rcd,
/obj/item/mecha_parts/mecha_equipment/gravcatapult
diff --git a/code/game/mecha/components/_component.dm b/code/game/mecha/components/_component.dm
index aadf390c61..3d770e0dce 100644
--- a/code/game/mecha/components/_component.dm
+++ b/code/game/mecha/components/_component.dm
@@ -43,7 +43,7 @@
. += "It is completely destroyed."
/obj/item/mecha_parts/component/Initialize()
- ..()
+ . = ..()
integrity = max_integrity
if(start_damaged)
diff --git a/code/game/mecha/equipment/tools/inflatables.dm b/code/game/mecha/equipment/tools/inflatables.dm
index b18ba2eae1..ff766577de 100644
--- a/code/game/mecha/equipment/tools/inflatables.dm
+++ b/code/game/mecha/equipment/tools/inflatables.dm
@@ -14,7 +14,7 @@
var/obj/item/weapon/inflatable_dispenser/my_deployer = null
/obj/item/mecha_parts/mecha_equipment/tool/powertool/inflatables/Initialize()
- ..()
+ . = ..()
my_deployer = my_tool
/obj/item/mecha_parts/mecha_equipment/tool/powertool/inflatables/Topic(href, href_list)
diff --git a/code/game/mecha/equipment/tools/syringe_gun.dm b/code/game/mecha/equipment/tools/syringe_gun.dm
index 1658a01df6..fd73d74fc2 100644
--- a/code/game/mecha/equipment/tools/syringe_gun.dm
+++ b/code/game/mecha/equipment/tools/syringe_gun.dm
@@ -318,7 +318,7 @@
equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/crisis_drone/Initialize()
- ..()
+ . = ..()
drone_overlay = new(src.icon, icon_state = droid_state)
/obj/item/mecha_parts/mecha_equipment/crisis_drone/Destroy()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index bd2cf8460f..60bb48c5f6 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -198,7 +198,7 @@
var/weapons_only_cycle = FALSE //So combat mechs don't switch to their equipment at times.
/obj/mecha/Initialize()
- ..()
+ . = ..()
for(var/path in starting_components)
var/obj/item/mecha_parts/component/C = new path(src)
diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm
index 4db6332cb1..316d39bace 100644
--- a/code/game/mecha/medical/odysseus.dm
+++ b/code/game/mecha/medical/odysseus.dm
@@ -127,7 +127,7 @@
C.images += holder
*/
/obj/mecha/medical/odysseus/loaded/Initialize()
- ..()
+ . = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/sleeper
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tool/sleeper
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index def044c9bb..4e92f757d2 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -70,7 +70,7 @@
max_special_equip = 1
/obj/mecha/working/ripley/deathripley/Initialize()
- ..()
+ . = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/safety
ME.attach(src)
return
@@ -80,7 +80,7 @@
name = "APLU \"Miner\""
/obj/mecha/working/ripley/mining/Initialize()
- ..()
+ . = ..()
//Attach drill
if(prob(25)) //Possible diamond drill... Feeling lucky?
var/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill
diff --git a/code/game/objects/effects/chem/coating.dm b/code/game/objects/effects/chem/coating.dm
index a777bbe5e0..2e9ad26049 100644
--- a/code/game/objects/effects/chem/coating.dm
+++ b/code/game/objects/effects/chem/coating.dm
@@ -11,7 +11,7 @@
create_reagents(100)
/obj/effect/decal/cleanable/chemcoating/Initialize()
- ..()
+ . = ..()
var/turf/T = get_turf(src)
if(T)
for(var/obj/O in get_turf(src))
diff --git a/code/game/objects/effects/decals/warning_stripes.dm b/code/game/objects/effects/decals/warning_stripes.dm
index db7c4bf74f..0e3d12897d 100644
--- a/code/game/objects/effects/decals/warning_stripes.dm
+++ b/code/game/objects/effects/decals/warning_stripes.dm
@@ -1,10 +1,10 @@
/obj/effect/decal/warning_stripes
icon = 'icons/effects/warning_stripes.dmi'
-/obj/effect/decal/warning_stripes/New()
+/obj/effect/decal/warning_stripes/Initialize()
. = ..()
var/turf/T=get_turf(src)
var/image/I=image(icon, icon_state = icon_state, dir = dir)
I.color=color
T.overlays += I
- qdel(src)
+ return INITIALIZE_HINT_QDEL
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index c5e1f26c61..c49a4e0666 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -10,32 +10,37 @@
var/obj/item/weapon/mine/mineitemtype = /obj/item/weapon/mine
var/panel_open = 0
var/datum/wires/mines/wires = null
- register_as_dangerous_object = TRUE
-
var/camo_net = FALSE // Will the mine 'cloak' on deployment?
// The trap item will be triggered in some manner when detonating. Default only checks for grenades.
var/obj/item/trap = null
-/obj/effect/mine/New()
+/obj/effect/mine/Initialize()
icon_state = "uglyminearmed"
wires = new(src)
-
+ . = ..()
if(ispath(trap))
trap = new trap(src)
-
-/obj/effect/mine/Initialize()
- ..()
-
+ register_dangerous_to_step()
if(camo_net)
alpha = 50
/obj/effect/mine/Destroy()
+ unregister_dangerous_to_step()
if(trap)
QDEL_NULL(trap)
qdel_null(wires)
return ..()
+/obj/effect/mine/Moved(atom/oldloc)
+ . = ..()
+ if(.)
+ var/turf/old_turf = get_turf(oldloc)
+ var/turf/new_turf = get_turf(src)
+ if(old_turf != new_turf)
+ old_turf.unregister_dangerous_object(src)
+ new_turf.register_dangerous_object(src)
+
/obj/effect/mine/proc/explode(var/mob/living/M)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
triggered = 1
diff --git a/code/game/objects/effects/prop/columnblast.dm b/code/game/objects/effects/prop/columnblast.dm
index fc604235c8..ce0e4b2aad 100644
--- a/code/game/objects/effects/prop/columnblast.dm
+++ b/code/game/objects/effects/prop/columnblast.dm
@@ -17,7 +17,7 @@
..()
/obj/effect/temporary_effect/eruption/Initialize()
- ..()
+ . = ..()
flick("[icon_state]_create",src)
/obj/effect/temporary_effect/eruption/Destroy()
diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm
index c848a2f1df..eb025f9ba4 100644
--- a/code/game/objects/effects/spawners/bombspawner.dm
+++ b/code/game/objects/effects/spawners/bombspawner.dm
@@ -159,7 +159,6 @@
/obj/effect/spawner/newbomb/Initialize(newloc)
..(newloc)
-
var/obj/item/device/transfer_valve/V = new(src.loc)
var/obj/item/weapon/tank/phoron/PT = new(V)
var/obj/item/weapon/tank/oxygen/OT = new(V)
@@ -183,19 +182,14 @@
OT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE+1
OT.air_contents.update_values()
-
var/obj/item/device/assembly/S = new assembly_type(V)
-
-
V.attached_device = S
S.holder = V
S.toggle_secure()
V.update_icon()
-
- qdel(src)
-
+ return INITIALIZE_HINT_QDEL
///////////////////////
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 2247674f60..facc87ae64 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -33,7 +33,7 @@
var/cell_type = /obj/item/weapon/cell/device
/obj/item/device/flash/Initialize()
- ..()
+ . = ..()
power_supply = new cell_type(src)
/obj/item/device/flash/attackby(var/obj/item/W, var/mob/user)
diff --git a/code/game/objects/items/stacks/fifty_spawner.dm b/code/game/objects/items/stacks/fifty_spawner.dm
index 81dfce9691..e3ba667703 100644
--- a/code/game/objects/items/stacks/fifty_spawner.dm
+++ b/code/game/objects/items/stacks/fifty_spawner.dm
@@ -7,15 +7,12 @@
var/obj/item/stack/type_to_spawn = null
/obj/fiftyspawner/Initialize()
- ..() //We're not returning . because we're going to ask to be deleted.
-
+ ..()
var/turf/T = get_turf(src)
- var/obj/item/stack/M = new type_to_spawn(T)
+ var/obj/structure/closet/C = locate() in T
+ var/obj/item/stack/M = new type_to_spawn(C || T)
M.amount = M.max_amount //some stuff spawns with 60, we're still calling it fifty
M.update_icon() // Some stacks have different sprites depending on how full they are.
- var/obj/structure/closet/C = locate() in T
- if(C)
- C.contents += M
return INITIALIZE_HINT_QDEL //Bye!
/obj/fiftyspawner/rods
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index 6ffa7100ca..c88527608f 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -24,8 +24,8 @@
stacktype = /obj/item/stack/rods
no_variants = TRUE
-/obj/item/stack/rods/New()
- ..()
+/obj/item/stack/rods/Initialize()
+ . = ..()
recipes = rods_recipes
update_icon()
diff --git a/code/game/objects/items/stacks/sandbags.dm b/code/game/objects/items/stacks/sandbags.dm
index c4e755c485..6eff93bfc5 100644
--- a/code/game/objects/items/stacks/sandbags.dm
+++ b/code/game/objects/items/stacks/sandbags.dm
@@ -32,19 +32,15 @@
bag_material = MAT_SYNCLOTH
-/obj/item/stack/sandbags/New(var/newloc, var/amt, var/bag_mat)
- ..()
+/obj/item/stack/sandbags/Initialize(var/ml, var/amt, var/bag_mat)
+ . = ..(ml, amt)
recipes = sandbag_recipes
update_icon()
-
if(bag_mat)
bag_material = bag_mat
-
var/datum/material/M = get_material_by_name("[bag_material]")
if(!M)
- qdel(src)
- return
-
+ return INITIALIZE_HINT_QDEL
color = M.icon_colour
/obj/item/stack/sandbags/update_icon()
@@ -136,17 +132,13 @@ var/global/list/datum/stack_recipe/sandbag_recipes = list( \
var/bag_material = "cloth"
-/obj/item/stack/emptysandbag/New(var/newloc, var/amt, var/bag_mat)
- ..(newloc, amt)
-
+/obj/item/stack/emptysandbag/Initialize(var/ml, var/amt, var/bag_mat)
+ . = ..(ml, amt)
if(bag_mat)
bag_material = bag_mat
-
var/datum/material/M = get_material_by_name("[bag_material]")
if(!M)
- qdel(src)
- return
-
+ return INITIALIZE_HINT_QDEL
color = M.icon_colour
/obj/item/stack/emptysandbag/attack_self(var/mob/user)
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index d42d6c0e56..7d9783df68 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -29,14 +29,13 @@
var/pass_color = FALSE // Will the item pass its own color var to the created item? Dyed cloth, wood, etc.
var/strict_color_stacking = FALSE // Will the stack merge with other stacks that are different colors? (Dyed cloth, wood, etc)
-/obj/item/stack/New(var/loc, var/amount=null)
- ..()
- if (!stacktype)
+/obj/item/stack/Initialize(var/ml, var/amount)
+ . = ..()
+ if(!stacktype)
stacktype = type
- if (amount)
+ if(amount)
src.amount = amount
update_icon()
- return
/obj/item/stack/Destroy()
if(uses_charge)
diff --git a/code/game/objects/items/stacks/tickets.dm b/code/game/objects/items/stacks/tickets.dm
index 1d9cbf047e..6681934f7c 100644
--- a/code/game/objects/items/stacks/tickets.dm
+++ b/code/game/objects/items/stacks/tickets.dm
@@ -7,7 +7,7 @@
w_class = ITEMSIZE_TINY
max_amount = 30
-/obj/item/stack/arcadeticket/New(loc, amount = null)
+/obj/item/stack/arcadeticket/Initialize()
. = ..()
update_icon()
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 5e5ac1a746..aefe9a0cd0 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -20,8 +20,8 @@
drop_sound = 'sound/items/drop/axe.ogg'
pickup_sound = 'sound/items/pickup/axe.ogg'
-/obj/item/stack/tile/New()
- ..()
+/obj/item/stack/tile/Initialize()
+ . = ..()
randpixel_xy()
/*
diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm
index d8906955a1..bfa8b61680 100644
--- a/code/game/objects/items/weapons/material/misc.dm
+++ b/code/game/objects/items/weapons/material/misc.dm
@@ -77,14 +77,14 @@
//visible_message("[user] has smashed the snowball in their hand!", "You smash the snowball in your hand.")
to_chat(user, "You smash the snowball in your hand.")
var/atom/S = new /obj/item/stack/material/snow(user.loc)
- del(src)
+ qdel(src)
user.put_in_hands(S)
else
//visible_message("[user] starts compacting the snowball.", "You start compacting the snowball.")
to_chat(user, "You start compacting the snowball.")
if(do_after(user, 2 SECONDS))
var/atom/S = new /obj/item/weapon/material/snow/snowball/reinforced(user.loc)
- del(src)
+ qdel(src)
user.put_in_hands(S)
/obj/item/weapon/material/snow/snowball/reinforced
diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm
index 277a083d54..1764b0d8be 100644
--- a/code/game/objects/items/weapons/tanks/tank_types.dm
+++ b/code/game/objects/items/weapons/tanks/tank_types.dm
@@ -174,7 +174,7 @@
gauge_icon = "indicator_emergency"
/obj/item/weapon/tank/emergency/nitrogen/Initialize()
- ..()
+ . = ..()
src.air_contents.adjust_gas("nitrogen", (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/weapon/tank/emergency/nitrogen/double
diff --git a/code/game/objects/items/weapons/tools/weldingtool.dm b/code/game/objects/items/weapons/tools/weldingtool.dm
index f315872669..bd5b5a57c3 100644
--- a/code/game/objects/items/weapons/tools/weldingtool.dm
+++ b/code/game/objects/items/weapons/tools/weldingtool.dm
@@ -671,7 +671,7 @@
always_process = TRUE
/obj/item/weapon/weldingtool/electric/mounted/exosuit/Initialize()
- ..()
+ . = ..()
if(istype(loc, /obj/item/mecha_parts/mecha_equipment))
equip_mount = loc
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 688236eda8..d1d5146c2a 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -19,19 +19,12 @@
var/can_speak = 0 //For MMIs and admin trickery. If an object has a brainmob in its contents, set this to 1 to allow it to speak.
var/show_examine = TRUE // Does this pop up on a mob when the mob is examined?
- var/register_as_dangerous_object = FALSE // Should this tell its turf that it is dangerous automatically?
-
-/obj/Initialize()
- if(register_as_dangerous_object)
- register_dangerous_to_step()
- return ..()
/obj/Destroy()
STOP_PROCESSING(SSobj, src)
- if(register_as_dangerous_object)
- unregister_dangerous_to_step()
return ..()
+<<<<<<< HEAD
/obj/Moved(atom/oldloc)
. = ..()
if(register_as_dangerous_object)
@@ -43,6 +36,9 @@
new_turf.register_dangerous_object(src)
/obj/Topic(href, href_list, var/datum/tgui_state/state = GLOB.tgui_default_state)
+=======
+/obj/Topic(href, href_list, var/datum/topic_state/state = default_state)
+>>>>>>> b22a056... Sideports a couple of init unit tests from Neb. (#7893)
if(usr && ..())
return 1
diff --git a/code/game/objects/random/_random.dm b/code/game/objects/random/_random.dm
index 67f82ea155..7b9cc60617 100644
--- a/code/game/objects/random/_random.dm
+++ b/code/game/objects/random/_random.dm
@@ -8,7 +8,7 @@
// creates a new object and deletes itself
/obj/random/Initialize()
- . = ..()
+ ..()
if (!prob(spawn_nothing_percentage))
spawn_item()
return INITIALIZE_HINT_QDEL
diff --git a/code/game/objects/structures/cliff.dm b/code/game/objects/structures/cliff.dm
index 66fb945988..b8c1b84039 100644
--- a/code/game/objects/structures/cliff.dm
+++ b/code/game/objects/structures/cliff.dm
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
GLOBAL_LIST_EMPTY(cliff_icon_cache)
/*
@@ -234,3 +235,257 @@ two tiles on initialization, and which way a cliff is facing may change during m
if(should_fall(L))
return FALSE
return ..()
+=======
+GLOBAL_LIST_EMPTY(cliff_icon_cache)
+
+/*
+Cliffs give a visual illusion of depth by seperating two places while presenting a 'top' and 'bottom' side.
+
+Mobs moving into a cliff from the bottom side will simply bump into it and be denied moving into the tile,
+where as mobs moving into a cliff from the top side will 'fall' off the cliff, forcing them to the bottom, causing significant damage and stunning them.
+
+Mobs can climb this while wearing climbing equipment by clickdragging themselves onto a cliff, as if it were a table.
+
+Flying mobs can pass over all cliffs with no risk of falling.
+
+Projectiles and thrown objects can pass, however if moving upwards, there is a chance for it to be stopped by the cliff.
+This makes fighting something that is on top of a cliff more challenging.
+
+As a note, dir points upwards, e.g. pointing WEST means the left side is 'up', and the right side is 'down'.
+
+When mapping these in, be sure to give at least a one tile clearance, as NORTH facing cliffs expand to
+two tiles on initialization, and which way a cliff is facing may change during maploading.
+*/
+
+/obj/structure/cliff
+ name = "cliff"
+ desc = "A steep rock ledge. You might be able to climb it if you feel bold enough."
+ description_info = "Walking off the edge of a cliff while on top will cause you to fall off, causing severe injury. \
+ You can climb this cliff if wearing special climbing equipment, by click-dragging yourself onto the cliff. \
+ Projectiles traveling up a cliff may hit the cliff instead, making it more difficult to fight something \
+ on top."
+ icon = 'icons/obj/flora/rocks.dmi'
+
+ anchored = TRUE
+ density = TRUE
+ opacity = FALSE
+ climbable = TRUE
+ climb_delay = 10 SECONDS
+ block_turf_edges = TRUE // Don't want turf edges popping up from the cliff edge.
+
+ var/icon_variant = null // Used to make cliffs less repeative by having a selection of sprites to display.
+ var/corner = FALSE // Used for icon things.
+ var/ramp = FALSE // Ditto.
+ var/bottom = FALSE // Used for 'bottom' typed cliffs, to avoid infinite cliffs, and for icons.
+
+ var/is_double_cliff = FALSE // Set to true when making the two-tile cliffs, used for projectile checks.
+ var/uphill_penalty = 30 // Odds of a projectile not making it up the cliff.
+
+/obj/structure/cliff/Initialize()
+ . = ..()
+ register_dangerous_to_step()
+
+/obj/structure/cliff/Destroy()
+ unregister_dangerous_to_step()
+ . = ..()
+
+/obj/structure/cliff/Moved(atom/oldloc)
+ . = ..()
+ if(.)
+ var/turf/old_turf = get_turf(oldloc)
+ var/turf/new_turf = get_turf(src)
+ if(old_turf != new_turf)
+ old_turf.unregister_dangerous_object(src)
+ new_turf.register_dangerous_object(src)
+
+// These arrange their sprites at runtime, as opposed to being statically placed in the map file.
+/obj/structure/cliff/automatic
+ icon_state = "cliffbuilder"
+ dir = NORTH
+
+/obj/structure/cliff/automatic/corner
+ icon_state = "cliffbuilder-corner"
+ dir = NORTHEAST
+ corner = TRUE
+
+// Tiny part that doesn't block, used for making 'ramps'.
+/obj/structure/cliff/automatic/ramp
+ icon_state = "cliffbuilder-ramp"
+ dir = NORTHEAST
+ density = FALSE
+ ramp = TRUE
+
+// Made automatically as needed by automatic cliffs.
+/obj/structure/cliff/bottom
+ bottom = TRUE
+
+/obj/structure/cliff/automatic/Initialize()
+ ..()
+ return INITIALIZE_HINT_LATELOAD
+
+// Paranoid about the maploader, direction is very important to cliffs, since they may get bigger if initialized while facing NORTH.
+/obj/structure/cliff/automatic/LateInitialize()
+ if(dir in GLOB.cardinal)
+ icon_variant = pick("a", "b", "c")
+
+ if(dir & NORTH && !bottom) // North-facing cliffs require more cliffs to be made.
+ make_bottom()
+
+ update_icon()
+
+/obj/structure/cliff/proc/make_bottom()
+ // First, make sure there's room to put the bottom side.
+ var/turf/T = locate(x, y - 1, z)
+ if(!istype(T))
+ return FALSE
+
+ // Now make the bottom cliff have mostly the same variables.
+ var/obj/structure/cliff/bottom/bottom = new(T)
+ is_double_cliff = TRUE
+ climb_delay /= 2 // Since there are two cliffs to climb when going north, both take half the time.
+
+ bottom.dir = dir
+ bottom.is_double_cliff = TRUE
+ bottom.climb_delay = climb_delay
+ bottom.icon_variant = icon_variant
+ bottom.corner = corner
+ bottom.ramp = ramp
+ bottom.layer = layer - 0.1
+ bottom.density = density
+ bottom.update_icon()
+
+/obj/structure/cliff/set_dir(new_dir)
+ ..()
+ update_icon()
+
+/obj/structure/cliff/update_icon()
+ icon_state = "cliff-[dir][icon_variant][bottom ? "-bottom" : ""][corner ? "-corner" : ""][ramp ? "-ramp" : ""]"
+
+ // Now for making the top-side look like a different turf.
+ var/turf/T = get_step(src, dir)
+ if(!istype(T))
+ return
+
+ var/subtraction_icon_state = "[icon_state]-subtract"
+ var/cache_string = "[icon_state]_[T.icon]_[T.icon_state]"
+ if(T && subtraction_icon_state in cached_icon_states(icon))
+ cut_overlays()
+ // If we've made the same icon before, just recycle it.
+ if(cache_string in GLOB.cliff_icon_cache)
+ add_overlay(GLOB.cliff_icon_cache[cache_string])
+
+ else // Otherwise make a new one, but only once.
+ var/icon/underlying_ground = icon(T.icon, T.icon_state, T.dir)
+ var/icon/subtract = icon(icon, subtraction_icon_state)
+ underlying_ground.Blend(subtract, ICON_SUBTRACT)
+ var/image/final = image(underlying_ground)
+ final.layer = src.layer - 0.2
+ GLOB.cliff_icon_cache[cache_string] = final
+ add_overlay(final)
+
+
+// Movement-related code.
+
+/obj/structure/cliff/CanPass(atom/movable/mover, turf/target)
+ if(isliving(mover))
+ var/mob/living/L = mover
+ if(L.hovering) // Flying mobs can always pass.
+ return TRUE
+ return ..()
+
+ // Projectiles and objects flying 'upward' have a chance to hit the cliff instead, wasting the shot.
+ else if(istype(mover, /obj))
+ var/obj/O = mover
+ if(check_shield_arc(src, dir, O)) // This is actually for mobs but it will work for our purposes as well.
+ if(prob(uphill_penalty / (1 + is_double_cliff) )) // Firing upwards facing NORTH means it will likely have to pass through two cliffs, so the chance is halved.
+ return FALSE
+ return TRUE
+
+/obj/structure/cliff/Bumped(atom/A)
+ if(isliving(A))
+ var/mob/living/L = A
+ if(should_fall(L))
+ fall_off_cliff(L)
+ return
+ ..()
+
+/obj/structure/cliff/proc/should_fall(mob/living/L)
+ if(L.hovering)
+ return FALSE
+
+ var/turf/T = get_turf(L)
+ if(T && get_dir(T, loc) & reverse_dir[dir]) // dir points 'up' the cliff, e.g. cliff pointing NORTH will cause someone to fall if moving SOUTH into it.
+ return TRUE
+ return FALSE
+
+/obj/structure/cliff/proc/fall_off_cliff(mob/living/L)
+ if(!istype(L))
+ return FALSE
+ var/turf/T = get_step(src, reverse_dir[dir])
+ var/displaced = FALSE
+
+ if(dir in list(EAST, WEST)) // Apply an offset if flying sideways, to help maintain the illusion of depth.
+ for(var/i = 1 to 2)
+ var/turf/new_T = locate(T.x, T.y - i, T.z)
+ if(!new_T || locate(/obj/structure/cliff) in new_T)
+ break
+ T = new_T
+ displaced = TRUE
+
+ if(istype(T))
+ visible_message(span("danger", "\The [L] falls off \the [src]!"))
+ L.forceMove(T)
+
+ // Do the actual hurting. Double cliffs do halved damage due to them most likely hitting twice.
+ var/harm = !is_double_cliff ? 1 : 0.5
+ if(istype(L.buckled, /obj/vehicle)) // People falling off in vehicles will take less damage, but will damage the vehicle severely.
+ var/obj/vehicle/vehicle = L.buckled
+ vehicle.adjust_health(40 * harm)
+ to_chat(L, span("warning", "\The [vehicle] absorbs some of the impact, damaging it."))
+ harm /= 2
+
+ playsound(L, 'sound/effects/break_stone.ogg', 70, 1)
+ L.Weaken(5 * harm)
+ var/fall_time = 3
+ if(displaced) // Make the fall look more natural when falling sideways.
+ L.pixel_z = 32 * 2
+ animate(L, pixel_z = 0, time = fall_time)
+ sleep(fall_time) // A brief delay inbetween the two sounds helps sell the 'ouch' effect.
+ playsound(L, "punch", 70, 1)
+ shake_camera(L, 1, 1)
+ visible_message(span("danger", "\The [L] hits the ground!"))
+
+ // The bigger they are, the harder they fall.
+ // They will take at least 20 damage at the minimum, and tries to scale up to 40% of their max health.
+ // This scaling is capped at 100 total damage, which occurs if the thing that fell has more than 250 health.
+ var/damage = between(20, L.getMaxHealth() * 0.4, 100)
+ var/target_zone = ran_zone()
+ var/blocked = L.run_armor_check(target_zone, "melee") * harm
+ var/soaked = L.get_armor_soak(target_zone, "melee") * harm
+
+ L.apply_damage(damage * harm, BRUTE, target_zone, blocked, soaked, used_weapon=src)
+
+ // Now fall off more cliffs below this one if they exist.
+ var/obj/structure/cliff/bottom_cliff = locate() in T
+ if(bottom_cliff)
+ visible_message(span("danger", "\The [L] rolls down towards \the [bottom_cliff]!"))
+ sleep(5)
+ bottom_cliff.fall_off_cliff(L)
+
+/obj/structure/cliff/can_climb(mob/living/user, post_climb_check = FALSE)
+ // Cliff climbing requires climbing gear.
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ var/obj/item/clothing/shoes/shoes = H.shoes
+ if(shoes && shoes.rock_climbing)
+ return ..() // Do the other checks too.
+
+ to_chat(user, span("warning", "\The [src] is too steep to climb unassisted."))
+ return FALSE
+
+// This tells AI mobs to not be dumb and step off cliffs willingly.
+/obj/structure/cliff/is_safe_to_step(mob/living/L)
+ if(should_fall(L))
+ return FALSE
+ return ..()
+>>>>>>> b22a056... Sideports a couple of init unit tests from Neb. (#7893)
diff --git a/code/game/objects/structures/crates_lockers/__closets.dm b/code/game/objects/structures/crates_lockers/__closets.dm
index f7e399a267..4e18d87207 100644
--- a/code/game/objects/structures/crates_lockers/__closets.dm
+++ b/code/game/objects/structures/crates_lockers/__closets.dm
@@ -37,7 +37,6 @@
/obj/structure/closet/Initialize()
..()
- // Closets need to come later because of spawners potentially creating objects during init.
return INITIALIZE_HINT_LATELOAD
/obj/structure/closet/LateInitialize()
diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm
index bccdcf56c3..f584fd8838 100644
--- a/code/game/objects/structures/fireaxe.dm
+++ b/code/game/objects/structures/fireaxe.dm
@@ -14,7 +14,7 @@
var/smashed = 0
/obj/structure/fireaxecabinet/Initialize()
- ..()
+ . = ..()
fireaxe = new /obj/item/weapon/material/twohanded/fireaxe()
/obj/structure/fireaxecabinet/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
diff --git a/code/game/objects/structures/flora/flora.dm b/code/game/objects/structures/flora/flora.dm
index cc5c5b510f..e97c7b84bb 100644
--- a/code/game/objects/structures/flora/flora.dm
+++ b/code/game/objects/structures/flora/flora.dm
@@ -22,7 +22,7 @@
var/list/harvest_loot = null // Should be an associative list for things to spawn, and their weights. An example would be a branch from a tree.
/obj/structure/flora/Initialize()
- ..()
+ . = ..()
if(randomize_size)
icon_scale_x = rand(min_x_scale * 100, max_x_scale * 100) / 100
diff --git a/code/game/objects/structures/ghost_pods/ghost_pods.dm b/code/game/objects/structures/ghost_pods/ghost_pods.dm
index 386d493d2d..7649c8573f 100644
--- a/code/game/objects/structures/ghost_pods/ghost_pods.dm
+++ b/code/game/objects/structures/ghost_pods/ghost_pods.dm
@@ -28,7 +28,7 @@
icon_state = icon_state_opened
if(needscharger)
new /obj/machinery/recharge_station/ghost_pod_recharger(src.loc)
- del(src)
+ qdel(src)
return TRUE
else
return FALSE
diff --git a/code/game/objects/structures/ghost_pods/human.dm b/code/game/objects/structures/ghost_pods/human.dm
index 814db9cd75..f2b3291597 100644
--- a/code/game/objects/structures/ghost_pods/human.dm
+++ b/code/game/objects/structures/ghost_pods/human.dm
@@ -25,7 +25,7 @@
var/list/clothing_possibilities
/obj/structure/ghost_pod/ghost_activated/human/Initialize()
- ..()
+ . = ..()
handle_clothing_setup()
@@ -153,7 +153,7 @@
var/list/clothing_possibilities
/obj/structure/ghost_pod/manual/human/Initialize()
- ..()
+ . = ..()
handle_clothing_setup()
diff --git a/code/game/objects/structures/ghost_pods/silicon.dm b/code/game/objects/structures/ghost_pods/silicon.dm
index 32a26ce479..74f53e9204 100644
--- a/code/game/objects/structures/ghost_pods/silicon.dm
+++ b/code/game/objects/structures/ghost_pods/silicon.dm
@@ -89,7 +89,7 @@
qdel(src)
/obj/structure/ghost_pod/ghost_activated/swarm_drone/event/Initialize()
- ..()
+ . = ..()
var/turf/T = get_turf(src)
say_dead_object("A [drone_class] swarm drone shell is now available in \the [T.loc].", src)
diff --git a/code/game/objects/structures/props/nest.dm b/code/game/objects/structures/props/nest.dm
index 4cb515fc36..ba16b0b055 100644
--- a/code/game/objects/structures/props/nest.dm
+++ b/code/game/objects/structures/props/nest.dm
@@ -20,7 +20,7 @@
var/total_creature_max //If set, it can spawn this many creatures, total, ever.
/obj/structure/prop/nest/Initialize()
- ..()
+ . = ..()
den_mobs = list()
START_PROCESSING(SSobj, src)
last_spawn = world.time
diff --git a/code/game/objects/structures/props/swarm.dm b/code/game/objects/structures/props/swarm.dm
index 128254a456..51f59072f4 100644
--- a/code/game/objects/structures/props/swarm.dm
+++ b/code/game/objects/structures/props/swarm.dm
@@ -23,7 +23,7 @@
return ..()
/obj/structure/cult/pylon/swarm/Initialize()
- ..()
+ . = ..()
active_beams = list()
/obj/structure/cult/pylon/swarm/Destroy()
diff --git a/code/game/objects/structures/window_spawner.dm b/code/game/objects/structures/window_spawner.dm
index bb8b5cff6b..dfeecb7be7 100644
--- a/code/game/objects/structures/window_spawner.dm
+++ b/code/game/objects/structures/window_spawner.dm
@@ -27,11 +27,10 @@
return FALSE
/obj/effect/wingrille_spawn/Initialize()
- . = ..()
- if(!win_path)
- return
- if(ticker && ticker.current_state < GAME_STATE_PLAYING)
+ if(win_path && ticker && ticker.current_state < GAME_STATE_PLAYING)
activate()
+ ..()
+ return INITIALIZE_HINT_QDEL
/obj/effect/wingrille_spawn/proc/activate()
if(activated) return
@@ -58,7 +57,8 @@
activated = 1
for(var/obj/effect/wingrille_spawn/other in neighbours)
if(!other.activated) other.activate()
- qdel(src)
+ if(initialized && !QDELETED(src))
+ qdel(src)
/obj/effect/wingrille_spawn/proc/handle_window_spawn(var/obj/structure/window/W)
return
diff --git a/code/game/turfs/flooring/flooring_decals.dm b/code/game/turfs/flooring/flooring_decals.dm
index 0fe768f944..578fb80f54 100644
--- a/code/game/turfs/flooring/flooring_decals.dm
+++ b/code/game/turfs/flooring/flooring_decals.dm
@@ -12,9 +12,13 @@ var/list/floor_decals = list()
/obj/effect/floor_decal/New(var/newloc, var/newdir, var/newcolour)
supplied_dir = newdir
- if(newcolour) color = newcolour
+ if(newcolour)
+ color = newcolour
..(newloc)
+// TODO: identify what is causing these atoms to be qdeleted in New()/Initialize()
+// somewhere in this chain. Alternatively repath to /obj/floor_decal or some other
+// abstract handler that explicitly doesn't invoke any obj behavior.
/obj/effect/floor_decal/Initialize()
add_to_turf_decals()
initialized = TRUE
@@ -42,11 +46,11 @@ var/list/floor_decals = list()
name = "reset marker"
/obj/effect/floor_decal/reset/Initialize()
+ ..()
var/turf/T = get_turf(src)
if(T.decals && T.decals.len)
T.decals.Cut()
T.update_icon()
- initialized = TRUE
return INITIALIZE_HINT_QDEL
/obj/effect/floor_decal/corner
diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm
index 151efd819c..437912b4d2 100644
--- a/code/game/turfs/simulated/floor_types.dm
+++ b/code/game/turfs/simulated/floor_types.dm
@@ -86,7 +86,7 @@
var/static/list/antilight_cache
/turf/simulated/shuttle/Initialize(mapload)
- ..()
+ . = ..()
if(!antilight_cache)
antilight_cache = list()
for(var/diag in cornerdirs)
diff --git a/code/game/turfs/simulated/floor_types_eris.dm b/code/game/turfs/simulated/floor_types_eris.dm
index bfc9945678..1cd067b957 100644
--- a/code/game/turfs/simulated/floor_types_eris.dm
+++ b/code/game/turfs/simulated/floor_types_eris.dm
@@ -1014,10 +1014,3 @@
oxygen = 0
nitrogen = 0
temperature = TCMB
-
-/*
-/turf/simulated/floor/hull/New()
- if(icon_state != "hullcenter0")
- overrided_icon_state = icon_state
- ..()
-*/
\ No newline at end of file
diff --git a/code/game/turfs/space/cracked_asteroid.dm b/code/game/turfs/space/cracked_asteroid.dm
index ca77a8cd2c..224997ca8d 100644
--- a/code/game/turfs/space/cracked_asteroid.dm
+++ b/code/game/turfs/space/cracked_asteroid.dm
@@ -11,9 +11,3 @@
/turf/space/cracked_asteroid/is_space() // So people don't start floating when standing on it.
return FALSE
-
-// u wot m8? ~Leshana
-// /turf/space/cracked_asteroid/New()
-// ..()
-// spawn(2 SECONDS)
-// overlays.Cut()
diff --git a/code/game/turfs/unsimulated.dm b/code/game/turfs/unsimulated.dm
index 584137ff45..39c217a006 100644
--- a/code/game/turfs/unsimulated.dm
+++ b/code/game/turfs/unsimulated.dm
@@ -2,7 +2,13 @@
name = "command"
oxygen = MOLES_O2STANDARD
nitrogen = MOLES_N2STANDARD
- initialized = TRUE // Don't call init on unsimulated turfs (at least not yet)
+ var/skip_init = TRUE // Don't call down the chain, apparently for performance when loading maps at runtime.
+
+/turf/unsimulated/Initialize(mapload)
+ if(skip_init)
+ initialized = TRUE
+ return INITIALIZE_HINT_NORMAL
+ . = ..()
//VOREStation Add
/turf/unsimulated/fake_space
diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm
index c5338b3db9..b1841dadad 100644
--- a/code/game/turfs/unsimulated/beach.dm
+++ b/code/game/turfs/unsimulated/beach.dm
@@ -14,7 +14,7 @@
/turf/unsimulated/beach/water
name = "Water"
icon_state = "water"
- initialized = FALSE
+ skip_init = FALSE
movement_cost = 4 // Water should slow you down, just like simulated turf.
/turf/unsimulated/beach/water/Initialize()
diff --git a/code/game/turfs/unsimulated/planetary.dm b/code/game/turfs/unsimulated/planetary.dm
index 4fb26f16b6..9fe487410f 100644
--- a/code/game/turfs/unsimulated/planetary.dm
+++ b/code/game/turfs/unsimulated/planetary.dm
@@ -9,7 +9,6 @@
density = 1
alpha = 0
blocks_air = 0
- initialized = FALSE
// Set these to get your desired planetary atmosphere.
oxygen = 0
@@ -17,6 +16,7 @@
carbon_dioxide = 0
phoron = 0
temperature = T20C
+ skip_init = FALSE
/turf/unsimulated/wall/planetary/Initialize()
. = ..()
diff --git a/code/modules/artifice/cursedform.dm b/code/modules/artifice/cursedform.dm
index 17f8fbf618..43acac8bf3 100644
--- a/code/modules/artifice/cursedform.dm
+++ b/code/modules/artifice/cursedform.dm
@@ -2,7 +2,7 @@
name = "Form - Inventory Requisition r10.7.1E"
/obj/item/weapon/paper/carbon/cursedform/Initialize()
- ..()
+ . = ..()
info = {"
Form - Inventory Requisition r10.7.1E
General Request Form
General
Name: Department: Departmental Rank: Organization(If not Nanotrasen): Date:
Requested Item(s): Quantity: Reason for request: Is this replacement equipment?: If `Yes`; above, specify equiment and reason for replacement:
Authorization
Authorizing Department: Authorizing Dept. Head:
Contact and Delivery
EPv2 Address of requesting party(Do not leave blank): Delivery location or department:
Nanotrasen Employee Identification Number: Signature of Requester and Date
Requested Item(s): write Quantity: write Reason for request: write Is this replacement equipment?: write If `Yes` above, specify equiment and reason for replacement: write