diff --git a/code/modules/heavy_vehicle/_mech_setup.dm b/code/modules/heavy_vehicle/_mech_setup.dm
index 0e870814e52..2b1f8ade590 100644
--- a/code/modules/heavy_vehicle/_mech_setup.dm
+++ b/code/modules/heavy_vehicle/_mech_setup.dm
@@ -35,4 +35,9 @@ var/global/list/mecha_damage_overlay_cache = list()
#define FRAME_REINFORCED_WELDED 3
#define FRAME_WIRED 1
-#define FRAME_WIRED_ADJUSTED 2
\ No newline at end of file
+#define FRAME_WIRED_ADJUSTED 2
+
+//POWER!
+#define MECH_POWER_OFF 0
+#define MECH_POWER_TRANSITION 1
+#define MECH_POWER_ON 2
\ No newline at end of file
diff --git a/code/modules/heavy_vehicle/components/head.dm b/code/modules/heavy_vehicle/components/head.dm
index 2148b199758..318deebfa68 100644
--- a/code/modules/heavy_vehicle/components/head.dm
+++ b/code/modules/heavy_vehicle/components/head.dm
@@ -62,18 +62,18 @@
camera = locate() in src
software = locate() in src
-/obj/item/mech_component/sensors/proc/get_sight()
+/obj/item/mech_component/sensors/proc/get_sight(powered)
var/flags = 0
- if(total_damage >= 0.8 * max_damage)
+ if((total_damage >= 0.8 * max_damage) || !powered)
flags |= BLIND
- else if(active_sensors)
+ else if(active_sensors && powered)
flags |= vision_flags
return flags
-/obj/item/mech_component/sensors/proc/get_invisible()
+/obj/item/mech_component/sensors/proc/get_invisible(powered)
var/invisible = 0
- if((total_damage <= 0.8 * max_damage) && active_sensors)
+ if((total_damage <= 0.8 * max_damage) && active_sensors && powered)
invisible = see_invisible
return invisible
diff --git a/code/modules/heavy_vehicle/equipment/_equipment.dm b/code/modules/heavy_vehicle/equipment/_equipment.dm
index 632804a5640..385fd0ef662 100644
--- a/code/modules/heavy_vehicle/equipment/_equipment.dm
+++ b/code/modules/heavy_vehicle/equipment/_equipment.dm
@@ -15,6 +15,7 @@
var/passive_power_use = 0
var/active_power_use = 1 KILOWATTS
var/require_adjacent = TRUE
+ var/active = FALSE //For gear that has an active state (ie, floodlights)
/obj/item/mecha_equipment/examine(mob/user, distance)
. = ..()
@@ -59,12 +60,18 @@
else
return 0
+/obj/item/mecha_equipment/proc/deactivate()
+ active = FALSE
+ return
+
/obj/item/mecha_equipment/proc/installed(var/mob/living/heavy_vehicle/_owner)
owner = _owner
//generally attached. Nothing should be able to grab it
canremove = FALSE
/obj/item/mecha_equipment/proc/uninstalled()
+ if(active)
+ deactivate()
owner = null
canremove = TRUE
diff --git a/code/modules/heavy_vehicle/equipment/combat.dm b/code/modules/heavy_vehicle/equipment/combat.dm
index 50c0fe6d56a..78b30d161ce 100644
--- a/code/modules/heavy_vehicle/equipment/combat.dm
+++ b/code/modules/heavy_vehicle/equipment/combat.dm
@@ -295,8 +295,15 @@
START_PROCESSING(SSprocessing, src)
else
STOP_PROCESSING(SSprocessing, src)
+ active = aura.active
+ passive_power_use = active ? 1 KILOWATTS : 0
owner.update_icon()
+/obj/item/mecha_equipment/shield/deactivate()
+ if(active)
+ toggle()
+ ..()
+
/obj/item/mecha_equipment/shield/update_icon()
. = ..()
if(!aura)
@@ -314,7 +321,8 @@
var/obj/item/cell/cell = owner.get_cell()
var/actual_required_power = Clamp(max_charge - charge, 0, charging_rate)
- charge += cell.use(actual_required_power)
+ if(cell)
+ charge += cell.use(actual_required_power)
/obj/item/mecha_equipment/shield/get_hardpoint_status_value()
return charge / max_charge
diff --git a/code/modules/heavy_vehicle/equipment/utility.dm b/code/modules/heavy_vehicle/equipment/utility.dm
index 051a2764cd0..2ef3113ac4c 100644
--- a/code/modules/heavy_vehicle/equipment/utility.dm
+++ b/code/modules/heavy_vehicle/equipment/utility.dm
@@ -202,10 +202,20 @@
/obj/item/mecha_equipment/light/attack_self(var/mob/user)
. = ..()
if(.)
- on = !on
+ toggle()
to_chat(user, "You switch \the [src] [on ? "on" : "off"].")
- update_icon()
- owner.update_icon()
+
+/obj/item/mecha_equipment/light/proc/toggle()
+ on = !on
+ update_icon()
+ owner.update_icon()
+ active = on
+ passive_power_use = on ? 0.1 KILOWATTS : 0
+
+/obj/item/mecha_equipment/light/deactivate()
+ if(on)
+ toggle()
+ ..()
/obj/item/mecha_equipment/light/update_icon()
if(on)
diff --git a/code/modules/heavy_vehicle/interface/_interface.dm b/code/modules/heavy_vehicle/interface/_interface.dm
index 4d2f116405a..109a15bdb10 100644
--- a/code/modules/heavy_vehicle/interface/_interface.dm
+++ b/code/modules/heavy_vehicle/interface/_interface.dm
@@ -21,6 +21,7 @@
i++
var/list/additional_hud_elements = list(
+ /obj/screen/mecha/toggle/power_control,
/obj/screen/mecha/toggle/maint,
/obj/screen/mecha/eject,
/obj/screen/mecha/toggle/hardpoint,
@@ -55,6 +56,7 @@
hud_power = new /obj/screen/mecha/power(src)
hud_power.screen_loc = "EAST-1:12,CENTER-4:25"
hud_elements |= hud_power
+ hud_power_control = locate(/obj/screen/mecha/toggle/power_control) in hud_elements
refresh_hud()
diff --git a/code/modules/heavy_vehicle/interface/screen_objects.dm b/code/modules/heavy_vehicle/interface/screen_objects.dm
index b51cb504535..21bfecf3869 100644
--- a/code/modules/heavy_vehicle/interface/screen_objects.dm
+++ b/code/modules/heavy_vehicle/interface/screen_objects.dm
@@ -69,6 +69,7 @@
var/list/new_overlays = list()
if(!owner.get_cell() || (owner.get_cell().charge <= 0))
overlays.Cut()
+ maptext = ""
return
maptext = "[holding.get_hardpoint_maptext()]"
@@ -223,6 +224,23 @@
maptext = "MAINT"
notify_user(usr, SPAN_NOTICE("Maintenance protocols [owner.maintenance_protocols ? "enabled" : "disabled"]."))
+/obj/screen/mecha/toggle/power_control
+ name = "power control"
+ icon_state = "large_base"
+ maptext = "POWER"
+ maptext_x = 1
+ maptext_y = 11
+
+/obj/screen/mecha/toggle/power_control/toggled()
+ toggled = !toggled
+ owner.toggle_power(usr)
+ var/main_color = toggled ? "#d1d1d1" : "#525252"
+ maptext = "POWER"
+
+/obj/screen/mecha/toggle/power_control/update_icon()
+ toggled = (owner.power == MECH_POWER_ON)
+ return ..()
+
/obj/screen/mecha/toggle/hardpoint
name = "toggle hardpoint lock"
icon_state = "base"
diff --git a/code/modules/heavy_vehicle/mech_interaction.dm b/code/modules/heavy_vehicle/mech_interaction.dm
index 8ddd6fc7045..b0087494f9c 100644
--- a/code/modules/heavy_vehicle/mech_interaction.dm
+++ b/code/modules/heavy_vehicle/mech_interaction.dm
@@ -76,7 +76,8 @@
return
if(!(get_cell()?.checked_use(arms.power_use * CELLRATE)))
- to_chat(user, "Error: Power levels insufficient.")
+ to_chat(user, power == MECH_POWER_ON ? SPAN_WARNING("Error: Power levels insufficient.") : SPAN_WARNING("\The [src] is powered off."))
+ return
if(user != src)
set_intent(user.a_intent)
@@ -236,7 +237,6 @@
LAZYDISTINCTADD(pilots, user)
sync_access()
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
- user << sound('sound/mecha/nominal.ogg',volume=50)
if(user.client) user.client.screen |= hud_elements
LAZYDISTINCTADD(user.additional_vision_handlers, src)
update_icon()
@@ -426,6 +426,8 @@
to_chat(user, "You remove \the [body.cell] from \the [src].")
playsound(user.loc, thing.usesound, 50, 1)
visible_message("\The [user] pries out \the [body.cell] using the \the [thing].")
+ power = MECH_POWER_OFF
+ hud_power_control.update_icon()
body.cell = null
return
else if(istype(thing, /obj/item/cell))
diff --git a/code/modules/heavy_vehicle/mech_life.dm b/code/modules/heavy_vehicle/mech_life.dm
index e7e22b28e4f..cfd6e07b10d 100644
--- a/code/modules/heavy_vehicle/mech_life.dm
+++ b/code/modules/heavy_vehicle/mech_life.dm
@@ -21,15 +21,25 @@
UNSETEMPTY(pilots)
if(radio)
- radio.on = (head?.radio && head.radio.is_functional())
+ radio.on = (head?.radio && head.radio.is_functional() && get_cell())
if(camera)
camera.status = (head?.camera && head.camera.is_functional())
body.update_air(hatch_closed && use_air)
- if((client || LAZYLEN(pilots)) && get_cell())
- get_cell()?.drain_power(0, 0, calc_power_draw())
+ var/powered = FALSE
+ if(get_cell())
+ powered = get_cell().drain_power(0, 0, calc_power_draw()) > 0
+
+ if(!powered)
+ //Shut down all systems
+ if(head)
+ head.active_sensors = FALSE
+ for(var/hardpoint in hardpoints)
+ var/obj/item/mecha_equipment/M = hardpoints[hardpoint]
+ if(istype(M) && M.active && M.passive_power_use)
+ M.deactivate()
updatehealth()
if(health <= 0 && stat != DEAD)
@@ -38,7 +48,7 @@
..()
lying = 0 // Fuck off, carp.
- handle_vision()
+ handle_vision(powered)
handle_hud_icons()
/mob/living/heavy_vehicle/think()
@@ -60,9 +70,11 @@
else
walk(src, 0) // this stops them from moving
-/mob/living/heavy_vehicle/get_cell()
+/mob/living/heavy_vehicle/get_cell(force)
RETURN_TYPE(/obj/item/cell)
- return body?.cell
+ if(power == MECH_POWER_ON || force) //For most intents we can assume that a powered off exosuit acts as if it lacked a cell
+ return body ? body.cell : null
+ return null
/mob/living/heavy_vehicle/proc/calc_power_draw()
var/total_draw = 0
@@ -147,13 +159,18 @@
qdel(src)
return
-/mob/living/heavy_vehicle/handle_vision()
+/mob/living/heavy_vehicle/handle_vision(powered)
+ var/was_blind = sight & BLIND
if(head)
- sight = head.get_sight()
- see_invisible = head.get_invisible()
- if(body && (body.pilot_coverage < 100 || body.transparent_cabin))
+ sight = head.get_sight(powered)
+ see_invisible = head.get_invisible(powered)
+ if(!hatch_closed || (body && (body.pilot_coverage < 100 || body.transparent_cabin)))
sight &= ~BLIND
+ if(sight & BLIND && !was_blind)
+ for(var/mob/pilot in pilots)
+ to_chat(pilot, SPAN_WARNING("The camera sensors flicker out and you lose sight of the outside world!"))
+
/mob/living/heavy_vehicle/additional_sight_flags()
return sight
diff --git a/code/modules/heavy_vehicle/mecha.dm b/code/modules/heavy_vehicle/mecha.dm
index 79b3e0fd624..6b357750585 100644
--- a/code/modules/heavy_vehicle/mecha.dm
+++ b/code/modules/heavy_vehicle/mecha.dm
@@ -85,6 +85,9 @@
var/obj/screen/mecha/health/hud_health
var/obj/screen/mecha/toggle/hatch_open/hud_open
var/obj/screen/mecha/power/hud_power
+ var/obj/screen/mecha/toggle/power_control/hud_power_control
+ //POWER
+ var/power = MECH_POWER_OFF
/mob/living/heavy_vehicle/Destroy()
unassign_leader()
@@ -229,6 +232,26 @@
/mob/living/heavy_vehicle/GetIdCard()
return access_card
+/mob/living/heavy_vehicle/proc/toggle_power(var/mob/user)
+ if(power == MECH_POWER_TRANSITION)
+ to_chat(user, SPAN_NOTICE("Power transition in progress. Please wait."))
+ else if(power == MECH_POWER_ON) //Turning it off is instant
+ playsound(src, 'sound/mecha/mech-shutdown.ogg', 100, 0)
+ power = MECH_POWER_OFF
+ else if(get_cell(TRUE))
+ //Start power up sequence
+ power = MECH_POWER_TRANSITION
+ playsound(src, 'sound/mecha/powerup.ogg', 50, 0)
+ if(do_after(user, 1.5 SECONDS) && power == MECH_POWER_TRANSITION)
+ playsound(src, 'sound/mecha/nominal.ogg', 50, 0)
+ power = MECH_POWER_ON
+ else
+ to_chat(user, SPAN_WARNING("You abort the powerup sequence."))
+ power = MECH_POWER_OFF
+ hud_power_control?.queue_icon_update()
+ else
+ to_chat(user, SPAN_WARNING("Error: No power cell was detected."))
+
/obj/item/device/radio/exosuit
name = "exosuit radio"
cell = null
diff --git a/html/changelogs/geeves-mech_power_states.yml b/html/changelogs/geeves-mech_power_states.yml
new file mode 100644
index 00000000000..966481de284
--- /dev/null
+++ b/html/changelogs/geeves-mech_power_states.yml
@@ -0,0 +1,7 @@
+author: Geeves
+
+delete-after: True
+
+changes:
+ - rscadd: "Added the ability to turn off exosuits. This counts as physically disconnecting the power cell, it will no longer drain, but it will also no longer charge."
+ - tweak: "Exosuits with open hatches will no longer cause blindness if the camera system goes down."
\ No newline at end of file
diff --git a/sound/mecha/mech-shutdown.ogg b/sound/mecha/mech-shutdown.ogg
new file mode 100644
index 00000000000..9733bb26df5
Binary files /dev/null and b/sound/mecha/mech-shutdown.ogg differ