diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index 145e29a834e..2f1417fe1e8 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -64,6 +64,8 @@
#define MAX_MANIA_SEVERITY 100 //how high the mania severity can go
#define MANIA_DAMAGE_TO_CONVERT 90 //how much damage is required before it'll convert affected targets
+#define STATUS_EFFECT_CHOKINGSTRAND /datum/status_effect/strandling //Choking Strand
+
#define STATUS_EFFECT_HISWRATH /datum/status_effect/his_wrath //His Wrath.
#define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost and can't use manifest runes
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 751ef8bc6a3..b1cd0092962 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -65,6 +65,9 @@
#define TRAIT_ABDUCTOR_TRAINING "abductor-training"
#define TRAIT_ABDUCTOR_SCIENTIST_TRAINING "abductor-scientist-training"
#define TRAIT_SURGEON "surgeon"
+#define TRAIT_STRONG_GRABBER "strong_grabber"
+#define TRAIT_CALCIUM_HEALER "calcium_healer"
+#define TRAIT_MAGIC_CHOKE "magic_choke"
#define TRAIT_SOOTHED_THROAT "soothed-throat"
#define TRAIT_LAW_ENFORCEMENT_METABOLISM "law-enforcement-metabolism"
#define TRAIT_ALWAYS_CLEAN "always-clean"
diff --git a/code/datums/components/footstep.dm b/code/datums/components/footstep.dm
index 683deddd337..fa6ea8b0576 100644
--- a/code/datums/components/footstep.dm
+++ b/code/datums/components/footstep.dm
@@ -92,8 +92,11 @@
TRUE,
GLOB.footstep[T.footstep][3] + e)
- if(!H.shoes && !feetCover) //are we NOT wearing shoes?
- playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
- GLOB.barefootstep[T.barefootstep][2] * v,
- TRUE,
- GLOB.barefootstep[T.barefootstep][3] + e)
\ No newline at end of file
+ if((!H.shoes && !feetCover) || !(H.mobility_flags & MOBILITY_STAND)) //are we NOT wearing shoes or are we lying/crawling (using hands to move around)?
+ if(H.dna.species.special_step_sounds)
+ playsound(T, pick(H.dna.species.special_step_sounds), 50, TRUE)
+ else
+ playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
+ GLOB.barefootstep[T.barefootstep][2] * v,
+ TRUE,
+ GLOB.barefootstep[T.barefootstep][3] + e)
\ No newline at end of file
diff --git a/code/datums/footstep.dm b/code/datums/footstep.dm
deleted file mode 100644
index f312aba3c1a..00000000000
--- a/code/datums/footstep.dm
+++ /dev/null
@@ -1,99 +0,0 @@
-/datum/component/footstep
- var/steps = 0
- var/volume
- var/e_range
-
-/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
- if(!isliving(parent))
- return COMPONENT_INCOMPATIBLE
- volume = volume_
- e_range = e_range_
- RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
-
-/datum/component/footstep/proc/play_footstep()
- var/turf/open/T = get_turf(parent)
- if(!istype(T))
- return
-
- var/mob/living/LM = parent
- var/v = volume
- var/e = e_range
- if(!T.footstep || LM.buckled || !CHECK_MULTIPLE_BITFIELDS(LM.mobility_flags, MOBILITY_STAND | MOBILITY_MOVE) || LM.throwing || LM.movement_type & (VENTCRAWLING | FLYING) || (LM.stat != CONSCIOUS) || LM.incapacitated() || LM.IsStun() || LM.IsParalyzed())
- return
-
- if(iscarbon(LM))
- var/mob/living/carbon/C = LM
- if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
- return
- if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
- v /= 2
- e -= 5
- steps++
-
- if(steps >= 6)
- steps = 0
-
- if(steps % 2)
- return
-
- if(!LM.has_gravity(T) && steps != 0) // don't need to step as often when you hop around
- return
-
- //begin playsound shenanigans//
-
- //for barefooted non-clawed mobs like monkeys
- if(isbarefoot(LM))
- playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
- GLOB.barefootstep[T.barefootstep][2] * v,
- TRUE,
- GLOB.barefootstep[T.barefootstep][3] + e)
- return
-
- //for xenomorphs, dogs, and other clawed mobs
- if(isclawfoot(LM))
- if(isalienadult(LM)) //xenos are stealthy and get quieter footsteps
- v /= 3
- e -= 3
-
- playsound(T, pick(GLOB.clawfootstep[T.clawfootstep][1]),
- GLOB.clawfootstep[T.clawfootstep][2] * v,
- TRUE,
- GLOB.clawfootstep[T.clawfootstep][3] + e)
- return
-
- //for megafauna and other large and imtimidating mobs such as the bloodminer
- if(isheavyfoot(LM))
- playsound(T, pick(GLOB.heavyfootstep[T.heavyfootstep][1]),
- GLOB.heavyfootstep[T.heavyfootstep][2] * v,
- TRUE,
- GLOB.heavyfootstep[T.heavyfootstep][3] + e)
- return
-
- //for slimes
- if(isslime(LM))
- playsound(T, 'sound/effects/footstep/slime1.ogg', 15 * v)
- return
-
- //for (simple) humanoid mobs (clowns, russians, pirates, etc.)
- if(isshoefoot(LM))
- if(!ishuman(LM))
- playsound(T, pick(GLOB.footstep[T.footstep][1]),
- GLOB.footstep[T.footstep][2] * v,
- TRUE,
- GLOB.footstep[T.footstep][3] + e)
- return
- if(ishuman(LM)) //for proper humans, they're special
- var/mob/living/carbon/human/H = LM
- var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET))
-
- if(H.shoes || feetCover) //are we wearing shoes
- playsound(T, pick(GLOB.footstep[T.footstep][1]),
- GLOB.footstep[T.footstep][2] * v,
- TRUE,
- GLOB.footstep[T.footstep][3] + e)
-
- if((!H.shoes && !feetCover) || !(H.mobility_flags & MOBILITY_STAND)) //are we NOT wearing shoes or are we lying/crawling (using hands to move around)?
- playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
- GLOB.barefootstep[T.barefootstep][2] * v,
- TRUE,
- GLOB.barefootstep[T.barefootstep][3] + e)
\ No newline at end of file
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index bd615ef7366..f617ade5c72 100644
--- a/code/datums/mood_events/generic_negative_events.dm
+++ b/code/datums/mood_events/generic_negative_events.dm
@@ -137,6 +137,16 @@
mood_change = -5
timeout = 600
+/datum/mood_event/spooked
+ description = "The rattling of those bones...It still haunts me.\n"
+ mood_change = -4
+ timeout = 2400
+
+/datum/mood_event/loud_gong
+ description = "That loud gong noise really hurt my ears!\n"
+ mood_change = -3
+ timeout = 1200
+
/datum/mood_event/notcreeping
description = "I sure wish I was around my obsession...\n"
mood_change = -6
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index f719af523b3..6802926e7de 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -82,6 +82,51 @@
desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are."
icon_state = "asleep"
+
+//GOLEM GANG
+
+//OTHER DEBUFFS
+/datum/status_effect/strandling //get it, strand as in durathread strand + strangling = strandling hahahahahahahahahahhahahaha i want to die
+ id = "strandling"
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = /obj/screen/alert/status_effect/strandling
+
+/datum/status_effect/strandling/on_apply()
+ owner.add_trait(TRAIT_MAGIC_CHOKE, "dumbmoron")
+ return ..()
+
+/datum/status_effect/strandling/on_remove()
+ owner.remove_trait(TRAIT_MAGIC_CHOKE, "dumbmoron")
+ return ..()
+
+/obj/screen/alert/status_effect/strandling
+ name = "Choking strand"
+ desc = "A magical strand of Durathread is wrapped around your neck, preventing you from breathing! Click this icon to remove the strand."
+ icon_state = "his_grace"
+ alerttooltipstyle = "hisgrace"
+
+/obj/screen/alert/status_effect/strandling/Click(location, control, params)
+ . = ..()
+ to_chat(mob_viewer, "You attempt to remove the durathread strand from around your neck.")
+ if(do_after(mob_viewer, 35, null, mob_viewer))
+ if(isliving(mob_viewer))
+ var/mob/living/L = mob_viewer
+ to_chat(mob_viewer, "You succesfuly remove the durathread strand.")
+ L.remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
+
+
+/datum/status_effect/pacify/on_creation(mob/living/new_owner, set_duration)
+ if(isnum(set_duration))
+ duration = set_duration
+ . = ..()
+
+/datum/status_effect/pacify/on_apply()
+ owner.add_trait(TRAIT_PACIFISM, "status_effect")
+ return ..()
+
+/datum/status_effect/pacify/on_remove()
+ owner.remove_trait(TRAIT_PACIFISM, "status_effect")
+
//OTHER DEBUFFS
/datum/status_effect/pacify
id = "pacify"
diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm
index b071062edca..c4de2bcb738 100644
--- a/code/game/objects/items/tools/wirecutters.dm
+++ b/code/game/objects/items/tools/wirecutters.dm
@@ -53,6 +53,11 @@
user.visible_message("[user] cuts [C]'s restraints with [src]!")
qdel(C.handcuffed)
return
+ else if(istype(C) && C.has_status_effect(STATUS_EFFECT_CHOKINGSTRAND))
+ to_chat(C, "You attempt to remove the durathread strand from around your neck.")
+ if(do_after(user, 15, null, C))
+ to_chat(C, "You succesfuly remove the durathread strand.")
+ C.remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
else
..()
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index 1347bd2376d..8b825bfc5f5 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -149,6 +149,9 @@
log_admin("[key_name(new_spawn)] possessed a golem shell enslaved to [key_name(owner)].")
if(ishuman(new_spawn))
var/mob/living/carbon/human/H = new_spawn
+ if(has_owner)
+ var/datum/species/golem/G = H.dna.species
+ G.owner = owner
H.set_cloned_appearance()
if(!name)
if(has_owner)
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index c3bd70841ec..f0349ec4ae4 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -350,7 +350,7 @@
if(istype(ears) && (deafen_pwr || damage_pwr))
var/ear_damage = damage_pwr * effect_amount
- var/deaf = max(ears.deaf, deafen_pwr * effect_amount)
+ var/deaf = deafen_pwr * effect_amount
adjustEarDamage(ear_damage,deaf)
if(ears.ear_damage >= 15)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index fec4461f7bf..32b34eb698f 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -968,6 +968,21 @@
/mob/living/carbon/human/species/golem/plastic
race = /datum/species/golem/plastic
+/mob/living/carbon/human/species/golem/bronze
+ race = /datum/species/golem/bronze
+
+/mob/living/carbon/human/species/golem/cardboard
+ race = /datum/species/golem/cardboard
+
+/mob/living/carbon/human/species/golem/leather
+ race = /datum/species/golem/leather
+
+/mob/living/carbon/human/species/golem/bone
+ race = /datum/species/golem/bone
+
+/mob/living/carbon/human/species/golem/durathread
+ race = /datum/species/golem/durathread
+
/mob/living/carbon/human/species/golem/clockwork
race = /datum/species/golem/clockwork
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index aaa757cf6e4..8b297333419 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -649,8 +649,17 @@
return
if(src == M)
+ if(has_status_effect(STATUS_EFFECT_CHOKINGSTRAND))
+ to_chat(src, "You attempt to remove the durathread strand from around your neck.")
+ if(do_after(src, 35, null, src))
+ to_chat(src, "You succesfuly remove the durathread strand.")
+ remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
+ return
+ visible_message("[src] examines [p_them()]self.", \
+ "You check yourself for injuries.")
check_self_for_injuries()
+
else
if(wear_suit)
wear_suit.add_fingerprint(M)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 67214d0bb51..f35e5b1ddec 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -47,6 +47,8 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/fixed_mut_color = "" //to use MUTCOLOR with a fixed color that's independent of dna.feature["mcolor"]
var/inert_mutation = DWARFISM //special mutation that can be found in the genepool. Dont leave empty or changing species will be a headache
var/deathsound //used to set the mobs deathsound on species change
+ var/list/special_step_sounds //Sounds to override barefeet walkng
+ var/grab_sound //Special sound for grabbing
// species-only traits. Can be found in DNA.dm
var/list/species_traits = list()
@@ -1219,6 +1221,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
+ user.dna.species.spec_unarmedattacked(user, target)
if(user.limb_destroyer)
target.dismembering_strike(user, affecting.body_zone)
@@ -1232,6 +1235,9 @@ GLOBAL_LIST_EMPTY(roundstart_races)
else if(!(target.mobility_flags & MOBILITY_STAND))
target.forcesay(GLOB.hit_appends)
+/datum/species/proc/spec_unarmedattacked(mob/living/carbon/human/user, mob/living/carbon/human/target)
+ return
+
/datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(target.check_block())
target.visible_message("[target] blocks [user]'s disarm attempt!")
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 6a7384b4f62..8aa2f26f468 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -30,6 +30,7 @@
var/list/special_names = list("Tarkus")
var/human_surname_chance = 3
var/special_name_chance = 5
+ var/owner //dobby is a free golem
/datum/species/golem/random_name(gender,unique,lastname)
var/golem_surname = pick(GLOB.golem_names)
@@ -807,3 +808,204 @@
/datum/species/golem/plastic/on_species_loss(mob/living/carbon/C)
. = ..()
C.ventcrawler = initial(C.ventcrawler)
+
+/datum/species/golem/bronze
+ name = "Bronze Golem"
+ id = "bronze golem"
+ prefix = "Bronze"
+ special_names = list("Bell")
+ fixed_mut_color = "cd7f32"
+ info_text = "As a Bronze Golem, you are very resistant to loud noises, and make loud noises if something hard hits you, however this ability does hurt your hearing."
+ special_step_sounds = list('sound/machines/clockcult/integration_cog_install.ogg', 'sound/magic/clockwork/fellowship_armory.ogg' )
+ mutantears = /obj/item/organ/ears/bronze
+ var/last_gong_time = 0
+ var/gong_cooldown = 150
+
+/datum/species/golem/bronze/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
+ if(!(world.time > last_gong_time + gong_cooldown))
+ return 0
+ if(P.flag == "bullet" || P.flag == "bomb")
+ gong(H)
+ return 0
+
+/datum/species/golem/bronze/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
+ ..()
+ if(world.time > last_gong_time + gong_cooldown)
+ gong(H)
+
+/datum/species/golem/bronze/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
+ ..()
+ if(world.time > last_gong_time + gong_cooldown && M.a_intent != INTENT_HELP)
+ gong(H)
+
+/datum/species/golem/bronze/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
+ ..()
+ if(world.time > last_gong_time + gong_cooldown)
+ gong(H)
+
+/datum/species/golem/bronze/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
+ ..()
+ if(world.time > last_gong_time + gong_cooldown)
+ gong(H)
+
+/datum/species/golem/bronze/proc/gong(mob/living/carbon/human/H)
+ last_gong_time = world.time
+ for(var/mob/living/M in get_hearers_in_view(7,H))
+ if(M.stat == DEAD) //F
+ return
+ if(M == H)
+ H.show_message("You cringe with pain as your body rings around you!", 2)
+ H.playsound_local(H, 'sound/effects/gong.ogg', 100, TRUE)
+ H.soundbang_act(2, 0, 100, 1)
+ H.jitteriness += 7
+ var/distance = max(0,get_dist(get_turf(H),get_turf(M)))
+ switch(distance)
+ if(0 to 1)
+ M.show_message("GONG!", 2)
+ M.playsound_local(H, 'sound/effects/gong.ogg', 100, TRUE)
+ M.soundbang_act(1, 0, 30, 3)
+ M.confused += 10
+ M.jitteriness += 4
+ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "gonged", /datum/mood_event/loud_gong)
+ if(2 to 3)
+ M.show_message("GONG!", 2)
+ M.playsound_local(H, 'sound/effects/gong.ogg', 75, TRUE)
+ M.soundbang_act(1, 0, 15, 2)
+ M.jitteriness += 3
+ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "gonged", /datum/mood_event/loud_gong)
+ else
+ M.show_message("GONG!", 2)
+ M.playsound_local(H, 'sound/effects/gong.ogg', 50, TRUE)
+
+
+/datum/species/golem/cardboard //Faster but weaker, can also make new shells on its own
+ name = "Cardboard Golem"
+ id = "cardboard golem"
+ prefix = "Cardboard"
+ special_names = list("Box")
+ info_text = "As a Cardboard Golem, you aren't very strong, but you are a bit quicker and can easily create more brethren by using cardboard on yourself."
+ species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES)
+ inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
+ limbs_id = "c_golem" //special sprites
+ attack_verb = "whips"
+ attack_sound = 'sound/weapons/whip.ogg'
+ miss_sound = 'sound/weapons/etherealmiss.ogg'
+ fixed_mut_color = null
+ armor = 25
+ burnmod = 1.25
+ heatmod = 2
+ speedmod = 1.5
+ punchdamagelow = 4
+ punchstunthreshold = 7
+ punchdamagehigh = 8
+ var/last_creation
+ var/brother_creation_cooldown = 300
+
+/datum/species/golem/cardboard/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
+ . = ..()
+ if(user != H || intent != INTENT_HELP)
+ return FALSE //forced reproduction is rape.
+ if(istype(I, /obj/item/stack/sheet/cardboard))
+ var/obj/item/stack/sheet/cardboard/C = I
+ if(last_creation + brother_creation_cooldown < world.time) //no cheesing dork
+ return
+ to_chat(H, "You attempt to create a new cardboard brother.")
+ if(do_after(user, 30, target = user))
+ if(last_creation + brother_creation_cooldown < world.time) //no cheesing dork
+ return
+ if(!C.use(10))
+ to_chat(H, "You do not have enough cardboard!")
+ return FALSE
+ to_chat(H, "You create a new cardboard golem shell.")
+ create_brother(H.loc)
+
+/datum/species/golem/cardboard/proc/create_brother(var/location)
+ new /obj/effect/mob_spawn/human/golem/servant(location, /datum/species/golem/cardboard, owner)
+ last_creation = world.time
+
+/datum/species/golem/leather
+ name = "Leather Golem"
+ id = "leather golem"
+ special_names = list("Face", "Man")
+ inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER, TRAIT_STRONG_GRABBER)
+ prefix = "Leather"
+ fixed_mut_color = "624a2e"
+ info_text = "As a Leather Golem, you are flammable, but you can grab things with incredible ease, allowing all your grabs to start at a strong level."
+ grab_sound = 'sound/weapons/whipgrab.ogg'
+ attack_sound = 'sound/weapons/whip.ogg'
+
+/datum/species/golem/durathread
+ name = "Durathread Golem"
+ id = "durathread golem"
+ prefix = "Durathread"
+ limbs_id = "d_golem"
+ special_names = list("Boll","Weave")
+ species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES)
+ fixed_mut_color = null
+ inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
+ info_text = "As a Durathread Golem, your strikes will cause those your targets to start choking, but your woven body won't withstand fire as well."
+
+/datum/species/golem/durathread/spec_unarmedattacked(mob/living/carbon/human/user, mob/living/carbon/human/target)
+ . = ..()
+ target.apply_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
+
+/datum/species/golem/bone
+ name = "Bone Golem"
+ id = "bone golem"
+ prefix = "Bone"
+ limbs_id = "b_golem"
+ special_names = list("Head", "Broth", "Fracture")
+ liked_food = GROSS | MEAT | RAW
+ toxic_food = null
+ species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES)
+ inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID)
+ sexes = FALSE
+ fixed_mut_color = null
+ inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_FAKEDEATH,TRAIT_CALCIUM_HEALER)
+ info_text = "As a Bone Golem, You have a powerful spell that lets you chill your enemies with fear, and milk heals you! Just make sure to watch our for bone-hurting juice."
+ var/datum/action/innate/bonechill/bonechill
+
+/datum/species/golem/bone/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ ..()
+ if(ishuman(C))
+ bonechill = new
+ bonechill.Grant(C)
+
+/datum/species/golem/bone/on_species_loss(mob/living/carbon/C)
+ if(bonechill)
+ bonechill.Remove(C)
+ ..()
+
+/datum/action/innate/bonechill
+ name = "Bone Chill"
+ desc = "Rattle your bones and strike fear into your enemies!"
+ check_flags = AB_CHECK_CONSCIOUS
+ icon_icon = 'icons/mob/actions/actions_spells.dmi'
+ button_icon_state = "bonechill"
+ var/cooldown = 600
+ var/last_use
+ var/snas_chance = 3
+
+/datum/action/innate/bonechill/Activate()
+ if(world.time < last_use + cooldown)
+ to_chat("You aren't ready yet to rattle your bones again")
+ owner.visible_message("[owner] rattles [owner.p_their()] bones harrowingly.", "You rattle your bones")
+ last_use = world.time
+ if(prob(snas_chance))
+ playsound(get_turf(owner),'sound/magic/RATTLEMEBONES2.ogg', 100)
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ var/mutable_appearance/badtime = mutable_appearance('icons/mob/human_parts.dmi', "b_golem_eyes", -FIRE_LAYER-0.5)
+ badtime.appearance_flags = RESET_COLOR
+ H.overlays_standing[FIRE_LAYER+0.5] = badtime
+ H.apply_overlay(FIRE_LAYER+0.5)
+ addtimer(CALLBACK(H, /mob/living/carbon/.proc/remove_overlay, FIRE_LAYER+0.5), 25)
+ else
+ playsound(get_turf(owner),'sound/magic/RATTLEMEBONES.ogg', 100)
+ for(var/mob/living/L in orange(7, get_turf(owner)))
+ if((MOB_UNDEAD in L.mob_biotypes) || isgolem(L))
+ return //Do not affect our brothers
+ to_chat(L, "A spine-chilling sound chills you to the bone!")
+ L.apply_status_effect(/datum/status_effect/bonechill)
+ SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "spooked", /datum/mood_event/spooked)
+
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 c6bbc9d2dba..0302bf531ee 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -5,7 +5,7 @@
sexes = 0
meat = /obj/item/stack/sheet/mineral/plasma
species_traits = list(NOBLOOD,NOTRANSSTING)
- inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_NOHUNGER)
+ inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_NOHUNGER, TRAIT_CALCIUM_HEALER)
inherent_biotypes = list(MOB_INORGANIC, MOB_HUMANOID)
mutantlungs = /obj/item/organ/lungs/plasmaman
mutanttongue = /obj/item/organ/tongue/bone/plasmaman
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 d079080eaa6..8539e585dfd 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -7,7 +7,7 @@
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
species_traits = list(NOBLOOD)
- inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH)
+ inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER)
inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID)
mutanttongue = /obj/item/organ/tongue/bone
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 9b14c26991f..1e31954cb0e 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -72,7 +72,7 @@
var/datum/gas_mixture/breath
if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE))
- if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL))
+ if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || has_trait(TRAIT_MAGIC_CHOKE))
losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath
else if(health <= crit_threshold)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 2be289d840b..095253bf933 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -251,14 +251,21 @@
pulling = AM
AM.pulledby = src
if(!supress_message)
- playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ var/sound_to_play = 'sound/weapons/thudswoosh.ogg'
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ if(H.dna.species.grab_sound)
+ sound_to_play = H.dna.species.grab_sound
+ if(H.has_trait(TRAIT_STRONG_GRABBER))
+ sound_to_play = null
+ playsound(src.loc, sound_to_play, 50, 1, -1)
update_pull_hud_icon()
if(ismob(AM))
var/mob/M = AM
log_combat(src, M, "grabbed", addition="passive grab")
- if(!supress_message)
+ if(!supress_message && !(iscarbon(AM) && has_trait(TRAIT_STRONG_GRABBER)))
visible_message("[src] has grabbed [M] passively!")
if(!iscarbon(src))
M.LAssailant = null
@@ -277,6 +284,11 @@
if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
ContactContractDisease(D)
+ if(iscarbon(L))
+ var/mob/living/carbon/C = L
+ if(src.has_trait(TRAIT_STRONG_GRABBER))
+ C.grippedby(src)
+
set_pull_offsets(M, state)
/mob/living/proc/set_pull_offsets(mob/living/M, grab_state = GRAB_PASSIVE)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 625a3170081..f4f6fc15596 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -140,14 +140,18 @@
if(user.has_trait(TRAIT_PACIFISM))
to_chat(user, "You don't want to risk hurting [src]!")
return FALSE
-
grippedby(user)
//proc to upgrade a simple pull into a more aggressive grab.
/mob/living/proc/grippedby(mob/living/carbon/user, instant = FALSE)
if(user.grab_state < GRAB_KILL)
user.changeNext_move(CLICK_CD_GRABBING)
- playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ var/sound_to_play = 'sound/weapons/thudswoosh.ogg'
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.dna.species.grab_sound)
+ sound_to_play = H.dna.species.grab_sound
+ playsound(src.loc, sound_to_play, 50, 1, -1)
if(user.grab_state) //only the first upgrade is instantaneous
var/old_grab_state = user.grab_state
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index f02c8becab9..61980f72660 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -215,15 +215,15 @@
glass_desc = "White and nutritious goodness!"
/datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M)
- if(M.getBruteLoss() && prob(20))
- M.heal_bodypart_damage(1,0, 0)
+ if(M.has_trait(TRAIT_CALCIUM_HEALER))
+ M.heal_bodypart_damage(1.5,0, 0)
. = 1
+ else
+ if(M.getBruteLoss() && prob(20))
+ M.heal_bodypart_damage(1,0, 0)
+ . = 1
if(holder.has_reagent("capsaicin"))
holder.remove_reagent("capsaicin", 2)
- var/datum/dna/Mdna = M.has_dna()
- if(Mdna && Mdna.species && (Mdna.species.id == "plasmaman" || Mdna.species.id == "skeleton"))
- M.heal_bodypart_damage(1,0, 0)
- . = 1
..()
/datum/reagent/consumable/soymilk
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 94918db936d..c48170f6eef 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -921,7 +921,7 @@
/datum/reagent/toxin/bonehurtingjuice/on_mob_life(mob/living/carbon/M)
M.adjustStaminaLoss(15, 0)
- if(M.dna.species.type == /datum/species/skeleton || M.dna.species.type == /datum/species/plasmaman)
+ if(M.has_trait(TRAIT_CALCIUM_HEALER))
M.adjustBruteLoss(0.5, 0)
if(prob(20))
switch(rand(1, 3))
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index d47555ea16b..50eb577973a 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -199,6 +199,33 @@
/datum/status_effect/bloodchill/on_remove()
owner.remove_movespeed_modifier("bloodchilled")
+/obj/screen/alert/status_effect/bloodchill
+ name = "Bloodchilled"
+ desc = "You feel a shiver down your spine after getting hit with a glob of cold blood. You'll move slower and get frostbite for a while!"
+ icon_state = "bloodchill"
+
+/datum/status_effect/bonechill
+ id = "bonechill"
+ duration = 60
+ alert_type = /obj/screen/alert/status_effect/bonechill
+
+/datum/status_effect/bonechill/on_apply()
+ owner.add_movespeed_modifier("bonechilled", TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = 3)
+ return ..()
+
+/datum/status_effect/bonechill/tick()
+ if(prob(50))
+ owner.adjustFireLoss(1)
+ owner.Jitter(3)
+
+/datum/status_effect/bonechill/on_remove()
+ owner.remove_movespeed_modifier("bonechilled")
+
+/obj/screen/alert/status_effect/bonechill
+ name = "Bonechilled"
+ desc = "You feel a shiver down your spine after hearing the haunting noise of bone rattling. You'll move slower and get frostbite for a while!"
+ icon_state = "bloodchill"
+
/datum/status_effect/rebreathing
id = "rebreathing"
duration = -1
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index b0f99ae3c21..87ce7d63819 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -70,7 +70,12 @@
/obj/item/stack/sheet/cloth = /datum/species/golem/cloth,
/obj/item/stack/sheet/mineral/adamantine = /datum/species/golem/adamantine,
/obj/item/stack/sheet/plastic = /datum/species/golem/plastic,
- /obj/item/stack/tile/brass = /datum/species/golem/clockwork)
+ /obj/item/stack/tile/brass = /datum/species/golem/clockwork,
+ /obj/item/stack/tile/bronze = /datum/species/golem/bronze,
+ /obj/item/stack/sheet/cardboard = /datum/species/golem/cardboard,
+ /obj/item/stack/sheet/leather = /datum/species/golem/leather,
+ /obj/item/stack/sheet/bone = /datum/species/golem/bone,
+ /obj/item/stack/sheet/cotton/durathread = /datum/species/golem/durathread)
if(istype(I, /obj/item/stack))
var/obj/item/stack/O = I
diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm
index 5e54de746f7..86d4707eaf5 100644
--- a/code/modules/surgery/organs/ears.dm
+++ b/code/modules/surgery/organs/ears.dm
@@ -111,3 +111,10 @@
if(istype(H))
to_chat(H, "Your sense of balance comes back to you.")
QDEL_NULL(waddle)
+
+/obj/item/organ/ears/bronze
+ name = "tin ears"
+ desc = "The robust ears of a bronze golem. "
+ damage_multiplier = 0.1 //STRONK
+ bang_protect = 1 //Fear me weaklings.
+
diff --git a/icons/mob/actions/actions_spells.dmi b/icons/mob/actions/actions_spells.dmi
index 49f006000a8..e303cf96eb3 100644
Binary files a/icons/mob/actions/actions_spells.dmi and b/icons/mob/actions/actions_spells.dmi differ
diff --git a/icons/mob/human_parts.dmi b/icons/mob/human_parts.dmi
index 0d20842cc9e..1304f37a214 100644
Binary files a/icons/mob/human_parts.dmi and b/icons/mob/human_parts.dmi differ
diff --git a/sound/effects/gong.ogg b/sound/effects/gong.ogg
new file mode 100644
index 00000000000..1e9c3d4e6c5
Binary files /dev/null and b/sound/effects/gong.ogg differ
diff --git a/sound/magic/RATTLEMEBONES.ogg b/sound/magic/RATTLEMEBONES.ogg
new file mode 100644
index 00000000000..e606fa7a851
Binary files /dev/null and b/sound/magic/RATTLEMEBONES.ogg differ
diff --git a/sound/magic/RATTLEMEBONES2.ogg b/sound/magic/RATTLEMEBONES2.ogg
new file mode 100644
index 00000000000..29ff6db510a
Binary files /dev/null and b/sound/magic/RATTLEMEBONES2.ogg differ
diff --git a/sound/weapons/whipgrab.ogg b/sound/weapons/whipgrab.ogg
new file mode 100644
index 00000000000..b05bdd743bb
Binary files /dev/null and b/sound/weapons/whipgrab.ogg differ