From 3e804dc7991228bd412a2d2e00d72f2b04002d6e Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Mon, 22 Feb 2021 08:03:34 +1100 Subject: [PATCH] Sideports a couple of init unit tests from Neb. --- .../ProcessScheduler/core/process.dm | 388 +++++++++++++ .../ProcessScheduler/core/processScheduler.dm | 234 ++++++++ code/controllers/subsystems/overlays.dm | 2 - .../subsystems/processing/chemistry.dm | 1 + code/datums/mind.dm | 6 + code/datums/roundstats/departmentgoal.dm | 2 + code/game/area/areas.dm | 3 - code/game/gamemodes/cult/cult_structures.dm | 2 +- code/game/machinery/Sleeper.dm | 2 +- code/game/machinery/computer/arcade.dm | 8 +- code/game/machinery/computer/cloning.dm | 2 +- code/game/machinery/computer/medical.dm | 2 +- code/game/machinery/computer/message.dm | 2 +- code/game/machinery/computer/pod.dm | 2 +- code/game/machinery/computer/security.dm | 2 +- code/game/machinery/computer/skills.dm | 2 +- code/game/machinery/doors/brigdoors.dm | 1 - code/game/machinery/newscaster.dm | 2 +- code/game/machinery/transportpod.dm | 2 +- code/game/mecha/combat/gorilla.dm | 2 +- code/game/mecha/combat/phazon.dm | 2 +- code/game/mecha/components/_component.dm | 2 +- .../game/mecha/equipment/tools/inflatables.dm | 2 +- .../game/mecha/equipment/tools/syringe_gun.dm | 2 +- code/game/mecha/mecha.dm | 2 +- code/game/mecha/medical/odysseus.dm | 2 +- code/game/mecha/working/ripley.dm | 4 +- code/game/objects/effects/chem/coating.dm | 2 +- .../objects/effects/decals/warning_stripes.dm | 4 +- code/game/objects/effects/mines.dm | 21 +- code/game/objects/effects/prop/columnblast.dm | 2 +- .../objects/effects/spawners/bombspawner.dm | 8 +- code/game/objects/items/devices/flash.dm | 2 +- .../objects/items/stacks/fifty_spawner.dm | 9 +- code/game/objects/items/stacks/rods.dm | 4 +- code/game/objects/items/stacks/sandbags.dm | 20 +- code/game/objects/items/stacks/stack.dm | 9 +- code/game/objects/items/stacks/tickets.dm | 2 +- .../objects/items/stacks/tiles/tile_types.dm | 4 +- .../objects/items/weapons/material/misc.dm | 4 +- .../objects/items/weapons/tanks/tank_types.dm | 2 +- .../items/weapons/tools/weldingtool.dm | 2 +- code/game/objects/objs.dm | 12 +- code/game/objects/random/_random.dm | 2 +- code/game/objects/structures/cliff.dm | 255 +++++++++ .../structures/crates_lockers/__closets.dm | 1 - code/game/objects/structures/fireaxe.dm | 2 +- code/game/objects/structures/flora/flora.dm | 2 +- .../structures/ghost_pods/ghost_pods.dm | 2 +- .../objects/structures/ghost_pods/human.dm | 4 +- .../objects/structures/ghost_pods/silicon.dm | 2 +- code/game/objects/structures/props/nest.dm | 2 +- code/game/objects/structures/props/swarm.dm | 2 +- .../game/objects/structures/window_spawner.dm | 10 +- code/game/turfs/flooring/flooring_decals.dm | 8 +- code/game/turfs/simulated/floor_types.dm | 2 +- code/game/turfs/simulated/floor_types_eris.dm | 7 - code/game/turfs/space/cracked_asteroid.dm | 6 - code/game/turfs/unsimulated.dm | 8 +- code/game/turfs/unsimulated/beach.dm | 2 +- code/game/turfs/unsimulated/planetary.dm | 2 +- code/modules/artifice/cursedform.dm | 2 +- code/modules/awaymissions/loot.dm | 4 - code/modules/client/client procs.dm | 1 - .../preference_setup/traits/trait_defines.dm | 6 + code/modules/clothing/gloves/antagonist.dm | 2 +- .../clothing/under/accessories/storage.dm | 4 +- code/modules/clothing/under/xenos/vox.dm | 2 +- code/modules/fishing/fishing_net.dm | 2 +- code/modules/fishing/fishing_rod.dm | 2 +- .../food/drinkingglass/drinkingglass.dm | 2 +- code/modules/food/food/cans.dm | 10 +- code/modules/food/food/drinks.dm | 4 +- code/modules/food/food/drinks/bottle.dm | 4 +- code/modules/food/food/snacks.dm | 10 +- code/modules/food/food/thecake.dm | 2 +- code/modules/food/kitchen/microwave.dm | 2 +- .../modules/hydroponics/beekeeping/beehive.dm | 4 +- code/modules/hydroponics/trays/tray.dm | 4 + .../integrated_electronics/core/tools.dm | 1 - .../integrated_electronics/subtypes/input.dm | 6 +- .../integrated_electronics/subtypes/output.dm | 2 +- code/modules/library/lib_machines.dm | 2 +- code/modules/maps/tg/map_template.dm | 6 +- code/modules/materials/material_sheets.dm | 9 +- code/modules/materials/material_synth.dm | 10 +- code/modules/mining/machine_stacking.dm | 10 +- code/modules/mining/mine_items.dm | 5 +- code/modules/mining/ore.dm | 2 +- code/modules/mob/freelook/ai/eye.dm | 10 +- code/modules/mob/freelook/update_triggers.dm | 4 +- .../human/ai_controlled/ai_controlled.dm | 2 +- code/modules/mob/living/silicon/ai/ai.dm | 2 +- .../mob/living/silicon/robot/drone/swarm.dm | 2 +- .../living/silicon/robot/drone/swarm_items.dm | 2 +- .../mob/living/silicon/robot/robot_items.dm | 4 +- .../subtypes/animal/passive/crab.dm | 2 +- .../subtypes/animal/passive/fish.dm | 6 +- .../subtypes/animal/passive/lizard.dm | 2 +- .../subtypes/animal/sif/frostfly.dm | 4 + .../subtypes/animal/sif/glitterfly.dm | 4 +- .../simple_mob/subtypes/animal/sif/kururak.dm | 4 +- .../simple_mob/subtypes/animal/sif/leech.dm | 2 +- .../simple_mob/subtypes/animal/sif/moth.dm | 2 +- .../simple_mob/subtypes/animal/space/worm.dm | 2 +- code/modules/mob/living/voice/voice.dm | 4 +- code/modules/multiz/stairs.dm | 18 +- code/modules/nano/nanoui.dm | 526 ++++++++++++++++++ code/modules/organs/internal/augment.dm | 4 +- .../organs/internal/augment/armmounted.dm | 2 +- code/modules/organs/internal/spleen.dm | 4 +- code/modules/organs/internal/stomach.dm | 3 +- code/modules/organs/organ.dm | 3 +- code/modules/organs/robolimbs.dm | 2 +- code/modules/organs/subtypes/diona.dm | 2 +- code/modules/organs/subtypes/slime.dm | 2 +- code/modules/overmap/turfs.dm | 1 - code/modules/paperwork/pen.dm | 2 +- code/modules/pda/cart.dm | 313 +++++++++++ code/modules/pda/radio.dm | 139 +++++ .../particle_accelerator/particle_smasher.dm | 2 +- code/modules/power/turbine.dm | 2 +- code/modules/projectiles/ammunition/rounds.dm | 2 +- code/modules/projectiles/broken.dm | 2 +- .../modules/reagents/distilling/distilling.dm | 2 +- code/modules/reagents/hoses/connector.dm | 6 +- .../reagents/reagent_containers/spray.dm | 2 +- code/modules/recycling/disposal.dm | 4 +- code/modules/shuttles/landmarks.dm | 2 +- code/modules/turbolift/turbolift_turfs.dm | 2 +- code/unit_tests/subsystem_tests.dm | 46 ++ vorestation.dme | 1 + 132 files changed, 2133 insertions(+), 248 deletions(-) create mode 100644 code/controllers/ProcessScheduler/core/process.dm create mode 100644 code/controllers/ProcessScheduler/core/processScheduler.dm create mode 100644 code/modules/nano/nanoui.dm create mode 100644 code/unit_tests/subsystem_tests.dm 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





Authorizor`s Nanotrasen Employee Identification Number:
Authorizing Signature and Date(Include authorizing department`s stamp below)




Shipping Department Only

(Do not write below this line)

Nanotrasen Purchasing Approval Code:
Nanotrasen Employee Identification Number:
Receiving Shipping Employee:
Signature and Date


"} info_links = {"

Form - Inventory Requisition r10.7.1E

General Request Form


General


Name: write
Department: write
Departmental Rank: write
Organization(If not Nanotrasen): write
Date: write



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


Authorization


Authorizing Department: write
Authorizing Dept. Head: write


Contact and Delivery


EPv2 Address of requesting party(Do not leave blank): write
Delivery location or department: write


Nanotrasen Employee Identification Number: write
Signature of Requester and Date

write



Authorizor`s Nanotrasen Employee Identification Number: write
Authorizing Signature and Date(Include authorizing department`s stamp below)

write


Shipping Department Only

(Do not write below this line)

Nanotrasen Purchasing Approval Code: write
Nanotrasen Employee Identification Number: write
Receiving Shipping Employee: write
Signature and Date

