diff --git a/code/game/machinery/_machines_base/machine_construction/_construction.dm b/code/game/machinery/_machines_base/machine_construction/_construction.dm
index 3555ee7173f1..72679df311c5 100644
--- a/code/game/machinery/_machines_base/machine_construction/_construction.dm
+++ b/code/game/machinery/_machines_base/machine_construction/_construction.dm
@@ -14,6 +14,7 @@
// Called on state transition; can intercept, but must call parent.
/obj/machinery/proc/state_transition(var/decl/machine_construction/new_state, var/mob/user)
+ SHOULD_CALL_PARENT(TRUE)
construct_state = new_state
// Return a change state define or a fail message to block transition.
diff --git a/code/game/machinery/_machines_base/machine_construction/emitter.dm b/code/game/machinery/_machines_base/machine_construction/emitter.dm
new file mode 100644
index 000000000000..f1b87c2ad6a4
--- /dev/null
+++ b/code/game/machinery/_machines_base/machine_construction/emitter.dm
@@ -0,0 +1,217 @@
+// Emitters are not screwed apart like most machines; they are bolted down with a wrench and then welded in place.
+// Some subtypes like gyrotrons also use panel_state to gain the usual maintenance hatch on top of that.
+// Yes I hate this, yes it should be done differently, no I do not have it in me to do it any other way.
+// Maybe we should just bite the bullet and make gyrotrons not emitters??
+/decl/machine_construction/emitter
+ visible_components = FALSE
+ /// The state entered when the emitter is fastened down further, if any.
+ var/down_state
+ /// The state entered when the emitter is loosened, if any.
+ var/up_state
+ /// Whether the emitter is anchored to the floor in this state.
+ var/anchored = FALSE
+ // gyrotron stuff below
+ /// The state entered when the maintenance hatch is toggled via screwdriver. Null if the emitter has no hatch.
+ var/panel_state
+ /// Whether the maintenance hatch is open in this state.
+ var/panel_open = FALSE
+
+/decl/machine_construction/emitter/state_is_valid(obj/machinery/machine)
+ return (machine.anchored == anchored) && (machine.panel_open == panel_open)
+
+/decl/machine_construction/emitter/validate_state(obj/machinery/machine)
+ . = ..()
+ if(!.)
+ if(machine.panel_open != panel_open)
+ try_change_state(machine, panel_state)
+ else
+ try_change_state(machine, machine.anchored ? down_state : up_state)
+
+// the panel starts open after construction, again taken from /decl/machine_construction/default/panel_closed
+/decl/machine_construction/emitter/post_construct(obj/machinery/machine)
+ if(!panel_state || panel_open)
+ return
+ try_change_state(machine, panel_state)
+ machine.panel_open = TRUE
+ machine.queue_icon_update()
+
+/// Handles a wrench applied to the emitter in this state. Return TRUE if the interaction was handled.
+/decl/machine_construction/emitter/proc/wrench_interaction(obj/item/used_item, mob/user, obj/machinery/emitter/machine)
+ return FALSE
+
+/// Handles a welding tool applied to the emitter in this state. Return TRUE if the interaction was handled.
+/decl/machine_construction/emitter/proc/welder_interaction(obj/item/weldingtool/welder, mob/user, obj/machinery/emitter/machine)
+ return FALSE
+
+/decl/machine_construction/emitter/attackby(obj/item/used_item, mob/user, obj/machinery/emitter/machine)
+ if((. = ..()))
+ return
+ if(machine.active) // can't open/close/unweld/etc while operating
+ to_chat(user, SPAN_WARNING("Turn \the [machine] off first."))
+ return TRUE
+ if(IS_WRENCH(used_item))
+ return wrench_interaction(used_item, user, machine)
+ else if(IS_WELDER(used_item))
+ return welder_interaction(used_item, user, machine)
+ // everything after this is for gyrotrons/etc
+ if(!panel_state)
+ return FALSE
+ // handle this here because otherwise we'd have some nasty code duplication
+ if(IS_SCREWDRIVER(used_item))
+ TRANSFER_STATE(panel_state)
+ playsound(get_turf(machine), 'sound/items/Screwdriver.ogg', 50, 1)
+ machine.panel_open = !panel_open
+ to_chat(user, SPAN_NOTICE("You [machine.panel_open ? "open" : "close"] the maintenance hatch of \the [machine]."))
+ machine.update_icon() // could be done in a machinery level /state_transition() override but whatever
+ return TRUE
+ // sigh. copied from /decl/machine_construction/default/panel_open and /decl/machine_construction/default/panel_closed
+ // again done this way to avoid duplication because gyrotrons can have any combo of panel + emitter state
+ if(!panel_open)
+ // closed panel (taken from panel_closed)
+ // maybe these should be on the part replacer or something...
+ // there's so much code duplication between different panel open/closed states and i hate it.
+ // maybe we just need to separate it out to a separate state machine and let construct state determine if panel state can change
+ if(istype(used_item, /obj/item/part_replacer))
+ var/obj/item/part_replacer/replacer = used_item
+ if(replacer.remote_interaction)
+ machine.part_replacement(user, replacer)
+ for(var/line in machine.get_part_info_strings(user))
+ to_chat(user, line)
+ return TRUE
+ return FALSE
+ // open panel (taken from panel_open)
+ if(IS_CROWBAR(used_item))
+ TRANSFER_STATE(/decl/machine_construction/default/deconstructed)
+ playsound(get_turf(machine), 'sound/items/Crowbar.ogg', 50, 1)
+ machine.visible_message(SPAN_NOTICE("\The [user] deconstructs \the [machine]."))
+ machine.dismantle()
+ return
+ if(istype(used_item, /obj/item/part_replacer))
+ return machine.part_replacement(user, used_item)
+ if(istype(used_item))
+ return machine.part_insertion(user, used_item)
+ return FALSE
+
+/decl/machine_construction/emitter/mechanics_info()
+ . = list()
+ if(!panel_state)
+ return
+ if(panel_open)
+ . += "Use a screwdriver to close the maintenance hatch."
+ . += "Use a parts replacer to upgrade some parts."
+ . += "Use a crowbar to remove the circuit and deconstruct the emitter."
+ . += "Insert a new part to install it."
+ else
+ . += "Use a screwdriver to open the maintenance hatch."
+ . += "Use a parts replacer to view installed parts."
+
+/decl/machine_construction/emitter/unsecured
+ down_state = /decl/machine_construction/emitter/anchored
+
+/decl/machine_construction/emitter/unsecured/wrench_interaction(obj/item/used_item, mob/user, obj/machinery/emitter/machine)
+ TRANSFER_STATE(down_state)
+ playsound(machine.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ user.visible_message(
+ "\The [user] secures \the [machine] to the floor.",
+ "You secure the external reinforcing bolts to the floor.",
+ "You hear a ratchet.")
+ machine.anchored = TRUE
+ return TRUE
+
+/decl/machine_construction/emitter/unsecured/welder_interaction(obj/item/weldingtool/welder, mob/user, obj/machinery/emitter/machine)
+ to_chat(user, SPAN_WARNING("\The [machine] needs to be wrenched to the floor."))
+ return TRUE
+
+/decl/machine_construction/emitter/unsecured/mechanics_info()
+ . = ..()
+ . += "Use a wrench to anchor the emitter to the floor."
+
+/decl/machine_construction/emitter/anchored
+ anchored = TRUE
+ down_state = /decl/machine_construction/emitter/welded
+ up_state = /decl/machine_construction/emitter/unsecured
+
+/decl/machine_construction/emitter/anchored/wrench_interaction(obj/item/used_item, mob/user, obj/machinery/emitter/machine)
+ TRANSFER_STATE(up_state)
+ playsound(machine.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ user.visible_message(
+ "\The [user] unsecures \the [machine]'s reinforcing bolts from the floor.",
+ "You undo the external reinforcing bolts.",
+ "You hear a ratchet.")
+ machine.anchored = FALSE
+ return TRUE
+
+/decl/machine_construction/emitter/anchored/welder_interaction(obj/item/weldingtool/welder, mob/user, obj/machinery/emitter/machine)
+ if(!welder.do_tool_interaction(TOOL_WELDER, user, machine, 2 SECONDS, \
+ "welding", \
+ "welding", \
+ "You fail to weld \the [machine] to the floor.", \
+ fuel_expenditure = 1) \
+ )
+ return TRUE // failed for whatever reason
+ TRANSFER_STATE(down_state)
+ return TRUE
+
+/decl/machine_construction/emitter/anchored/mechanics_info()
+ . = ..()
+ . += "Use a wrench to undo the bolts anchoring the emitter to the floor."
+ . += "Use a welding tool to weld the emitter to the floor, allowing it to fire."
+
+/decl/machine_construction/emitter/welded
+ anchored = TRUE
+ up_state = /decl/machine_construction/emitter/anchored
+
+/decl/machine_construction/emitter/welded/wrench_interaction(obj/item/used_item, mob/user, obj/machinery/emitter/machine)
+ to_chat(user, SPAN_WARNING("\The [machine] needs to be unwelded from the floor."))
+ return TRUE
+
+/decl/machine_construction/emitter/welded/welder_interaction(obj/item/weldingtool/welder, mob/user, obj/machinery/emitter/machine)
+ if(!welder.do_tool_interaction(TOOL_WELDER, user, machine, 2 SECONDS, \
+ "cutting free", \
+ "cutting free", \
+ "You fail to cut \the [machine] free from the floor.", \
+ fuel_expenditure = 1) \
+ )
+ return TRUE // failed for whatever reason
+ TRANSFER_STATE(up_state)
+ return TRUE
+
+/decl/machine_construction/emitter/welded/mechanics_info()
+ . = ..()
+ . += "Use a welding tool to cut the emitter free from the floor."
+
+// Emitters built from a circuitboard also have a maintenance hatch, giving one state per (bolting, hatch) pair.
+/decl/machine_construction/emitter/unsecured/gyrotron
+ needs_board = "machine"
+ down_state = /decl/machine_construction/emitter/anchored/gyrotron
+ panel_state = /decl/machine_construction/emitter/unsecured/gyrotron/panel_open
+
+/decl/machine_construction/emitter/unsecured/gyrotron/panel_open
+ panel_open = TRUE
+ visible_components = TRUE
+ down_state = /decl/machine_construction/emitter/anchored/gyrotron/panel_open
+ panel_state = /decl/machine_construction/emitter/unsecured/gyrotron
+
+/decl/machine_construction/emitter/anchored/gyrotron
+ needs_board = "machine"
+ down_state = /decl/machine_construction/emitter/welded/gyrotron
+ up_state = /decl/machine_construction/emitter/unsecured/gyrotron
+ panel_state = /decl/machine_construction/emitter/anchored/gyrotron/panel_open
+
+/decl/machine_construction/emitter/anchored/gyrotron/panel_open
+ panel_open = TRUE
+ visible_components = TRUE
+ down_state = /decl/machine_construction/emitter/welded/gyrotron/panel_open
+ up_state = /decl/machine_construction/emitter/unsecured/gyrotron/panel_open
+ panel_state = /decl/machine_construction/emitter/anchored/gyrotron
+
+/decl/machine_construction/emitter/welded/gyrotron
+ needs_board = "machine"
+ up_state = /decl/machine_construction/emitter/anchored/gyrotron
+ panel_state = /decl/machine_construction/emitter/welded/gyrotron/panel_open
+
+/decl/machine_construction/emitter/welded/gyrotron/panel_open
+ panel_open = TRUE
+ visible_components = TRUE
+ up_state = /decl/machine_construction/emitter/anchored/gyrotron/panel_open
+ panel_state = /decl/machine_construction/emitter/welded/gyrotron
diff --git a/code/modules/power/singularity/emitter.dm b/code/game/machinery/emitter.dm
similarity index 63%
rename from code/modules/power/singularity/emitter.dm
rename to code/game/machinery/emitter.dm
index 192376cc994f..a497a6d2c5f6 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/game/machinery/emitter.dm
@@ -12,17 +12,17 @@
var/efficiency = 0.3 // Energy efficiency. 30% at this time, so 100kW load means 30kW laser pulses.
var/minimum_power = 10 KILOWATTS // The minimum power below which the emitter will turn off; different than the power needed to fire.
- var/active = 0
+ var/active = FALSE
var/fire_delay = 100
var/max_burst_delay = 100
var/min_burst_delay = 20
var/burst_shots = 3
var/last_shot = 0
var/shot_number = 0
- var/state = 0
- var/locked = 0
- var/powered = 0
+ var/locked = FALSE
+ var/powered = FALSE
core_skill = SKILL_ENGINES
+ construct_state = /decl/machine_construction/emitter/unsecured
uncreated_component_parts = list(
/obj/item/stock_parts/radio/receiver,
@@ -39,7 +39,11 @@
/obj/machinery/emitter/anchored
anchored = TRUE
- state = 2
+ construct_state = /decl/machine_construction/emitter/welded
+
+/// Returns TRUE if the emitter is able to fire based on its construction state (currently checks if welded down).
+/obj/machinery/emitter/proc/can_fire()
+ return istype(construct_state, /decl/machine_construction/emitter/welded)
/obj/machinery/emitter/Destroy()
log_and_message_admins("deleted \the [src]")
@@ -62,29 +66,28 @@
if(!istype(user))
user = null // safety, as the proc is publicly available.
- if(state == 2)
- if(!locked)
- if(active==1)
- active = 0
- to_chat(user, "You turn off \the [src].")
- log_and_message_admins("turned off \the [src]", user)
- investigate_log("turned off by [key_name_admin(user)]","singulo")
- else
- active = 1
- if(user)
- operator_skill = user.get_skill_value(core_skill)
- update_efficiency()
- to_chat(user, "You turn on \the [src].")
- shot_number = 0
- fire_delay = get_initial_fire_delay()
- log_and_message_admins("turned on \the [src]", user)
- investigate_log("turned on by [key_name_admin(user)]","singulo")
- update_icon()
+ if(!can_fire())
+ to_chat(user, SPAN_WARNING("\The [src] needs to be firmly secured to the floor first."))
+ return 1
+ if(!locked)
+ if(active)
+ active = FALSE
+ to_chat(user, SPAN_NOTICE("You turn off \the [src]."))
+ log_and_message_admins("turned off \the [src]", user)
+ investigate_log("turned off by [key_name_admin(user)]","singulo")
else
- to_chat(user, "The controls are locked!")
+ active = TRUE
+ if(user)
+ operator_skill = user.get_skill_value(core_skill)
+ update_efficiency()
+ to_chat(user, SPAN_NOTICE("You turn on \the [src]."))
+ shot_number = 0
+ fire_delay = get_initial_fire_delay()
+ log_and_message_admins("turned on \the [src]", user)
+ investigate_log("turned on by [key_name_admin(user)]","singulo")
+ update_icon()
else
- to_chat(user, "\The [src] needs to be firmly secured to the floor first.")
- return 1
+ to_chat(user, SPAN_WARNING("The controls are locked!"))
/obj/machinery/emitter/proc/update_efficiency()
efficiency = initial(efficiency)
@@ -99,11 +102,11 @@
/obj/machinery/emitter/Process()
if(stat & (BROKEN))
return
- if(state != 2)
+ if(!can_fire())
active = FALSE
update_icon()
return
- if(((last_shot + fire_delay) <= world.time) && (active == 1))
+ if(((last_shot + fire_delay) <= world.time) && active)
if(active_power_usage - can_use_power_oneoff(active_power_usage) < minimum_power)
powered = FALSE
update_icon()
@@ -111,10 +114,10 @@
var/drawn_power = min(active_power_usage, active_power_usage - use_power_oneoff(active_power_usage))
last_shot = world.time
if(shot_number < burst_shots)
- fire_delay = get_burst_delay()
+ fire_delay = get_shot_delay()
shot_number ++
else
- fire_delay = get_rand_burst_delay()
+ fire_delay = get_burst_delay()
shot_number = 0
//need to calculate the power per shot as the emitter doesn't fire continuously.
@@ -134,66 +137,6 @@
update_icon()
/obj/machinery/emitter/attackby(obj/item/used_item, mob/user)
-
- if(IS_WRENCH(used_item))
- if(active)
- to_chat(user, "Turn off [src] first.")
- return TRUE
- switch(state)
- if(0)
- state = 1
- playsound(loc, 'sound/items/Ratchet.ogg', 75, 1)
- user.visible_message("[user.name] secures [src] to the floor.", \
- "You secure the external reinforcing bolts to the floor.", \
- "You hear a ratchet.")
- anchored = TRUE
- if(1)
- state = 0
- playsound(loc, 'sound/items/Ratchet.ogg', 75, 1)
- user.visible_message("[user.name] unsecures [src] reinforcing bolts from the floor.", \
- "You undo the external reinforcing bolts.", \
- "You hear a ratchet.")
- anchored = FALSE
- if(2)
- to_chat(user, "\The [src] needs to be unwelded from the floor.")
- return TRUE
-
- if(IS_WELDER(used_item))
- var/obj/item/weldingtool/welder = used_item
- if(active)
- to_chat(user, "Turn off [src] first.")
- return TRUE
- switch(state)
- if(0)
- to_chat(user, "\The [src] needs to be wrenched to the floor.")
- if(1)
- if (!welder.weld(0,user))
- to_chat(user, "You need more welding fuel to complete this task.")
- return TRUE
- playsound(loc, 'sound/items/Welder2.ogg', 50, 1)
- user.visible_message("[user.name] starts to weld [src] to the floor.", \
- "You start to weld [src] to the floor.", \
- "You hear welding.")
- if (!do_after(user, 2 SECONDS, src))
- return TRUE
- if(!src || !welder.isOn()) return TRUE
- state = 2
- to_chat(user, "You weld [src] to the floor.")
- if(2)
- if (welder.weld(0,user))
- playsound(loc, 'sound/items/Welder2.ogg', 50, 1)
- user.visible_message("[user.name] starts to cut [src] free from the floor.", \
- "You start to cut [src] free from the floor.", \
- "You hear welding.")
- if (!do_after(user, 2 SECONDS, src))
- return TRUE
- if(!src || !welder.isOn()) return TRUE
- state = 1
- to_chat(user, "You cut [src] free from the floor.")
- else
- to_chat(user, "You need more welding fuel to complete this task.")
- return TRUE
-
if(istype(used_item, /obj/item/card/id) || istype(used_item, /obj/item/modular_computer))
if(emagged)
to_chat(user, "The lock seems to be broken.")
@@ -208,8 +151,8 @@
/obj/machinery/emitter/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
- locked = 0
- emagged = 1
+ locked = FALSE
+ emagged = TRUE
req_access.Cut()
user.visible_message("[user.name] emags [src].","You short out the lock.")
return 1
@@ -220,13 +163,15 @@
return ..()
/obj/machinery/emitter/proc/get_initial_fire_delay()
- return 100
+ return 10 SECONDS
-/obj/machinery/emitter/proc/get_rand_burst_delay()
+/// The number of deciseconds between each burst-fire grouping.
+/obj/machinery/emitter/proc/get_burst_delay()
return rand(min_burst_delay, max_burst_delay)
-/obj/machinery/emitter/proc/get_burst_delay()
- return 2
+/// The number of deciseconds between each shot in a burst.
+/obj/machinery/emitter/proc/get_shot_delay()
+ return 0.2 SECONDS
/obj/machinery/emitter/proc/get_emitter_beam()
return new /obj/item/projectile/beam/emitter(get_turf(src))
diff --git a/code/modules/fusion/gyrotron/gyrotron.dm b/code/modules/fusion/gyrotron/gyrotron.dm
index f70c73ffb5d1..27fef671223c 100644
--- a/code/modules/fusion/gyrotron/gyrotron.dm
+++ b/code/modules/fusion/gyrotron/gyrotron.dm
@@ -10,10 +10,11 @@
active_power_usage = GYRO_POWER
var/initial_id_tag
+ /// Time between shots, in SECONDS, NOT DECISECONDS
var/rate = 3
var/mega_energy = 1
- construct_state = /decl/machine_construction/default/panel_closed
+ construct_state = /decl/machine_construction/emitter/unsecured/gyrotron
uncreated_component_parts = list(
/obj/item/stock_parts/radio/receiver
)
@@ -21,7 +22,7 @@
/obj/machinery/emitter/gyrotron/anchored
anchored = TRUE
- state = 2
+ construct_state = /decl/machine_construction/emitter/welded/gyrotron
/obj/machinery/emitter/gyrotron/Initialize()
set_extension(src, /datum/extension/local_network_member)
@@ -39,11 +40,11 @@
change_power_consumption(mega_energy * GYRO_POWER, POWER_USE_ACTIVE)
. = ..()
-/obj/machinery/emitter/gyrotron/get_rand_burst_delay()
- return rate*10
-
/obj/machinery/emitter/gyrotron/get_burst_delay()
- return rate*10
+ return rate SECONDS
+
+/obj/machinery/emitter/gyrotron/get_shot_delay()
+ return rate SECONDS
/obj/machinery/emitter/gyrotron/get_emitter_beam()
var/obj/item/projectile/beam/emitter/beam = ..()
diff --git a/code/modules/power/singularity/collector.dm b/code/modules/singularity/collector.dm
similarity index 100%
rename from code/modules/power/singularity/collector.dm
rename to code/modules/singularity/collector.dm
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/singularity/containment_field.dm
similarity index 100%
rename from code/modules/power/singularity/containment_field.dm
rename to code/modules/singularity/containment_field.dm
diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/singularity/field_generator.dm
similarity index 100%
rename from code/modules/power/singularity/field_generator.dm
rename to code/modules/singularity/field_generator.dm
diff --git a/code/modules/power/singularity/generator.dm b/code/modules/singularity/generator.dm
similarity index 100%
rename from code/modules/power/singularity/generator.dm
rename to code/modules/singularity/generator.dm
diff --git a/code/modules/power/singularity/particle_accelerator/particle.dm b/code/modules/singularity/particle_accelerator/particle.dm
similarity index 100%
rename from code/modules/power/singularity/particle_accelerator/particle.dm
rename to code/modules/singularity/particle_accelerator/particle.dm
diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/singularity/particle_accelerator/particle_accelerator.dm
similarity index 100%
rename from code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
rename to code/modules/singularity/particle_accelerator/particle_accelerator.dm
diff --git a/code/modules/power/singularity/particle_accelerator/particle_chamber.dm b/code/modules/singularity/particle_accelerator/particle_chamber.dm
similarity index 100%
rename from code/modules/power/singularity/particle_accelerator/particle_chamber.dm
rename to code/modules/singularity/particle_accelerator/particle_chamber.dm
diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/singularity/particle_accelerator/particle_control.dm
similarity index 100%
rename from code/modules/power/singularity/particle_accelerator/particle_control.dm
rename to code/modules/singularity/particle_accelerator/particle_control.dm
diff --git a/code/modules/power/singularity/particle_accelerator/particle_emitter.dm b/code/modules/singularity/particle_accelerator/particle_emitter.dm
similarity index 100%
rename from code/modules/power/singularity/particle_accelerator/particle_emitter.dm
rename to code/modules/singularity/particle_accelerator/particle_emitter.dm
diff --git a/code/modules/power/singularity/particle_accelerator/particle_power.dm b/code/modules/singularity/particle_accelerator/particle_power.dm
similarity index 100%
rename from code/modules/power/singularity/particle_accelerator/particle_power.dm
rename to code/modules/singularity/particle_accelerator/particle_power.dm
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/singularity/singularity.dm
similarity index 100%
rename from code/modules/power/singularity/singularity.dm
rename to code/modules/singularity/singularity.dm
diff --git a/code/modules/power/singularity/singularity_events.dm b/code/modules/singularity/singularity_events.dm
similarity index 100%
rename from code/modules/power/singularity/singularity_events.dm
rename to code/modules/singularity/singularity_events.dm
diff --git a/code/modules/power/singularity/singularity_stages.dm b/code/modules/singularity/singularity_stages.dm
similarity index 100%
rename from code/modules/power/singularity/singularity_stages.dm
rename to code/modules/singularity/singularity_stages.dm
diff --git a/maps/away/derelict/derelict-station.dmm b/maps/away/derelict/derelict-station.dmm
index 8943ba108f6c..327b778a2921 100644
--- a/maps/away/derelict/derelict-station.dmm
+++ b/maps/away/derelict/derelict-station.dmm
@@ -3321,10 +3321,8 @@
/turf/floor/plating/airless,
/area/AIsattele)
"lZ" = (
-/obj/machinery/emitter{
- anchored = 1;
- dir = 4;
- state = 2
+/obj/machinery/emitter/anchored{
+ dir = 4
},
/turf/floor/plating/airless,
/area/constructionsite/engineering)
@@ -3333,10 +3331,8 @@
/turf/floor/plating/airless,
/area/constructionsite/engineering)
"mb" = (
-/obj/machinery/emitter{
- anchored = 1;
- dir = 8;
- state = 2
+/obj/machinery/emitter/anchored{
+ dir = 8
},
/turf/floor/plating/airless,
/area/constructionsite/engineering)
diff --git a/maps/exodus/exodus-2.dmm b/maps/exodus/exodus-2.dmm
index 931f81211199..beecd85bba5d 100644
--- a/maps/exodus/exodus-2.dmm
+++ b/maps/exodus/exodus-2.dmm
@@ -61848,10 +61848,8 @@
/turf/floor/plating,
/area/exodus/engineering/engine_room)
"cIa" = (
-/obj/machinery/emitter{
- anchored = 1;
- id_tag = "EngineEmitter";
- state = 2
+/obj/machinery/emitter/anchored{
+ id_tag = "EngineEmitter"
},
/obj/structure/cable/cyan,
/obj/machinery/power/terminal{
diff --git a/maps/ministation/ministation-0.dmm b/maps/ministation/ministation-0.dmm
index e3f4b0c453f8..5441d9f8411c 100644
--- a/maps/ministation/ministation-0.dmm
+++ b/maps/ministation/ministation-0.dmm
@@ -11078,10 +11078,8 @@
/obj/machinery/power/terminal{
dir = 1
},
-/obj/machinery/emitter{
- anchored = 1;
- id_tag = "EngineEmitter";
- state = 2
+/obj/machinery/emitter/anchored{
+ id_tag = "EngineEmitter"
},
/obj/structure/cable,
/turf/floor/plating,
diff --git a/nebula.dme b/nebula.dme
index f904c51d0309..0113eccdcfa4 100644
--- a/nebula.dme
+++ b/nebula.dme
@@ -834,6 +834,7 @@
#include "code\game\machinery\dehumidifier.dm"
#include "code\game\machinery\deployable.dm"
#include "code\game\machinery\doppler_array.dm"
+#include "code\game\machinery\emitter.dm"
#include "code\game\machinery\flasher.dm"
#include "code\game\machinery\floodlight.dm"
#include "code\game\machinery\floor_light.dm"
@@ -886,6 +887,7 @@
#include "code\game\machinery\_machines_base\machine_construction\blast_doors.dm"
#include "code\game\machinery\_machines_base\machine_construction\computer.dm"
#include "code\game\machinery\_machines_base\machine_construction\default.dm"
+#include "code\game\machinery\_machines_base\machine_construction\emitter.dm"
#include "code\game\machinery\_machines_base\machine_construction\frame.dm"
#include "code\game\machinery\_machines_base\machine_construction\item_chassis.dm"
#include "code\game\machinery\_machines_base\machine_construction\noninteractive.dm"
@@ -3470,20 +3472,6 @@
#include "code\modules\power\cable\heavycable.dm"
#include "code\modules\power\cell\_cell.dm"
#include "code\modules\power\cell\cell_types.dm"
-#include "code\modules\power\singularity\collector.dm"
-#include "code\modules\power\singularity\containment_field.dm"
-#include "code\modules\power\singularity\emitter.dm"
-#include "code\modules\power\singularity\field_generator.dm"
-#include "code\modules\power\singularity\generator.dm"
-#include "code\modules\power\singularity\singularity.dm"
-#include "code\modules\power\singularity\singularity_events.dm"
-#include "code\modules\power\singularity\singularity_stages.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_accelerator.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_chamber.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_control.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_power.dm"
#include "code\modules\power\solar\solar_control.dm"
#include "code\modules\power\solar\solar_panel.dm"
#include "code\modules\power\solar\tracker.dm"
@@ -3805,6 +3793,19 @@
#include "code\modules\shuttles\shuttle_specops.dm"
#include "code\modules\shuttles\shuttle_supply.dm"
#include "code\modules\shuttles\shuttles_multi.dm"
+#include "code\modules\singularity\collector.dm"
+#include "code\modules\singularity\containment_field.dm"
+#include "code\modules\singularity\field_generator.dm"
+#include "code\modules\singularity\generator.dm"
+#include "code\modules\singularity\singularity.dm"
+#include "code\modules\singularity\singularity_events.dm"
+#include "code\modules\singularity\singularity_stages.dm"
+#include "code\modules\singularity\particle_accelerator\particle.dm"
+#include "code\modules\singularity\particle_accelerator\particle_accelerator.dm"
+#include "code\modules\singularity\particle_accelerator\particle_chamber.dm"
+#include "code\modules\singularity\particle_accelerator\particle_control.dm"
+#include "code\modules\singularity\particle_accelerator\particle_emitter.dm"
+#include "code\modules\singularity\particle_accelerator\particle_power.dm"
#include "code\modules\smes\_smes.dm"
#include "code\modules\smes\smes_buildable.dm"
#include "code\modules\smes\smes_circuit.dm"
diff --git a/tools/map_migrations/5401_emitter_construct_state.txt b/tools/map_migrations/5401_emitter_construct_state.txt
new file mode 100644
index 000000000000..8ce764621f54
--- /dev/null
+++ b/tools/map_migrations/5401_emitter_construct_state.txt
@@ -0,0 +1,8 @@
+# emitters use construct states instead of a bespoke state var
+# handle redundant var sets if present
+/obj/machinery/emitter/anchored{state = 2} : @OLD{@OLD; state = @SKIP; anchored = @SKIP}
+/obj/machinery/emitter/gyrotron/anchored{state = 2} : @OLD{@OLD; state = @SKIP; anchored = @SKIP}
+# remove state/anchored vars, change subtype if needed
+/obj/machinery/emitter/@SUBTYPES{state = 2} : /obj/machinery/emitter/@SUBTYPES/anchored{@OLD; state = @SKIP; anchored = @SKIP}
+/obj/machinery/emitter/@SUBTYPES{state = 1} : /obj/machinery/emitter/@SUBTYPES{@OLD; state = @SKIP; anchored = @SKIP}
+/obj/machinery/emitter/@SUBTYPES{state = 0} : /obj/machinery/emitter/@SUBTYPES{@OLD; state = @SKIP; anchored = @SKIP}