diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm index e0b8def1581..3784a079ce0 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm @@ -11,6 +11,8 @@ #define COMSIG_ATOM_NO_LONGER_PULLING "movable_no_longer_pulling" ///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels) #define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact" +///signal sent out by an atom upon onZImpact : (turf/impacted_turf, levels) +#define COMSIG_ATOM_ON_Z_IMPACT "movable_on_z_impact" ///called on a movable (NOT living) when it starts pulling (atom/movable/pulled, state, force) #define COMSIG_ATOM_START_PULL "movable_start_pull" ///called on /living when someone starts pulling (atom/movable/pulled, state, force) diff --git a/code/datums/elements/falling_hazard.dm b/code/datums/elements/falling_hazard.dm new file mode 100644 index 00000000000..cfa9285e7f8 --- /dev/null +++ b/code/datums/elements/falling_hazard.dm @@ -0,0 +1,80 @@ +/// An element that will make a target thing do damage to any mob that it falls on from a z-level above +/datum/element/falling_hazard + element_flags = ELEMENT_BESPOKE + id_arg_index = 2 + + /// The amount of damage to do when the target falls onto a mob + var/fall_damage = 5 + /// The wound bonus to give damage dealt against mobs we fall on + var/fall_wound_bonus = 0 + /// Does we take into consideration if the target has head protection (hardhat, or a strong enough helmet) + var/obeys_hardhats = TRUE + /// Does the target crush and flatten whoever it falls on + var/crushes_people = FALSE + /// What sound is played when the target falls onto a mob + var/impact_sound = 'sound/magic/clockwork/fellowship_armory.ogg' //CLANG + +/datum/element/falling_hazard/Attach(datum/target, damage, wound_bonus, hardhat_safety, crushes, impact_sound) + . = ..() + if(!isatom(target)) + return ELEMENT_INCOMPATIBLE + + src.fall_damage = damage + src.fall_wound_bonus = wound_bonus + src.obeys_hardhats = hardhat_safety + src.crushes_people = crushes + src.impact_sound = impact_sound + + RegisterSignal(target, COMSIG_ATOM_ON_Z_IMPACT, PROC_REF(fall_onto_stuff)) + +/datum/element/falling_hazard/Detach(datum/target) + . = ..() + UnregisterSignal(target, COMSIG_ATOM_ON_Z_IMPACT) + +/// Gathers every mob in the turf the target falls on, and does damage/crushes them/makes a message about the target falling on them +/datum/element/falling_hazard/proc/fall_onto_stuff(datum/source, turf/impacted_turf, levels) + SIGNAL_HANDLER + + var/mob/living/poor_target = locate(/mob/living) in impacted_turf + + if(!poor_target) + return + + var/target_head_armor = poor_target.run_armor_check(BODY_ZONE_HEAD, MELEE, silent = TRUE) + + if(obeys_hardhats && target_head_armor >= 15) // 15 melee armor is enough that most head items dont have this, but anything above a hardhat should protect you + poor_target.visible_message( + span_warning("[source] falls on [poor_target], thankfully [poor_target.p_they()] had a helmet on!"), + span_userdanger("You are hit on the head by [source], good thing you had a helmet on!"), + span_hear("You hear a [crushes_people ? "crash" : "bonk"]!"), + ) + + if(crushes_people) + poor_target.Knockdown(0.25 SECONDS * fall_damage) // For a piano, that would be 15 seconds + + playsound(poor_target, 'sound/weapons/parry.ogg', 50, TRUE) // You PARRIED the falling object with your EPIC hardhat + return + + var/obj/item/bodypart/target_head = poor_target.get_bodypart(BODY_ZONE_HEAD) + + // This does more damage the more levels the falling object has fallen + if(!crushes_people && target_head) + poor_target.apply_damage(fall_damage * levels, def_zone = BODY_ZONE_HEAD, forced = TRUE, wound_bonus = fall_wound_bonus) + else + poor_target.apply_damage(fall_damage * levels, forced = TRUE, spread_damage = TRUE, wound_bonus = fall_wound_bonus) + + poor_target.visible_message( + span_userdanger("[source] falls on [poor_target], [crushes_people ? "crushing [poor_target.p_them()]" : "hitting [poor_target.p_them()]"] [target_head ? "on the head!" : "!"]"), + span_userdanger("You are [crushes_people ? "crushed" : "hit"] by [source]!"), + span_hear("You hear a [crushes_people ? "crash" : "bonk"]!"), + ) + + playsound(poor_target, impact_sound, 50, TRUE) + + if(!crushes_people) + return + + poor_target.AddElement(/datum/element/squish, 30 SECONDS) + poor_target.Paralyze(0.5 SECONDS * fall_damage) // For a piano, that would be 30 seconds + + add_memory_in_range(poor_target, 7, MEMORY_VENDING_CRUSHED, list(DETAIL_PROTAGONIST = poor_target, DETAIL_WHAT_BY = src), story_value = STORY_VALUE_AMAZING, memory_flags = MEMORY_CHECK_BLINDNESS, protagonist_memory_flags = MEMORY_SKIP_UNCONSCIOUS) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 769cd233734..98a91e610aa 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -223,6 +223,7 @@ . += emissive_block /atom/movable/proc/onZImpact(turf/impacted_turf, levels, message = TRUE) + SHOULD_CALL_PARENT(TRUE) if(message) visible_message(span_danger("[src] crashes into [impacted_turf]!")) var/atom/highest = impacted_turf @@ -233,6 +234,7 @@ if(hurt_atom.layer > highest.layer) highest = hurt_atom INVOKE_ASYNC(src, PROC_REF(SpinAnimation), 5, 2) + SEND_SIGNAL(src, COMSIG_ATOM_ON_Z_IMPACT, impacted_turf, levels) return TRUE /* diff --git a/code/game/objects/items/paint.dm b/code/game/objects/items/paint.dm index f83dae18c8b..c8fe4db5bfe 100644 --- a/code/game/objects/items/paint.dm +++ b/code/game/objects/items/paint.dm @@ -16,6 +16,10 @@ /// How many uses are left var/paintleft = 10 +/obj/item/paint/Initialize(mapload) + . = ..() + AddElement(/datum/element/falling_hazard, damage = 20, wound_bonus = 5, hardhat_safety = TRUE, crushes = FALSE) // You ever watched home alone? + /obj/item/paint/red name = "red paint" paint_color = COLOR_RED diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 1c88ab8a16d..cd4c77401b5 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -33,6 +33,8 @@ latches = "triple_latch" update_appearance() + AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound) + /obj/item/storage/toolbox/update_overlays() . = ..() if(has_latches) diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index e6cc1c23793..5c8672efd0c 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -24,6 +24,10 @@ armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 50, ACID = 30) var/force_opens = FALSE +/obj/item/crowbar/Initialize(mapload) + . = ..() + AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound) + /obj/item/crowbar/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1) diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index 01300df0512..bb769f1a0ba 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -54,6 +54,7 @@ set_greyscale(colors=list(screwdriver_colors[our_color])) . = ..() AddElement(/datum/element/eyestab) + AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound) /obj/item/screwdriver/abductor name = "alien screwdriver" diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 59dcbaaf2ea..d93e6e931dd 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -53,6 +53,8 @@ . = ..() AddElement(/datum/element/update_icon_updates_onmob, ITEM_SLOT_HANDS) AddElement(/datum/element/tool_flash, light_range) + AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound) + create_reagents(max_fuel) reagents.add_reagent(/datum/reagent/fuel, max_fuel) update_appearance() diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm index 0d850600aef..10e603594f5 100644 --- a/code/game/objects/items/tools/wirecutters.dm +++ b/code/game/objects/items/tools/wirecutters.dm @@ -46,6 +46,9 @@ if(random_color) var/our_color = pick(wirecutter_colors) set_greyscale(colors=list(wirecutter_colors[our_color])) + + AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound) + return ..() /obj/item/wirecutters/attack(mob/living/carbon/attacked_carbon, mob/user) diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm index f969d1e00f7..ea43940dc05 100644 --- a/code/game/objects/items/tools/wrench.dm +++ b/code/game/objects/items/tools/wrench.dm @@ -24,6 +24,10 @@ toolspeed = 1 armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 50, ACID = 30) +/obj/item/wrench/Initialize(mapload) + . = ..() + AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound) + /obj/item/wrench/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1) diff --git a/code/modules/instruments/stationary.dm b/code/modules/instruments/stationary.dm index 1b726e823ff..a1cc70dace2 100644 --- a/code/modules/instruments/stationary.dm +++ b/code/modules/instruments/stationary.dm @@ -41,6 +41,10 @@ density = TRUE var/broken_icon_state = "pianobroken" +/obj/structure/musician/piano/Initialize(mapload) + . = ..() + AddElement(/datum/element/falling_hazard, damage = 60, wound_bonus = 10, hardhat_safety = FALSE, crushes = TRUE, impact_sound = 'sound/effects/piano_hit.ogg') + /obj/structure/musician/piano/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) if(BRUTE) diff --git a/code/modules/library/book.dm b/code/modules/library/book.dm index e1d58a155d2..22358fe20e4 100644 --- a/code/modules/library/book.dm +++ b/code/modules/library/book.dm @@ -110,6 +110,8 @@ . = ..() book_data = new(starting_title, starting_author, starting_content) + AddElement(/datum/element/falling_hazard, damage = 5, wound_bonus = 0, hardhat_safety = TRUE, crushes = FALSE, impact_sound = drop_sound) + /obj/item/book/proc/on_read(mob/living/user) if(book_data?.content) user << browse("Penned by [book_data.author].
" + "[book_data.content]", "window=book[window_size != null ? ";size=[window_size]" : ""]") diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index 1438503b54f..b835eb2f55e 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -258,6 +258,8 @@ thing.attach(src, FALSE) equip_by_category[key] -= path + AddElement(/datum/element/falling_hazard, damage = 80, wound_bonus = 10, hardhat_safety = FALSE, crushes = TRUE) + /obj/vehicle/sealed/mecha/Destroy() for(var/ejectee in occupants) mob_exit(ejectee, silent = TRUE) diff --git a/modular_skyrat/modules/primitive_fun/code/big_mortar.dm b/modular_skyrat/modules/primitive_fun/code/big_mortar.dm index a957abf57d9..bfb0a47fef3 100644 --- a/modular_skyrat/modules/primitive_fun/code/big_mortar.dm +++ b/modular_skyrat/modules/primitive_fun/code/big_mortar.dm @@ -18,6 +18,8 @@ . = ..() create_reagents(200, OPENCONTAINER) + AddElement(/datum/element/falling_hazard, damage = 20, wound_bonus = 5, hardhat_safety = TRUE, crushes = FALSE) + /obj/structure/large_mortar/examine(mob/user) . = ..() . += span_notice("It currently contains [length(contents)]/[maximum_contained_items] items.") diff --git a/modular_skyrat/modules/reagent_forging/code/anvil.dm b/modular_skyrat/modules/reagent_forging/code/anvil.dm index 9979556ec33..5d3f4a757b9 100644 --- a/modular_skyrat/modules/reagent_forging/code/anvil.dm +++ b/modular_skyrat/modules/reagent_forging/code/anvil.dm @@ -10,6 +10,8 @@ /obj/structure/reagent_anvil/Initialize(mapload) . = ..() + AddElement(/datum/element/falling_hazard, damage = 40, wound_bonus = 10, hardhat_safety = FALSE, crushes = TRUE) + /obj/structure/reagent_anvil/update_appearance() . = ..() cut_overlays() diff --git a/tgstation.dme b/tgstation.dme index 95865ebb100..c772c17c56a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1113,6 +1113,7 @@ #include "code\datums\elements\embed.dm" #include "code\datums\elements\empprotection.dm" #include "code\datums\elements\eyestab.dm" +#include "code\datums\elements\falling_hazard.dm" #include "code\datums\elements\firestacker.dm" #include "code\datums\elements\footstep.dm" #include "code\datums\elements\forced_gravity.dm"