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