diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm
index 5a0132f6bd8..8cd5affe814 100644
--- a/code/modules/mob/living/carbon/brain/brain_item.dm
+++ b/code/modules/mob/living/carbon/brain/brain_item.dm
@@ -102,6 +102,13 @@
desc = "A complex, organic knot of jelly and crystalline particles."
icon = 'icons/mob/slimes.dmi'
icon_state = "green slime extract"
+ parent_organ = "chest"
+
+/obj/item/organ/brain/slime/take_damage(var/amount)
+ //Slimes are 50% more vulnerable to brain damage
+ src.damage = between(0, src.damage + (0.5*amount), max_damage) //Since they take the damage twice, this is +50%
+ return ..()
+
/obj/item/organ/brain/golem
name = "chem"
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 57c29c3d51d..3ff04b2885e 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1461,6 +1461,8 @@
if(species.default_language)
remove_language(species.default_language)
+ species.handle_pre_change(src)
+
species = all_species[new_species]
if(oldspecies)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 8677aa80420..158ab7f8056 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -70,6 +70,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
handle_pain()
handle_heartbeat()
handle_heartattack()
+ species.handle_life(src)
if(!client)
species.handle_npc(src)
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index cfb04c5427d..c4660aae24c 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -613,4 +613,19 @@ It'll return null if the organ doesn't correspond, so include null checks when u
/datum/species/proc/return_organ(var/organ_slot)
if(!(organ_slot in has_organ))
return null
- return has_organ[organ_slot]
\ No newline at end of file
+ return has_organ[organ_slot]
+
+// Do species-specific reagent handling here
+// Return 1 if it should do normal processing too
+// Return 0 if it shouldn't deplete and do its normal effect
+// Other return values will cause weird badness
+/datum/species/proc/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R)
+ return 1
+
+// For special snowflake species effects
+// (Slime People changing color based on the reagents they consume)
+/datum/species/proc/handle_life(var/mob/living/carbon/human/H)
+ return 1
+
+/datum/species/proc/handle_pre_change(var/mob/living/carbon/human/H)
+ return 0
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm
index 349b28b6efb..12f2b8f168a 100644
--- a/code/modules/mob/living/carbon/human/species/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station.dm
@@ -55,7 +55,7 @@
flesh_color = "#34AF10"
reagent_tag = PROCESS_ORG
base_color = "#066000"
-
+
suicide_messages = list(
"is attempting to bite their tongue off!",
"is jamming their claws into their eye sockets!",
@@ -106,7 +106,7 @@
reagent_tag = PROCESS_ORG
flesh_color = "#AFA59E"
base_color = "#333333"
-
+
suicide_messages = list(
"is attempting to bite their tongue off!",
"is jamming their claws into their eye sockets!",
@@ -147,7 +147,7 @@
reagent_tag = PROCESS_ORG
flesh_color = "#966464"
base_color = "#B43214"
-
+
suicide_messages = list(
"is attempting to bite their tongue off!",
"is jamming their claws into their eye sockets!",
@@ -224,7 +224,7 @@
flesh_color = "#808D11"
reagent_tag = PROCESS_ORG
-
+
suicide_messages = list(
"is attempting to bite their tongue off!",
"is jamming their claws into their eye sockets!",
@@ -317,7 +317,7 @@
"eyes" = /obj/item/organ/eyes,
"stack" = /obj/item/organ/stack/vox
)
-
+
suicide_messages = list(
"is attempting to bite their tongue off!",
"is jamming their claws into their eye sockets!",
@@ -343,7 +343,7 @@
dietflags = DIET_HERB
blood_color = "#FB9800"
reagent_tag = PROCESS_ORG
-
+
suicide_messages = list(
"is attempting to bite their antenna off!",
"is jamming their claws into their eye sockets!",
@@ -360,6 +360,17 @@
path = /mob/living/carbon/human/slime
unarmed_type = /datum/unarmed_attack/punch
+ burn_mod = 1.5 // Slimes don't react well to extreme temperatures
+
+ // More sensitive to the cold
+ cold_level_1 = 280
+ cold_level_2 = 240
+ cold_level_3 = 200
+
+ heat_level_1 = 340
+ heat_level_2 = 360
+ heat_level_3 = 400
+
flags = IS_WHITELISTED | NO_BREATHE | HAS_LIPS | NO_INTORGANS | NO_SCAN
clothing_flags = HAS_SOCKS
bodyflags = HAS_SKIN_COLOR | NO_EYES
@@ -371,11 +382,113 @@
has_organ = list(
"brain" = /obj/item/organ/brain/slime
)
-
+
+ has_limbs = list(
+ "chest" = list("path" = /obj/item/organ/external/chest/slime),
+ "groin" = list("path" = /obj/item/organ/external/groin/slime),
+ "head" = list("path" = /obj/item/organ/external/head/slime),
+ "l_arm" = list("path" = /obj/item/organ/external/arm/slime),
+ "r_arm" = list("path" = /obj/item/organ/external/arm/right/slime),
+ "l_leg" = list("path" = /obj/item/organ/external/leg/slime),
+ "r_leg" = list("path" = /obj/item/organ/external/leg/right/slime),
+ "l_hand" = list("path" = /obj/item/organ/external/hand/slime),
+ "r_hand" = list("path" = /obj/item/organ/external/hand/right/slime),
+ "l_foot" = list("path" = /obj/item/organ/external/foot/slime),
+ "r_foot" = list("path" = /obj/item/organ/external/foot/right/slime)
+ )
+
suicide_messages = list(
"is melting into a puddle!",
"is turning a dull, brown color and melting into a puddle!")
+/datum/species/slime/handle_life(var/mob/living/carbon/human/H)
+ // Slowly shifting to the color of the reagents
+ if(H.reagents.total_volume > 0.1)
+ var/blood_amount = H.vessel.total_volume
+ var/r_color = mix_color_from_reagents(H.reagents.reagent_list)
+ var/new_body_color = BlendRGB(r_color, rgb(H.r_skin, H.g_skin, H.b_skin), blood_amount/(blood_amount+(H.reagents.total_volume)))
+ var/list/new_color_list = ReadRGB(new_body_color)
+ H.r_skin = new_color_list[1]
+ H.g_skin = new_color_list[2]
+ H.b_skin = new_color_list[3]
+ if(world.time % 200 == 42) // Once every 20 seconds - update_body is expensive
+ for(var/organname in H.organs_by_name)
+ var/obj/item/organ/external/E = H.organs_by_name[organname]
+ if(E.dna.species == "Slime People")
+ E.sync_colour_to_human(E)
+ H.update_body()
+ return ..()
+
+/mob/living/carbon/human/proc/regrow_limbs()
+ set category = "IC"
+ set name = "Regrow Limbs"
+ set desc = "Regrow one of your missing limbs at the cost of a large amount of hunger"
+
+ var/const/hungercost = 200
+ var/const/minhunger = 400
+
+ if(stat || paralysis || stunned || weakened)
+ src << "You cannot regenerate missing limbs in your current state."
+ return
+
+ if(nutrition < minhunger)
+ src << "You're too hungry to regenerate a limb!"
+ return
+
+ var/list/missing_limbs = list()
+ for(var/l in src.organs_by_name)
+ var/obj/item/organ/external/E = src.organs_by_name[l]
+ if(!istype(E) || istype(E, /obj/item/organ/external/stump))
+ var/obj/item/organ/external/limb = src.species.has_limbs[l]
+ world << "[l] is missing!"
+ world << "Checking that [l]'s parent [initial(limb.parent_organ)] is in [src]'s organs!"
+ if(!(initial(limb.parent_organ) in src.organs_by_name))
+ world << "[initial(limb.parent_organ)] is not in [src]'s organs!"
+ continue
+ world << "[initial(limb.parent_organ)] is in [src]'s organs!"
+ missing_limbs |= l
+
+ if(missing_limbs.len == 0)
+ src << "You're not missing any limbs!"
+ return
+
+ var/chosen_limb = input(src, "Choose a limb to regrow", "Limb Regrowth") as null|anything in missing_limbs
+
+ if(do_after(src, 200, needhand=0))
+ if(stat || paralysis || stunned || weakened)
+ src << "You cannot regenerate missing limbs in your current state."
+ return
+
+ if(nutrition < minhunger)
+ src << "You're too hungry to regenerate a limb!"
+ return
+
+ if(istype(src.organs[chosen_limb], /obj/item/organ/external) && !istype(src.organs[chosen_limb], /obj/item/organ/external/stump))
+ src << "Your limb has already been replaced in some way!"
+ return
+
+ if(istype(src.organs[chosen_limb], /obj/item/organ/external/stump))
+ qdel(src.organs[chosen_limb])
+
+ var/limb_path = src.species.has_limbs[chosen_limb]
+ var/obj/item/organ/external/new_limb = new limb_path(src)
+ new_limb.owner = src // This line is probably unneeded but will shut up the compiler
+ src.update_body()
+ src.updatehealth()
+ src.UpdateDamageIcon()
+ nutrition -= hungercost
+ return
+ else
+ src << "You need to hold still in order to regrow a limb!"
+
+/datum/species/slime/handle_post_spawn(var/mob/living/carbon/human/H)
+ ..()
+ H.verbs += /mob/living/carbon/human/proc/regrow_limbs
+
+/datum/species/slime/handle_pre_change(var/mob/living/carbon/human/H)
+ ..()
+ H.verbs -= /mob/living/carbon/human/proc/regrow_limbs
+
/datum/species/grey
name = "Grey"
name_plural = "Greys"
@@ -475,7 +588,7 @@
"l_foot" = list("path" = /obj/item/organ/external/diona/foot),
"r_foot" = list("path" = /obj/item/organ/external/diona/foot/right)
)
-
+
suicide_messages = list(
"is losing branches!",
"is pulling themselves apart!")
@@ -572,7 +685,7 @@
"l_foot" = list("path" = /obj/item/organ/external/foot/ipc),
"r_foot" = list("path" = /obj/item/organ/external/foot/right/ipc)
)
-
+
suicide_messages = list(
"is powering down!",
"is smashing their own monitor!",
@@ -587,3 +700,7 @@
/datum/species/machine/handle_post_spawn(var/mob/living/carbon/human/H)
..()
H.verbs += /mob/living/carbon/human/proc/change_monitor
+
+/datum/species/machine/handle_pre_change(var/mob/living/carbon/human/H)
+ ..()
+ H.verbs -= /mob/living/carbon/human/proc/change_monitor
\ No newline at end of file
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index f6c08a20d84..96762bf6acd 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -34,6 +34,7 @@
var/list/wounds = list()
var/number_wounds = 0 // cache the number of wounds, which is NOT wounds.len!
var/perma_injury = 0
+ var/fail_at_full_damage = 0
var/obj/item/organ/external/parent
@@ -146,6 +147,7 @@
// Robot parts also lack bones
// This is so surgery isn't kaput, let's see how this does
encased = null
+ fail_at_full_damage = 1
/****************************************************
DAMAGE PROCS
@@ -208,7 +210,7 @@
burn = max(0, burn - can_inflict)
//If there are still hurties to dispense
if (burn || brute)
- if (status & ORGAN_ROBOT && body_part != UPPER_TORSO && body_part != LOWER_TORSO)
+ if ((status & ORGAN_ROBOT || fail_at_full_damage) && body_part != UPPER_TORSO && body_part != LOWER_TORSO)
droplimb(1) //Robot limbs just kinda fail at full damage.
else
//List organs we can pass it to
diff --git a/code/modules/organs/organ_stump.dm b/code/modules/organs/organ_stump.dm
index 1f9cdb1217b..c850575efde 100644
--- a/code/modules/organs/organ_stump.dm
+++ b/code/modules/organs/organ_stump.dm
@@ -1,6 +1,7 @@
/obj/item/organ/external/stump
name = "limb stump"
icon_name = ""
+ var/can_intake_reagents = 0
/obj/item/organ/external/stump/New(var/mob/living/carbon/holder, var/internal, var/obj/item/organ/external/limb)
if(istype(limb))
@@ -23,4 +24,5 @@
qdel(src)
/obj/item/organ/external/stump/is_usable()
- return 0
\ No newline at end of file
+ return 0
+
diff --git a/code/modules/organs/subtypes/slime.dm b/code/modules/organs/subtypes/slime.dm
new file mode 100644
index 00000000000..90e57d5c185
--- /dev/null
+++ b/code/modules/organs/subtypes/slime.dm
@@ -0,0 +1,47 @@
+/obj/item/organ/external/head/slime
+ vital = 0
+ max_damage = 50
+ min_broken_damage = 30
+ cannot_break = 1
+ encased = null
+ fail_at_full_damage = 1
+
+/obj/item/organ/external/chest/slime
+ encased = null
+ cannot_break = 1
+
+/obj/item/organ/external/groin/slime
+ cannot_break = 1
+
+/obj/item/organ/external/arm/slime
+ cannot_break = 1
+ fail_at_full_damage = 1
+
+/obj/item/organ/external/arm/right/slime
+ cannot_break = 1
+ fail_at_full_damage = 1
+
+/obj/item/organ/external/leg/slime
+ cannot_break = 1
+ fail_at_full_damage = 1
+
+/obj/item/organ/external/leg/right/slime
+ cannot_break = 1
+ fail_at_full_damage = 1
+
+/obj/item/organ/external/foot/slime
+ cannot_break = 1
+ fail_at_full_damage = 1
+
+/obj/item/organ/external/foot/right/slime
+ cannot_break = 1
+ fail_at_full_damage = 1
+
+/obj/item/organ/external/hand/slime
+ cannot_break = 1
+ fail_at_full_damage = 1
+
+/obj/item/organ/external/hand/right/slime
+ cannot_break = 1
+ fail_at_full_damage = 1
+
diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm
index 9bfb67034ab..f75101b0298 100644
--- a/code/modules/surgery/bones.dm
+++ b/code/modules/surgery/bones.dm
@@ -16,7 +16,7 @@
can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
- return affected && !(affected.status & ORGAN_ROBOT) && affected.open == 2 && affected.stage == 0
+ return affected && !(affected.status & ORGAN_ROBOT) && !(affected.cannot_break) && affected.open == 2 && affected.stage == 0
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
diff --git a/paradise.dme b/paradise.dme
index e31271b9e11..5442ec1df3e 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1575,6 +1575,7 @@
#include "code\modules\organs\subtypes\machine.dm"
#include "code\modules\organs\subtypes\misc.dm"
#include "code\modules\organs\subtypes\nucleation.dm"
+#include "code\modules\organs\subtypes\slime.dm"
#include "code\modules\organs\subtypes\standard.dm"
#include "code\modules\organs\subtypes\unbreakable.dm"
#include "code\modules\organs\subtypes\wryn.dm"