write
write"} diff --git a/code/modules/awaymissions/loot.dm b/code/modules/awaymissions/loot.dm index 1c1d901161..530358940c 100644 --- a/code/modules/awaymissions/loot.dm +++ b/code/modules/awaymissions/loot.dm @@ -8,18 +8,14 @@ /obj/effect/spawner/lootdrop/Initialize() ..() var/list/things = params2list(loot) - if(things && things.len) for(var/i = lootcount, i > 0, i--) if(!things.len) return - var/loot_spawn = pick(things) var/loot_path = text2path(loot_spawn) - if(!loot_path || !lootdoubles) things.Remove(loot_spawn) continue - new loot_path(get_turf(src)) return INITIALIZE_HINT_QDEL diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 83164afd3c..3513e9b99d 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -45,7 +45,6 @@ if( findtext(href,">>>>>> b22a056... Sideports a couple of init unit tests from Neb. (#7893) /datum/trait/modifier/physical/flimsy @@ -194,6 +199,7 @@ // 'Mental' traits are just those that only sapients can have, for now, and generally involves fears. // So far, all of them are just for fluff/don't have mechanical effects. /datum/trait/modifier/mental + name = "Mental" category = "Mental" /datum/trait/modifier/mental/test_for_invalidity(var/datum/category_item/player_setup_item/traits/setup) diff --git a/code/modules/clothing/gloves/antagonist.dm b/code/modules/clothing/gloves/antagonist.dm index d1a01d0e68..2f369adba0 100644 --- a/code/modules/clothing/gloves/antagonist.dm +++ b/code/modules/clothing/gloves/antagonist.dm @@ -104,7 +104,7 @@ return battery /obj/item/clothing/gloves/ring/buzzer/Initialize() - ..() + . = ..() if(!battery) battery = new battery_type(src) diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm index f3fd40fa00..0bd0549e7a 100644 --- a/code/modules/clothing/under/accessories/storage.dm +++ b/code/modules/clothing/under/accessories/storage.dm @@ -12,7 +12,7 @@ var/hide_on_roll = FALSE /obj/item/clothing/accessory/storage/Initialize() - ..() + . = ..() hold = new/obj/item/weapon/storage/internal(src) hold.max_storage_space = slots * 2 hold.max_w_class = ITEMSIZE_SMALL @@ -95,7 +95,7 @@ slots = 2 /obj/item/clothing/accessory/storage/knifeharness/Initialize() - ..() + . = ..() hold.max_storage_space = ITEMSIZE_COST_SMALL * 2 hold.can_hold = list(/obj/item/weapon/material/knife/machete/hatchet/unathiknife,\ /obj/item/weapon/material/knife,\ diff --git a/code/modules/clothing/under/xenos/vox.dm b/code/modules/clothing/under/xenos/vox.dm index 7e90ad4665..9897fa5c6d 100644 --- a/code/modules/clothing/under/xenos/vox.dm +++ b/code/modules/clothing/under/xenos/vox.dm @@ -28,6 +28,6 @@ slots = 3 /obj/item/clothing/accessory/storage/vox/Initialize() - ..() + . = ..() hold.max_storage_space = slots * ITEMSIZE_COST_NORMAL hold.max_w_class = ITEMSIZE_NORMAL \ No newline at end of file diff --git a/code/modules/fishing/fishing_net.dm b/code/modules/fishing/fishing_net.dm index 740e3a2a6d..ab1e35ea6a 100644 --- a/code/modules/fishing/fishing_net.dm +++ b/code/modules/fishing/fishing_net.dm @@ -23,7 +23,7 @@ var/list/accepted_mobs = list(/mob/living/simple_mob/animal/passive/fish) /obj/item/weapon/material/fishing_net/Initialize() - ..() + . = ..() update_icon() /obj/item/weapon/material/fishing_net/afterattack(var/atom/A, var/mob/user, var/proximity) diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 52578a31c7..ea4571442f 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -47,7 +47,7 @@ ..() /obj/item/weapon/material/fishing_rod/Initialize() - ..() + . = ..() update_icon() /obj/item/weapon/material/fishing_rod/attackby(obj/item/I as obj, mob/user as mob) diff --git a/code/modules/food/drinkingglass/drinkingglass.dm b/code/modules/food/drinkingglass/drinkingglass.dm index c2c5dc4219..a83c869495 100644 --- a/code/modules/food/drinkingglass/drinkingglass.dm +++ b/code/modules/food/drinkingglass/drinkingglass.dm @@ -66,7 +66,7 @@ return 0 /obj/item/weapon/reagent_containers/food/drinks/glass2/Initialize() - ..() + . = ..() icon_state = base_icon /obj/item/weapon/reagent_containers/food/drinks/glass2/on_reagent_change() diff --git a/code/modules/food/food/cans.dm b/code/modules/food/food/cans.dm index b876a0e1d1..8f2e135d73 100644 --- a/code/modules/food/food/cans.dm +++ b/code/modules/food/food/cans.dm @@ -38,7 +38,7 @@ center_of_mass = list("x"=16, "y"=8) /obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind/Initialize() - ..() + . = ..() reagents.add_reagent("spacemountainwind", 30) /obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko @@ -92,7 +92,7 @@ center_of_mass = list("x"=16, "y"=8) /obj/item/weapon/reagent_containers/food/drinks/cans/space_up/Initialize() - ..() + . = ..() reagents.add_reagent("space_up", 30) /obj/item/weapon/reagent_containers/food/drinks/cans/lemon_lime @@ -103,7 +103,7 @@ center_of_mass = list("x"=16, "y"=8) /obj/item/weapon/reagent_containers/food/drinks/cans/lemon_lime/Initialize() - ..() + . = ..() reagents.add_reagent("lemon_lime", 30) /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea @@ -114,7 +114,7 @@ center_of_mass = list("x"=16, "y"=8) /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea/Initialize() - ..() + . = ..() reagents.add_reagent("icetea", 30) /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice @@ -125,7 +125,7 @@ center_of_mass = list("x"=16, "y"=8) /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice/Initialize() - ..() + . = ..() reagents.add_reagent("grapejuice", 30) /obj/item/weapon/reagent_containers/food/drinks/cans/tonic diff --git a/code/modules/food/food/drinks.dm b/code/modules/food/food/drinks.dm index 9549627c56..1f7bbc23d1 100644 --- a/code/modules/food/food/drinks.dm +++ b/code/modules/food/food/drinks.dm @@ -239,7 +239,7 @@ pickup_sound = 'sound/items/pickup/papercup.ogg' /obj/item/weapon/reagent_containers/food/drinks/h_chocolate/Initialize() - ..() + . = ..() reagents.add_reagent("hot_coco", 30) /obj/item/weapon/reagent_containers/food/drinks/greentea @@ -298,7 +298,7 @@ pickup_sound = 'sound/items/pickup/papercup.ogg' /obj/item/weapon/reagent_containers/food/drinks/dry_ramen/Initialize() - ..() + . = ..() reagents.add_reagent("dry_ramen", 30) /obj/item/weapon/reagent_containers/food/drinks/sillycup diff --git a/code/modules/food/food/drinks/bottle.dm b/code/modules/food/food/drinks/bottle.dm index a5fd76417b..9472f8459d 100644 --- a/code/modules/food/food/drinks/bottle.dm +++ b/code/modules/food/food/drinks/bottle.dm @@ -388,7 +388,7 @@ center_of_mass = list("x"=16, "y"=6) /obj/item/weapon/reagent_containers/food/drinks/bottle/space_up/Initialize() - ..() + . = ..() reagents.add_reagent("space_up", 100) /obj/item/weapon/reagent_containers/food/drinks/bottle/space_mountain_wind @@ -398,7 +398,7 @@ center_of_mass = list("x"=16, "y"=6) /obj/item/weapon/reagent_containers/food/drinks/bottle/space_mountain_wind/Initialize() - ..() + . = ..() reagents.add_reagent("spacemountainwind", 100) /obj/item/weapon/reagent_containers/food/drinks/bottle/pwine diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm index 793c881b7c..edbbbdc0d3 100644 --- a/code/modules/food/food/snacks.dm +++ b/code/modules/food/food/snacks.dm @@ -3720,26 +3720,32 @@ /obj/item/pizzabox/margherita/Initialize() pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita(src) boxtag = "Margherita Deluxe" + . = ..() /obj/item/pizzabox/vegetable/Initialize() pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza(src) boxtag = "Gourmet Vegatable" + . = ..() /obj/item/pizzabox/mushroom/Initialize() pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza(src) boxtag = "Mushroom Special" + . = ..() /obj/item/pizzabox/meat/Initialize() pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza(src) boxtag = "Meatlover's Supreme" + . = ..() /obj/item/pizzabox/pineapple/Initialize() pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pineapple(src) boxtag = "Hawaiian Sunrise" + . = ..() /obj/item/pizzabox/old/Initialize() pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/oldpizza(src) boxtag = "Deluxe Gourmet" + . = ..() /obj/item/weapon/reagent_containers/food/snacks/dionaroast name = "roast diona" @@ -4547,7 +4553,7 @@ icon_state = "bagelplain" /obj/item/weapon/reagent_containers/food/snacks/bageltwo/Initialize() - ..() //Not returning . because asking to be qdel'd below. + ..() spawn_bagels() spawn_bagels() return INITIALIZE_HINT_QDEL @@ -6261,7 +6267,7 @@ nutriment_desc = list("tomato" = 4, "meat" = 2) /obj/item/weapon/reagent_containers/food/snacks/lasagna/Initialize() - ..() + . = ..() reagents.add_reagent("protein", 2) //For meaty things. /obj/item/weapon/reagent_containers/food/snacks/gigapuddi diff --git a/code/modules/food/food/thecake.dm b/code/modules/food/food/thecake.dm index 05f5ef6440..491e6dca9c 100644 --- a/code/modules/food/food/thecake.dm +++ b/code/modules/food/food/thecake.dm @@ -183,7 +183,7 @@ volume = 80 /obj/item/weapon/reagent_containers/food/snacks/chaoscakeslice/Initialize() - ..() + . = ..() var/i = rand(1,6) icon_state = "chaoscake_slice-[i]" switch(i) diff --git a/code/modules/food/kitchen/microwave.dm b/code/modules/food/kitchen/microwave.dm index 5a499ae846..6b866d23ba 100644 --- a/code/modules/food/kitchen/microwave.dm +++ b/code/modules/food/kitchen/microwave.dm @@ -586,7 +586,7 @@ item_level = 1 /obj/machinery/microwave/advanced/Initialize() - ..() + . = ..() reagents.maximum_volume = 1000 /datum/recipe/splat // We use this to handle cooking micros (or mice, etc) in a microwave. Janky but it works better than snowflake code to handle the same thing. diff --git a/code/modules/hydroponics/beekeeping/beehive.dm b/code/modules/hydroponics/beekeeping/beehive.dm index e91624724f..dcef997e36 100644 --- a/code/modules/hydroponics/beekeeping/beehive.dm +++ b/code/modules/hydroponics/beekeeping/beehive.dm @@ -244,8 +244,8 @@ pass_color = TRUE strict_color_stacking = TRUE -/obj/item/stack/material/wax/New() - ..() +/obj/item/stack/material/wax/Initialize() + . = ..() recipes = wax_recipes /datum/material/wax diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index fba3f9ad99..195e1bba59 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -175,9 +175,13 @@ return /obj/machinery/portable_atmospherics/hydroponics/Initialize() +<<<<<<< HEAD . = ..() if(!ov_lowhealth) setup_overlays() +======= + ..() +>>>>>>> b22a056... Sideports a couple of init unit tests from Neb. (#7893) temp_chem_holder = new() temp_chem_holder.create_reagents(10) create_reagents(200) diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm index 5bf48370e2..4f1b16ca74 100644 --- a/code/modules/integrated_electronics/core/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -289,7 +289,6 @@ new /obj/item/weapon/storage/bag/circuits/mini/transfer(src) new /obj/item/weapon/storage/bag/circuits/mini/converter(src) new /obj/item/weapon/storage/bag/circuits/mini/power(src) - new /obj/item/device/electronic_assembly(src) new /obj/item/device/assembly/electronic_assembly(src) new /obj/item/device/assembly/electronic_assembly(src) diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index 9c140cedae..855c01c539 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -356,11 +356,9 @@ /obj/item/integrated_circuit/input/signaler/Initialize() . = ..() - set_frequency(frequency) - // Set the pins so when someone sees them, they won't show as null set_pin_data(IC_INPUT, 1, frequency) set_pin_data(IC_INPUT, 2, code) - push_data() + addtimer(CALLBACK(src, .proc/set_frequency, frequency), 40) /obj/item/integrated_circuit/input/signaler/Destroy() if(radio_controller) @@ -574,7 +572,7 @@ ) /obj/item/integrated_circuit/input/microphone/sign/Initialize() - ..() + . = ..() for(var/lang in readable_langs) var/datum/language/newlang = GLOB.all_languages[lang] my_langs |= newlang diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm index 5f4685da95..39dae33784 100644 --- a/code/modules/integrated_electronics/subtypes/output.dm +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -150,7 +150,7 @@ var/mob/living/voice/my_voice /obj/item/integrated_circuit/output/text_to_speech/advanced/Initialize() - ..() + . = ..() my_voice = new (src) mob_list -= my_voice // no life() ticks my_voice.name = "TTS Circuit" diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 9a226b836d..e68425111f 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -139,7 +139,7 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f var/static/list/base_genre_books /obj/machinery/librarycomp/Initialize() - ..() + . = ..() if(!base_genre_books || !base_genre_books.len) base_genre_books = list( diff --git a/code/modules/maps/tg/map_template.dm b/code/modules/maps/tg/map_template.dm index 5fa66e3b47..019dff407a 100644 --- a/code/modules/maps/tg/map_template.dm +++ b/code/modules/maps/tg/map_template.dm @@ -9,9 +9,9 @@ var/annihilate = FALSE // If true, all (movable) atoms at the location where the map is loaded will be deleted before the map is loaded in. var/fixed_orientation = FALSE // If true, the submap will not be rotated randomly when loaded. - var/cost = null // The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until \ - it runs out. The cost of a submap should roughly corrispond with several factors such as size, loot, difficulty, desired scarcity, etc. \ - Set to -1 to force the submap to always be made. + var/cost = null /* The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until + it runs out. The cost of a submap should roughly corrispond with several factors such as size, loot, difficulty, desired scarcity, etc. + Set to -1 to force the submap to always be made. */ var/allow_duplicates = FALSE // If false, only one map template will be spawned by the game. Doesn't affect admins spawning then manually. var/discard_prob = 0 // If non-zero, there is a chance that the map seeding algorithm will skip this template when selecting potential templates to use. diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index 2a17e05d36..f837ec3e59 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -20,16 +20,16 @@ drop_sound = 'sound/items/drop/axe.ogg' pickup_sound = 'sound/items/pickup/axe.ogg' -/obj/item/stack/material/New() - ..() +/obj/item/stack/material/Initialize() + . = ..() + randpixel_xy() if(!default_type) default_type = DEFAULT_WALL_MATERIAL material = get_material_by_name("[default_type]") if(!material) - qdel(src) - return 0 + return INITIALIZE_HINT_QDEL recipes = material.get_recipes() stacktype = material.stack_type @@ -44,7 +44,6 @@ matter = material.get_matter() update_strings() - return 1 /obj/item/stack/material/get_material() return material diff --git a/code/modules/materials/material_synth.dm b/code/modules/materials/material_synth.dm index f7088839ff..972b8b61ed 100644 --- a/code/modules/materials/material_synth.dm +++ b/code/modules/materials/material_synth.dm @@ -6,11 +6,11 @@ gender = NEUTER matter = null // Don't shove it in the autholathe. -/obj/item/stack/material/cyborg/New() - if(..()) - name = "[material.display_name] synthesiser" - desc = "A device that synthesises [material.display_name]." - matter = null +/obj/item/stack/material/cyborg/Initialize() + . = ..() + name = "[material.display_name] synthesiser" + desc = "A device that synthesises [material.display_name]." + matter = null /obj/item/stack/material/cyborg/update_strings() return diff --git a/code/modules/mining/machine_stacking.dm b/code/modules/mining/machine_stacking.dm index edd065d5a4..de0ad60aed 100644 --- a/code/modules/mining/machine_stacking.dm +++ b/code/modules/mining/machine_stacking.dm @@ -87,11 +87,11 @@ /obj/machinery/mineral/stacking_machine/New() ..() - for(var/stacktype in typesof(/obj/item/stack/material)-/obj/item/stack/material) - var/obj/item/stack/S = new stacktype(src) - stack_storage[S.name] = 0 - stack_paths[S.name] = stacktype - qdel(S) + for(var/stacktype in subtypesof(/obj/item/stack/material)) + var/obj/item/stack/S = stacktype + var/s_name = initial(S.name) + stack_storage[s_name] = 0 + stack_paths[s_name] = stacktype stack_storage["glass"] = 0 stack_paths["glass"] = /obj/item/stack/material/glass diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 4595b6fbb7..e74c241ffb 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -158,9 +158,10 @@ var/upright = 0 var/base_state -/obj/item/stack/flag/New() - ..() +/obj/item/stack/flag/Initialize() + . = ..() base_state = icon_state + update_icon() /obj/item/stack/flag/blue name = "blue flags" diff --git a/code/modules/mining/ore.dm b/code/modules/mining/ore.dm index 1c345021ab..8aaf648c86 100644 --- a/code/modules/mining/ore.dm +++ b/code/modules/mining/ore.dm @@ -114,7 +114,7 @@ material = null /obj/item/weapon/ore/Initialize() - ..() + . = ..() randpixel_xy() /obj/item/weapon/ore/attackby(obj/item/weapon/W as obj, mob/user as mob) diff --git a/code/modules/mob/freelook/ai/eye.dm b/code/modules/mob/freelook/ai/eye.dm index 67a1b810d7..711dbd3085 100644 --- a/code/modules/mob/freelook/ai/eye.dm +++ b/code/modules/mob/freelook/ai/eye.dm @@ -12,11 +12,11 @@ visualnet = cameranet /mob/observer/eye/aiEye/Destroy() - if(owner) - var/mob/living/silicon/ai/ai = owner - ai.all_eyes -= src - owner = null - . = ..() + if(owner) + var/mob/living/silicon/ai/ai = owner + ai.all_eyes -= src + owner = null + . = ..() /mob/observer/eye/aiEye/setLoc(var/T, var/cancel_tracking = 1) if(owner) diff --git a/code/modules/mob/freelook/update_triggers.dm b/code/modules/mob/freelook/update_triggers.dm index e6d1976fad..a678ff319c 100644 --- a/code/modules/mob/freelook/update_triggers.dm +++ b/code/modules/mob/freelook/update_triggers.dm @@ -38,8 +38,8 @@ updateVisibility(src) return ..() -/obj/effect/New() - ..() +/obj/effect/Initialize() + . = ..() updateVisibility(src) // DOORS diff --git a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm index 7b222d8a61..1f15f6a07a 100644 --- a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm +++ b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm @@ -140,6 +140,6 @@ to_wear_r_hand = null /mob/living/carbon/human/ai_controlled/replicant/Initialize() - ..() + . = ..() name = species.get_random_name(gender) add_modifier(/datum/modifier/homeothermic, 0, null) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 0c20f6bf31..f3cdc716e3 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -978,7 +978,7 @@ var/list/ai_verbs_default = list( drop_new_multicam() //Special subtype kept around for global announcements -/mob/living/silicon/ai/announcer/ +/mob/living/silicon/ai/announcer is_dummy = 1 /mob/living/silicon/ai/announcer/Initialize() diff --git a/code/modules/mob/living/silicon/robot/drone/swarm.dm b/code/modules/mob/living/silicon/robot/drone/swarm.dm index 3ac3f4574e..3db976437b 100644 --- a/code/modules/mob/living/silicon/robot/drone/swarm.dm +++ b/code/modules/mob/living/silicon/robot/drone/swarm.dm @@ -57,7 +57,7 @@ ) /mob/living/silicon/robot/drone/swarm/Initialize() - ..() + . = ..() add_language(LANGUAGE_SWARMBOT, 1) diff --git a/code/modules/mob/living/silicon/robot/drone/swarm_items.dm b/code/modules/mob/living/silicon/robot/drone/swarm_items.dm index f739285078..2bbba0b082 100644 --- a/code/modules/mob/living/silicon/robot/drone/swarm_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/swarm_items.dm @@ -158,5 +158,5 @@ ) /obj/item/weapon/gun/energy/xray/swarm/Initialize() - ..() + . = ..() adjust_scale(-1, 1) diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm index d45d35cef3..e8077db22f 100644 --- a/code/modules/mob/living/silicon/robot/robot_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_items.dm @@ -131,7 +131,7 @@ var/dummy_card_type = /obj/item/weapon/card/id/science/roboticist/dummy_cyborg /obj/item/weapon/card/robot/Initialize() - ..() + . = ..() dummy_card = new dummy_card_type(src) /obj/item/weapon/card/robot/Destroy() @@ -149,7 +149,7 @@ access = list(access_robotics) /obj/item/weapon/card/id/syndicate/dummy_cyborg/Initialize() - ..() + . = ..() access |= access_robotics //A harvest item for serviceborgs. diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/crab.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/crab.dm index 9fe548ee61..26b8eff0b4 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/crab.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/crab.dm @@ -46,7 +46,7 @@ catalogue_data = list(/datum/category_item/catalogue/fauna/sif_crab) /mob/living/simple_mob/animal/passive/crab/sif/Initialize() - ..() + . = ..() adjust_scale(rand(5,12) / 10) // Meat! diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/fish.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/fish.dm index b5c811b81c..7ba595b47b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/fish.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/fish.dm @@ -34,7 +34,7 @@ var/randomize_location = TRUE /mob/living/simple_mob/animal/passive/fish/Initialize() - ..() + . = ..() if(!default_pixel_x && randomize_location) default_pixel_x = rand(-12, 12) @@ -174,7 +174,7 @@ var/image/belly_image /mob/living/simple_mob/animal/passive/fish/icebass/Initialize() - ..() + . = ..() dorsal_color = rgb(rand(min_red,max_red), rand(min_green,max_green), rand(min_blue,max_blue)) belly_color = rgb(rand(min_red,max_red), rand(min_green,max_green), rand(min_blue,max_blue)) update_icon() @@ -248,7 +248,7 @@ meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat/sif /mob/living/simple_mob/animal/passive/fish/rockfish/Initialize() - ..() + . = ..() head_color = rgb(rand(min_red,max_red), rand(min_green,max_green), rand(min_blue,max_blue)) update_icon() diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/lizard.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/lizard.dm index af647587a6..ca94f0373f 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/lizard.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/lizard.dm @@ -34,7 +34,7 @@ attack_sharp = TRUE /mob/living/simple_mob/animal/passive/lizard/large/Initialize() - ..() + . = ..() adjust_scale(rand(12, 20) / 10) /mob/living/simple_mob/animal/passive/lizard/large/defensive diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/frostfly.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/frostfly.dm index 73d7b10e57..ffba5af281 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/frostfly.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/frostfly.dm @@ -81,7 +81,11 @@ return 1 // It literally produces a cryogenic mist inside itself. Cold doesn't bother it. /mob/living/simple_mob/animal/sif/frostfly/Initialize() +<<<<<<< HEAD . = ..() //VOREStation Edit +======= + . = ..() +>>>>>>> b22a056... Sideports a couple of init unit tests from Neb. (#7893) smoke_special = new verbs += /mob/living/proc/ventcrawl verbs += /mob/living/proc/hide diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/glitterfly.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/glitterfly.dm index 3687a67c51..f7bec21beb 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/glitterfly.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/glitterfly.dm @@ -62,7 +62,7 @@ ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive/glitterfly /mob/living/simple_mob/animal/sif/glitterfly/Initialize() - ..() + . = ..() var/colorlist = list(rgb(rand(100,255), rand(100,255), rand(100,255)) = 10, rgb(rand(5,100), rand(5,100), rand(5,100)) = 2, "#222222" = 1) color = pickweight(colorlist) @@ -85,7 +85,7 @@ plane = PLANE_LIGHTING_ABOVE /mob/living/simple_mob/animal/sif/glitterfly/rare/Initialize() - ..() + . = ..() /mob/living/simple_mob/animal/sif/glitterfly/unique_tame_check(var/obj/O, var/mob/user) . = ..() diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/kururak.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/kururak.dm index d24d28231b..8a54faf874 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/kururak.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/kururak.dm @@ -92,7 +92,7 @@ instinct = 50 /mob/living/simple_mob/animal/sif/kururak/Initialize() - ..() + . = ..() if(!instinct) if(prob(20)) instinct = rand(6, 10) @@ -331,7 +331,7 @@ remove_modifiers_of_type(/datum/modifier/ace) /mob/living/simple_mob/animal/sif/kururak/hibernate/Initialize() - ..() + . = ..() lay_down() instinct = 0 diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm index c59e292a4d..a6c6aabbf2 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/leech.dm @@ -115,7 +115,7 @@ emote_hear = list("chitters", "clicks", "gurgles") /mob/living/simple_mob/animal/sif/leech/Initialize() - ..() + . = ..() verbs += /mob/living/proc/ventcrawl verbs += /mob/living/proc/hide diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/moth.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/moth.dm index d153540dd5..8ad7f2b8c9 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/moth.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/moth.dm @@ -116,7 +116,7 @@ return FALSE /mob/living/simple_mob/animal/sif/tymisian/Initialize() - ..() + . = ..() smoke_spore = new verbs += /mob/living/proc/ventcrawl verbs += /mob/living/proc/hide diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/worm.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/worm.dm index b2ff320b52..aef54e599d 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/space/worm.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/worm.dm @@ -108,7 +108,7 @@ icon_state = "[icon_state]_dead" /mob/living/simple_mob/animal/space/space_worm/head/Initialize() - ..() + . = ..() var/mob/living/simple_mob/animal/space/space_worm/current = src diff --git a/code/modules/mob/living/voice/voice.dm b/code/modules/mob/living/voice/voice.dm index 919e302bcf..8b9491d902 100644 --- a/code/modules/mob/living/voice/voice.dm +++ b/code/modules/mob/living/voice/voice.dm @@ -7,13 +7,13 @@ emote_type = 2 //This lets them emote through containers. The communicator has a image feed of the person calling them so... -/mob/living/voice/New(loc) +/mob/living/voice/Initialize(loc) add_language(LANGUAGE_GALCOM) set_default_language(GLOB.all_languages[LANGUAGE_GALCOM]) if(istype(loc, /obj/item/device/communicator)) comm = loc - ..() + . = ..() // Proc: transfer_identity() // Parameters: 1 (speaker - the mob (usually an observer) to copy information from) diff --git a/code/modules/multiz/stairs.dm b/code/modules/multiz/stairs.dm index 4deedc8ed4..fdb4a02ac4 100644 --- a/code/modules/multiz/stairs.dm +++ b/code/modules/multiz/stairs.dm @@ -11,9 +11,9 @@ layer = STAIRS_LAYER /obj/structure/stairs/Initialize() + . = ..() if(check_integrity()) update_icon() - return INITIALIZE_HINT_NORMAL // Returns TRUE if the stairs are a complete and connected unit, FALSE if a piece is missing or obstructed // Will attempt to reconnect broken pieces @@ -70,10 +70,10 @@ var/obj/structure/stairs/middle/middle = null /obj/structure/stairs/bottom/Initialize() + . = ..() if(!GetAbove(src)) warning("Stair created without level above: ([loc.x], [loc.y], [loc.z])") return INITIALIZE_HINT_QDEL - . = ..() /obj/structure/stairs/bottom/Destroy() if(top) @@ -160,10 +160,8 @@ // If the object is pulling or grabbing anything, we'll want to move those too. A grab chain may be disrupted in doing so. if(L.pulling && !L.pulling.anchored) - to_world("adding [L.pulling] to pulling") pulling |= L.pulling for(var/obj/item/weapon/grab/G in list(L.l_hand, L.r_hand)) - to_world("adding [G.affecting] to pulling") pulling |= G.affecting // If the stairs aren't broken, go up. @@ -182,7 +180,6 @@ // Bring the pulled/grabbed object(s) along behind us for(var/atom/movable/P in pulling) - to_world("attempting to move [P]") P.forceMove(get_turf(src)) // They will move onto the turf but won't get past the check earlier in crossed. Aligns animation more cleanly switch(src.dir) if(NORTH) @@ -249,10 +246,10 @@ var/obj/structure/stairs/bottom/bottom = null /obj/structure/stairs/middle/Initialize() + . = ..() if(!GetAbove(src)) warning("Stair created without level above: ([loc.x], [loc.y], [loc.z])") return INITIALIZE_HINT_QDEL - . = ..() /obj/structure/stairs/middle/Destroy() if(top) @@ -332,10 +329,10 @@ var/obj/structure/stairs/bottom/bottom = null /obj/structure/stairs/top/Initialize() + . = ..() if(!GetBelow(src)) warning("Stair created without level below: ([loc.x], [loc.y], [loc.z])") return INITIALIZE_HINT_QDEL - . = ..() /obj/structure/stairs/top/Destroy() if(middle) @@ -422,10 +419,8 @@ // If the object is pulling or grabbing anything, we'll want to move those too. A grab chain may be disrupted in doing so. if(L.pulling && !L.pulling.anchored) - to_world("adding [L.pulling] to pulling") pulling |= L.pulling for(var/obj/item/weapon/grab/G in list(L.l_hand, L.r_hand)) - to_world("adding [G.affecting] to pulling") pulling |= G.affecting // If the stairs aren't broken, go up. @@ -444,7 +439,6 @@ // Bring the pulled/grabbed object(s) along behind us for(var/atom/movable/P in pulling) - to_world("attempting to move [P]") P.forceMove(get_turf(src)) // They will move onto the turf but won't get past the check earlier in crossed. Aligns animation more cleanly switch(src.dir) if(NORTH) @@ -505,7 +499,7 @@ icon_state = "" /obj/structure/stairs/spawner/Initialize() - . = ..() + ..() var/turf/B1 = get_step(get_turf(src), turn(dir, 180)) var/turf/B2 = get_turf(src) var/turf/T1 = GetAbove(B1) @@ -553,4 +547,4 @@ /obj/structure/stairs/spawner/west dir = WEST - bound_width = 64 \ No newline at end of file + bound_width = 64 diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm new file mode 100644 index 0000000000..f0331f77da --- /dev/null +++ b/code/modules/nano/nanoui.dm @@ -0,0 +1,526 @@ +/********************************************************** +NANO UI FRAMEWORK + +nanoui class (or whatever Byond calls classes) + +nanoui is used to open and update nano browser uis +**********************************************************/ + +/datum/nanoui + // the user who opened this ui + var/mob/user + // the object this ui "belongs" to + var/datum/src_object + // the title of this ui + var/title + // the key of this ui, this is to allow multiple (different) uis for each src_object + var/ui_key + // window_id is used as the window name/identifier for browse and onclose + var/window_id + // the browser window width + var/width = 0 + // the browser window height + var/height = 0 + // whether to use extra logic when window closes + var/on_close_logic = 1 + // an extra ref to use when the window is closed, usually null + var/atom/ref = null + // options for modifying window behaviour + var/window_options = "focus=0;can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id + // the list of stylesheets to apply to this ui + var/list/stylesheets = list() + // the list of javascript scripts to use for this ui + var/list/scripts = list() + // a list of templates which can be used with this ui + var/templates[0] + // the layout key for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing) + var/layout_key = "default" + // this sets whether to re-render the ui layout with each update (default 0, turning on will break the map ui if it's in use) + var/auto_update_layout = 0 + // this sets whether to re-render the ui content with each update (default 1) + var/auto_update_content = 1 + // the default state to use for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing) + var/state_key = "default" + // show the map ui, this is used by the default layout + var/show_map = 0 + // the map z level to display + var/map_z_level = 1 + // initial data, containing the full data structure, must be sent to the ui (the data structure cannot be extended later on) + var/list/initial_data[0] + // set to 1 to update the ui automatically every master_controller tick + var/is_auto_updating = 0 + // the current status/visibility of the ui + var/status = STATUS_INTERACTIVE + + // Relationship between a master interface and its children. Used in update_status + var/datum/nanoui/master_ui + var/list/datum/nanoui/children = list() + var/datum/topic_state/state = null + + /** + * Create a new nanoui instance. + * + * @param nuser /mob The mob who has opened/owns this ui + * @param nsrc_object /obj|/mob The obj or mob which this ui belongs to + * @param nui_key string A string key to use for this ui. Allows for multiple unique uis on one src_oject + * @param ntemplate string The filename of the template file from /nano/templates (e.g. "my_template.tmpl") + * @param ntitle string The title of this ui + * @param nwidth int the width of the ui window + * @param nheight int the height of the ui window + * @param nref /atom A custom ref to use if "on_close_logic" is set to 1 + * + * @return /nanoui new nanoui object + */ +/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state) + user = nuser + src_object = nsrc_object + ui_key = nui_key + window_id = "[ui_key]\ref[src_object]" + + src.master_ui = master_ui + if(master_ui) + master_ui.children += src + src.state = state + + // add the passed template filename as the "main" template, this is required + add_template("main", ntemplate_filename) + + if (ntitle) + title = sanitize(ntitle) + if (nwidth) + width = nwidth + if (nheight) + height = nheight + if (nref) + ref = nref + + add_common_assets() + + /** + * Use this proc to add assets which are common to (and required by) all nano uis + * + * @return nothing + */ +/datum/nanoui/proc/add_common_assets() + add_script("libraries.min.js") // A JS file comprising of jQuery, doT.js and jQuery Timer libraries (compressed together) + add_script("nano_utility.js") // The NanoUtility JS, this is used to store utility functions. + add_script("nano_template.js") // The NanoTemplate JS, this is used to render templates. + add_script("nano_state_manager.js") // The NanoStateManager JS, it handles updates from the server and passes data to the current state + add_script("nano_state.js") // The NanoState JS, this is the base state which all states must inherit from + add_script("nano_state_default.js") // The NanoStateDefault JS, this is the "default" state (used by all UIs by default), which inherits from NanoState + add_script("nano_base_callbacks.js") // The NanoBaseCallbacks JS, this is used to set up (before and after update) callbacks which are common to all UIs + add_script("nano_base_helpers.js") // The NanoBaseHelpers JS, this is used to set up template helpers which are common to all UIs + add_stylesheet("shared.css") // this CSS sheet is common to all UIs + add_stylesheet("icons.css") // this CSS sheet is common to all UIs + + /** + * Set the current status (also known as visibility) of this ui. + * + * @param state int The status to set, see the defines at the top of this file + * @param push_update int (bool) Push an update to the ui to update it's status (an update is always sent if the status has changed to red (0)) + * + * @return nothing + */ +/datum/nanoui/proc/set_status(state, push_update) + if (state != status) // Only update if it is different + if (status == STATUS_DISABLED) + status = state + if (push_update) + update() + else + status = state + if (push_update || status == 0) + push_data(null, 1) // Update the UI, force the update in case the status is 0, data is null so that previous data is used + + /** + * Update the status (visibility) of this ui based on the user's status + * + * @param push_update int (bool) Push an update to the ui to update it's status. This is set to 0/false if an update is going to be pushed anyway (to avoid unnessary updates) + * + * @return nothing + */ +/datum/nanoui/proc/update_status(var/push_update = 0) + var/obj/host = src_object.nano_host() + var/new_status = host.CanUseTopic(user, state) + if(master_ui) + new_status = min(new_status, master_ui.status) + + set_status(new_status, push_update) + if(new_status == STATUS_CLOSE) + close() + + /** + * Set the ui to auto update (every master_controller tick) + * + * @param state int (bool) Set auto update to 1 or 0 (true/false) + * + * @return nothing + */ +/datum/nanoui/proc/set_auto_update(nstate = 1) + is_auto_updating = nstate + + /** + * Set the initial data for the ui. This is vital as the data structure set here cannot be changed when pushing new updates. + * + * @param data /list The list of data for this ui + * + * @return nothing + */ +/datum/nanoui/proc/set_initial_data(list/data) + initial_data = data + + /** + * Get config data to sent to the ui. + * + * @return /list config data + */ +/datum/nanoui/proc/get_config_data() + var/name = "[src_object]" + name = sanitize(name) + var/list/config_data = list( + "title" = title, + "srcObject" = list("name" = name), + "stateKey" = state_key, + "status" = status, + "autoUpdateLayout" = auto_update_layout, + "autoUpdateContent" = auto_update_content, + "showMap" = show_map, + "mapZLevel" = map_z_level, + "user" = list("name" = user.name) + ) + return config_data + + /** + * Get data to sent to the ui. + * + * @param data /list The list of general data for this ui (can be null to use previous data sent) + * + * @return /list data to send to the ui + */ +/datum/nanoui/proc/get_send_data(var/list/data) + var/list/config_data = get_config_data() + + var/list/send_data = list("config" = config_data) + + if (!isnull(data)) + send_data["data"] = data + + return send_data + + /** + * Set the browser window options for this ui + * + * @param nwindow_options string The new window options + * + * @return nothing + */ +/datum/nanoui/proc/set_window_options(nwindow_options) + window_options = nwindow_options + + /** + * Add a CSS stylesheet to this UI + * These must be added before the UI has been opened, adding after that will have no effect + * + * @param file string The name of the CSS file from /nano/css (e.g. "my_style.css") + * + * @return nothing + */ +/datum/nanoui/proc/add_stylesheet(file) + stylesheets.Add(file) + + /** + * Add a JavsScript script to this UI + * These must be added before the UI has been opened, adding after that will have no effect + * + * @param file string The name of the JavaScript file from /nano/js (e.g. "my_script.js") + * + * @return nothing + */ +/datum/nanoui/proc/add_script(file) + scripts.Add(file) + + /** + * Add a template for this UI + * Templates are combined with the data sent to the UI to create the rendered view + * These must be added before the UI has been opened, adding after that will have no effect + * + * @param key string The key which is used to reference this template in the frontend + * @param filename string The name of the template file from /nano/templates (e.g. "my_template.tmpl") + * + * @return nothing + */ +/datum/nanoui/proc/add_template(key, filename) + templates[key] = filename + + /** + * Set the layout key for use in the frontend Javascript + * The layout key is the basic layout key for the page + * Two files are loaded on the client based on the layout key varable: + * -> a template in /nano/templates with the filename "layout_.tmpl + * -> a CSS stylesheet in /nano/css with the filename "layout_.css + * + * @param nlayout string The layout key to use + * + * @return nothing + */ +/datum/nanoui/proc/set_layout_key(nlayout_key) + layout_key = lowertext(nlayout_key) + + /** + * Set the ui to update the layout (re-render it) on each update, turning this on will break the map ui (if it's being used) + * + * @param state int (bool) Set update to 1 or 0 (true/false) (default 0) + * + * @return nothing + */ +/datum/nanoui/proc/set_auto_update_layout(nstate) + auto_update_layout = nstate + + /** + * Set the ui to update the main content (re-render it) on each update + * + * @param state int (bool) Set update to 1 or 0 (true/false) (default 1) + * + * @return nothing + */ +/datum/nanoui/proc/set_auto_update_content(nstate) + auto_update_content = nstate + + /** + * Set the state key for use in the frontend Javascript + * + * @param nstate_key string The key of the state to use + * + * @return nothing + */ +/datum/nanoui/proc/set_state_key(nstate_key) + state_key = nstate_key + + /** + * Toggle showing the map ui + * + * @param nstate_key boolean 1 to show map, 0 to hide (default is 0) + * + * @return nothing + */ +/datum/nanoui/proc/set_show_map(nstate) + show_map = nstate + + /** + * Toggle showing the map ui + * + * @param nstate_key boolean 1 to show map, 0 to hide (default is 0) + * + * @return nothing + */ +/datum/nanoui/proc/set_map_z_level(nz) + map_z_level = nz + + /** + * Set whether or not to use the "old" on close logic (mainly unset_machine()) + * + * @param state int (bool) Set on_close_logic to 1 or 0 (true/false) + * + * @return nothing + */ +/datum/nanoui/proc/use_on_close_logic(state) + on_close_logic = state + + /** + * Return the HTML for this UI + * + * @return string HTML for the UI + */ +/datum/nanoui/proc/get_html() + + // before the UI opens, add the layout files based on the layout key + add_stylesheet("layout_[layout_key].css") + add_template("layout", "layout_[layout_key].tmpl") + + var/head_content = "" + + for (var/filename in scripts) + head_content += " " + + for (var/filename in stylesheets) + head_content += " " + + var/template_data_json = "{}" // An empty JSON object + if (templates.len > 0) + template_data_json = strip_improper(json_encode(templates)) + + var/list/send_data = get_send_data(initial_data) + var/initial_data_json = replacetext(replacetext(json_encode(send_data), """, "&#34;"), "'", "'") + initial_data_json = strip_improper(initial_data_json); + + var/url_parameters_json = json_encode(list("src" = "\ref[src]")) + + return {" + + + + + + + [head_content] + + +
+
+ + + + "} + + /** + * Open this UI + * + * @return nothing + */ +/datum/nanoui/proc/open() + if(!user.client) + return + + // An attempted fix to UIs sometimes locking up spamming runtime errors due to src_object being null for whatever reason. + // This hard-deletes the UI, preventing the device that uses the UI from being locked up permanently. + if(!src_object) + qdel(src) + + var/window_size = "" + if (width && height) + window_size = "size=[width]x[height];" + update_status(0) + if(status == STATUS_CLOSE) + return + + user << browse(get_html(), "window=[window_id];[window_size][window_options]") + winset(user, "mapwindow.map", "focus=true") // return keyboard focus to map + on_close_winset() + //onclose(user, window_id) + SSnanoui.ui_opened(src) + + /** + * Reinitialise this UI, potentially with a different template and/or initial data + * + * @return nothing + */ +/datum/nanoui/proc/reinitialise(template, new_initial_data) + if(template) + add_template("main", template) + if(new_initial_data) + set_initial_data(new_initial_data) + open() + + /** + * Close this UI + * + * @return nothing + */ +/datum/nanoui/proc/close() + is_auto_updating = 0 + SSnanoui.ui_closed(src) + user << browse(null, "window=[window_id]") + for(var/datum/nanoui/child in children) + child.close() + children.Cut() + state = null + master_ui = null + + /** + * Set the UI window to call the nanoclose verb when the window is closed + * This allows Nano to handle closed windows + * + * @return nothing + */ +/datum/nanoui/proc/on_close_winset() + if(!user.client) + return + var/params = "\ref[src]" + + winset(user, window_id, "on-close=\"nanoclose [params]\"") + + /** + * Push data to an already open UI window + * + * @return nothing + */ +/datum/nanoui/proc/push_data(data, force_push = 0) + update_status(0) + if (status == STATUS_DISABLED && !force_push) + return // Cannot update UI, no visibility + + var/list/send_data = get_send_data(data) + + //to_chat(user,list2json_usecache(send_data)) // used for debugging //NANO DEBUG HOOK + user << output(list2params(list(strip_improper(json_encode(send_data)))),"[window_id].browser:receiveUpdateData") + + /** + * This Topic() proc is called whenever a user clicks on a link within a Nano UI + * If the UI status is currently STATUS_INTERACTIVE then call the src_object Topic() + * If the src_object Topic() returns 1 (true) then update all UIs attached to src_object + * + * @return nothing + */ +/datum/nanoui/Topic(href, href_list) + update_status(0) // update the status + if (status != STATUS_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user + return + + // This is used to toggle the nano map ui + var/map_update = 0 + if(href_list["showMap"]) + set_show_map(text2num(href_list["showMap"])) + map_update = 1 + + if(href_list["mapZLevel"]) + set_map_z_level(text2num(href_list["mapZLevel"])) + map_update = 1 + + if ((src_object && src_object.Topic(href, href_list, state)) || map_update) + SSnanoui.update_uis(src_object) // update all UIs attached to src_object + + /** + * Process this UI, updating the entire UI or just the status (aka visibility) + * This process proc is called by the master_controller + * + * @param update string For this UI to update + * + * @return nothing + */ +/datum/nanoui/process(update = 0) + if (!src_object || !user) + close() + return + + if (status && (update || is_auto_updating)) + update() // Update the UI (update_status() is called whenever a UI is updated) + else + update_status(1) // Not updating UI, so lets check here if status has changed + + /** + * Update the UI + * + * @return nothing + */ +/datum/nanoui/proc/update(var/force_open = 0) + src_object.ui_interact(user, ui_key, src, force_open, master_ui, state) diff --git a/code/modules/organs/internal/augment.dm b/code/modules/organs/internal/augment.dm index da8ee8d577..bb899e5c2b 100644 --- a/code/modules/organs/internal/augment.dm +++ b/code/modules/organs/internal/augment.dm @@ -31,10 +31,8 @@ var/last_activate = null /obj/item/organ/internal/augment/Initialize() - ..() - + . ..() setup_radial_icon() - if(integrated_object_type) integrated_object = new integrated_object_type(src) integrated_object.canremove = FALSE diff --git a/code/modules/organs/internal/augment/armmounted.dm b/code/modules/organs/internal/augment/armmounted.dm index 4131955e15..833d4be435 100644 --- a/code/modules/organs/internal/augment/armmounted.dm +++ b/code/modules/organs/internal/augment/armmounted.dm @@ -189,7 +189,7 @@ ) /obj/item/organ/internal/augment/armmounted/shoulder/multiple/Initialize() - ..() + . = ..() if(integrated_object) integrated_tools[integrated_object_type] = integrated_object diff --git a/code/modules/organs/internal/spleen.dm b/code/modules/organs/internal/spleen.dm index 352a36207f..88d42bb8bb 100644 --- a/code/modules/organs/internal/spleen.dm +++ b/code/modules/organs/internal/spleen.dm @@ -73,7 +73,7 @@ spleen_efficiency = 0.5 /obj/item/organ/internal/spleen/skrell/Initialize() - ..() + . = ..() adjust_scale(0.8,0.7) /obj/item/organ/internal/spleen/minor @@ -83,5 +83,5 @@ spleen_tick = 15 /obj/item/organ/internal/spleen/minor/Initialize() - ..() + . = ..() adjust_scale(0.7) diff --git a/code/modules/organs/internal/stomach.dm b/code/modules/organs/internal/stomach.dm index 31adb758ae..2ebfefea61 100644 --- a/code/modules/organs/internal/stomach.dm +++ b/code/modules/organs/internal/stomach.dm @@ -12,8 +12,7 @@ var/deadly_hold = TRUE // Does the stomach do damage to mobs eaten by its owner? Xenos should probably have this FALSE. /obj/item/organ/internal/stomach/Initialize() - ..() - + . = ..() if(reagents) reagents.maximum_volume = 30 else diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 9047eb2665..e5df765bdc 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -115,8 +115,7 @@ var/list/organ_cache = list() handle_organ_mod_special() /obj/item/organ/Initialize() - ..() - + . = ..() if(owner) if(!meat_type) if(owner.isSynthetic()) diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index e7be5f4912..9eb4c97d4b 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -471,7 +471,7 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ var/species = SPECIES_HUMAN /obj/item/weapon/disk/species/Initialize() - ..() + . = ..() if(species) name = "[species] [initial(name)]" diff --git a/code/modules/organs/subtypes/diona.dm b/code/modules/organs/subtypes/diona.dm index 3e8f6eadd5..6b6367e8a0 100644 --- a/code/modules/organs/subtypes/diona.dm +++ b/code/modules/organs/subtypes/diona.dm @@ -212,7 +212,7 @@ vital = TRUE /obj/item/organ/internal/brain/cephalon/Initialize() - ..() + . = ..() spawn(30 SECONDS) // FBP Dionaea need some way to be disassembled through surgery, if absolutely necessary. if(!owner.isSynthetic()) vital = FALSE diff --git a/code/modules/organs/subtypes/slime.dm b/code/modules/organs/subtypes/slime.dm index 5fb54a21b4..eef360a515 100644 --- a/code/modules/organs/subtypes/slime.dm +++ b/code/modules/organs/subtypes/slime.dm @@ -92,7 +92,7 @@ var/strain_regen_cooldown = 5 MINUTES /obj/item/organ/internal/regennetwork/Initialize() - ..() + . = ..() var/mob/living/carbon/human/H = null spawn(15) if(ishuman(owner)) diff --git a/code/modules/overmap/turfs.dm b/code/modules/overmap/turfs.dm index bd31d6bc9a..916a8f4159 100644 --- a/code/modules/overmap/turfs.dm +++ b/code/modules/overmap/turfs.dm @@ -10,7 +10,6 @@ var/global/list/map_sectors = list() /turf/unsimulated/map icon = 'icons/turf/space.dmi' icon_state = "map" - initialized = FALSE // TODO - Fix unsimulated turf initialization so this override is not necessary! /turf/unsimulated/map/edge opacity = 1 diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 6876b5af36..6601e7965c 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -129,7 +129,7 @@ var/default_icon_state /obj/item/weapon/pen/blade/Initialize() - ..() + . = ..() active_icon_state = "[icon_state]-x" default_icon_state = icon_state diff --git a/code/modules/pda/cart.dm b/code/modules/pda/cart.dm index 936674061a..c877e7cf0c 100644 --- a/code/modules/pda/cart.dm +++ b/code/modules/pda/cart.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD var/list/command_cartridges = list( /obj/item/weapon/cartridge/captain, /obj/item/weapon/cartridge/hop, @@ -308,3 +309,315 @@ var/list/civilian_cartridges = list( icon_state = "cart" charges = 5 messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/frame) +======= +var/list/command_cartridges = list( + /obj/item/weapon/cartridge/captain, + /obj/item/weapon/cartridge/hop, + /obj/item/weapon/cartridge/hos, + /obj/item/weapon/cartridge/ce, + /obj/item/weapon/cartridge/rd, + /obj/item/weapon/cartridge/cmo, + /obj/item/weapon/cartridge/head, + /obj/item/weapon/cartridge/lawyer // Internal Affaris, + ) + +var/list/security_cartridges = list( + /obj/item/weapon/cartridge/security, + /obj/item/weapon/cartridge/detective, + /obj/item/weapon/cartridge/hos + ) + +var/list/engineering_cartridges = list( + /obj/item/weapon/cartridge/engineering, + /obj/item/weapon/cartridge/atmos, + /obj/item/weapon/cartridge/ce + ) + +var/list/medical_cartridges = list( + /obj/item/weapon/cartridge/medical, + /obj/item/weapon/cartridge/chemistry, + /obj/item/weapon/cartridge/cmo + ) + +var/list/research_cartridges = list( + /obj/item/weapon/cartridge/signal/science, + /obj/item/weapon/cartridge/rd + ) + +var/list/cargo_cartridges = list( + /obj/item/weapon/cartridge/quartermaster, // This also covers cargo-techs, apparently, + /obj/item/weapon/cartridge/miner, + /obj/item/weapon/cartridge/hop + ) + +var/list/civilian_cartridges = list( + /obj/item/weapon/cartridge/janitor, + /obj/item/weapon/cartridge/service, + /obj/item/weapon/cartridge/hop + ) + +/obj/item/weapon/cartridge + name = "generic cartridge" + desc = "A data cartridge for portable microcomputers." + icon = 'icons/obj/pda.dmi' + icon_state = "cart" + item_state = "electronic" + w_class = ITEMSIZE_TINY + drop_sound = 'sound/items/drop/component.ogg' + pickup_sound = 'sound/items/pickup/component.ogg' + + var/obj/item/radio/integrated/radio = null + + var/charges = 0 + + var/list/stored_data = list() + var/list/programs = list() + var/list/messenger_plugins = list() + +/obj/item/weapon/cartridge/Destroy() + QDEL_NULL(radio) + QDEL_LIST(programs) + QDEL_LIST(messenger_plugins) + return ..() + +/obj/item/weapon/cartridge/proc/update_programs(obj/item/device/pda/pda) + for(var/A in programs) + var/datum/data/pda/P = A + P.pda = pda + for(var/A in messenger_plugins) + var/datum/data/pda/messenger_plugin/P = A + P.pda = pda + +/obj/item/weapon/cartridge/engineering + name = "\improper Power-ON cartridge" + icon_state = "cart-e" + programs = list( + new/datum/data/pda/app/power, + new/datum/data/pda/utility/scanmode/halogen) + +/obj/item/weapon/cartridge/atmos + name = "\improper BreatheDeep cartridge" + icon_state = "cart-a" + programs = list(new/datum/data/pda/utility/scanmode/gas) + +/obj/item/weapon/cartridge/medical + name = "\improper Med-U cartridge" + icon_state = "cart-m" + programs = list( + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical) + +/obj/item/weapon/cartridge/chemistry + name = "\improper ChemWhiz cartridge" + icon_state = "cart-chem" + programs = list( + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical, + new/datum/data/pda/utility/scanmode/reagent) + +/obj/item/weapon/cartridge/security + name = "\improper R.O.B.U.S.T. cartridge" + icon_state = "cart-s" + programs = list( + new/datum/data/pda/app/crew_records/security) + +/obj/item/weapon/cartridge/detective + name = "\improper D.E.T.E.C.T. cartridge" + icon_state = "cart-s" + programs = list( + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical, + + new/datum/data/pda/app/crew_records/security) + + +/obj/item/weapon/cartridge/janitor + name = "\improper CustodiPRO cartridge" + desc = "The ultimate in clean-room design." + icon_state = "cart-j" + programs = list(new/datum/data/pda/app/janitor) + +/obj/item/weapon/cartridge/lawyer + name = "\improper P.R.O.V.E. cartridge" + icon_state = "cart-s" + programs = list(new/datum/data/pda/app/crew_records/security) + +/obj/item/weapon/cartridge/clown + name = "\improper Honkworks 5.0 cartridge" + icon_state = "cart-clown" + charges = 5 + programs = list(new/datum/data/pda/utility/honk) + messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/clown) + +/obj/item/weapon/cartridge/mime + name = "\improper Gestur-O 1000 cartridge" + icon_state = "cart-mi" + charges = 5 + messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/mime) + +/obj/item/weapon/cartridge/service + name = "\improper Serv-U Pro cartridge" + desc = "A data cartridge designed to serve YOU!" + +/obj/item/weapon/cartridge/signal + name = "generic signaler cartridge" + desc = "A data cartridge with an integrated radio signaler module." + programs = list(new/datum/data/pda/app/signaller) + +/obj/item/weapon/cartridge/signal/Initialize() + radio = new /obj/item/radio/integrated/signal(src) + . = ..() + +/obj/item/weapon/cartridge/signal/science + name = "\improper Signal Ace 2 cartridge" + desc = "Complete with integrated radio signaler!" + icon_state = "cart-tox" + programs = list( + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/signaller) + +/obj/item/weapon/cartridge/quartermaster + name = "\improper Space Parts & Space Vendors cartridge" + desc = "Perfect for the Quartermaster on the go!" + icon_state = "cart-q" + programs = list( + new/datum/data/pda/app/supply) + +/obj/item/weapon/cartridge/miner + name = "\improper Drill-Jockey 4.5 cartridge" + desc = "It's covered in some sort of sand." + icon_state = "cart-q" + +/obj/item/weapon/cartridge/head + name = "\improper Easy-Record DELUXE cartridge" + icon_state = "cart-h" + programs = list(new/datum/data/pda/app/status_display) + +/obj/item/weapon/cartridge/hop + name = "\improper HumanResources9001 cartridge" + icon_state = "cart-h" + programs = list( + new/datum/data/pda/app/crew_records/security, + + new/datum/data/pda/app/janitor, + + new/datum/data/pda/app/supply, + + new/datum/data/pda/app/status_display) + +/obj/item/weapon/cartridge/hos + name = "\improper R.O.B.U.S.T. DELUXE cartridge" + icon_state = "cart-hos" + programs = list( + new/datum/data/pda/app/crew_records/security, + + new/datum/data/pda/app/status_display) + +/obj/item/weapon/cartridge/ce + name = "\improper Power-On DELUXE cartridge" + icon_state = "cart-ce" + programs = list( + new/datum/data/pda/app/power, + new/datum/data/pda/utility/scanmode/halogen, + + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/app/status_display) + +/obj/item/weapon/cartridge/cmo + name = "\improper Med-U DELUXE cartridge" + icon_state = "cart-cmo" + programs = list( + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/status_display) + +/obj/item/weapon/cartridge/rd + name = "\improper Signal Ace DELUXE cartridge" + icon_state = "cart-rd" + programs = list( + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/signaller, + + new/datum/data/pda/app/status_display) + +/obj/item/weapon/cartridge/rd/Initialize() + radio = new /obj/item/radio/integrated/signal(src) + . = ..() + +/obj/item/weapon/cartridge/captain + name = "\improper Value-PAK cartridge" + desc = "Now with 200% more value!" + icon_state = "cart-c" + programs = list( + new/datum/data/pda/app/power, + new/datum/data/pda/utility/scanmode/halogen, + + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/crew_records/security, + + new/datum/data/pda/app/janitor, + + new/datum/data/pda/app/supply, + + new/datum/data/pda/app/status_display) + +/obj/item/weapon/cartridge/syndicate + name = "\improper Detomatix cartridge" + icon_state = "cart" + var/initial_remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing. + charges = 4 + programs = list(new/datum/data/pda/utility/toggle_door) + messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/detonate) + +/obj/item/weapon/cartridge/syndicate/New() + var/datum/data/pda/utility/toggle_door/D = programs[1] + if(istype(D)) + D.remote_door_id = initial_remote_door_id + +/obj/item/weapon/cartridge/proc/post_status(var/command, var/data1, var/data2) + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) + if(!frequency) return + + var/datum/signal/status_signal = new + status_signal.source = src + status_signal.transmission_method = TRANSMISSION_RADIO + status_signal.data["command"] = command + + switch(command) + if("message") + status_signal.data["msg1"] = data1 + status_signal.data["msg2"] = data2 + if(loc) + var/obj/item/PDA = loc + var/mob/user = PDA.fingerprintslast + log_admin("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") + message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") + + if("alert") + status_signal.data["picture_state"] = data1 + + frequency.post_signal(src, status_signal) + +/obj/item/weapon/cartridge/frame + name = "F.R.A.M.E. cartridge" + icon_state = "cart" + charges = 5 + messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/frame) +>>>>>>> b22a056... Sideports a couple of init unit tests from Neb. (#7893) diff --git a/code/modules/pda/radio.dm b/code/modules/pda/radio.dm index 0d3b115a13..c5cd57c440 100644 --- a/code/modules/pda/radio.dm +++ b/code/modules/pda/radio.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD /obj/item/radio/integrated name = "\improper PDA radio module" desc = "An electronic radio system." @@ -136,3 +137,141 @@ spawn(0) radio_connection.post_signal(src, signal) +======= +/obj/item/radio/integrated + name = "\improper PDA radio module" + desc = "An electronic radio system." + icon = 'icons/obj/module.dmi' + icon_state = "power_mod" + var/obj/item/device/pda/hostpda = null + + var/list/botlist = null // list of bots + var/mob/living/bot/active // the active bot; if null, show bot list + var/list/botstatus // the status signal sent by the bot + + var/bot_type //The type of bot it is. + var/bot_filter //Determines which radio filter to use. + + var/control_freq = BOT_FREQ + + var/on = 0 //Are we currently active?? + var/menu_message = "" + +/obj/item/radio/integrated/New() + ..() + if(istype(loc.loc, /obj/item/device/pda)) + hostpda = loc.loc + if(bot_filter) + spawn(5) + add_to_radio(bot_filter) + +/obj/item/radio/integrated/Destroy() + if(radio_controller) + radio_controller.remove_object(src, control_freq) + hostpda = null + return ..() + +/obj/item/radio/integrated/proc/post_signal(var/freq, var/key, var/value, var/key2, var/value2, var/key3, var/value3, s_filter) + + //to_world("Post: [freq]: [key]=[value], [key2]=[value2]") + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) + return + + var/datum/signal/signal = new() + signal.source = src + signal.transmission_method = TRANSMISSION_RADIO + signal.data[key] = value + if(key2) + signal.data[key2] = value2 + if(key3) + signal.data[key3] = value3 + + frequency.post_signal(src, signal, radio_filter = s_filter) + +/obj/item/radio/integrated/Topic(href, href_list) + ..() + switch(href_list["op"]) + if("control") + active = locate(href_list["bot"]) + spawn(0) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) + + if("scanbots") // find all bots + botlist = null + spawn(0) + post_signal(control_freq, "command", "bot_status", s_filter = bot_filter) + + if("botlist") + active = null + + if("stop", "go", "home") + spawn(0) + post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = bot_filter) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) + + if("summon") + spawn(0) + post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(hostpda), "useraccess", hostpda.GetAccess(), "user", usr, s_filter = bot_filter) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) + +/obj/item/radio/integrated/receive_signal(datum/signal/signal) + if(bot_type && istype(signal.source, /mob/living/bot) && signal.data["type"] == bot_type) + if(!botlist) + botlist = new() + + botlist |= signal.source + + if(active == signal.source) + var/list/b = signal.data + botstatus = b.Copy() + +/obj/item/radio/integrated/proc/add_to_radio(bot_filter) //Master filter control for bots. Must be placed in the bot's local New() to support map spawned bots. + if(radio_controller) + radio_controller.add_object(src, control_freq, radio_filter = bot_filter) + +/* + * Radio Cartridge, essentially a signaler. + */ +/obj/item/radio/integrated/signal + var/frequency = 1457 + var/code = 30.0 + var/last_transmission + var/datum/radio_frequency/radio_connection + +/obj/item/radio/integrated/signal/Destroy() + if(radio_controller) + radio_controller.remove_object(src, frequency) + radio_connection = null + return ..() + +/obj/item/radio/integrated/signal/Initialize() + . = ..() + if(radio_controller) + if(src.frequency < PUBLIC_LOW_FREQ || src.frequency > PUBLIC_HIGH_FREQ) + src.frequency = sanitize_frequency(src.frequency) + set_frequency(frequency) + +/obj/item/radio/integrated/signal/proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency) + +/obj/item/radio/integrated/signal/proc/send_signal(message="ACTIVATE") + if(last_transmission && world.time < (last_transmission + 5)) + return + last_transmission = world.time + + var/time = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + + var/datum/signal/signal = new + signal.source = src + signal.encryption = code + signal.data["message"] = message + + spawn(0) + radio_connection.post_signal(src, signal) +>>>>>>> b22a056... Sideports a couple of init unit tests from Neb. (#7893) diff --git a/code/modules/power/singularity/particle_accelerator/particle_smasher.dm b/code/modules/power/singularity/particle_accelerator/particle_smasher.dm index 01fa9932d9..adff836cee 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_smasher.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_smasher.dm @@ -25,7 +25,7 @@ var/list/recipes // The list containing the Particle Smasher's recipes. /obj/machinery/particle_smasher/Initialize() - ..() + . = ..() storage = list() update_icon() prepare_recipes() diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 1d5262044e..e93ee62c71 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -318,7 +318,7 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /obj/machinery/computer/turbine_computer/Initialize() - . = ..() + ..() return INITIALIZE_HINT_LATELOAD /obj/machinery/computer/turbine_computer/LateInitialize() diff --git a/code/modules/projectiles/ammunition/rounds.dm b/code/modules/projectiles/ammunition/rounds.dm index 02d4b4aa5e..1b461a0c47 100644 --- a/code/modules/projectiles/ammunition/rounds.dm +++ b/code/modules/projectiles/ammunition/rounds.dm @@ -307,7 +307,7 @@ projectile_type = /obj/item/projectile/bullet/rifle/a145 /obj/item/ammo_casing/a145/spent/Initialize() - ..() + . = ..() expend() /* diff --git a/code/modules/projectiles/broken.dm b/code/modules/projectiles/broken.dm index 15f63f4c54..f972d1f6bd 100644 --- a/code/modules/projectiles/broken.dm +++ b/code/modules/projectiles/broken.dm @@ -18,7 +18,7 @@ setup_repair_needs() /obj/item/weapon/broken_gun/Initialize() - ..() + . = ..() spawn(30 SECONDS) if(!my_guntype && !QDELETED(src)) qdel(src) diff --git a/code/modules/reagents/distilling/distilling.dm b/code/modules/reagents/distilling/distilling.dm index 5d37f8510c..4bd8bd163e 100644 --- a/code/modules/reagents/distilling/distilling.dm +++ b/code/modules/reagents/distilling/distilling.dm @@ -74,7 +74,7 @@ ..() /obj/machinery/portable_atmospherics/powered/reagent_distillery/Initialize() - ..() + . = ..() Reservoir = new (src) Reservoir.Master = src diff --git a/code/modules/reagents/hoses/connector.dm b/code/modules/reagents/hoses/connector.dm index bac7fc7c6a..e165877041 100644 --- a/code/modules/reagents/hoses/connector.dm +++ b/code/modules/reagents/hoses/connector.dm @@ -53,7 +53,7 @@ ..() /obj/item/hose_connector/Initialize() - ..() + . = ..() create_reagents(100) @@ -105,7 +105,7 @@ ..() /obj/item/hose_connector/input/active/Initialize() - ..() + . = ..() START_PROCESSING(SSobj, src) if(!isturf(loc)) @@ -127,7 +127,7 @@ ..() /obj/item/hose_connector/output/active/Initialize() - ..() + . = ..() START_PROCESSING(SSobj, src) if(!isturf(loc)) diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index eb4bba2387..fe0a4c1381 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -226,7 +226,7 @@ var/obj/item/hose_connector/input/active/InputSocket /obj/item/weapon/reagent_containers/spray/chemsprayer/hosed/Initialize() - ..() + . = ..() InputSocket = new(src) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 642871f99f..2372be085a 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -548,7 +548,7 @@ density = FALSE /obj/machinery/disposal/wall/Initialize() - ..() + . = ..() spawn(1 SECOND) // Fixfix for weird interaction with buildmode or other late-spawning. update() @@ -1394,7 +1394,7 @@ var/obj/linked // the linked obj/machinery/disposal or obj/disposaloutlet /obj/structure/disposalpipe/trunk/Initialize() - ..() //Lateload below + ..() dpdir = dir return INITIALIZE_HINT_LATELOAD diff --git a/code/modules/shuttles/landmarks.dm b/code/modules/shuttles/landmarks.dm index 0c750dc246..cf6a76cb5c 100644 --- a/code/modules/shuttles/landmarks.dm +++ b/code/modules/shuttles/landmarks.dm @@ -143,7 +143,7 @@ return INITIALIZE_HINT_LATELOAD /obj/effect/shuttle_landmark/automatic/clearing/LateInitialize() - ..() + . = ..() for(var/turf/T in range(radius, src)) if(T.density) T.ChangeTurf(get_base_turf_by_area(T)) diff --git a/code/modules/turbolift/turbolift_turfs.dm b/code/modules/turbolift/turbolift_turfs.dm index 8949f71448..0fb3302885 100644 --- a/code/modules/turbolift/turbolift_turfs.dm +++ b/code/modules/turbolift/turbolift_turfs.dm @@ -1,2 +1,2 @@ /turf/simulated/wall/elevator/Initialize(mapload) - ..(mapload, "elevatorium") + . = ..(mapload, "elevatorium") diff --git a/code/unit_tests/subsystem_tests.dm b/code/unit_tests/subsystem_tests.dm new file mode 100644 index 0000000000..0e62c2896b --- /dev/null +++ b/code/unit_tests/subsystem_tests.dm @@ -0,0 +1,46 @@ +/datum/unit_test/subsystem_shall_be_initialized + name = "SUBSYSTEM - INIT: Subsystems shall be initalized" + +/datum/unit_test/subsystem_shall_be_initialized/start_test() + var/list/bad_subsystems = list() + for(var/datum/controller/subsystem/SS in Master.subsystems) + if (SS.flags & SS_NO_INIT) + continue + if(!SS.subsystem_initialized) + bad_subsystems += SS.type + + if(bad_subsystems.len) + fail("Found improperly initialized subsystems: [english_list(bad_subsystems)]") + else + pass("All susbsystems have initialized properly") + + return 1 + +/* Uncomment when all atoms init properly +/datum/unit_test/subsystem_atom_shall_have_no_bad_init_calls + name = "SUBSYSTEM - ATOMS: Shall have no bad init calls" + +/datum/unit_test/subsystem_atom_shall_have_no_bad_init_calls/start_test() + if(SSatoms.BadInitializeCalls.len) + log_bad(jointext(SSatoms.InitLog(), null)) + fail("[SSatoms] had bad initialization calls.") + else + pass("[SSatoms] had no bad initialization calls.") + return 1 + +/datum/unit_test/all_atoms_shall_be_initialized + name = "SUBSYSTEM - ATOMS: All atoms shall be initialized." + +/datum/unit_test/all_atoms_shall_be_initialized/start_test() + set background = TRUE // avoid infinite loop warning; SS will still wait for us. + var/fail = FALSE + for(var/atom/atom in world) + if(!(atom.initialized)) + log_bad("Uninitialized atom: [atom.log_info_line()]") + fail = TRUE + if(fail) + fail("There were uninitialized atoms.") + else + pass("All atoms were initialized") + return 1 +*/ \ No newline at end of file diff --git a/vorestation.dme b/vorestation.dme index 41a4ae7edd..6692d49337 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -3795,6 +3795,7 @@ #include "code\unit_tests\mob_tests.dm" #include "code\unit_tests\research_tests.dm" #include "code\unit_tests\sqlite_tests.dm" +#include "code\unit_tests\subsystem_tests.dm" #include "code\unit_tests\unit_test.dm" #include "code\unit_tests\unit_test_vr.dm" #include "code\unit_tests\vore_tests_vr.dm"