diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index d095491529e..be5f36f1e15 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -89861,6 +89861,7 @@
/obj/effect/turf_decal/tile/blue{
dir = 1
},
+/obj/item/blood_filter,
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dsO" = (
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
index f4820d5e5c3..d199a3d52fa 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
@@ -49981,6 +49981,7 @@
/obj/item/clothing/glasses/hud/health,
/obj/item/clothing/glasses/hud/health,
/obj/item/clothing/glasses/hud/health,
+/obj/item/blood_filter,
/turf/open/floor/plasteel/dark,
/area/medical/storage)
"ddy" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index ca515cf737d..5954c6b398b 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -49992,6 +49992,7 @@
/obj/item/storage/backpack/duffelbag/med/surgery,
/obj/item/reagent_containers/glass/bottle/ethanol,
/obj/item/reagent_containers/glass/bottle/ethanol,
+/obj/item/blood_filter,
/turf/open/floor/plasteel/dark,
/area/medical/storage)
"cpV" = (
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 87854b146fc..30fb3ad9e91 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -36167,6 +36167,7 @@
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/item/blood_filter,
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"bMP" = (
diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm
index 6fe9b44eee0..58c503fc5c5 100644
--- a/code/__DEFINES/tools.dm
+++ b/code/__DEFINES/tools.dm
@@ -16,6 +16,7 @@
#define TOOL_SAW "saw"
#define TOOL_BONESET "bonesetter"
#define TOOL_KNIFE "knife"
+#define TOOL_BLOODFILTER "bloodfilter"
// If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY,
// tool sound is only played when op is started. If not, it's played twice.
diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm
index a38dcc04d59..460591b1192 100644
--- a/code/datums/components/food/edible.dm
+++ b/code/datums/components/food/edible.dm
@@ -165,9 +165,7 @@ Behavior that's still missing from this component that original food items had t
return
if(!CanConsume(eater, feeder))
return
- var/fullness = eater.nutrition + 10 //The theoretical fullness of the person eating if they were to eat this
- for(var/datum/reagent/consumable/C in eater.reagents.reagent_list) //we add the nutrition value of what we're currently digesting
- fullness += C.nutriment_factor * C.volume / C.metabolization_rate
+ var/fullness = eater.get_fullness() + 10 //The theoretical fullness of the person eating if they were to eat this
. = COMPONENT_ITEM_NO_ATTACK //Point of no return I suppose
diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm
index 77b154f2017..50a8e9101ee 100644
--- a/code/datums/materials/basemats.dm
+++ b/code/datums/materials/basemats.dm
@@ -217,8 +217,9 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = -0.01
armor_modifiers = list(MELEE = 1.5, BULLET = 1.1, LASER = 0.3, ENERGY = 0.5, BOMB = 1, BIO = 1, RAD = 1, FIRE = 1.1, ACID = 1)
-/datum/material/plastic/on_accidental_mat_consumption(mob/living/carbon/M, obj/item/S)
- M.adjust_disgust(17)
+/datum/material/plastic/on_accidental_mat_consumption(mob/living/carbon/eater, obj/item/food)
+ eater.reagents.add_reagent(/datum/reagent/plastic_polymers, rand(6, 8))
+ food?.reagents?.add_reagent(/datum/reagent/plastic_polymers, food.reagents.total_volume*(2/5))
return TRUE
///Force decrease and mushy sound effect. (Not yet implemented)
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 13875334132..3479f5c4697 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -377,6 +377,7 @@
new /obj/item/surgical_drapes(src)
new /obj/item/clothing/mask/surgical(src)
new /obj/item/razor(src)
+ new /obj/item/blood_filter(src)
/obj/item/storage/backpack/duffelbag/sec
name = "security duffel bag"
@@ -398,6 +399,7 @@
new /obj/item/cautery(src)
new /obj/item/surgical_drapes(src)
new /obj/item/clothing/mask/surgical(src)
+ new /obj/item/blood_filter(src)
/obj/item/storage/backpack/duffelbag/engineering
name = "industrial duffel bag"
@@ -486,6 +488,7 @@
new /obj/item/clothing/suit/straight_jacket(src)
new /obj/item/clothing/mask/muzzle(src)
new /obj/item/mmi/syndie(src)
+ new /obj/item/blood_filter(src)
/obj/item/storage/backpack/duffelbag/syndie/ammo
name = "ammunition duffel bag"
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index fba202d2544..fdcd2759309 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -560,18 +560,20 @@ GLOBAL_LIST_EMPTY(station_turfs)
if (iscarbon(M))
var/mob/living/carbon/C = M
if(C.reagents)
- clear_reagents_to_vomit_pool(C,V, purge)
+ clear_reagents_to_vomit_pool(C, V, purge)
/proc/clear_reagents_to_vomit_pool(mob/living/carbon/M, obj/effect/decal/cleanable/vomit/V, purge = FALSE)
- var/chemicals_lost = M.reagents.total_volume / 10
+ var/obj/item/organ/stomach/belly = M.getorganslot(ORGAN_SLOT_STOMACH)
+ if(!belly)
+ return
+ var/chemicals_lost = belly.reagents.total_volume * 0.1
if(purge)
- chemicals_lost = (2 * M.reagents.total_volume)/3 //For detoxification surgery, we're manually pumping the stomach out of chemcials, so it's far more efficient.
- M.reagents.trans_to(V, chemicals_lost, transfered_by = M)
- for(var/datum/reagent/R in M.reagents.reagent_list) //clears the stomach of anything that might be digested as food
- if(istype(R, /datum/reagent/consumable) || purge)
- var/datum/reagent/consumable/nutri_check = R
- if(nutri_check.nutriment_factor >0)
- M.reagents.remove_reagent(R.type, min(R.volume, 10))
+ chemicals_lost = belly.reagents.total_volume * 0.67 //For detoxification surgery, we're manually pumping the stomach out of chemcials, so it's far more efficient.
+ belly.reagents.trans_to(V, chemicals_lost, transfered_by = M)
+ //clear the stomach of anything even not food
+ for(var/bile in belly.reagents.reagent_list)
+ var/datum/reagent/reagent = bile
+ belly.reagents.remove_reagent(reagent.type, min(reagent.volume, 10))
//Whatever happens after high temperature fire dies out or thermite reaction works.
//Should return new turf
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index f41282af2bc..c64d6212c94 100644
--- a/code/modules/food_and_drinks/drinks/drinks.dm
+++ b/code/modules/food_and_drinks/drinks/drinks.dm
@@ -44,10 +44,12 @@
M.visible_message("[user] fed [M] the contents of [src].", \
"[user] fed you the contents of [src].")
log_combat(user, M, "fed", reagents.log_list())
+
SEND_SIGNAL(src, COMSIG_DRINK_DRANK, M, user)
var/fraction = min(gulp_size/reagents.total_volume, 1)
- checkLiked(fraction, M)
reagents.trans_to(M, gulp_size, transfered_by = user, methods = INGEST)
+ checkLiked(fraction, M)
+
playsound(M.loc,'sound/items/drink.ogg', rand(10,50), TRUE)
if(iscarbon(M))
var/mob/living/carbon/carbon_drinker = M
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index 72e37f6079f..370b911b91d 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -109,9 +109,7 @@ All foods are distributed among various categories. Use common sense.
if(!canconsume(M, user))
return FALSE
- var/fullness = M.nutrition + 10
- for(var/datum/reagent/consumable/C in M.reagents.reagent_list) //we add the nutrition value of what we're currently digesting
- fullness += C.nutriment_factor * C.volume / C.metabolization_rate
+ var/fullness = M.get_fullness() + 10
if(M == user) //If you're eating it yourself.
if(junkiness && M.satiety < -150 && M.nutrition > NUTRITION_LEVEL_STARVING + 50 && !HAS_TRAIT(user, TRAIT_VORACIOUS))
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index b35d690ef3f..cdfb56181f8 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -490,23 +490,44 @@
if(!blood)
adjust_nutrition(-lost_nutrition)
adjustToxLoss(-3)
+
+ var/obj/item/organ/stomach/belly = getorganslot(ORGAN_SLOT_STOMACH)
for(var/i=0 to distance)
if(blood)
if(T)
add_splatter_floor(T)
if(harm)
adjustBruteLoss(3)
- else if(src.reagents.has_reagent(/datum/reagent/consumable/ethanol/blazaam, needs_metabolizing = TRUE))
- if(T)
- T.add_vomit_floor(src, VOMIT_PURPLE)
else
- if(T)
- T.add_vomit_floor(src, VOMIT_TOXIC, purge)//toxic barf looks different || call purge when doing detoxicfication to pump more chems out of the stomach.
+ if(belly?.reagents.has_reagent(/datum/reagent/consumable/ethanol/blazaam, needs_metabolizing = TRUE))
+ if(T)
+ T.add_vomit_floor(src, VOMIT_PURPLE)
+ else
+ if(T)
+ T.add_vomit_floor(src, VOMIT_TOXIC, purge) //toxic barf looks different || call purge when doing detoxicfication to pump more chems out of the stomach.
T = get_step(T, dir)
if (T?.is_blocked_turf())
break
return TRUE
+/**
+ * Expel the reagents you just tried to ingest
+ *
+ * When you try to ingest reagents but you do not have a stomach
+ * you will spew the reagents on the floor.
+ *
+ * Vars:
+ * * bite: /atom the reagents to expel
+ * * amount: int The amount of reagent
+ */
+/mob/living/carbon/proc/expel_ingested(var/atom/bite, amount)
+ visible_message("[src] throws up all over [p_them()]self!", \
+ "You are unable to keep the [bite] down without a stomach!")
+
+ var/turf/floor = get_turf(src)
+ var/obj/effect/decal/cleanable/vomit/spew = new(floor, get_static_viruses())
+ bite.reagents.trans_to(spew, amount, transfered_by = src)
+
/mob/living/carbon/proc/spew_organ(power = 5, amt = 1)
for(var/i in 1 to amt)
if(!internal_organs.len)
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 7b2a3831aef..f9ac4269965 100644
--- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
@@ -25,17 +25,7 @@
if(chem.type == /datum/reagent/toxin/pestkiller)
H.adjustToxLoss(3)
H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM)
- return 1
-
-/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
- if(istype(chem, /datum/reagent/consumable))
- var/datum/reagent/consumable/nutri_check = chem
- if(nutri_check.nutriment_factor > 0)
- var/turf/pos = get_turf(H)
- H.vomit(0, FALSE, FALSE, 2, TRUE)
- playsound(pos, 'sound/effects/splat.ogg', 50, TRUE)
- H.visible_message("[H] vomits on the floor!", \
- "You throw up on the floor!")
+ return TRUE
..()
/datum/species/fly/check_species_weakness(obj/item/weapon, mob/living/attacker)
@@ -79,6 +69,21 @@
name = odd_organ_name()
icon_state = pick("brain-x-d", "liver-x", "kidneys-x", "stomach-x", "lungs-x", "random_fly_1", "random_fly_2", "random_fly_3", "random_fly_4", "random_fly_5")
+/obj/item/organ/stomach/fly/on_life()
+ for(var/bile in reagents.reagent_list)
+ if(!istype(bile, /datum/reagent/consumable))
+ continue
+ var/datum/reagent/consumable/chunk = bile
+ if(chunk.nutriment_factor <= 0)
+ continue
+ var/mob/living/carbon/body = owner
+ var/turf/pos = get_turf(owner)
+ body.vomit(reagents.total_volume, FALSE, FALSE, 2, TRUE)
+ playsound(pos, 'sound/effects/splat.ogg', 50, TRUE)
+ body.visible_message("[body] vomits on the floor!", \
+ "You throw up on the floor!")
+ return ..()
+
/obj/item/organ/appendix/fly
desc = "You have no idea what the hell this is, or how it manages to keep something alive in any capacity."
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 b1d3c9a5951..72dca526e30 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -919,6 +919,7 @@
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES,HAS_BONE)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutanttongue = /obj/item/organ/tongue/bone
+ mutantstomach = /obj/item/organ/stomach/bone
sexes = FALSE
fixed_mut_color = null
inherent_traits = list(TRAIT_NOFLASH,TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_FAKEDEATH)
@@ -939,15 +940,6 @@
/datum/species/golem/bone/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
. = ..()
- if(chem.type == /datum/reagent/consumable/milk)
- if(chem.volume > 10)
- H.reagents.remove_reagent(chem.type, chem.volume - 10)
- to_chat(H, "The excess milk is dripping off your bones!")
- H.heal_bodypart_damage(1.5,0, 0)
- for(var/i in H.all_wounds)
- var/datum/wound/iter_wound = i
- iter_wound.on_xadone(2)
- H.reagents.remove_reagent(chem.type, chem.metabolization_rate)
if(chem.type == /datum/reagent/toxin/bonehurtingjuice)
H.adjustStaminaLoss(7.5, 0)
H.adjustBruteLoss(0.5, 0)
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 b70c3b6c90c..64dd32f3a43 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -172,16 +172,6 @@
/datum/species/plasmaman/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
. = ..()
- if(istype(chem, /datum/reagent/consumable/milk))
- if(chem.volume > 10)
- H.reagents.remove_reagent(chem.type, chem.volume - 10)
- to_chat(H, "The excess milk is dripping off your bones!")
- H.heal_bodypart_damage(1.5,0, 0)
- H.reagents.remove_reagent(chem.type, chem.metabolization_rate)
- for(var/i in H.all_wounds)
- var/datum/wound/iter_wound = i
- iter_wound.on_xadone(2)
- return TRUE
if(istype(chem, /datum/reagent/toxin/plasma))
H.reagents.remove_reagent(chem.type, chem.metabolization_rate)
for(var/i in H.all_wounds)
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 8f23b246213..d7663e777eb 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -10,6 +10,7 @@
TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH,TRAIT_XENO_IMMUNE,TRAIT_NOCLONELOSS)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutanttongue = /obj/item/organ/tongue/bone
+ mutantstomach = /obj/item/organ/stomach/bone
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
disliked_food = NONE
liked_food = GROSS | MEAT | RAW
@@ -25,16 +26,6 @@
//Can still metabolize milk through meme magic
/datum/species/skeleton/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
. = ..()
- if(chem.type == /datum/reagent/consumable/milk)
- if(chem.volume > 10)
- H.reagents.remove_reagent(chem.type, chem.volume - 10)
- to_chat(H, "The excess milk is dripping off your bones!")
- for(var/i in H.all_wounds)
- var/datum/wound/iter_wound = i
- iter_wound.on_xadone(2)
- H.heal_bodypart_damage(1,1, 0)
- H.reagents.remove_reagent(chem.type, chem.metabolization_rate)
- return TRUE
if(chem.type == /datum/reagent/toxin/bonehurtingjuice)
H.adjustStaminaLoss(7.5, 0)
H.adjustBruteLoss(0.5, 0)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 82fee6cbabb..66b17f7fe6d 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -702,6 +702,27 @@ All effects don't start immediately, but rather get worse over time; the rate is
bodytemperature = clamp(bodytemperature + amount,min_temp,max_temp)
+///////////
+//Stomach//
+///////////
+
+/mob/living/carbon/get_fullness()
+ var/fullness = nutrition
+
+ var/obj/item/organ/stomach/belly = getorganslot(ORGAN_SLOT_STOMACH)
+ if(!belly) //nothing to see here if we do not have a stomach
+ return fullness
+
+ for(var/bile in belly.reagents.reagent_list)
+ var/datum/reagent/bits = bile
+ if(istype(bits, /datum/reagent/consumable))
+ var/datum/reagent/consumable/goodbit = bile
+ fullness += goodbit.nutriment_factor * goodbit.volume / goodbit.metabolization_rate
+ continue
+ fullness += 0.6 * bits.volume / bits.metabolization_rate //not food takes up space
+
+ return fullness
+
/////////
//LIVER//
/////////
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index ac7d6f3bd59..e01ed2440ee 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -115,6 +115,23 @@
var/turf/location = get_turf(src)
location.hotspot_expose(700, 50, 1)
+/**
+ * Get the fullness of the mob
+ *
+ * This returns a value form 0 upwards to represent how full the mob is.
+ * The value is a total amount of consumable reagents in the body combined
+ * with the total amount of nutrition they have.
+ * This does not have an upper limit.
+ */
+/mob/living/proc/get_fullness()
+ var/fullness = nutrition
+ // we add the nutrition value of what we're currently digesting
+ for(var/bile in reagents.reagent_list)
+ var/datum/reagent/consumable/bits = bile
+ if(bits)
+ fullness += bits.nutriment_factor * bits.volume / bits.metabolization_rate
+ return fullness
+
//this updates all special effects: knockdown, druggy, stuttering, etc..
/mob/living/proc/handle_status_effects()
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index ef4a424ee20..2c25e1e9dc2 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -209,8 +209,9 @@
* * methods - passed through to [/datum/reagents/proc/react_single] and [/datum/reagent/proc/on_transfer]
* * show_message - passed through to [/datum/reagents/proc/react_single]
* * round_robin - if round_robin=TRUE, so transfer 5 from 15 water, 15 sugar and 15 plasma becomes 10, 15, 15 instead of 13.3333, 13.3333 13.3333. Good if you hate floating point errors
+ * * ignore_stomach - when using methods INGEST will not use the stomach as the target
*/
-/datum/reagents/proc/trans_to(obj/target, amount = 1, multiplier = 1, preserve_data = TRUE, no_react = FALSE, mob/transfered_by, remove_blacklisted = FALSE, methods = NONE, show_message = TRUE, round_robin = FALSE)
+/datum/reagents/proc/trans_to(obj/target, amount = 1, multiplier = 1, preserve_data = TRUE, no_react = FALSE, mob/transfered_by, remove_blacklisted = FALSE, methods = NONE, show_message = TRUE, round_robin = FALSE, ignore_stomach = FALSE)
var/list/cached_reagents = reagent_list
if(!target || !total_volume)
return
@@ -223,10 +224,19 @@
R = target
target_atom = R.my_atom
else
- if(!target.reagents)
+ if(!ignore_stomach && (methods & INGEST) && istype(target, /mob/living/carbon))
+ var/mob/living/carbon/eater = target
+ var/obj/item/organ/stomach/belly = eater.getorganslot(ORGAN_SLOT_STOMACH)
+ if(!belly)
+ eater.expel_ingested(my_atom, amount)
+ return
+ R = belly.reagents
+ target_atom = belly
+ else if(!target.reagents)
return
- R = target.reagents
- target_atom = target
+ else
+ R = target.reagents
+ target_atom = target
amount = min(min(amount, src.total_volume), R.maximum_volume-R.total_volume)
var/trans_data = null
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index c8fa1a1dc24..483e0b020cf 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -495,6 +495,15 @@
build_path = /obj/item/clothing/head/foilhat
category = list("hacked", "Misc")
+/datum/design/blood_filter
+ name = "Blood Filter"
+ id = "blood_filter"
+ build_type = AUTOLATHE | PROTOLATHE
+ materials = list(/datum/material/iron = 4000, /datum/material/glass = 1500, /datum/material/silver = 500)
+ build_path = /obj/item/blood_filter
+ category = list("initial", "Medical", "Tool Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
/datum/design/scalpel
name = "Scalpel"
id = "scalpel"
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 9423cabdef2..2709183d363 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -56,8 +56,10 @@
starting_node = TRUE
display_name = "Basic Medical Equipment"
description = "Basic medical tools and equipment."
- design_ids = list("cybernetic_liver", "cybernetic_heart", "cybernetic_lungs","cybernetic_stomach", "scalpel", "circular_saw", "bonesetter", "surgicaldrill", "retractor", "cautery", "hemostat", "stethoscope",
- "surgical_drapes", "syringe", "plumbing_rcd", "beaker", "large_beaker", "xlarge_beaker", "dropper", "defibmountdefault", "surgical_tape", "portable_chem_mixer")
+ design_ids = list("cybernetic_liver", "cybernetic_heart", "cybernetic_lungs","cybernetic_stomach", "scalpel",
+ "blood_filter", "circular_saw", "bonesetter", "surgicaldrill", "retractor", "cautery", "hemostat",
+ "stethoscope", "surgical_drapes", "syringe", "plumbing_rcd", "beaker", "large_beaker", "xlarge_beaker",
+ "dropper", "defibmountdefault", "surgical_tape", "portable_chem_mixer")
/////////////////////////Biotech/////////////////////////
/datum/techweb_node/biotech
diff --git a/code/modules/surgery/blood_filter.dm b/code/modules/surgery/blood_filter.dm
new file mode 100644
index 00000000000..46b0c1f9194
--- /dev/null
+++ b/code/modules/surgery/blood_filter.dm
@@ -0,0 +1,44 @@
+/datum/surgery/blood_filter
+ name = "Filter blood"
+ steps = list(/datum/surgery_step/incise,
+ /datum/surgery_step/retract_skin,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/filter_blood,
+ /datum/surgery_step/close)
+
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ possible_locs = list(BODY_ZONE_CHEST)
+ requires_bodypart_type = TRUE
+ ignore_clothes = FALSE
+
+/datum/surgery_step/filter_blood
+ name = "Filter blood"
+ implements = list(/obj/item/blood_filter = 95)
+ repeatable = TRUE
+ time = 2.5 SECONDS
+
+/datum/surgery/filter_blood/can_start(mob/user, mob/living/carbon/target)
+ if(HAS_TRAIT(target, TRAIT_HUSK)) //You can filter the blood of a dead person just not husked
+ return FALSE
+ return ..()
+
+/datum/surgery_step/filter_blood/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You begin filtering [target]'s blood...",
+ "[user] uses the [tool] to filtering your blood.",
+ "[user] uses the [tool] on [target]'s chest.")
+
+/datum/surgery_step/filter_blood/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
+ if(target.reagents?.total_volume)
+ for(var/blood_chem in target.reagents.reagent_list)
+ var/datum/reagent/chem = blood_chem
+ target.reagents.remove_reagent(chem.type, min(chem.volume * 0.22, 10))
+ display_results(user, target, "The [tool] pings as it finishes filtering [target]'s blood.",
+ "The [tool] pings as it stops pumping your blood.",
+ "The [tool] pings as it stops pumping.")
+ return ..()
+
+/datum/surgery_step/filter_blood/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You screw up, brusing [target]'s chest!",
+ "[user] screws up, brusing [target]'s chest!",
+ "[user] screws up!")
+ target.adjustBruteLoss(5)
diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm
index c4fadb46c4c..d517e435111 100755
--- a/code/modules/surgery/organs/stomach.dm
+++ b/code/modules/surgery/organs/stomach.dm
@@ -18,30 +18,40 @@
var/disgust_metabolism = 1
-/obj/item/organ/stomach/on_life()
- var/mob/living/carbon/human/H = owner
- var/datum/reagent/Nutri
+/obj/item/organ/stomach/Initialize()
+ . = ..()
+ create_reagents(1000)
- ..()
- if(istype(H))
+/obj/item/organ/stomach/on_life()
+ . = ..()
+
+ //Manage species digestion
+ if(istype(owner, /mob/living/carbon/human))
+ var/mob/living/carbon/human/humi = owner
if(!(organ_flags & ORGAN_FAILING))
- H.dna.species.handle_digestion(H)
- handle_disgust(H)
+ humi.dna.species.handle_digestion(humi)
+
+ //digest food
+ var/mob/living/carbon/body = owner
+ reagents.metabolize(body, can_overdose=TRUE)
+ if(body)
+ handle_disgust(body)
if(damage < low_threshold)
return
- Nutri = locate(/datum/reagent/consumable/nutriment) in H.reagents.reagent_list
+ var/datum/reagent/nutri = locate(/datum/reagent/consumable/nutriment) in reagents.reagent_list
+ if(!nutri)
+ return
- if(Nutri)
- if(prob((damage/40) * Nutri.volume * Nutri.volume))
- H.vomit(damage)
- to_chat(H, "Your stomach reels in pain as you're incapable of holding down all that food!")
+ if(prob(damage * 0.025 * nutri.volume * nutri.volume))
+ body.vomit(damage)
+ to_chat(body, "Your stomach reels in pain as you're incapable of holding down all that food!")
+ return
- else if(Nutri && damage > high_threshold)
- if(prob((damage/10) * Nutri.volume * Nutri.volume))
- H.vomit(damage)
- to_chat(H, "Your stomach reels in pain as you're incapable of holding down all that food!")
+ if(damage > high_threshold && prob(damage * 0.1 * nutri.volume * nutri.volume))
+ body.vomit(damage)
+ to_chat(body, "Your stomach reels in pain as you're incapable of holding down all that food!")
/obj/item/organ/stomach/get_availability(datum/species/S)
return !(NOSTOMACH in S.inherent_traits)
@@ -88,11 +98,42 @@
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "disgust")
..()
+/obj/item/organ/stomach/bone
+ desc = "You have no idea what this strange ball of bones does."
+
+/obj/item/organ/stomach/bone/on_life()
+ var/datum/reagent/consumable/milk/milk = locate(/datum/reagent/consumable/milk) in reagents.reagent_list
+ if(milk)
+ var/mob/living/carbon/body = owner
+ if(milk.volume > 10)
+ reagents.remove_reagent(milk.type, milk.volume - 10)
+ to_chat(owner, "The excess milk is dripping off your bones!")
+ body.heal_bodypart_damage(1.5,0, 0)
+ for(var/i in body.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(2)
+ reagents.remove_reagent(milk.type, milk.metabolization_rate)
+ return ..()
+
/obj/item/organ/stomach/plasmaman
name = "digestive crystal"
icon_state = "stomach-p"
desc = "A strange crystal that is responsible for metabolizing the unseen energy force that feeds plasmamen."
+/obj/item/organ/stomach/plasmaman/on_life()
+ var/datum/reagent/consumable/milk/milk = locate(/datum/reagent/consumable/milk) in reagents.reagent_list
+ if(milk)
+ var/mob/living/carbon/body = owner
+ if(milk.volume > 10)
+ reagents.remove_reagent(milk.type, milk.volume - 10)
+ to_chat(owner, "The excess milk is dripping off your bones!")
+ body.heal_bodypart_damage(1.5,0, 0)
+ for(var/i in body.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(2)
+ reagents.remove_reagent(milk.type, milk.metabolization_rate)
+ return ..()
+
/obj/item/organ/stomach/ethereal
name = "biological battery"
icon_state = "stomach-p" //Welp. At least it's more unique in functionaliy.
diff --git a/code/modules/surgery/stomachpump.dm b/code/modules/surgery/stomachpump.dm
index 89c3233720b..a07f45a9f4c 100644
--- a/code/modules/surgery/stomachpump.dm
+++ b/code/modules/surgery/stomachpump.dm
@@ -15,8 +15,6 @@
/datum/surgery/stomach_pump/can_start(mob/user, mob/living/carbon/target)
var/obj/item/organ/stomach/S = target.getorganslot(ORGAN_SLOT_STOMACH)
- if(target.stat != DEAD) //shamelessly lifted off the revival surgery but we're looking for the same critera here, a dead, non-husked, revivable patient.
- return FALSE
if(HAS_TRAIT(target, TRAIT_HUSK))
return FALSE
if(!S)
diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm
index 6ed7f36020f..bd58c70c3f9 100644
--- a/code/modules/surgery/tools.dm
+++ b/code/modules/surgery/tools.dm
@@ -423,3 +423,18 @@
attack_verb_simple = list("correct", "properly set")
tool_behaviour = TOOL_BONESET
toolspeed = 1
+
+/obj/item/blood_filter
+ name = "blood filter"
+ desc = "For filtering the blood."
+ icon = 'icons/obj/surgery.dmi'
+ icon_state = "bloodfilter"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ custom_materials = list(/datum/material/iron=2000, /datum/material/glass=1500, /datum/material/silver=500)
+ item_flags = SURGICAL_TOOL
+ w_class = WEIGHT_CLASS_NORMAL
+ attack_verb_continuous = list("pumps", "siphons")
+ attack_verb_simple = list("pumps", "siphons")
+ tool_behaviour = TOOL_BLOODFILTER
+ toolspeed = 1
diff --git a/icons/mob/inhands/equipment/medical_lefthand.dmi b/icons/mob/inhands/equipment/medical_lefthand.dmi
index 2e05ca17cd9..a47b319c5ff 100644
Binary files a/icons/mob/inhands/equipment/medical_lefthand.dmi and b/icons/mob/inhands/equipment/medical_lefthand.dmi differ
diff --git a/icons/mob/inhands/equipment/medical_righthand.dmi b/icons/mob/inhands/equipment/medical_righthand.dmi
index a570a3cd189..d72231c4b94 100644
Binary files a/icons/mob/inhands/equipment/medical_righthand.dmi and b/icons/mob/inhands/equipment/medical_righthand.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 68d1bd6f35a..c681bcfd235 100755
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 93653898e7e..6a4b636ef28 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3052,6 +3052,7 @@
#include "code\modules\station_goals\shield.dm"
#include "code\modules\station_goals\station_goal.dm"
#include "code\modules\surgery\amputation.dm"
+#include "code\modules\surgery\blood_filter.dm"
#include "code\modules\surgery\bone_mending.dm"
#include "code\modules\surgery\brain_surgery.dm"
#include "code\modules\surgery\burn_dressing.dm"