From 97db4ecca46ddac5b10f6bd7b2088fc2bd1f5aea Mon Sep 17 00:00:00 2001 From: Jeremiah <42397676+jlsnow301@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:18:24 -0800 Subject: [PATCH] Adds the Cursed quirk (#72317) ## About The Pull Request Adds a silly negative quirk inspired by fallout's bloody mess. Bad luck interactions for - Microwaving - Cigarette coupons - Russian roulette - Vending machines - Ledges - Slipping All of which have a chance to kill you, which, by the way, causes you to **delimb and explode**. This changes the admin smite as well since it's all the omen component. Giving permanent omens will mean the player will gib on death, which is super probable given the insane base damage from bonking your head. Permanent omen smites are basically dooming someone to die of natural causes.
GIFs ![dreamseeker_ZE6hyRdYet](https://user-images.githubusercontent.com/42397676/209779120-f7d76862-91e2-4366-a49d-e93366d96faf.gif) updated: Death no longer fully gibs (carbons) ![dreamseeker_8S8r6B6gMM](https://user-images.githubusercontent.com/42397676/209874302-2e24f581-ffda-42e7-9794-dbe0fff2ff5b.gif) Panic at seeing bad omen coupons ![dreamseeker_tykHbePTSS](https://user-images.githubusercontent.com/42397676/209887936-5d7f5edf-6fa2-41c7-8503-37432b49c7c0.gif) ![3](https://user-images.githubusercontent.com/42397676/209885388-90523f2c-531a-4928-96b2-c902552cbbbc.png)
## Why It's Good For The Game Adds a bit of physical comedy and difficulty for players that want it. ## Changelog :cl: add: Hope you saved for a rainy day: Added the 'Cursed' quirk which causes excessive slippage and... other difficulties. /:cl: Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com> Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: Timberpoes Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com> --- code/__DEFINES/traits.dm | 2 + code/datums/components/omen.dm | 143 +++++++++++++----- code/datums/quirks/negative_quirks.dm | 13 ++ code/game/objects/structures/mirror.dm | 4 +- code/game/turfs/open/_open.dm | 85 ++++++----- code/modules/admin/smites/bad_luck.dm | 8 +- code/modules/cargo/coupon.dm | 39 ++++- .../food_and_drinks/machinery/microwave.dm | 11 +- code/modules/mob/living/carbon/death.dm | 12 +- .../projectiles/guns/ballistic/revolver.dm | 3 + .../religion/sparring/sparring_datum.dm | 2 +- 11 files changed, 230 insertions(+), 92 deletions(-) diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 58e278d4b3a..13cf67dd218 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -147,6 +147,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_BLIND "blind" /// Mute. Can't talk. #define TRAIT_MUTE "mute" +/// Gibs on death and slips like ice. +#define TRAIT_CURSED "cursed" /// Emotemute. Can't... emote. #define TRAIT_EMOTEMUTE "emotemute" #define TRAIT_DEAF "deaf" diff --git a/code/datums/components/omen.dm b/code/datums/components/omen.dm index b7df9006ee4..e3596b903c3 100644 --- a/code/datums/components/omen.dm +++ b/code/datums/components/omen.dm @@ -8,46 +8,44 @@ */ /datum/component/omen dupe_mode = COMPONENT_DUPE_UNIQUE - /// Whatever's causing the omen, if there is one. Destroying the vessel won't stop the omen, but we destroy the vessel (if one exists) upon the omen ending var/obj/vessel - - /// Whether this is a permanent omen that cannot be removed by any non-admin means. + /// If the omen is permanent, it will never go away var/permanent = FALSE + /// Base probability of negative events. Cursed are half as unlucky. + var/luck_mod = 1 + /// Base damage from negative events. Cursed take 25% less damage. + var/damage_mod = 1 -/datum/component/omen/Initialize(silent = FALSE, _vessel, _permanent = FALSE) +/datum/component/omen/Initialize(vessel) if(!isliving(parent)) return COMPONENT_INCOMPATIBLE - vessel = _vessel - permanent = _permanent - if(!silent) - var/warning = "You get a bad feeling..." - if(permanent) - warning += " A very bad feeling... As if you are surrounded by a twisted aura of pure malevolence..." - to_chat(parent, span_warning("[warning]")) + src.vessel = vessel + +/datum/component/omen/Destroy(force) + var/mob/living/person = parent + to_chat(person, span_nicegreen("You feel a horrible omen lifted off your shoulders!")) -/datum/component/omen/Destroy(force, silent) - if(!silent) - var/mob/living/person = parent - to_chat(person, span_nicegreen("You feel a horrible omen lifted off your shoulders!")) if(vessel) vessel.visible_message(span_warning("[vessel] burns up in a sinister flash, taking an evil energy with it...")) vessel = null + return ..() /datum/component/omen/RegisterWithParent() RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(check_accident)) - RegisterSignal(parent, COMSIG_LIVING_STATUS_KNOCKDOWN, PROC_REF(check_slip)) + RegisterSignal(parent, COMSIG_ON_CARBON_SLIP, PROC_REF(check_slip)) RegisterSignal(parent, COMSIG_CARBON_MOOD_UPDATE, PROC_REF(check_bless)) + RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(check_death)) /datum/component/omen/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_MOVABLE_MOVED, COMSIG_CARBON_MOOD_UPDATE)) + UnregisterSignal(parent, list(COMSIG_ON_CARBON_SLIP, COMSIG_MOVABLE_MOVED, COMSIG_CARBON_MOOD_UPDATE, COMSIG_LIVING_DEATH)) /** * check_accident() is called each step we take * - * While we're walking around, roll to see if there's any environmental hazards (currently only vending machines) on one of the adjacent tiles we can trigger. + * While we're walking around, roll to see if there's any environmental hazards on one of the adjacent tiles we can trigger. * We do the prob() at the beginning to A. add some tension for /when/ it will strike, and B. (more importantly) ameliorate the fact that we're checking up to 5 turfs's contents each time */ /datum/component/omen/proc/check_accident(atom/movable/our_guy) @@ -55,11 +53,11 @@ if(!isliving(our_guy)) return - var/mob/living/living_guy = our_guy - if(!prob(15)) + if(!prob(15 * luck_mod)) return + var/our_guy_pos = get_turf(living_guy) for(var/turf_content in our_guy_pos) if(istype(turf_content, /obj/machinery/door/airlock)) @@ -67,7 +65,7 @@ var/obj/machinery/door/airlock/darth_airlock = turf_content living_guy.apply_status_effect(/datum/status_effect/incapacitating/paralyzed, 10) INVOKE_ASYNC(darth_airlock, TYPE_PROC_REF(/obj/machinery/door/airlock, close), TRUE) - if(!permanent) + if(!permanent && !prob(66.6)) qdel(src) return @@ -91,28 +89,103 @@ /datum/component/omen/proc/check_slip(mob/living/our_guy, amount) SIGNAL_HANDLER - if(amount <= 0 || prob(50)) // 50% chance to bonk our head - return + if(prob(30)) // AAAA + INVOKE_ASYNC(our_guy, TYPE_PROC_REF(/mob, emote), "scream") + to_chat(our_guy, span_warning("What a horrible night... To have a curse!")) - var/obj/item/bodypart/the_head = our_guy.get_bodypart(BODY_ZONE_HEAD) - if(!the_head) - return + if(prob(30 * luck_mod)) /// Bonk! + var/obj/item/bodypart/the_head = our_guy.get_bodypart(BODY_ZONE_HEAD) + if(!the_head) + return + playsound(get_turf(our_guy), 'sound/effects/tableheadsmash.ogg', 90, TRUE) + our_guy.visible_message(span_danger("[our_guy] hits [our_guy.p_their()] head really badly falling down!"), span_userdanger("You hit your head really badly falling down!")) + the_head.receive_damage(75 * damage_mod) + our_guy.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100 * damage_mod) + if(!permanent) + qdel(src) - playsound(get_turf(our_guy), 'sound/effects/tableheadsmash.ogg', 90, TRUE) - our_guy.visible_message(span_danger("[our_guy] hits [our_guy.p_their()] head really badly falling down!"), span_userdanger("You hit your head really badly falling down!")) - the_head.receive_damage(75) - our_guy.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) - if(!permanent) - qdel(src) + return /// Hijack the mood system to see if we get the blessing mood event to cancel the omen /datum/component/omen/proc/check_bless(mob/living/our_guy, category) SIGNAL_HANDLER - if(permanent) - return - if (!("blessing" in our_guy.mob_mood.mood_events)) return qdel(src) + +/// Severe deaths. Normally lifts the curse. +/datum/component/omen/proc/check_death(mob/living/our_guy) + SIGNAL_HANDLER + + qdel(src) + return + +/// Creates a localized explosion that shakes the camera +/datum/component/omen/proc/death_explode(mob/living/our_guy) + explosion(our_guy, explosion_cause = src) + + for(var/mob/witness as anything in view(2, our_guy)) + shake_camera(witness, 1 SECONDS, 2) + + return + +/** + * The smite omen. Permanent. + */ +/datum/component/omen/smite + +/datum/component/omen/smite/Initialize(vessel, permanent) + . = ..() + src.permanent = permanent + +/datum/component/omen/smite/check_bless(mob/living/our_guy, category) + if(!permanent) + return ..() + + return + +/datum/component/omen/smite/check_death(mob/living/our_guy) + if(!permanent) + return ..() + + death_explode(our_guy) + our_guy.gib() + + return + +/** + * The quirk omen. Permanent. + * Has only a 50% chance of bad things happening, and takes only 25% of normal damage. + */ +/datum/component/omen/quirk + permanent = TRUE + luck_mod = 0.5 // 50% chance of bad things happening + damage_mod = 0.25 // 25% of normal damage + +/datum/component/omen/quirk/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(check_accident)) + RegisterSignal(parent, COMSIG_ON_CARBON_SLIP, PROC_REF(check_slip)) + RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(check_death)) + +/datum/component/omen/quirk/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ON_CARBON_SLIP, COMSIG_MOVABLE_MOVED, COMSIG_LIVING_DEATH)) + +/datum/component/omen/quirk/check_death(mob/living/our_guy) + if(!iscarbon(our_guy)) + our_guy.gib() + return + + // Don't explode if buckled to a stasis bed + if(our_guy.buckled) + var/obj/machinery/stasis/stasis_bed = our_guy.buckled + if(istype(stasis_bed)) + return + + death_explode(our_guy) + var/mob/living/carbon/player = our_guy + player.spread_bodyparts(skip_head = TRUE) + player.spawn_gibs() + + return diff --git a/code/datums/quirks/negative_quirks.dm b/code/datums/quirks/negative_quirks.dm index c8fd0a31ed1..20f5da2e4c1 100644 --- a/code/datums/quirks/negative_quirks.dm +++ b/code/datums/quirks/negative_quirks.dm @@ -1131,3 +1131,16 @@ if(!IS_ORGANIC_LIMB(old_limb)) cybernetics_level-- update_mood() +/datum/quirk/cursed + name = "Cursed" + desc = "You are cursed with bad luck. You are much more likely to suffer from accidents and mishaps. When it rains, it pours." + icon = "cloud-showers-heavy" + value = -8 + mob_trait = TRAIT_CURSED + gain_text = span_danger("You feel like you're going to have a bad day.") + lose_text = span_notice("You feel like you're going to have a good day.") + medical_record_text = "Patient is cursed with bad luck." + hardcore_value = 8 + +/datum/quirk/cursed/add(client/client_source) + quirk_holder.AddComponent(/datum/component/omen/quirk) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 6bcd09a9dc1..62234452315 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -65,7 +65,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28) . = ..() if(broken) // breaking a mirror truly gets you bad luck! to_chat(user, span_warning("A chill runs down your spine as [src] shatters...")) - user.AddComponent(/datum/component/omen, silent = TRUE) // we have our own message + user.AddComponent(/datum/component/omen) /obj/structure/mirror/bullet_act(obj/projectile/P) if(broken || !isliving(P.firer) || !P.damage) @@ -75,7 +75,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28) if(broken) // breaking a mirror truly gets you bad luck! var/mob/living/unlucky_dude = P.firer to_chat(unlucky_dude, span_warning("A chill runs down your spine as [src] shatters...")) - unlucky_dude.AddComponent(/datum/component/omen, silent=TRUE) // we have our own message + unlucky_dude.AddComponent(/datum/component/omen) /obj/structure/mirror/atom_break(damage_flag, mapload) . = ..() diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index 87a9a824299..be71cfee659 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -213,49 +213,58 @@ movable_content.wash(CLEAN_WASH) return TRUE -/turf/open/handle_slip(mob/living/carbon/slipper, knockdown_amount, obj/O, lube, paralyze_amount, force_drop) +/turf/open/handle_slip(mob/living/carbon/slipper, knockdown_amount, obj/slippable, lube, paralyze_amount, force_drop) if(slipper.movement_type & (FLYING | FLOATING)) return FALSE - if(has_gravity(src)) - var/obj/buckled_obj - if(slipper.buckled) - buckled_obj = slipper.buckled - if(!(lube&GALOSHES_DONT_HELP)) //can't slip while buckled unless it's lube. - return FALSE - else - if(!(lube & SLIP_WHEN_CRAWLING) && (slipper.body_position == LYING_DOWN || !(slipper.status_flags & CANKNOCKDOWN))) // can't slip unbuckled mob if they're lying or can't fall. - return FALSE - if(slipper.m_intent == MOVE_INTENT_WALK && (lube&NO_SLIP_WHEN_WALKING)) - return FALSE - if(!(lube&SLIDE_ICE)) - to_chat(slipper, span_notice("You slipped[ O ? " on the [O.name]" : ""]!")) - playsound(slipper.loc, 'sound/misc/slip.ogg', 50, TRUE, -3) + if(!has_gravity(src)) + return FALSE - SEND_SIGNAL(slipper, COMSIG_ON_CARBON_SLIP) - slipper.add_mood_event("slipped", /datum/mood_event/slipped) - if(force_drop) - for(var/obj/item/I in slipper.held_items) - slipper.accident(I) + var/slide_distance = 4 + if(HAS_TRAIT(slipper, TRAIT_CURSED)) + if(!(lube & SLIDE_ICE)) // Ensures we are at least sliding + lube |= SLIDE + slide_distance = rand(5, 9) - var/olddir = slipper.dir - slipper.moving_diagonally = 0 //If this was part of diagonal move slipping will stop it. - if(!(lube & SLIDE_ICE)) - slipper.Knockdown(knockdown_amount) - slipper.Paralyze(paralyze_amount) - slipper.stop_pulling() - else - slipper.Knockdown(20) + var/obj/buckled_obj + if(slipper.buckled) + buckled_obj = slipper.buckled + if(!(lube & GALOSHES_DONT_HELP)) //can't slip while buckled unless it's lube. + return FALSE + else + if(!(lube & SLIP_WHEN_CRAWLING) && (slipper.body_position == LYING_DOWN || !(slipper.status_flags & CANKNOCKDOWN))) // can't slip unbuckled mob if they're lying or can't fall. + return FALSE + if(slipper.m_intent == MOVE_INTENT_WALK && (lube & NO_SLIP_WHEN_WALKING)) + return FALSE - if(buckled_obj) - buckled_obj.unbuckle_mob(slipper) - lube |= SLIDE_ICE + if(!(lube & SLIDE_ICE)) + to_chat(slipper, span_notice("You slipped[ slippable ? " on the [slippable.name]" : ""]!")) + playsound(slipper.loc, 'sound/misc/slip.ogg', 50, TRUE, -3) - var/turf/target = get_ranged_target_turf(slipper, olddir, 4) - if(lube & SLIDE) - slipper.AddComponent(/datum/component/force_move, target, TRUE) - else if(lube&SLIDE_ICE) - slipper.AddComponent(/datum/component/force_move, target, FALSE)//spinning would be bad for ice, fucks up the next dir - return TRUE + SEND_SIGNAL(slipper, COMSIG_ON_CARBON_SLIP) + slipper.add_mood_event("slipped", /datum/mood_event/slipped) + if(force_drop) + for(var/obj/item/item in slipper.held_items) + slipper.accident(item) + + var/olddir = slipper.dir + slipper.moving_diagonally = 0 //If this was part of diagonal move slipping will stop it. + if(!(lube & SLIDE_ICE)) + slipper.Knockdown(knockdown_amount) + slipper.Paralyze(paralyze_amount) + slipper.stop_pulling() + else + slipper.Knockdown(20) + + if(buckled_obj) + buckled_obj.unbuckle_mob(slipper) + lube |= SLIDE_ICE + + var/turf/target = get_ranged_target_turf(slipper, olddir, slide_distance) + if(lube & SLIDE) + slipper.AddComponent(/datum/component/force_move, target, TRUE) + else if(lube & SLIDE_ICE) + slipper.AddComponent(/datum/component/force_move, target, FALSE)//spinning would be bad for ice, fucks up the next dir + return TRUE /turf/open/proc/MakeSlippery(wet_setting = TURF_WET_WATER, min_wet_time = 0, wet_time_to_add = 0, max_wet_time = MAXIMUM_WET_TIME, permanent) AddComponent(/datum/component/wet_floor, wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent) @@ -306,7 +315,7 @@ if(!used_tiles.use(1)) balloon_alert(user, "need a floor tile to build!") return - + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) var/turf/open/floor/plating/new_plating = PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) if(lattice) diff --git a/code/modules/admin/smites/bad_luck.dm b/code/modules/admin/smites/bad_luck.dm index 083b5015a95..a5c00aea43d 100644 --- a/code/modules/admin/smites/bad_luck.dm +++ b/code/modules/admin/smites/bad_luck.dm @@ -14,4 +14,10 @@ /datum/smite/bad_luck/effect(client/user, mob/living/target) . = ..() - target.AddComponent(/datum/component/omen, silent, null, permanent) + target.AddComponent(/datum/component/omen/smite, permanent = permanent) + + if(silent) + return + to_chat(target, span_warning("You get a bad feeling...")) + if(permanent) + to_chat(target, span_warning("A very bad feeling... As if malevolent forces are watching you...")) diff --git a/code/modules/cargo/coupon.dm b/code/modules/cargo/coupon.dm index dba06acb96f..fc1c3a6cc65 100644 --- a/code/modules/cargo/coupon.dm +++ b/code/modules/cargo/coupon.dm @@ -15,20 +15,43 @@ /obj/item/coupon/proc/generate(rig_omen=FALSE) discounted_pack = pick(subtypesof(/datum/supply_pack/goody)) var/list/chances = list("0.10" = 4, "0.15" = 8, "0.20" = 10, "0.25" = 8, "0.50" = 4, COUPON_OMEN = 1) + if(rig_omen) discount_pct_off = COUPON_OMEN else discount_pct_off = pick_weight(chances) - if(discount_pct_off == COUPON_OMEN) - name = "coupon - fuck you" - desc = "The small text reads, 'You will be slaughtered'... That doesn't sound right, does it?" - if(ismob(loc)) - var/mob/M = loc - to_chat(M, span_warning("The coupon reads 'fuck you' in large, bold text... is- is that a prize, or?")) - M.AddComponent(/datum/component/omen, TRUE, src) - else + + if(discount_pct_off != COUPON_OMEN) discount_pct_off = text2num(discount_pct_off) name = "coupon - [round(discount_pct_off * 100)]% off [initial(discounted_pack.name)]" + return + + name = "coupon - fuck you" + desc = "The small text reads, 'You will be slaughtered'... That doesn't sound right, does it?" + if(!ismob(loc)) + return FALSE + + var/mob/cursed = loc + to_chat(cursed, span_warning("The coupon reads 'fuck you' in large, bold text... is- is that a prize, or?")) + + if(!cursed.GetComponent(/datum/component/omen)) + cursed.AddComponent(/datum/component/omen) + return TRUE + if(HAS_TRAIT(cursed, TRAIT_CURSED)) + to_chat(cursed, span_warning("What a horrible night... To have a curse!")) + addtimer(CALLBACK(src, PROC_REF(curse_heart), cursed), 5 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE) + +/// Play stupid games, win stupid prizes +/obj/item/coupon/proc/curse_heart(mob/living/cursed) + if(!iscarbon(cursed)) + cursed.gib() + return TRUE + + var/mob/living/carbon/player = cursed + INVOKE_ASYNC(player, TYPE_PROC_REF(/mob, emote), "scream") + to_chat(player, span_mind_control("What could that coupon mean?")) + to_chat(player, span_userdanger("...The suspense is killing you!")) + player.set_heartattack(status = TRUE) /obj/item/coupon/attack_atom(obj/O, mob/living/user, params) if(!istype(O, /obj/machinery/computer/cargo)) diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm index 951fe83e71a..e8afafa9673 100644 --- a/code/modules/food_and_drinks/machinery/microwave.dm +++ b/code/modules/food_and_drinks/machinery/microwave.dm @@ -382,6 +382,9 @@ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) return + if(HAS_TRAIT(cooker, TRAIT_CURSED) && prob(7)) + muck() + return if(prob(max((5 / efficiency) - 5, dirty * 5))) //a clean unupgraded microwave has no risk of failure muck() return @@ -467,12 +470,16 @@ metal_amount += (cooked_item.custom_materials?[GET_MATERIAL_REF(/datum/material/iron)] || 0) + if(HAS_TRAIT(cooker, TRAIT_CURSED) && prob(5)) + spark() + broken = REALLY_BROKEN + explosion(src, light_impact_range = 2, flame_range = 1) + if(metal_amount) spark() broken = REALLY_BROKEN - if(prob(max(metal_amount / 2, 33))) + if(HAS_TRAIT(cooker, TRAIT_CURSED) || prob(max(metal_amount / 2, 33))) // If we're unlucky and have metal, we're guaranteed to explode explosion(src, heavy_impact_range = 1, light_impact_range = 2) - else dump_inventory_contents() diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 56700223ada..56661d82c8f 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -66,8 +66,10 @@ organs.forceMove(Tsec) organs.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5) -/mob/living/carbon/spread_bodyparts() - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - BP.drop_limb() - BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5) +/// Launches all bodyparts away from the mob. skip_head will keep the head attached. +/mob/living/carbon/spread_bodyparts(skip_head = FALSE) + for(var/obj/item/bodypart/part as anything in bodyparts) + if(skip_head && part.body_zone == BODY_ZONE_HEAD) + continue + part.drop_limb() + part.throw_at(get_edge_target_turf(src, pick(GLOB.alldirs)), rand(1,3), 5) diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index c66aa9dd21d..d19abfc84bb 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -229,6 +229,9 @@ result = (chambered ? "lost" : "won")) if(chambered) + if(HAS_TRAIT(user, TRAIT_CURSED)) // I cannot live, I cannot die, trapped in myself, body my holding cell. + to_chat(user, span_warning("What a horrible night... To have a curse!")) + return var/obj/item/ammo_casing/AC = chambered if(AC.fire_casing(user, user, params, distro = 0, quiet = 0, zone_override = null, spread = 0, fired_from = src)) playsound(user, fire_sound, fire_sound_volume, vary_fire_sound) diff --git a/code/modules/religion/sparring/sparring_datum.dm b/code/modules/religion/sparring/sparring_datum.dm index 12ff983e3d0..00aac29a355 100644 --- a/code/modules/religion/sparring/sparring_datum.dm +++ b/code/modules/religion/sparring/sparring_datum.dm @@ -208,7 +208,7 @@ switch(pick(possible_punishments)) if(PUNISHMENT_OMEN) to_chat(interfering, span_warning("You get a bad feeling... for interfering with [chaplain]'s sparring match...")) - interfering.AddComponent(/datum/component/omen, TRUE, null, FALSE) + interfering.AddComponent(/datum/component/omen) if(PUNISHMENT_LIGHTNING) to_chat(interfering, span_warning("[GLOB.deity] has punished you for interfering with [chaplain]'s sparring match!")) lightningbolt(interfering)