diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
index 0839f8f5909..c5eaade7051 100644
--- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
@@ -9,6 +9,10 @@
#define COMSIG_MOB_LOGOUT "mob_logout"
///from base of mob/set_stat(): (new_stat, old_stat)
#define COMSIG_MOB_STATCHANGE "mob_statchange"
+///from base of mob/reagent_check(): (datum/reagent/chem, seconds_per_tick, times_fired)
+#define COMSIG_MOB_REAGENT_CHECK "mob_reagent_check"
+ ///stops the reagent check call
+ #define COMSIG_MOB_STOP_REAGENT_CHECK (1<<0)
///from base of mob/clickon(): (atom/A, params)
#define COMSIG_MOB_CLICKON "mob_clickon"
///from base of mob/MiddleClickOn(): (atom/A)
diff --git a/code/__DEFINES/dcs/signals/signals_specie.dm b/code/__DEFINES/dcs/signals/signals_species.dm
similarity index 52%
rename from code/__DEFINES/dcs/signals/signals_specie.dm
rename to code/__DEFINES/dcs/signals/signals_species.dm
index ab28febbb2c..ee5cc33ba35 100644
--- a/code/__DEFINES/dcs/signals/signals_specie.dm
+++ b/code/__DEFINES/dcs/signals/signals_species.dm
@@ -3,3 +3,6 @@
#define COMSIG_SPECIES_GAIN "species_gain"
///from datum/species/on_species_loss(): (datum/species/lost_species)
#define COMSIG_SPECIES_LOSS "species_loss"
+///from datum/species/handle_chemical(): (datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
+#define COMSIG_SPECIES_HANDLE_CHEMICAL "species_handle_chemicals"
+ // same return values as COMSIG_MOB_STOP_REAGENT_CHECK
diff --git a/code/datums/components/food/golem_food.dm b/code/datums/components/food/golem_food.dm
index 818bb555a38..e6b6fbbf4c3 100644
--- a/code/datums/components/food/golem_food.dm
+++ b/code/datums/components/food/golem_food.dm
@@ -43,7 +43,7 @@
source.balloon_alert(user, "not edible!")
return COMPONENT_CANCEL_ATTACK_CHAIN
if (!snack_type.can_consume(target))
- source.balloon_alert(user, "incompatible mineral!")
+ source.balloon_alert(user, "can't consume!")
return COMPONENT_CANCEL_ATTACK_CHAIN
if (!golem_snack)
golem_snack = new(
diff --git a/code/datums/mutations/_mutations.dm b/code/datums/mutations/_mutations.dm
index 0226326165c..9ea3c8dfb17 100644
--- a/code/datums/mutations/_mutations.dm
+++ b/code/datums/mutations/_mutations.dm
@@ -1,5 +1,4 @@
/datum/mutation
-
var/name
/datum/mutation/human
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 48d72c665c6..639586b2974 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -66,9 +66,6 @@
else
clear_alert(ALERT_XENO_FIRE)
-/mob/living/carbon/alien/reagent_check(datum/reagent/R, seconds_per_tick, times_fired) //can metabolize all reagents
- return FALSE
-
/mob/living/carbon/alien/getTrail()
if(getBruteLoss() < 200)
return pick (list("xltrails_1", "xltrails2"))
diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm
index 83ca1cac0e8..b4bf93d252d 100644
--- a/code/modules/mob/living/carbon/human/_species.dm
+++ b/code/modules/mob/living/carbon/human/_species.dm
@@ -830,7 +830,10 @@ GLOBAL_LIST_EMPTY(features_by_species)
return
/datum/species/proc/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired)
- if(HAS_TRAIT(H, TRAIT_NOBREATH) && H.stat != DEAD && (H.health < H.crit_threshold) && !HAS_TRAIT(H, TRAIT_NOCRITDAMAGE))
+ SHOULD_CALL_PARENT(TRUE)
+ if(H.stat == DEAD)
+ return
+ if(HAS_TRAIT(H, TRAIT_NOBREATH) && (H.health < H.crit_threshold) && !HAS_TRAIT(H, TRAIT_NOCRITDAMAGE))
H.adjustBruteLoss(0.5 * seconds_per_tick)
/datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H)
@@ -998,22 +1001,24 @@ GLOBAL_LIST_EMPTY(features_by_species)
return
/**
- * Handling special reagent types.
+ * Handling special reagent interactions.
*
- * Return False to run the normal on_mob_life() for that reagent.
- * Return True to not run the normal metabolism effects.
- * NOTE: If you return TRUE, that reagent will not be removed liike normal! You must handle it manually.
- */
-/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
+ * Return null continue running the normal on_mob_life() for that reagent.
+ * Return COMSIG_MOB_STOP_REAGENT_CHECK to not run the normal metabolism effects.
+ *
+ * NOTE: If you return COMSIG_MOB_STOP_REAGENT_CHECK, that reagent will not be removed liike normal! You must handle it manually.
+ **/
+/datum/species/proc/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
SHOULD_CALL_PARENT(TRUE)
if(chem.type == exotic_blood)
- H.blood_volume = min(H.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM)
- H.reagents.del_reagent(chem.type)
- return TRUE
+ affected.blood_volume = min(affected.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM)
+ affected.reagents.del_reagent(chem.type)
+ return COMSIG_MOB_STOP_REAGENT_CHECK
if(!chem.overdosed && chem.overdose_threshold && chem.volume >= chem.overdose_threshold)
chem.overdosed = TRUE
- chem.overdose_start(H)
- H.log_message("has started overdosing on [chem.name] at [chem.volume] units.", LOG_GAME)
+ chem.overdose_start(affected)
+ affected.log_message("has started overdosing on [chem.name] at [chem.volume] units.", LOG_GAME)
+ return SEND_SIGNAL(affected, COMSIG_SPECIES_HANDLE_CHEMICAL, chem, affected, seconds_per_tick, times_fired)
/datum/species/proc/check_species_weakness(obj/item, mob/living/attacker)
return 1 //This is not a boolean, it's the multiplier for the damage that the user takes from the item. The force of the item is multiplied by this value
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b5a7ff45b75..b4cf3010e4f 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -921,6 +921,12 @@
return ..()
+/mob/living/carbon/human/reagent_check(datum/reagent/chem, seconds_per_tick, times_fired)
+ . = ..()
+ if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
+ return
+ return dna.species.handle_chemical(chem, src, seconds_per_tick, times_fired)
+
/mob/living/carbon/human/updatehealth()
. = ..()
dna?.species.spec_updatehealth(src)
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 7a0ade3707a..5aa79eee0b4 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -110,10 +110,6 @@
//Check inventory slots
return (wear_id?.GetID() || belt?.GetID())
-/mob/living/carbon/human/reagent_check(datum/reagent/R, seconds_per_tick, times_fired)
- return dna.species.handle_chemicals(R, src, seconds_per_tick, times_fired)
- // if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species.
-
/mob/living/carbon/human/can_use_guns(obj/item/G)
. = ..()
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 18033f79479..8c7c8fd61f7 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -28,22 +28,20 @@
//Body temperature stability and damage
dna.species.handle_body_temperature(src, seconds_per_tick, times_fired)
-
if(!IS_IN_STASIS(src))
- if(.) //not dead
-
- for(var/datum/mutation/human/HM in dna.mutations) // Handle active genes
- HM.on_life(seconds_per_tick, times_fired)
-
if(stat != DEAD)
+ //handle active mutations
+ for(var/datum/mutation/human/human_mutation as anything in dna.mutations)
+ human_mutation.on_life(seconds_per_tick, times_fired)
//heart attack stuff
handle_heart(seconds_per_tick, times_fired)
+ //handles liver failure effects, if we lack a liver
handle_liver(seconds_per_tick, times_fired)
- dna.species.spec_life(src, seconds_per_tick, times_fired) // for mutantraces
+ // for special species interactions
+ dna.species.spec_life(src, seconds_per_tick, times_fired)
else
- for(var/i in all_wounds)
- var/datum/wound/iter_wound = i
+ for(var/datum/wound/iter_wound as anything in all_wounds)
iter_wound.on_stasis(seconds_per_tick, times_fired)
//Update our name based on whether our face is obscured/disfigured
diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
index fff80507fe0..9550c8c4e05 100644
--- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
@@ -71,6 +71,7 @@
human.reset_perspective(human)
/datum/species/dullahan/spec_life(mob/living/carbon/human/human, seconds_per_tick, times_fired)
+ . = ..()
if(QDELETED(my_head))
my_head = null
human.investigate_log("has been gibbed by the loss of [human.p_their()] head.", INVESTIGATE_DEATHS)
diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm
index 6989eabe3a4..6afacb454f1 100644
--- a/code/modules/mob/living/carbon/human/species_types/felinid.dm
+++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm
@@ -22,13 +22,14 @@
examine_limb_id = SPECIES_HUMAN
// Prevents felinids from taking toxin damage from carpotoxin
-/datum/species/human/felinid/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
+/datum/species/human/felinid/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
. = ..()
+ if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
+ return
if(istype(chem, /datum/reagent/toxin/carpotoxin))
var/datum/reagent/toxin/carpotoxin/fish = chem
fish.toxpwr = 0
-
/datum/species/human/felinid/on_species_gain(mob/living/carbon/carbon_being, datum/species/old_species, pref_load)
if(ishuman(carbon_being))
var/mob/living/carbon/human/target_human = carbon_being
diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
index 5d76627aeb5..de5716ed6e1 100644
--- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
@@ -35,12 +35,12 @@
BODY_ZONE_CHEST = /obj/item/bodypart/chest/fly,
)
-/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
+/datum/species/fly/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
+ . = ..()
+ if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
+ return
if(chem.type == /datum/reagent/toxin/pestkiller)
- H.adjustToxLoss(3 * REM * seconds_per_tick)
- H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick)
- return TRUE
- return ..()
+ affected.adjustToxLoss(3 * REM * seconds_per_tick)
/datum/species/fly/check_species_weakness(obj/item/weapon, mob/living/attacker)
if(istype(weapon, /obj/item/melee/flyswatter))
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 1d7ea3d0c21..381dd51d714 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -39,6 +39,7 @@
mutantbrain = /obj/item/organ/internal/brain/golem
mutanttongue = /obj/item/organ/internal/tongue/golem
mutantstomach = /obj/item/organ/internal/stomach/golem
+ mutantliver = /obj/item/organ/internal/liver/golem
mutantappendix = /obj/item/organ/internal/appendix/golem
bodypart_overrides = list(
BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/golem,
@@ -94,10 +95,3 @@
))
return to_add
-
-/// Remove nutrient value from non-mineral food, wish this was on an organ and not species but such is life
-/datum/species/golem/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, delta_time, times_fired)
- if(istype(chem, /datum/reagent/consumable) && !istype(chem, /datum/reagent/consumable/nutriment/mineral))
- var/datum/reagent/consumable/yummy_chem = chem
- yummy_chem.nutriment_factor = 0
- return ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index c96a8e3e4e1..e4aae3fb56c 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -67,6 +67,7 @@
return ..()
/datum/species/jelly/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired)
+ . = ..()
if(H.stat == DEAD) //can't farm slime jelly from a dead slime/jelly person indefinitely
return
@@ -240,6 +241,7 @@
bodies = old_species.bodies
/datum/species/jelly/slime/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired)
+ . = ..()
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
if(SPT_PROB(2.5, seconds_per_tick))
to_chat(H, span_notice("You feel very bloated!"))
@@ -249,8 +251,6 @@
if(H.blood_volume <= BLOOD_VOLUME_LOSE_NUTRITION)
H.adjust_nutrition(-1.25 * seconds_per_tick)
- ..()
-
/datum/action/innate/split_body
name = "Split Body"
check_flags = AB_CHECK_CONSCIOUS
diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm
index be33d8dd553..f3d36e27be7 100644
--- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm
@@ -51,11 +51,12 @@
return randname
-/datum/species/moth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
+/datum/species/moth/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
. = ..()
+ if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
+ return
if(chem.type == /datum/reagent/toxin/pestkiller)
- H.adjustToxLoss(3 * REM * seconds_per_tick)
- H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick)
+ affected.adjustToxLoss(3 * REM * seconds_per_tick)
/datum/species/moth/check_species_weakness(obj/item/weapon, mob/living/attacker)
if(istype(weapon, /obj/item/melee/flyswatter))
diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
index 93d7eee8a1e..40437bcff3c 100644
--- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
@@ -57,13 +57,13 @@
mush.remove(C)
QDEL_NULL(mush)
-/datum/species/mush/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
+/datum/species/mush/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
+ . = ..()
+ if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
+ return
if(chem.type == /datum/reagent/toxin/plantbgone/weedkiller)
- H.adjustToxLoss(3 * REM * seconds_per_tick)
- H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick)
- return TRUE
- return ..()
+ affected.adjustToxLoss(3 * REM * seconds_per_tick)
/datum/species/mush/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
forced_colour = FALSE
- ..()
+ return ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
index 6a82ef96a40..25d7e252965 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -20,7 +20,7 @@
inherent_respiration_type = RESPIRATION_PLASMA
mutantlungs = /obj/item/organ/internal/lungs/plasmaman
mutanttongue = /obj/item/organ/internal/tongue/bone/plasmaman
- mutantliver = /obj/item/organ/internal/liver/plasmaman
+ mutantliver = /obj/item/organ/internal/liver/bone/plasmaman
mutantstomach = /obj/item/organ/internal/stomach/bone/plasmaman
mutantappendix = null
mutantheart = null
@@ -62,6 +62,7 @@
C.set_safe_hunger_level()
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired)
+ . = ..()
var/atmos_sealed = TRUE
if(HAS_TRAIT(H, TRAIT_NOFIRE))
atmos_sealed = FALSE
@@ -133,57 +134,6 @@
return randname
-/datum/species/plasmaman/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
- . = ..()
- if(istype(chem, /datum/reagent/toxin/plasma) || istype(chem, /datum/reagent/toxin/hot_ice))
- for(var/i in H.all_wounds)
- var/datum/wound/iter_wound = i
- iter_wound.on_xadone(4 * REM * seconds_per_tick) // plasmamen use plasma to reform their bones or whatever
- return FALSE // do normal metabolism
-
- if(istype(chem, /datum/reagent/toxin/bonehurtingjuice))
- H.adjustStaminaLoss(7.5 * REM * seconds_per_tick, 0)
- H.adjustBruteLoss(0.5 * REM * seconds_per_tick, 0)
- if(SPT_PROB(10, seconds_per_tick))
- switch(rand(1, 3))
- if(1)
- H.say(pick("oof.", "ouch.", "my bones.", "oof ouch.", "oof ouch my bones."), forced = /datum/reagent/toxin/bonehurtingjuice)
- if(2)
- H.manual_emote(pick("oofs silently.", "looks like [H.p_their()] bones hurt.", "grimaces, as though [H.p_their()] bones hurt."))
- if(3)
- to_chat(H, span_warning("Your bones hurt!"))
- if(chem.overdosed)
- if(SPT_PROB(2, seconds_per_tick) && iscarbon(H)) //big oof
- var/selected_part = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) //God help you if the same limb gets picked twice quickly.
- var/obj/item/bodypart/bp = H.get_bodypart(selected_part) //We're so sorry skeletons, you're so misunderstood
- if(bp)
- playsound(H, get_sfx(SFX_DESECRATION), 50, TRUE, -1) //You just want to socialize
- H.visible_message(span_warning("[H] rattles loudly and flails around!!"), span_danger("Your bones hurt so much that your missing muscles spasm!!"))
- H.say("OOF!!", forced=/datum/reagent/toxin/bonehurtingjuice)
- bp.receive_damage(200, 0, 0) //But I don't think we should
- else
- to_chat(H, span_warning("Your missing arm aches from wherever you left it."))
- H.emote("sigh")
- H.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick)
- return TRUE
-
- if(istype(chem, /datum/reagent/gunpowder))
- H.set_timed_status_effect(15 SECONDS * seconds_per_tick, /datum/status_effect/drugginess)
- if(H.get_timed_status_effect_duration(/datum/status_effect/hallucination) / 10 < chem.volume)
- H.adjust_hallucinations(2.5 SECONDS * seconds_per_tick)
- // Do normal metabolism
- return FALSE
- if(chem.type == /datum/reagent/consumable/milk)
- if(chem.volume > 50)
- H.reagents.remove_reagent(chem.type, chem.volume - 5)
- to_chat(H, span_warning("The excess milk is dripping off your bones!"))
- H.heal_bodypart_damage(2.5 * REM * seconds_per_tick)
-
- for(var/datum/wound/iter_wound as anything in H.all_wounds)
- iter_wound.on_xadone(1 * REM * seconds_per_tick)
- H.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick)
- return FALSE
-
/datum/species/plasmaman/get_scream_sound(mob/living/carbon/human)
return pick(
'sound/voice/plasmaman/plasmeme_scream_1.ogg',
diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index 89e03756e19..617fab8c25e 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -48,6 +48,7 @@
return ..()
/datum/species/pod/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired)
+ . = ..()
if(H.stat == DEAD)
return
@@ -66,14 +67,13 @@
if(H.nutrition < NUTRITION_LEVEL_STARVING + 50)
H.take_overall_damage(brute = 1 * seconds_per_tick, required_bodytype = BODYTYPE_ORGANIC)
- ..()
-/datum/species/pod/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
+/datum/species/pod/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
+ . = ..()
+ if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
+ return
if(chem.type == /datum/reagent/toxin/plantbgone)
- H.adjustToxLoss(3 * REM * seconds_per_tick)
- H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick)
- return TRUE
- return ..()
+ affected.adjustToxLoss(3 * REM * seconds_per_tick)
/datum/species/pod/create_pref_unique_perks()
var/list/to_add = list()
diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
index 7e63318de3b..fb86b8952d2 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -17,7 +17,6 @@
TRAIT_LIMBATTACHMENT,
TRAIT_NOBREATH,
TRAIT_NOCLONELOSS,
- TRAIT_NOMETABOLISM,
TRAIT_RADIMMUNE,
TRAIT_PIERCEIMMUNE,
TRAIT_RESISTCOLD,
@@ -33,7 +32,7 @@
mutantstomach = /obj/item/organ/internal/stomach/bone
mutantappendix = null
mutantheart = null
- mutantliver = null
+ mutantliver = /obj/item/organ/internal/liver/bone
mutantlungs = null
disliked_food = NONE
liked_food = GROSS | MEAT | RAW | GORE
@@ -61,45 +60,6 @@
return TRUE
return ..()
-//Can still metabolize milk through meme magic
-/datum/species/skeleton/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
- . = ..()
- if(chem.type == /datum/reagent/toxin/bonehurtingjuice)
- H.adjustStaminaLoss(7.5 * REM * seconds_per_tick, 0)
- H.adjustBruteLoss(0.5 * REM * seconds_per_tick, 0)
- if(SPT_PROB(10, seconds_per_tick))
- switch(rand(1, 3))
- if(1)
- H.say(pick("oof.", "ouch.", "my bones.", "oof ouch.", "oof ouch my bones."), forced = /datum/reagent/toxin/bonehurtingjuice)
- if(2)
- H.manual_emote(pick("oofs silently.", "looks like [H.p_their()] bones hurt.", "grimaces, as though [H.p_their()] bones hurt."))
- if(3)
- to_chat(H, span_warning("Your bones hurt!"))
- if(chem.overdosed)
- if(SPT_PROB(2, seconds_per_tick) && iscarbon(H)) //big oof
- var/selected_part = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) //God help you if the same limb gets picked twice quickly.
- var/obj/item/bodypart/bp = H.get_bodypart(selected_part) //We're so sorry skeletons, you're so misunderstood
- if(bp)
- playsound(H, get_sfx(SFX_DESECRATION), 50, TRUE, -1) //You just want to socialize
- H.visible_message(span_warning("[H] rattles loudly and flails around!!"), span_danger("Your bones hurt so much that your missing muscles spasm!!"))
- H.say("OOF!!", forced=/datum/reagent/toxin/bonehurtingjuice)
- bp.receive_damage(200, 0, 0) //But I don't think we should
- else
- to_chat(H, span_warning("Your missing arm aches from wherever you left it."))
- H.emote("sigh")
- H.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick)
- return TRUE
- if(chem.type == /datum/reagent/consumable/milk)
- if(chem.volume > 50)
- H.reagents.remove_reagent(chem.type, chem.volume - 5)
- to_chat(H, span_warning("The excess milk is dripping off your bones!"))
- H.heal_bodypart_damage(2.5 * REM * seconds_per_tick, 2.5 * REM * seconds_per_tick)
-
- for(var/datum/wound/iter_wound as anything in H.all_wounds)
- iter_wound.on_xadone(1 * REM * seconds_per_tick)
- H.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick)
- return FALSE
-
/datum/species/skeleton/get_species_description()
return "A rattling skeleton! They descend upon Space Station 13 \
Every year to spook the crew! \"I've got a BONE to pick with you!\""
diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm
index b9b9c1533a9..8b4ed885459 100644
--- a/code/modules/mob/living/carbon/human/species_types/snail.dm
+++ b/code/modules/mob/living/carbon/human/species_types/snail.dm
@@ -28,13 +28,15 @@
BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/snail
)
-/datum/species/snail/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H, seconds_per_tick, times_fired)
+/datum/species/snail/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
. = ..()
+ if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
+ return
if(istype(chem,/datum/reagent/consumable/salt))
- H.adjustFireLoss(2 * REM * seconds_per_tick)
- playsound(H, 'sound/weapons/sear.ogg', 30, TRUE)
- H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick)
- return TRUE
+ playsound(affected, SFX_SEAR, 30, TRUE)
+ affected.adjustFireLoss(2 * REM * seconds_per_tick)
+ affected.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick)
+ return COMSIG_MOB_STOP_REAGENT_CHECK
/datum/species/snail/on_species_gain(mob/living/carbon/new_snailperson, datum/species/old_species, pref_load)
. = ..()
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 9bf815d529f..b031f03b322 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -1,5 +1,4 @@
/mob/living/carbon/Life(seconds_per_tick = SSMOBS_DT, times_fired)
-
if(notransform)
return
@@ -40,7 +39,7 @@
var/datum/addiction/addiction = SSaddiction.all_addictions[key]
addiction.process_addiction(src, seconds_per_tick, times_fired)
if(stat != DEAD)
- return 1
+ return TRUE
///////////////
// BREATHING //
@@ -482,10 +481,10 @@
D.stage_act(seconds_per_tick, times_fired)
/mob/living/carbon/handle_wounds(seconds_per_tick, times_fired)
- for(var/thing in all_wounds)
- var/datum/wound/W = thing
- if(W.processes) // meh
- W.handle_process(seconds_per_tick, times_fired)
+ for(var/datum/wound/wound as anything in all_wounds)
+ if(!wound.processes) // meh
+ continue
+ wound.handle_process(seconds_per_tick, times_fired)
/mob/living/carbon/handle_mutations(time_since_irradiated, seconds_per_tick, times_fired)
if(!dna?.temporary_mutations.len)
@@ -714,7 +713,7 @@
return
reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs
- reagents.metabolize(src, seconds_per_tick, times_fired, can_overdose=TRUE, liverless = TRUE)
+ reagents.metabolize(src, seconds_per_tick, times_fired, can_overdose = TRUE, liverless = TRUE)
if(HAS_TRAIT(src, TRAIT_STABLELIVER) || HAS_TRAIT(src, TRAIT_NOMETABOLISM))
return
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 8508b1c2ca8..95b7da5b9da 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -44,8 +44,6 @@
if(stat != DEAD)
//Mutations and radiation
handle_mutations(seconds_per_tick, times_fired)
-
- if(stat != DEAD)
//Breathing, if applicable
handle_breathing(seconds_per_tick, times_fired)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 66542714c70..06c384aa211 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1422,6 +1422,11 @@
stat = new_stat
SEND_SIGNAL(src, COMSIG_MOB_STATCHANGE, new_stat, .)
+/// Proc used for custom metabolization of reagents, if any
+/mob/proc/reagent_check(datum/reagent/chem, seconds_per_tick, times_fired)
+ SHOULD_CALL_PARENT(TRUE)
+ return SEND_SIGNAL(src, COMSIG_MOB_REAGENT_CHECK, chem, seconds_per_tick, times_fired)
+
/mob/vv_edit_var(var_name, var_value)
switch(var_name)
if(NAMEOF(src, control_object))
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 1be76be1f35..44eb4385955 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -222,11 +222,6 @@
return TRUE
return FALSE
-
-/mob/proc/reagent_check(datum/reagent/R, seconds_per_tick, times_fired) // utilized in the species code
- return TRUE
-
-
/**
* Fancy notifications for ghosts
*
diff --git a/code/modules/research/designs/limbgrower_designs.dm b/code/modules/research/designs/limbgrower_designs.dm
index 3c911a6567d..ef8c762acd7 100644
--- a/code/modules/research/designs/limbgrower_designs.dm
+++ b/code/modules/research/designs/limbgrower_designs.dm
@@ -162,7 +162,7 @@
id = "plasmamanliver"
build_type = LIMBGROWER
reagents_list = list(/datum/reagent/medicine/c2/synthflesh = 10, /datum/reagent/toxin/plasma = 20)
- build_path = /obj/item/organ/internal/liver/plasmaman
+ build_path = /obj/item/organ/internal/liver/bone/plasmaman
category = list(SPECIES_PLASMAMAN)
/datum/design/plasmaman_stomach
diff --git a/code/modules/surgery/organs/external/_external_organs.dm b/code/modules/surgery/organs/external/_external_organ.dm
similarity index 100%
rename from code/modules/surgery/organs/external/_external_organs.dm
rename to code/modules/surgery/organs/external/_external_organ.dm
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/internal/_internal_organ.dm
similarity index 100%
rename from code/modules/surgery/organs/organ_internal.dm
rename to code/modules/surgery/organs/internal/_internal_organ.dm
diff --git a/code/modules/surgery/organs/appendix.dm b/code/modules/surgery/organs/internal/appendix/_appendix.dm
similarity index 100%
rename from code/modules/surgery/organs/appendix.dm
rename to code/modules/surgery/organs/internal/appendix/_appendix.dm
diff --git a/code/modules/surgery/organs/appendix_golem.dm b/code/modules/surgery/organs/internal/appendix/appendix_golem.dm
similarity index 100%
rename from code/modules/surgery/organs/appendix_golem.dm
rename to code/modules/surgery/organs/internal/appendix/appendix_golem.dm
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm
similarity index 100%
rename from code/modules/surgery/organs/augments_arms.dm
rename to code/modules/surgery/organs/internal/cyberimp/augments_arms.dm
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm
similarity index 100%
rename from code/modules/surgery/organs/augments_chest.dm
rename to code/modules/surgery/organs/internal/cyberimp/augments_chest.dm
diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm
similarity index 100%
rename from code/modules/surgery/organs/augments_eyes.dm
rename to code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm
diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm
similarity index 100%
rename from code/modules/surgery/organs/augments_internal.dm
rename to code/modules/surgery/organs/internal/cyberimp/augments_internal.dm
diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm
similarity index 100%
rename from code/modules/surgery/organs/ears.dm
rename to code/modules/surgery/organs/internal/ears/_ears.dm
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm
similarity index 100%
rename from code/modules/surgery/organs/eyes.dm
rename to code/modules/surgery/organs/internal/eyes/_eyes.dm
diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm
similarity index 100%
rename from code/modules/surgery/organs/heart.dm
rename to code/modules/surgery/organs/internal/heart/_heart.dm
diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm
similarity index 78%
rename from code/modules/surgery/organs/liver.dm
rename to code/modules/surgery/organs/internal/liver/_liver.dm
index 7c0de6f043a..cf160fc4588 100644
--- a/code/modules/surgery/organs/liver.dm
+++ b/code/modules/surgery/organs/internal/liver/_liver.dm
@@ -5,12 +5,12 @@
/obj/item/organ/internal/liver
name = "liver"
+ desc = "Pairing suggestion: chianti and fava beans."
icon_state = "liver"
visual = FALSE
w_class = WEIGHT_CLASS_SMALL
zone = BODY_ZONE_CHEST
slot = ORGAN_SLOT_LIVER
- desc = "Pairing suggestion: chianti and fava beans."
maxHealth = STANDARD_ORGAN_THRESHOLD
healing_factor = STANDARD_ORGAN_HEALING
@@ -33,6 +33,7 @@
// If the liver handles foods like a clown, it honks like a bike horn
// Don't think about it too much.
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_COMEDY_METABOLISM), PROC_REF(on_add_comedy_metabolism))
+ RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_COMEDY_METABOLISM), PROC_REF(on_remove_comedy_metabolism))
/* Signal handler for the liver gaining the TRAIT_COMEDY_METABOLISM trait
*
@@ -50,30 +51,59 @@
// Would that make the clown more or less likely to honk it
AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50, falloff_exponent = 20)
+/* Signal handler for the liver losing the TRAIT_COMEDY_METABOLISM trait
+ *
+ * Basically just removes squeak component
+ */
+/obj/item/organ/internal/liver/proc/on_remove_comedy_metabolism()
+ SIGNAL_HANDLER
+
+ qdel(GetComponent(/datum/component/squeak))
+
+/// Registers COMSIG_MOB_REAGENT_CHECK from owner
+/obj/item/organ/internal/liver/on_insert(mob/living/carbon/organ_owner, special)
+ . = ..()
+ RegisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL, PROC_REF(handle_chemical))
+
+/// Unregisters COMSIG_MOB_REAGENT_CHECK from owner
+/obj/item/organ/internal/liver/on_remove(mob/living/carbon/organ_owner, special)
+ . = ..()
+ UnregisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL)
+
+/**
+ * This proc can be overriden by liver subtypes so they can handle certain chemicals in special ways.
+ * Return null to continue running the normal on_mob_life() for that reagent.
+ * Return COMSIG_MOB_STOP_REAGENT_CHECK to not run the normal metabolism effects.
+ *
+ * NOTE: If you return COMSIG_MOB_STOP_REAGENT_CHECK, that reagent will not be removed like normal! You must handle it manually.
+ **/
+/obj/item/organ/internal/liver/proc/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired)
+ SIGNAL_HANDLER
+
/obj/item/organ/internal/liver/examine(mob/user)
. = ..()
if(HAS_TRAIT(user, TRAIT_ENTRAILS_READER) || (user.mind && HAS_TRAIT(user.mind, TRAIT_ENTRAILS_READER)) || isobserver(user))
if(HAS_TRAIT(src, TRAIT_LAW_ENFORCEMENT_METABOLISM))
- . += "Fatty deposits and sprinkle residue, imply that this is the liver of someone in security."
+ . += span_info("Fatty deposits and sprinkle residue, imply that this is the liver of someone in security.")
if(HAS_TRAIT(src, TRAIT_CULINARY_METABOLISM))
- . += "The high iron content and slight smell of garlic, implies that this is the liver of a cook."
+ . += span_info("The high iron content and slight smell of garlic, implies that this is the liver of a cook.")
if(HAS_TRAIT(src, TRAIT_COMEDY_METABOLISM))
- . += "A smell of bananas, a slippery sheen and [span_clown("honking")] when depressed, implies that this is the liver of a clown."
+ . += span_info("A smell of bananas, a slippery sheen and [span_clown("honking")] when depressed, implies that this is the liver of a clown.")
if(HAS_TRAIT(src, TRAIT_MEDICAL_METABOLISM))
- . += "Marks of stress and a faint whiff of medicinal alcohol, imply that this is the liver of a medical worker."
+ . += span_info("Marks of stress and a faint whiff of medicinal alcohol, imply that this is the liver of a medical worker.")
if(HAS_TRAIT(src, TRAIT_ENGINEER_METABOLISM))
- . += "Signs of radiation exposure and space adaption, implies that this is the liver of an engineer."
+ . += span_info("Signs of radiation exposure and space adaption, implies that this is the liver of an engineer.")
if(HAS_TRAIT(src, TRAIT_BALLMER_SCIENTIST))
- . += "Strange glowing residues, sprinklings of congealed solid plasma, and what seem to be tumors indicate this is the radiated liver of a scientist."
+ . += span_info("Strange glowing residues, sprinklings of congealed solid plasma, and what seem to be tumors indicate this is the radiated liver of a scientist.")
if(HAS_TRAIT(src, TRAIT_MAINTENANCE_METABOLISM))
- . += "A half-digested rat's tail (somehow), disgusting sludge, and the faint smell of Grey Bull imply this is what remains of an assistant's liver."
+ . += span_info("A half-digested rat's tail (somehow), disgusting sludge, and the faint smell of Grey Bull imply this is what remains of an assistant's liver.")
// royal trumps pretender royal
if(HAS_TRAIT(src, TRAIT_ROYAL_METABOLISM))
- . += "A rich diet of luxury food, suppleness from soft beds, implies that this is the liver of a head of staff."
+ . += span_info("A rich diet of luxury food, suppleness from soft beds, implies that this is the liver of a head of staff.")
else if(HAS_TRAIT(src, TRAIT_PRETENDER_ROYAL_METABOLISM))
- . += "A diet of imitation caviar, and signs of insomnia, implies that this is the liver of someone who wants to be a head of staff."
+ . += span_info("A diet of imitation caviar, and signs of insomnia, implies that this is the liver of someone who wants to be a head of staff.")
/obj/item/organ/internal/liver/before_organ_replacement(obj/item/organ/replacement)
. = ..()
@@ -95,13 +125,15 @@
#define HAS_PAINFUL_TOXIN 2
/obj/item/organ/internal/liver/on_life(seconds_per_tick, times_fired)
- var/mob/living/carbon/liver_owner = owner
. = ..() //perform general on_life()
-
+ var/mob/living/carbon/liver_owner = owner
if(!istype(liver_owner))
return
- if(organ_flags & ORGAN_FAILING || HAS_TRAIT(liver_owner, TRAIT_NOMETABOLISM)) //If your liver is failing or you lack a metabolism then we use the liverless version of metabolize
- liver_owner.reagents.metabolize(liver_owner, seconds_per_tick, times_fired, can_overdose=TRUE, liverless=TRUE)
+
+ //If your liver is failing, then we use the liverless version of metabolize
+ //We don't check for TRAIT_NOMETABOLISM here because we do want a functional liver if somehow we have one inserted
+ if(organ_flags & ORGAN_FAILING)
+ liver_owner.reagents.metabolize(liver_owner, seconds_per_tick, times_fired, can_overdose = TRUE, liverless = TRUE)
return
var/obj/belly = liver_owner.get_organ_slot(ORGAN_SLOT_STOMACH)
@@ -123,7 +155,7 @@
if(provide_pain_message != HAS_PAINFUL_TOXIN)
provide_pain_message = toxin.silent_toxin ? HAS_SILENT_TOXIN : HAS_PAINFUL_TOXIN
- liver_owner.reagents.metabolize(liver_owner, seconds_per_tick, times_fired, can_overdose=TRUE)
+ liver_owner.reagents.metabolize(liver_owner, seconds_per_tick, times_fired, can_overdose = TRUE)
if(liver_damage)
apply_organ_damage(min(liver_damage * seconds_per_tick , MAX_TOXIN_LIVER_DAMAGE * seconds_per_tick))
@@ -205,24 +237,18 @@
/obj/item/organ/internal/liver/get_availability(datum/species/owner_species, mob/living/owner_mob)
return owner_species.mutantliver
-/obj/item/organ/internal/liver/plasmaman
- name = "reagent processing crystal"
- icon_state = "liver-p"
- desc = "A large crystal that is somehow capable of metabolizing chemicals, these are found in plasmamen."
- status = ORGAN_MINERAL
-
// alien livers can ignore up to 15u of toxins, but they take x3 liver damage
/obj/item/organ/internal/liver/alien
name = "alien liver" // doesnt matter for actual aliens because they dont take toxin damage
- icon_state = "liver-x" // Same sprite as fly-person liver.
desc = "A liver that used to belong to a killer alien, who knows what it used to eat."
+ icon_state = "liver-x" // Same sprite as fly-person liver.
liver_resistance = 0.333 * LIVER_DEFAULT_TOX_RESISTANCE // -66%
toxTolerance = 15 // complete toxin immunity like xenos have would be too powerful
/obj/item/organ/internal/liver/cybernetic
name = "basic cybernetic liver"
- icon_state = "liver-c"
desc = "A very basic device designed to mimic the functions of a human liver. Handles toxins slightly worse than an organic liver."
+ icon_state = "liver-c"
organ_flags = ORGAN_SYNTHETIC
toxTolerance = 2
liver_resistance = 0.9 * LIVER_DEFAULT_TOX_RESISTANCE // -10%
@@ -231,8 +257,8 @@
/obj/item/organ/internal/liver/cybernetic/tier2
name = "cybernetic liver"
- icon_state = "liver-c-u"
desc = "An electronic device designed to mimic the functions of a human liver. Handles toxins slightly better than an organic liver."
+ icon_state = "liver-c-u"
maxHealth = 1.5 * STANDARD_ORGAN_THRESHOLD
toxTolerance = 5 //can shrug off up to 5u of toxins
liver_resistance = 1.2 * LIVER_DEFAULT_TOX_RESISTANCE // +20%
@@ -240,8 +266,8 @@
/obj/item/organ/internal/liver/cybernetic/tier3
name = "upgraded cybernetic liver"
- icon_state = "liver-c-u2"
desc = "An upgraded version of the cybernetic liver, designed to improve further upon organic livers. It is resistant to alcohol poisoning and is very robust at filtering toxins."
+ icon_state = "liver-c-u2"
alcohol_tolerance = 0.001
maxHealth = 2 * STANDARD_ORGAN_THRESHOLD
toxTolerance = 10 //can shrug off up to 10u of toxins
diff --git a/code/modules/surgery/organs/internal/liver/liver_golem.dm b/code/modules/surgery/organs/internal/liver/liver_golem.dm
new file mode 100644
index 00000000000..69d1a0b9baf
--- /dev/null
+++ b/code/modules/surgery/organs/internal/liver/liver_golem.dm
@@ -0,0 +1,24 @@
+/**
+ * Golem liver
+ * Basically only exists to remove the nutriment factor from consumables,
+ * so golems can only consume minerals even when injecting reagents.
+ *
+ * Actually consuming golem food is handled by /obj/item/organ/internal/stomach/golem!
+ **/
+/obj/item/organ/internal/liver/golem
+ name = "porous rock"
+ desc = "A spongy rock capable of absorbing chemicals."
+ icon_state = "liver-p"
+ status = ORGAN_MINERAL
+ color = COLOR_GOLEM_GRAY
+
+/obj/item/organ/internal/liver/golem/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired)
+ . = ..()
+ // parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing
+ if(. || (organ_flags & ORGAN_FAILING))
+ return
+ // golems can only eat minerals
+ if(istype(chem, /datum/reagent/consumable) && !istype(chem, /datum/reagent/consumable/nutriment/mineral))
+ var/datum/reagent/consumable/yummy_chem = chem
+ yummy_chem.nutriment_factor = 0
+ return // Do normal metabolism
diff --git a/code/modules/surgery/organs/internal/liver/liver_plasmaman.dm b/code/modules/surgery/organs/internal/liver/liver_plasmaman.dm
new file mode 100644
index 00000000000..34dbec6ab61
--- /dev/null
+++ b/code/modules/surgery/organs/internal/liver/liver_plasmaman.dm
@@ -0,0 +1,25 @@
+/**
+ * Plasmaman liver
+ * Makes plasma and hot ice heal wounds, also makes gunpowder a hallucinogen.
+ **/
+/obj/item/organ/internal/liver/bone/plasmaman
+ name = "reagent processing crystal"
+ desc = "A large crystal that is somehow capable of metabolizing chemicals, these are found in plasmamen."
+ icon_state = "liver-p"
+ status = ORGAN_MINERAL
+
+/obj/item/organ/internal/liver/bone/plasmaman/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired)
+ . = ..()
+ //parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing
+ if(. || (organ_flags & ORGAN_FAILING))
+ return
+ // plasmamen use plasma to reform their bones or whatever
+ if(istype(chem, /datum/reagent/toxin/plasma) || istype(chem, /datum/reagent/toxin/hot_ice))
+ for(var/datum/wound/iter_wound as anything in organ_owner.all_wounds)
+ iter_wound.on_xadone(4 * REM * seconds_per_tick)
+ return // Do normal metabolism
+ if(istype(chem, /datum/reagent/gunpowder))
+ organ_owner.set_timed_status_effect(15 SECONDS * seconds_per_tick, /datum/status_effect/drugginess)
+ if(organ_owner.get_timed_status_effect_duration(/datum/status_effect/hallucination) / 10 < chem.volume)
+ organ_owner.adjust_hallucinations(2.5 SECONDS * seconds_per_tick)
+ return // Do normal metabolism
diff --git a/code/modules/surgery/organs/internal/liver/liver_skeleton.dm b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm
new file mode 100644
index 00000000000..3ddd3214353
--- /dev/null
+++ b/code/modules/surgery/organs/internal/liver/liver_skeleton.dm
@@ -0,0 +1,49 @@
+/**
+ * Bone liver
+ * Gives the owner liverless metabolism, makes them vulnerable to bone hurting juice and
+ * makes milk heal them through meme magic.
+ **/
+/obj/item/organ/internal/liver/bone
+ name = "mass of bones"
+ desc = "You have no idea what this strange ball of bones does."
+ icon_state = "liver-bone"
+ organ_traits = list(TRAIT_NOMETABOLISM)
+
+/obj/item/organ/internal/liver/bone/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired)
+ . = ..()
+ //parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing
+ if(. || (organ_flags & ORGAN_FAILING))
+ return
+ if(istype(chem, /datum/reagent/toxin/bonehurtingjuice))
+ organ_owner.adjustStaminaLoss(7.5 * REM * seconds_per_tick, 0)
+ organ_owner.adjustBruteLoss(0.5 * REM * seconds_per_tick, 0)
+ if(SPT_PROB(10, seconds_per_tick))
+ switch(rand(1, 3))
+ if(1)
+ INVOKE_ASYNC(organ_owner, TYPE_PROC_REF(/atom/movable, say), pick("oof.", "ouch.", "my bones.", "oof ouch.", "oof ouch my bones."), forced = chem.type)
+ if(2)
+ organ_owner.manual_emote(pick("oofs silently.", "looks like [organ_owner.p_their()] bones hurt.", "grimaces, as though [organ_owner.p_their()] bones hurt."))
+ if(3)
+ to_chat(organ_owner, span_warning("Your bones hurt!"))
+ if(chem.overdosed)
+ if(SPT_PROB(2, seconds_per_tick)) //big oof
+ var/selected_part = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) //God help you if the same limb gets picked twice quickly...
+ var/obj/item/bodypart/bodypart = organ_owner.get_bodypart(selected_part) //We're so sorry skeletons, you're so misunderstood
+ if(bodypart)
+ playsound(organ_owner, SFX_DESECRATION, 50, vary = TRUE) //You just want to socialize
+ organ_owner.visible_message(span_warning("[organ_owner] rattles loudly and flails around!!"), span_danger("Your bones hurt so much that your missing muscles spasm!!"))
+ INVOKE_ASYNC(organ_owner, TYPE_PROC_REF(/atom/movable, say), "OOF!!", forced = chem.type)
+ bodypart.receive_damage(brute = 200) //But I don't think we should
+ else
+ to_chat(organ_owner, span_warning("Your missing [parse_zone(selected_part)] aches from wherever you left it."))
+ INVOKE_ASYNC(organ_owner, TYPE_PROC_REF(/mob, emote), "sigh")
+ organ_owner.reagents.remove_reagent(chem.type, chem.metabolization_rate * seconds_per_tick)
+ return COMSIG_MOB_STOP_REAGENT_CHECK // Stop metabolism
+ if(chem.type == /datum/reagent/consumable/milk)
+ if(chem.volume > 50)
+ organ_owner.reagents.remove_reagent(chem.type, (chem.volume - 50))
+ to_chat(organ_owner, span_warning("The excess milk is dripping off your bones!"))
+ organ_owner.heal_bodypart_damage(2.5 * REM * seconds_per_tick)
+ for(var/datum/wound/iter_wound as anything in organ_owner.all_wounds)
+ iter_wound.on_xadone(1 * REM * seconds_per_tick)
+ return // Do normal metabolism
diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm
similarity index 100%
rename from code/modules/surgery/organs/lungs.dm
rename to code/modules/surgery/organs/internal/lungs/_lungs.dm
diff --git a/code/modules/surgery/organs/stomach/_stomach.dm b/code/modules/surgery/organs/internal/stomach/_stomach.dm
similarity index 99%
rename from code/modules/surgery/organs/stomach/_stomach.dm
rename to code/modules/surgery/organs/internal/stomach/_stomach.dm
index 345027ef5d7..8769076418a 100644
--- a/code/modules/surgery/organs/stomach/_stomach.dm
+++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm
@@ -3,6 +3,7 @@
/obj/item/organ/internal/stomach
name = "stomach"
+ desc = "Onaka ga suite imasu."
icon_state = "stomach"
visual = FALSE
w_class = WEIGHT_CLASS_SMALL
@@ -10,7 +11,6 @@
slot = ORGAN_SLOT_STOMACH
attack_verb_continuous = list("gores", "squishes", "slaps", "digests")
attack_verb_simple = list("gore", "squish", "slap", "digest")
- desc = "Onaka ga suite imasu."
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = STANDARD_ORGAN_DECAY * 1.15 // ~13 minutes, the stomach is one of the first organs to die
@@ -268,21 +268,23 @@
return ..()
/obj/item/organ/internal/stomach/bone
+ name = "mass of bones"
desc = "You have no idea what this strange ball of bones does."
+ icon_state = "stomach-bone"
metabolism_efficiency = 0.025 //very bad
organ_traits = list(TRAIT_NOHUNGER)
/obj/item/organ/internal/stomach/bone/plasmaman
name = "digestive crystal"
- icon_state = "stomach-p"
- organ_traits = list()
desc = "A strange crystal that is responsible for metabolizing the unseen energy force that feeds plasmamen."
+ icon_state = "stomach-p"
metabolism_efficiency = 0.06
+ organ_traits = null
/obj/item/organ/internal/stomach/cybernetic
name = "basic cybernetic stomach"
- icon_state = "stomach-c"
desc = "A basic device designed to mimic the functions of a human stomach"
+ icon_state = "stomach-c"
organ_flags = ORGAN_SYNTHETIC
maxHealth = STANDARD_ORGAN_THRESHOLD * 0.5
var/emp_vulnerability = 80 //Chance of permanent effects if emp-ed.
@@ -290,8 +292,8 @@
/obj/item/organ/internal/stomach/cybernetic/tier2
name = "cybernetic stomach"
- icon_state = "stomach-c-u"
desc = "An electronic device designed to mimic the functions of a human stomach. Handles disgusting food a bit better."
+ icon_state = "stomach-c-u"
maxHealth = 1.5 * STANDARD_ORGAN_THRESHOLD
disgust_metabolism = 2
emp_vulnerability = 40
@@ -299,8 +301,8 @@
/obj/item/organ/internal/stomach/cybernetic/tier3
name = "upgraded cybernetic stomach"
- icon_state = "stomach-c-u2"
desc = "An upgraded version of the cybernetic stomach, designed to improve further upon organic stomachs. Handles disgusting food very well."
+ icon_state = "stomach-c-u2"
maxHealth = 2 * STANDARD_ORGAN_THRESHOLD
disgust_metabolism = 3
emp_vulnerability = 20
diff --git a/code/modules/surgery/organs/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm
similarity index 100%
rename from code/modules/surgery/organs/stomach/stomach_ethereal.dm
rename to code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm
diff --git a/code/modules/surgery/organs/stomach/stomach_golem.dm b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm
similarity index 93%
rename from code/modules/surgery/organs/stomach/stomach_golem.dm
rename to code/modules/surgery/organs/internal/stomach/stomach_golem.dm
index 6b556c8d1f6..17adbe7ad0c 100644
--- a/code/modules/surgery/organs/stomach/stomach_golem.dm
+++ b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm
@@ -17,10 +17,7 @@
RegisterSignal(owner, COMSIG_CARBON_ATTEMPT_EAT, PROC_REF(try_eating))
if(!ishuman(organ_owner))
return
- setup_physiology(organ_owner)
-
-/// Physiology doesn't exist yet if this is added on initialisation of a golem, so we need to wait until it does
-/obj/item/organ/internal/stomach/golem/proc/setup_physiology(mob/living/carbon/human/human_owner)
+ var/mob/living/carbon/human/human_owner = organ_owner
human_owner.physiology?.hunger_mod *= hunger_mod
/obj/item/organ/internal/stomach/golem/on_remove(mob/living/carbon/organ_owner, special)
@@ -51,9 +48,10 @@
/// Slow down based on how full you are
/obj/item/organ/internal/stomach/golem/handle_hunger(mob/living/carbon/human/human, delta_time, times_fired)
+ // the effects are all negative, so just don't run them if you have the trait
+ . = ..()
if(HAS_TRAIT(human, TRAIT_NOHUNGER))
return
- . = ..()
var/hunger = (NUTRITION_LEVEL_HUNGRY - human.nutrition) / NUTRITION_LEVEL_HUNGRY // starving = 1, satisfied = 0
if(hunger > 0)
var/slowdown = LERP(min_hunger_slowdown, max_hunger_slowdown, hunger)
diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm
similarity index 100%
rename from code/modules/surgery/organs/tongue.dm
rename to code/modules/surgery/organs/internal/tongue/_tongue.dm
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/internal/vocal_cords/_vocal_cords.dm
similarity index 100%
rename from code/modules/surgery/organs/vocal_cords.dm
rename to code/modules/surgery/organs/internal/vocal_cords/_vocal_cords.dm
diff --git a/icons/obj/medical/organs/organs.dmi b/icons/obj/medical/organs/organs.dmi
index acab1e24840..b47584b321c 100644
Binary files a/icons/obj/medical/organs/organs.dmi and b/icons/obj/medical/organs/organs.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 01e80d08ec7..0caa8826527 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -302,7 +302,7 @@
#include "code\__DEFINES\dcs\signals\signals_scangate.dm"
#include "code\__DEFINES\dcs\signals\signals_screentips.dm"
#include "code\__DEFINES\dcs\signals\signals_spatial_grid.dm"
-#include "code\__DEFINES\dcs\signals\signals_specie.dm"
+#include "code\__DEFINES\dcs\signals\signals_species.dm"
#include "code\__DEFINES\dcs\signals\signals_spell.dm"
#include "code\__DEFINES\dcs\signals\signals_storage.dm"
#include "code\__DEFINES\dcs\signals\signals_subsystem.dm"
@@ -5040,32 +5040,35 @@
#include "code\modules\surgery\bodyparts\species_parts\moth_bodyparts.dm"
#include "code\modules\surgery\bodyparts\species_parts\plasmaman_bodyparts.dm"
#include "code\modules\surgery\organs\_organ.dm"
-#include "code\modules\surgery\organs\appendix.dm"
-#include "code\modules\surgery\organs\appendix_golem.dm"
-#include "code\modules\surgery\organs\augments_arms.dm"
-#include "code\modules\surgery\organs\augments_chest.dm"
-#include "code\modules\surgery\organs\augments_eyes.dm"
-#include "code\modules\surgery\organs\augments_internal.dm"
#include "code\modules\surgery\organs\autosurgeon.dm"
-#include "code\modules\surgery\organs\ears.dm"
-#include "code\modules\surgery\organs\eyes.dm"
-#include "code\modules\surgery\organs\heart.dm"
#include "code\modules\surgery\organs\helpers.dm"
-#include "code\modules\surgery\organs\liver.dm"
-#include "code\modules\surgery\organs\lungs.dm"
-#include "code\modules\surgery\organs\organ_internal.dm"
-#include "code\modules\surgery\organs\tongue.dm"
-#include "code\modules\surgery\organs\vocal_cords.dm"
-#include "code\modules\surgery\organs\external\_external_organs.dm"
+#include "code\modules\surgery\organs\external\_external_organ.dm"
#include "code\modules\surgery\organs\external\restyling.dm"
#include "code\modules\surgery\organs\external\spines.dm"
#include "code\modules\surgery\organs\external\tails.dm"
#include "code\modules\surgery\organs\external\wings\functional_wings.dm"
#include "code\modules\surgery\organs\external\wings\moth_wings.dm"
#include "code\modules\surgery\organs\external\wings\wings.dm"
-#include "code\modules\surgery\organs\stomach\_stomach.dm"
-#include "code\modules\surgery\organs\stomach\stomach_ethereal.dm"
-#include "code\modules\surgery\organs\stomach\stomach_golem.dm"
+#include "code\modules\surgery\organs\internal\_internal_organ.dm"
+#include "code\modules\surgery\organs\internal\appendix\_appendix.dm"
+#include "code\modules\surgery\organs\internal\appendix\appendix_golem.dm"
+#include "code\modules\surgery\organs\internal\cyberimp\augments_arms.dm"
+#include "code\modules\surgery\organs\internal\cyberimp\augments_chest.dm"
+#include "code\modules\surgery\organs\internal\cyberimp\augments_eyes.dm"
+#include "code\modules\surgery\organs\internal\cyberimp\augments_internal.dm"
+#include "code\modules\surgery\organs\internal\ears\_ears.dm"
+#include "code\modules\surgery\organs\internal\eyes\_eyes.dm"
+#include "code\modules\surgery\organs\internal\heart\_heart.dm"
+#include "code\modules\surgery\organs\internal\liver\_liver.dm"
+#include "code\modules\surgery\organs\internal\liver\liver_golem.dm"
+#include "code\modules\surgery\organs\internal\liver\liver_plasmaman.dm"
+#include "code\modules\surgery\organs\internal\liver\liver_skeleton.dm"
+#include "code\modules\surgery\organs\internal\lungs\_lungs.dm"
+#include "code\modules\surgery\organs\internal\stomach\_stomach.dm"
+#include "code\modules\surgery\organs\internal\stomach\stomach_ethereal.dm"
+#include "code\modules\surgery\organs\internal\stomach\stomach_golem.dm"
+#include "code\modules\surgery\organs\internal\tongue\_tongue.dm"
+#include "code\modules\surgery\organs\internal\vocal_cords\_vocal_cords.dm"
#include "code\modules\tgchat\message.dm"
#include "code\modules\tgchat\to_chat.dm"
#include "code\modules\tgs\includes.dm"