diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 05ae10d937c..860964cd74d 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -684,7 +684,10 @@ #define COMSIG_CARBON_HUGGED "carbon_hugged" ///When a carbon mob is headpatted, this is called on the carbon that is headpatted. (mob/living/headpatter) #define COMSIG_CARBON_HEADPAT "carbon_headpatted" -///When a carbon mob is disarmed, this is called on objects that have unique behavior when the target is shoved into it (obj/structure/table, obj/machinery/disposal/bin) +///Before a carbon mob is shoved, sent to the turf we're trying to shove onto (mob/living/carbon/shover, mob/living/carbon/target) +#define COMSIG_CARBON_DISARM_PRESHOVE "carbon_disarm_preshove" + #define COMSIG_CARBON_ACT_SOLID (1<<0) //Tells disarm code to act as if the mob was shoved into something solid, even we we're not +///When a carbon mob is disarmed, this is sent to the turf we're trying to shove onto (mob/living/carbon/shover, mob/living/carbon/target, shove_blocked) #define COMSIG_CARBON_DISARM_COLLIDE "carbon_disarm_collision" #define COMSIG_CARBON_SHOVE_HANDLED (1<<0) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 216a180863f..f60aad00eef 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -74,7 +74,12 @@ . = ..() update_appearance() PopulateContents() - RegisterSignal(src, COMSIG_CARBON_DISARM_COLLIDE, .proc/locker_carbon) + if(QDELETED(src)) //It turns out populate contents has a 1 in 100 chance of qdeling src on /obj/structure/closet/emcloset + return //Why + var/static/list/loc_connections = list( + COMSIG_CARBON_DISARM_COLLIDE = .proc/locker_carbon, + ) + AddElement(/datum/element/connect_loc, loc_connections) //USE THIS TO FILL IT, NOT INITIALIZE OR NEW /obj/structure/closet/proc/PopulateContents() @@ -679,19 +684,22 @@ /obj/structure/closet/return_temperature() return -/obj/structure/closet/proc/locker_carbon(obj/structure/closet/closet, mob/living/carbon/shover, mob/living/carbon/target) +/obj/structure/closet/proc/locker_carbon(datum/source, mob/living/carbon/shover, mob/living/carbon/target, shove_blocked) SIGNAL_HANDLER + if(!opened && (locked || welded)) //Yes this could be less code, no I don't care + return + if(!opened && !shove_blocked) + return if(opened) target.forceMove(src) - if(!(locked || welded)) - toggle() + else + target.Knockdown(SHOVE_KNOCKDOWN_SOLID) + toggle() update_icon() target.visible_message(span_danger("[shover.name] shoves [target.name] into \the [src]!"), span_userdanger("You're shoved into \the [src] by [target.name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) to_chat(src, span_danger("You shove [target.name] into \the [src]!")) log_combat(src, target, "shoved", "into [src] (locker/crate)") - if(locked || welded) - return return COMSIG_CARBON_SHOVE_HANDLED #undef LOCKER_FULL diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index 899b9bdc4ea..f52546a4d99 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -49,7 +49,7 @@ if ("nothing") // doot - // teehee + // teehee //Fuck you if ("delete") qdel(src) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 261c5c3b620..a7b855f25d8 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -41,7 +41,10 @@ if(_buildstack) buildstack = _buildstack AddElement(/datum/element/climbable) - RegisterSignal(src, COMSIG_CARBON_DISARM_COLLIDE, .proc/table_carbon) + var/static/list/loc_connections = list( + COMSIG_CARBON_DISARM_COLLIDE = .proc/table_carbon, + ) + AddElement(/datum/element/connect_loc, loc_connections) /obj/structure/table/examine(mob/user) . = ..() @@ -259,14 +262,16 @@ return TRUE return FALSE -/obj/structure/table/proc/table_carbon(obj/structure/table/the_table, mob/living/carbon/shover, mob/living/carbon/target) +/obj/structure/table/proc/table_carbon(datum/source, mob/living/carbon/shover, mob/living/carbon/target, shove_blocked) SIGNAL_HANDLER + if(!shove_blocked) + return target.Knockdown(SHOVE_KNOCKDOWN_TABLE) - target.visible_message(span_danger("[shover.name] shoves [target.name] onto \the [the_table]!"), - span_userdanger("You're shoved onto \the [the_table] by [shover.name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) - to_chat(shover, span_danger("You shove [target.name] onto \the [the_table]!")) + target.visible_message(span_danger("[shover.name] shoves [target.name] onto \the [src]!"), + span_userdanger("You're shoved onto \the [src] by [shover.name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) + to_chat(shover, span_danger("You shove [target.name] onto \the [src]!")) target.throw_at(src, 1, 1, null, FALSE) //1 speed throws with no spin are basically just forcemoves with a hard collision check - log_combat(src, target, "shoved", "onto [the_table] (table)") + log_combat(src, target, "shoved", "onto [src] (table)") return COMSIG_CARBON_SHOVE_HANDLED /obj/structure/table/greyscale diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 337dbf5a7a0..c4dbab7da6c 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -9,7 +9,11 @@ GLOB.carbon_list += src RegisterSignal(src, COMSIG_LIVING_DEATH, .proc/attach_rot) - RegisterSignal(src, COMSIG_CARBON_DISARM_COLLIDE, .proc/disarm_collision) + var/static/list/loc_connections = list( + COMSIG_CARBON_DISARM_PRESHOVE = .proc/disarm_precollide, + COMSIG_CARBON_DISARM_COLLIDE = .proc/disarm_collision, + ) + AddElement(/datum/element/connect_loc, loc_connections) /mob/living/carbon/Destroy() //This must be done first, so the mob ghosts correctly before DNA etc is nulled @@ -1318,13 +1322,20 @@ if(mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD)) AddComponent(/datum/component/rot, 6 MINUTES, 10 MINUTES, 1) -/mob/living/carbon/proc/disarm_collision(mob/living/carbon/collateral, mob/living/carbon/shover, mob/living/carbon/target) +/mob/living/carbon/proc/disarm_precollide(datum/source, mob/living/carbon/shover, mob/living/carbon/target) SIGNAL_HANDLER + if(can_be_shoved_into) + return COMSIG_CARBON_ACT_SOLID + +/mob/living/carbon/proc/disarm_collision(datum/source, mob/living/carbon/shover, mob/living/carbon/target, shove_blocked) + SIGNAL_HANDLER + if(src == target || !can_be_shoved_into) + return target.Knockdown(SHOVE_KNOCKDOWN_HUMAN) - if(!collateral.is_shove_knockdown_blocked()) - collateral.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL) - target.visible_message(span_danger("[shover] shoves [target.name] into [collateral.name]!"), - span_userdanger("You're shoved into [collateral.name] by [shover]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) - to_chat(src, span_danger("You shove [target.name] into [collateral.name]!")) - log_combat(src, target, "shoved", "into [collateral.name]") + if(!is_shove_knockdown_blocked()) + Knockdown(SHOVE_KNOCKDOWN_COLLATERAL) + target.visible_message(span_danger("[shover] shoves [target.name] into [name]!"), + span_userdanger("You're shoved into [name] by [shover]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) + to_chat(src, span_danger("You shove [target.name] into [name]!")) + log_combat(src, target, "shoved", "into [name]") return COMSIG_CARBON_SHOVE_HANDLED diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index f227f7899a7..781af439cd0 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -295,36 +295,20 @@ human_target.w_uniform?.add_fingerprint(src) SEND_SIGNAL(target, COMSIG_HUMAN_DISARM_HIT, src, zone_selected) - - var/turf/target_oldturf = target.loc - var/shove_dir = get_dir(loc, target_oldturf) + var/shove_dir = get_dir(loc, target.loc) var/turf/target_shove_turf = get_step(target.loc, shove_dir) - var/mob/living/carbon/target_collateral_carbon var/shove_blocked = FALSE //Used to check if a shove is blocked so that if it is knockdown logic can be applied - var/handled = FALSE - for(var/atom/movable/every_single_thing_but_target as anything in target_shove_turf.contents - target) - if(SEND_SIGNAL(every_single_thing_but_target, COMSIG_CARBON_DISARM_COLLIDE, src, target) & COMSIG_CARBON_SHOVE_HANDLED) - handled = TRUE - break - if(!handled) - SEND_SIGNAL(target, COMSIG_CARBON_DISARM_COLLIDE, src, target) - if(handled) - return //We are using an object's disarm collision reaction instead of base disarm reactions. - //Thank you based whoneedsspace - target_collateral_carbon = locate(/mob/living/carbon) in target_shove_turf.contents + var/turf/target_old_turf = target.loc - // If we can't shove the target into the carbon (such as if it's an alien), then just pretend nothing was there - if (!target_collateral_carbon?.can_be_shoved_into) - target_collateral_carbon = null - - if(target_collateral_carbon) + //Are we hitting anything? or + if(SEND_SIGNAL(target_shove_turf, COMSIG_CARBON_DISARM_PRESHOVE) & COMSIG_CARBON_ACT_SOLID) shove_blocked = TRUE else target.Move(target_shove_turf, shove_dir) - if(get_turf(target) == target_oldturf) + if(get_turf(target) == target_old_turf) shove_blocked = TRUE - if(target.IsKnockdown() && !target.IsParalyzed()) + if(target.IsKnockdown() && !target.IsParalyzed()) //KICK HIM IN THE NUTS target.Paralyze(SHOVE_CHAIN_PARALYZE) target.visible_message(span_danger("[name] kicks [target.name] onto [target.p_their()] side!"), span_userdanger("You're kicked onto your side by [name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) @@ -332,51 +316,56 @@ addtimer(CALLBACK(target, /mob/living/proc/SetKnockdown, 0), SHOVE_CHAIN_PARALYZE) log_combat(src, target, "kicks", "onto their side (paralyzing)") - if(shove_blocked && !target.is_shove_knockdown_blocked() && !target.buckled) - var/directional_blocked = FALSE - if(shove_dir in GLOB.cardinals) //Directional checks to make sure that we're not shoving through a windoor or something like that - var/target_turf = get_turf(target) - for(var/obj/obj_content in target_turf) - if(obj_content.flags_1 & ON_BORDER_1 && obj_content.dir == shove_dir && obj_content.density) + var/directional_blocked = FALSE + var/can_hit_something = (!target.is_shove_knockdown_blocked() && !target.buckled) + if(shove_blocked && can_hit_something) + if(!(shove_dir in GLOB.cardinals)) //Directional checks to make sure that we're not shoving through a windoor or something like that + return + var/target_turf = get_turf(target) + for(var/obj/obj_content in target_turf) + if(obj_content.flags_1 & ON_BORDER_1 && obj_content.dir == shove_dir && obj_content.density) + directional_blocked = TRUE + break + if(target_turf != target_shove_turf && !directional_blocked) //Make sure that we don't run the exact same check twice on the same tile + for(var/obj/obj_content in target_shove_turf) + if(obj_content.flags_1 & ON_BORDER_1 && obj_content.dir == turn(shove_dir, 180) && obj_content.density) directional_blocked = TRUE break - if(target_turf != target_shove_turf) //Make sure that we don't run the exact same check twice on the same tile - for(var/obj/obj_content in target_shove_turf) - if(obj_content.flags_1 & ON_BORDER_1 && obj_content.dir == turn(shove_dir, 180) && obj_content.density) - directional_blocked = TRUE - break - if((!target_collateral_carbon) || directional_blocked) + + if(can_hit_something) + if(directional_blocked || (!(SEND_SIGNAL(target_shove_turf, COMSIG_CARBON_DISARM_COLLIDE, src, target, shove_blocked) & COMSIG_CARBON_SHOVE_HANDLED) && shove_blocked)) target.Knockdown(SHOVE_KNOCKDOWN_SOLID) target.visible_message(span_danger("[name] shoves [target.name], knocking [target.p_them()] down!"), - span_userdanger("You're knocked down from a shove by [name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) + span_userdanger("You're knocked down from a shove by [name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) to_chat(src, span_danger("You shove [target.name], knocking [target.p_them()] down!")) log_combat(src, target, "shoved", "knocking them down") - else - target.visible_message(span_danger("[name] shoves [target.name]!"), - span_userdanger("You're shoved by [name]!"), span_hear("You hear aggressive shuffling!"), COMBAT_MESSAGE_RANGE, src) - to_chat(src, span_danger("You shove [target.name]!")) - var/target_held_item = target.get_active_held_item() - var/knocked_item = FALSE - if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types)) - target_held_item = null - if(!target.has_movespeed_modifier(/datum/movespeed_modifier/shove)) - target.add_movespeed_modifier(/datum/movespeed_modifier/shove) - if(target_held_item) - target.visible_message(span_danger("[target.name]'s grip on \the [target_held_item] loosens!"), - span_warning("Your grip on \the [target_held_item] loosens!"), null, COMBAT_MESSAGE_RANGE) - addtimer(CALLBACK(target, /mob/living/carbon/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH) - else if(target_held_item) - target.dropItemToGround(target_held_item) - knocked_item = TRUE - target.visible_message(span_danger("[target.name] drops \the [target_held_item]!"), - span_warning("You drop \the [target_held_item]!"), null, COMBAT_MESSAGE_RANGE) - var/append_message = "" + return + + target.visible_message(span_danger("[name] shoves [target.name]!"), + span_userdanger("You're shoved by [name]!"), span_hear("You hear aggressive shuffling!"), COMBAT_MESSAGE_RANGE, src) + to_chat(src, span_danger("You shove [target.name]!")) + + //Take their lunch money + var/target_held_item = target.get_active_held_item() + var/append_message = "" + if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types)) //It's too expensive we'll get caught + target_held_item = null + + if(!target.has_movespeed_modifier(/datum/movespeed_modifier/shove)) + target.add_movespeed_modifier(/datum/movespeed_modifier/shove) if(target_held_item) - if(knocked_item) - append_message = "causing [target.p_them()] to drop [target_held_item]" - else - append_message = "loosening [target.p_their()] grip on [target_held_item]" - log_combat(src, target, "shoved", append_message) + append_message = "loosening [target.p_their()] grip on [target_held_item]" + target.visible_message(span_danger("[target.name]'s grip on \the [target_held_item] loosens!"), //He's already out what are you doing + span_warning("Your grip on \the [target_held_item] loosens!"), null, COMBAT_MESSAGE_RANGE) + addtimer(CALLBACK(target, /mob/living/carbon/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH) + + else if(target_held_item) + target.dropItemToGround(target_held_item) + append_message = "causing [target.p_them()] to drop [target_held_item]" + target.visible_message(span_danger("[target.name] drops \the [target_held_item]!"), + span_warning("You drop \the [target_held_item]!"), null, COMBAT_MESSAGE_RANGE) + + log_combat(src, target, "shoved", append_message) /mob/living/carbon/proc/is_shove_knockdown_blocked() //If you want to add more things that block shove knockdown, extend this for (var/obj/item/clothing/clothing in get_equipped_items()) diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index a49b1415dbd..93f3dee2c23 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -41,8 +41,10 @@ //gas.volume = 1.05 * CELLSTANDARD update_appearance() RegisterSignal(src, COMSIG_RAT_INTERACT, .proc/on_rat_rummage) - RegisterSignal(src, COMSIG_CARBON_DISARM_COLLIDE, .proc/trash_carbon) - + var/static/list/loc_connections = list( + COMSIG_CARBON_DISARM_COLLIDE = .proc/trash_carbon, + ) + AddElement(/datum/element/connect_loc, loc_connections) return INITIALIZE_HINT_LATELOAD //we need turfs to have air /obj/machinery/disposal/proc/trunk_check() @@ -527,12 +529,14 @@ INVOKE_ASYNC(src, /obj/machinery/disposal/.proc/rat_rummage, king) -/obj/machinery/disposal/proc/trash_carbon(obj/machinery/disposal/binny, mob/living/carbon/shover, mob/living/carbon/target) +/obj/machinery/disposal/proc/trash_carbon(datum/source, mob/living/carbon/shover, mob/living/carbon/target, shove_blocked) SIGNAL_HANDLER + if(!shove_blocked) + return target.Knockdown(SHOVE_KNOCKDOWN_SOLID) - target.forceMove(binny) - target.visible_message(span_danger("[shover.name] shoves [target.name] into \the [binny]!"), - span_userdanger("You're shoved into \the [binny] by [target.name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, binny) - to_chat(binny, span_danger("You shove [target.name] into \the [binny]!")) - log_combat(binny, target, "shoved", "into [binny] (disposal bin)") + target.forceMove(src) + target.visible_message(span_danger("[shover.name] shoves [target.name] into \the [src]!"), + span_userdanger("You're shoved into \the [src] by [target.name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) + to_chat(src, span_danger("You shove [target.name] into \the [src]!")) + log_combat(src, target, "shoved", "into [src] (disposal bin)") return COMSIG_CARBON_SHOVE_HANDLED