From 9459c2d9d6e027c6583176da0b1893d73b7bffce Mon Sep 17 00:00:00 2001
From: QuiteLiterallyAnything
<154708292+QuiteLiterallyAnything@users.noreply.github.com>
Date: Mon, 13 Jul 2026 21:56:18 -0500
Subject: [PATCH] Adds charge checking interactions to ethereals (#96904)
## About The Pull Request
This PR adjusts the ethereal stomach equivalent (biological batteries)
such that they provide their charge whenever either they or their mob
owner get hit by a multitool. This is formatted in the exact same way as
seen when multitooling a cable. A tip of the round indicates that this
is possible.
Additionally, health analyzers will show stomach charge as well. While
coding this I made a couple of slight adjustments to the nearby blood
level formatting for spelling and a (sometimes) stray comma. In effect
this makes it go from displaying "Blood level: 100%, 560 cl, type:
O+" to "Blood level: 100%, 560 cl O+" (with the
underlining being a tooltip).
## Why It's Good For The Game
To my knowledge, there is currently no way to get the exact and
quantified charge of an ethereal. This makes it difficult for anyone
healing an ethereal to definitively tell whether toxins damage is from a
lack/excess of charge or some other source.
Aside from that, it's also just mildly comedic to be able to check the
charge of a living entity in the exact same way as a piece of insulated
copper.
## Changelog
:cl:
add: Health analyzers now display ethereal charge.
add: It is also possible to check the charge of an ethereal (or their
stomach equivalent) with a multitool.
/:cl:
---
.../items/devices/scanners/health_analyzer.dm | 29 ++++++++++++++++---
.../internal/stomach/stomach_ethereal.dm | 20 +++++++++++++
strings/tips.txt | 1 +
3 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm
index 894f20c1534..1f75ec1b4d7 100644
--- a/code/game/objects/items/devices/scanners/health_analyzer.dm
+++ b/code/game/objects/items/devices/scanners/health_analyzer.dm
@@ -389,22 +389,22 @@
if (blood_type.restoration_chem == /datum/reagent/iron)
recommendation += "[/datum/reagent/medicine/salglu_solution::name]"
if (length(recommendation))
- recommendation += "[blood_type.get_blood_name()] transufion"
+ recommendation += "[blood_type.get_blood_name()] transfusion"
else
- recommendation += "immediate [blood_type.get_blood_name()] transufion"
+ recommendation += "immediate [blood_type.get_blood_name()] transfusion"
level_format = conditional_tooltip(level_format, "Recommendation: [english_list(recommendation, and_text = " or ")].", tochat)
else
level_format = "[blood_percent]%, [cached_blood_volume] cl"
if (blood_type.get_type())
- blood_type_format = "type: [blood_type.get_type()]"
+ blood_type_format = "[blood_type.get_type()]"
if(tochat && length(blood_type.compatible_types))
var/list/compatible_types_readable = list()
for(var/datum/blood_type/comp_blood_type as anything in blood_type.compatible_types)
compatible_types_readable |= initial(comp_blood_type.name)
blood_type_format = span_tooltip("Can receive from types [english_list(compatible_types_readable)].", blood_type_format)
- render_list += "[blood_type.get_blood_name()] level: [level_format], [blood_type_format]
"
+ render_list += "[blood_type.get_blood_name()] level: [level_format] [blood_type_format]
"
var/blood_alcohol_content = target.get_blood_alcohol_content()
if(blood_alcohol_content > 0)
@@ -414,6 +414,27 @@
else
render_list += "[blood_type?.get_blood_name() || "Blood"] alcohol content: [blood_alcohol_content]%
"
+ // Ethereal Charge
+ if(istype(target.get_organ_slot(ORGAN_SLOT_STOMACH), /obj/item/organ/stomach/ethereal))
+ var/obj/item/organ/stomach/ethereal/battery_stomach = target.get_organ_slot(ORGAN_SLOT_STOMACH)
+ var/charge = battery_stomach.cell.charge
+ var/charge_dangerous = charge > ETHEREAL_CHARGE_FULL || charge < ETHEREAL_CHARGE_LOWPOWER
+ var/charge_format = "[display_power(charge)] / [display_power(ETHEREAL_CHARGE_FULL)]"
+
+ if(charge_dangerous)
+ var/recommendation = "Recommendation: "
+ switch(charge)
+ if(-INFINITY to ETHEREAL_CHARGE_LOWPOWER)
+ recommendation += "charging by LE-fortified food"
+ if(ETHEREAL_CHARGE_FULL to ETHEREAL_CHARGE_OVERLOAD)
+ recommendation += "discharge into nearest undercapacity APC"
+ if(ETHEREAL_CHARGE_OVERLOAD to ETHEREAL_CHARGE_DANGEROUS)
+ recommendation += "preparation for violent electrocardiac discharge event"
+ recommendation = uppertext(recommendation)
+ charge_format = span_tooltip("[recommendation] followed with toxins treatment.", charge_format)
+
+ render_list += "Electrical charge: [charge_format]
"
+
//Diseases
var/disease_hr = FALSE
for(var/datum/disease/disease as anything in target.diseases)
diff --git a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm
index aea5173ae86..6255b5dec3d 100644
--- a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm
+++ b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm
@@ -25,11 +25,13 @@
. = ..()
RegisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(charge))
RegisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT, PROC_REF(on_electrocute))
+ RegisterSignal(stomach_owner, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(on_multitool_act))
/obj/item/organ/stomach/ethereal/on_mob_remove(mob/living/carbon/stomach_owner)
. = ..()
UnregisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT)
UnregisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT)
+ UnregisterSignal(stomach_owner, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL))
stomach_owner.clear_mood_event("charge")
stomach_owner.clear_alert(ALERT_ETHEREAL_CHARGE)
stomach_owner.clear_alert(ALERT_ETHEREAL_OVERCHARGE)
@@ -49,6 +51,24 @@
adjust_charge(shock_damage * siemens_coeff * 2)
to_chat(owner, span_notice("You absorb some of the shock into your body!"))
+/obj/item/organ/stomach/ethereal/proc/on_multitool_act(atom/source, mob/user, obj/item/tool)
+ SIGNAL_HANDLER
+
+ return multitool_act(user, tool)
+
+/obj/item/organ/stomach/ethereal/multitool_act(mob/living/user, obj/item/tool)
+ . = ..()
+ // Intentionally formatted in the exact same way as multitooling a cable for comedic effect.
+ // It's as if the multitool is mistaking the ethereal/biological battery for a cable.
+ var/power_info
+ if(cell.charge > 0)
+ power_info = span_danger("Total power: [display_power(cell.charge)]\nLoad: [(owner && (owner.stat != DEAD)) ? display_power(ETHEREAL_DISCHARGE_RATE) : 0]\nExcess power: [display_power(max(0, (cell.charge - ETHEREAL_CHARGE_FULL)))]")
+ else
+ power_info = span_danger("The [owner ? owner.name : name] is not powered.")
+
+ to_chat(user, power_info)
+ return ITEM_INTERACT_SUCCESS
+
/**Changes the energy of the crystal stomach.
* Args:
* - amount: The change of the energy, in joules.
diff --git a/strings/tips.txt b/strings/tips.txt
index 7b7137fa0b2..84e366ffb5b 100644
--- a/strings/tips.txt
+++ b/strings/tips.txt
@@ -325,6 +325,7 @@ You can use :I / .I to speak through any intercom within arm's reach. This allow
You can use :L / .L or :R / .R to speak through an item being held in your left or right hand respectively. This allows you to talk into a station-bounced radio without manually turning on its microphone, or even to pretend to be a toy!
You can use a machine in the vault to deposit cash or rob Cargo's department funds.
You can use a multitool in your hand to track the area's local APC.
+You can use a multitool on an ethereal to check their charge!
You can use a screwdriver to remove an encryption key from a radio headset. The key can then be installed into your own headset, an intercom, or even a station-bounced radio, allowing you to eavesdrop on secure communications.
You can use an upgraded microwave to charge your PDA!
You don't need to destroy a Spacecoin machine to make your funds stop draining. Swiping your ID on it will stop the withdrawal.