Files
Batrachophreno 4ecb0bc21c Repath obj/machinery to obj/structure/machinery [MDB Ignore] (#22500)
Repaths obj/machinery to obj/structure/machinery. **Note for
reviewers:** the only meaningful changed code exists within
**code/game/objects/structures.dm** and
**code/game/objects/structures/_machinery.dm**, largely concerning
damage procs. With the exception of moving airlock defines to their own
file, ALL OTHER CHANGES ARE STRICTLY PATH CHANGES.

Objects, _categorically_, are largely divided between those you can hold
in your hand/inventory and those you can't. Machinery objects are
already subtypes of Structures behaviorally, this PR just makes their
pathing reflect that, and allows for future work (tool actions, more
health/destruction functionality) to be developed without unnecessary
code duplication.

I have tested this PR by loading up the Horizon and dismantling various
machines and structures with tools, shooting guns of various types
throughout the ship, and detonating a bunch of explosions throughout the
ship.
2026-05-26 19:35:48 +00:00

224 lines
7.5 KiB
Plaintext

/*
This is /obj/machinery level code to properly manage power usage from the area.
*/
// Note that we update the area even if the area is unpowered.
#define REPORT_POWER_CONSUMPTION_CHANGE(old_power, new_power)\
if(old_power != new_power){\
var/area/A = get_area(src);\
if(A) A.power_use_change(old_power, new_power, power_channel)}
// returns true if the area has power on given channel (or doesn't require power), defaults to power_channel.
// May also optionally specify an area, otherwise defaults to src.loc.loc
/obj/structure/machinery/proc/powered(var/chan = -1, var/area/check_area = null)
if(!src.loc)
return 0
//Don't do this. It allows machines that set use_power to 0 when off (many machines) to
//be turned on again and used after a power failure because they never gain the NOPOWER flag.
//if(!use_power)
// return 1
if(!check_area)
check_area = src.loc.loc // make sure it's in an area
if(!check_area || !isarea(check_area))
return 0 // if not, then not powered
if(chan == -1)
chan = power_channel
return check_area.powered(chan) // return power status of the area
/// called whenever the power settings of the containing area change
/// by default, check equipment channel & set flag can override if needed
/// This is NOT for when the machine's own status changes; update_use_power for that.
/obj/structure/machinery/proc/power_change()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_CALL_PARENT(TRUE)
var/oldstat = stat
if(powered(power_channel))
stat &= ~NOPOWER
else
stat |= NOPOWER
. = (stat != oldstat)
if(.)
queue_icon_update()
/obj/structure/machinery/proc/get_power_usage()
if(internal)
return 0
switch(use_power)
if(POWER_USE_IDLE)
return idle_power_usage
if(POWER_USE_ACTIVE)
return active_power_usage
else
return 0
/**
* This will have this machine have its area eat this much power next tick, and not afterwards
*
* Do not use for continued power draw.
*
* * amount - The amount of power to consume
* * chan - The channel to consume it from, see `code\__DEFINES\machinery.dm`
*/
/obj/structure/machinery/proc/use_power_oneoff(var/amount, var/chan = POWER_CHAN)
var/area/A = get_area(src) // make sure it's in an area
if(!A)
return
if(chan == POWER_CHAN)
chan = power_channel
A.use_power_oneoff(amount, chan)
// Do not do power stuff in New/Initialize until after ..()
/obj/structure/machinery/Initialize(mapload, d = 0, populate_components = TRUE, is_internal = FALSE)
internal = is_internal
REPORT_POWER_CONSUMPTION_CHANGE(0, get_power_usage())
power_init_complete = TRUE
. = ..()
// Or in Destroy at all, but especially after the ..().
/obj/structure/machinery/Destroy()
UnregisterSignal(src, COMSIG_MOVABLE_MOVED)
REPORT_POWER_CONSUMPTION_CHANGE(get_power_usage(), 0)
. = ..()
/obj/structure/machinery/LateInitialize()
post_machine_initialize()
/**
* Called in LateInitialize meant to be the machine replacement to it
* This sets up power for the machine and requires parent be called,
* ensuring power works on all machines unless exempted with POWER_USE_OFF.
* This is the proc to override if you want to do anything in LateInitialize.
*/
/obj/structure/machinery/proc/post_machine_initialize()
PROTECTED_PROC(TRUE)
SHOULD_CALL_PARENT(TRUE)
power_change()
if(use_power == POWER_USE_OFF)
return
update_current_power_usage()
setup_area_power_relationship()
// The three procs below are the only allowed ways of modifying the corresponding variables.
/// Use this to modify the use_power variable of machines, do not modify them directly!
/obj/structure/machinery/proc/update_use_power(new_use_power)
if(!power_init_complete)
use_power = new_use_power
return
if(use_power == new_use_power)
return
var/old_power = get_power_usage()
use_power = new_use_power
var/new_power = get_power_usage()
REPORT_POWER_CONSUMPTION_CHANGE(old_power, new_power)
/// Makes this machine draw power from its area according to which use_power mode it is set to.
/obj/structure/machinery/proc/update_current_power_usage()
var/area/our_area = get_area(src)
if(!our_area)
return FALSE
var/new_usage = 0
switch(use_power)
if(POWER_USE_IDLE)
new_usage = idle_power_usage
if(POWER_USE_ACTIVE)
new_usage = active_power_usage
if(POWER_USE_OFF)
return
if(new_usage)
update_use_power(new_usage)
return TRUE
/**
* proc to call when the machine starts to require power after a duration of not requiring power
* sets up power related connections to its area if it exists and becomes area sensitive
* does not affect power usage itself
*
* Returns TRUE if it triggered a full registration, FALSE otherwise
* We do this so machinery that want to sidestep the area sensitiveity optimization can
*/
/obj/structure/machinery/proc/setup_area_power_relationship()
var/area/our_area = get_area(src)
if(our_area)
RegisterSignal(our_area, COMSIG_AREA_POWER_CHANGE, PROC_REF(power_change))
if(HAS_TRAIT_FROM(src, TRAIT_AREA_SENSITIVE, INNATE_TRAIT)) // If we for some reason have not lost our area sensitivity, there's no reason to set it back up
return FALSE
become_area_sensitive(INNATE_TRAIT)
RegisterSignal(src, COMSIG_ENTER_AREA, PROC_REF(on_enter_area))
RegisterSignal(src, COMSIG_EXIT_AREA, PROC_REF(on_exit_area))
return TRUE
/**
* proc to call when the machine stops requiring power after a duration of requiring power
* saves memory by removing the power relationship with its area if it exists and loses area sensitivity
* does not affect power usage itself
*/
/obj/structure/machinery/proc/remove_area_power_relationship()
var/area/our_area = get_area(src)
if(our_area)
UnregisterSignal(our_area, COMSIG_AREA_POWER_CHANGE)
if(always_area_sensitive)
return
lose_area_sensitivity(INNATE_TRAIT)
UnregisterSignal(src, COMSIG_ENTER_AREA)
UnregisterSignal(src, COMSIG_EXIT_AREA)
/obj/structure/machinery/proc/on_enter_area(datum/source, area/area_to_register)
SIGNAL_HANDLER
// If we're always area sensitive, and this is called while we have no power usage, do nothing and return
if(always_area_sensitive && use_power == POWER_USE_OFF)
return
update_current_power_usage()
power_change()
RegisterSignal(area_to_register, COMSIG_AREA_POWER_CHANGE, PROC_REF(power_change))
/obj/structure/machinery/proc/on_exit_area(datum/source, area/area_to_unregister)
SIGNAL_HANDLER
// If we're always area sensitive, and this is called while we have no power usage, do nothing and return
if(always_area_sensitive && use_power == POWER_USE_OFF)
return
UnregisterSignal(area_to_unregister, COMSIG_AREA_POWER_CHANGE)
/// Use this to modify the power channel variable of machines, do not modify them directly!
/obj/structure/machinery/proc/update_power_channel(new_channel)
if(power_channel == new_channel)
return
if(!power_init_complete)
power_channel = new_channel
return
var/power = get_power_usage()
REPORT_POWER_CONSUMPTION_CHANGE(power, 0)
power_channel = new_channel
REPORT_POWER_CONSUMPTION_CHANGE(0, power)
/// Use this to modify either of the power usage variables of machines, do not modify them directly!
/obj/structure/machinery/proc/change_power_consumption(new_power_consumption, use_power_mode = POWER_USE_IDLE)
var/old_power
switch(use_power_mode)
if(POWER_USE_IDLE)
old_power = idle_power_usage
idle_power_usage = new_power_consumption
if(POWER_USE_ACTIVE)
old_power = active_power_usage
active_power_usage = new_power_consumption
else
return
if(power_init_complete && (use_power_mode == use_power))
REPORT_POWER_CONSUMPTION_CHANGE(old_power, new_power_consumption)
#undef REPORT_POWER_CONSUMPTION_CHANGE