diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index a6e60f1ced8..dd6f6fdccc4 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -132,10 +132,6 @@ #define COMSIG_HUMAN_CORETEMP_CHANGE "human_coretemp_change" ///from /datum/species/handle_fire. Called when the human is set on fire and burning clothes and stuff #define COMSIG_HUMAN_BURNING "human_burning" -///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity, modifiers) -#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack" -///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity, modifiers) -#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" ///from /mob/living/carbon/human/proc/check_shields(): (atom/hit_by, damage, attack_text, attack_type, armour_penetration, damage_type) #define COMSIG_HUMAN_CHECK_SHIELDS "human_check_shields" #define SHIELD_BLOCK (1<<0) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index b70f7f9013d..ceebe7f304b 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -133,7 +133,11 @@ #define COMSIG_LIVING_SLAM_TABLE "living_slam_table" ///from /obj/item/hand_item/slapper/attack(): (source=mob/living/slapper, mob/living/slapped) #define COMSIG_LIVING_SLAP_MOB "living_slap_mob" -///(NOT on humans) from mob/living/*/UnarmedAttack(): (mob/living/source, atom/target, proximity, modifiers) +/// from /mob/living/*/UnarmedAttack(), before sending [COMSIG_LIVING_UNARMED_ATTACK]: (mob/living/source, atom/target, proximity, modifiers) +/// The only reason this exists is so hulk can fire before Fists of the North Star. +/// Note that this is called before [/mob/living/proc/can_unarmed_attack] is called, so be wary of that. +#define COMSIG_LIVING_EARLY_UNARMED_ATTACK "human_pre_attack_hand" +/// from mob/living/*/UnarmedAttack(): (mob/living/source, atom/target, proximity, modifiers) #define COMSIG_LIVING_UNARMED_ATTACK "living_unarmed_attack" ///From base of mob/living/MobBump() (mob/living) #define COMSIG_LIVING_MOB_BUMP "living_mob_bump" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm index 65d96ea8c4c..8b19c1f0054 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm @@ -7,7 +7,7 @@ // /mob/living/simple_animal/hostile signals ///before attackingtarget has happened, source is the attacker and target is the attacked #define COMSIG_HOSTILE_PRE_ATTACKINGTARGET "hostile_pre_attackingtarget" - #define COMPONENT_HOSTILE_NO_ATTACK (1<<0) //cancel the attack, only works before attack happens + #define COMPONENT_HOSTILE_NO_ATTACK COMPONENT_CANCEL_ATTACK_CHAIN //cancel the attack, only works before attack happens ///after attackingtarget has happened, source is the attacker and target is the attacked, extra argument for if the attackingtarget was successful #define COMSIG_HOSTILE_POST_ATTACKINGTARGET "hostile_post_attackingtarget" ///from base of mob/living/basic/regal_rat: (mob/living/basic/regal_rat/king) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 0dbc6380233..6418b20abec 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -277,7 +277,10 @@ /** - * Translates into [atom/proc/attack_hand], etc. + * UnarmedAttack: The higest level of mob click chain discounting click itself. + * + * This handles, just "clicking on something" without an item. It translates + * into [atom/proc/attack_hand], [atom/proc/attack_animal] etc. * * Note: proximity_flag here is used to distinguish between normal usage (flag=1), * and usage when clicking on things telekinetically (flag=0). This proc will diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index aeb42361c05..ce281bb4ecf 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -9,33 +9,66 @@ else if (secondary_result != SECONDARY_ATTACK_CALL_NORMAL) CRASH("resolve_right_click_attack (probably attack_hand_secondary) did not return a SECONDARY_ATTACK_* define.") -/* - Humans: - Adds an exception for gloves, to allow special glove types like the ninja ones. +/** + * Checks if this mob is in a valid state to punch someone. + */ +/mob/living/proc/can_unarmed_attack() + return !HAS_TRAIT(src, TRAIT_HANDS_BLOCKED) + +/mob/living/carbon/can_unarmed_attack() + . = ..() + if(!.) + return FALSE - Otherwise pretty standard. -*/ -/mob/living/carbon/human/UnarmedAttack(atom/A, proximity_flag, list/modifiers) - if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED)) - if(src == A) - check_self_for_injuries() - return if(!has_active_hand()) //can't attack without a hand. var/obj/item/bodypart/check_arm = get_active_hand() if(check_arm?.bodypart_disabled) to_chat(src, span_warning("Your [check_arm.name] is in no condition to be used.")) - return + return FALSE to_chat(src, span_notice("You look at your arm and sigh.")) - return + return FALSE - //This signal is needed to prevent gloves of the north star + hulk. - if(SEND_SIGNAL(src, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, A, proximity_flag, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN) - return - SEND_SIGNAL(src, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, A, proximity_flag, modifiers) + return TRUE - if(!right_click_attack_chain(A, modifiers) && !dna?.species?.spec_unarmedattack(src, A, modifiers)) //Because species like monkeys dont use attack hand - A.attack_hand(src, modifiers) +/mob/living/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) + // The sole reason for this signal needing to exist is making FotNS incompatible with Hulk. + // Note that it is send before [proc/can_unarmed_attack] is called, keep this in mind. + var/sigreturn = SEND_SIGNAL(src, COMSIG_LIVING_EARLY_UNARMED_ATTACK, attack_target, modifiers) + if(sigreturn & COMPONENT_CANCEL_ATTACK_CHAIN) + return TRUE + if(sigreturn & COMPONENT_SKIP_ATTACK) + return FALSE + + if(!can_unarmed_attack(attack_target)) + return FALSE + + sigreturn = SEND_SIGNAL(src, COMSIG_LIVING_UNARMED_ATTACK, attack_target, proximity_flag, modifiers) + if(sigreturn & COMPONENT_CANCEL_ATTACK_CHAIN) + return TRUE + if(sigreturn & COMPONENT_SKIP_ATTACK) + return FALSE + + if(!right_click_attack_chain(attack_target, modifiers)) + resolve_unarmed_attack(attack_target, modifiers) + return TRUE + +/mob/living/carbon/human/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) + // Humans can always check themself regardless of having their hands blocked or w/e + if(src == attack_target) + check_self_for_injuries() + return TRUE + + return ..() + +/mob/living/carbon/resolve_unarmed_attack(atom/attack_target, list/modifiers) + return attack_target.attack_paw(src, modifiers) + +/mob/living/carbon/human/resolve_unarmed_attack(atom/attack_target, list/modifiers) + if(!ISADVANCEDTOOLUSER(src)) + return ..() + + return attack_target.attack_hand(src, modifiers) /mob/living/carbon/human/resolve_right_click_attack(atom/target, list/modifiers) return target.attack_hand_secondary(src, modifiers) @@ -119,17 +152,6 @@ Animals & All Unspecified */ -// If the UnarmedAttack chain is blocked -#define LIVING_UNARMED_ATTACK_BLOCKED(target_atom) (HAS_TRAIT(src, TRAIT_HANDS_BLOCKED) \ - || SEND_SIGNAL(src, COMSIG_LIVING_UNARMED_ATTACK, target_atom, proximity_flag, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN) - -/mob/living/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return FALSE - if(!right_click_attack_chain(attack_target, modifiers)) - resolve_unarmed_attack(attack_target, modifiers) - return TRUE - /** * Called when the unarmed attack hasn't been stopped by the LIVING_UNARMED_ATTACK_BLOCKED macro or the right_click_attack_chain proc. * This will call an attack proc that can vary from mob type to mob type on the target. @@ -295,8 +317,6 @@ GiveTarget(attack_target) INVOKE_ASYNC(src, PROC_REF(AttackingTarget), attack_target) -#undef LIVING_UNARMED_ATTACK_BLOCKED - /* New Players: Have no reason to click on anything at all. diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index 689de30db37..183203ed709 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -257,16 +257,16 @@ if(!(slot & source.slot_flags)) return butchering_enabled = TRUE - RegisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(butcher_target)) + RegisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(butcher_target)) ///Same as disable_butchering but for worn items /datum/component/butchering/wearable/proc/worn_disable_butchering(obj/item/source, mob/user) SIGNAL_HANDLER butchering_enabled = FALSE - UnregisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK) /datum/component/butchering/wearable/proc/butcher_target(mob/user, atom/target, proximity) SIGNAL_HANDLER if(!isliving(target)) - return - onItemAttack(parent, target, user) + return NONE + return onItemAttack(parent, target, user) diff --git a/code/datums/components/focused_attacker.dm b/code/datums/components/focused_attacker.dm index eda6bd17979..8635973f263 100644 --- a/code/datums/components/focused_attacker.dm +++ b/code/datums/components/focused_attacker.dm @@ -24,12 +24,12 @@ /datum/component/focused_attacker/RegisterWithParent() if (isliving(parent)) - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK), PROC_REF(pre_mob_attack)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(pre_mob_attack)) else RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(pre_item_attack)) /datum/component/focused_attacker/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_ITEM_PRE_ATTACK)) + UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ITEM_PRE_ATTACK)) /// Before a mob attacks, try increasing its attack power /datum/component/focused_attacker/proc/pre_mob_attack(mob/living/attacker, atom/target) diff --git a/code/datums/components/mob_chain.dm b/code/datums/components/mob_chain.dm index 8312d9d5504..2ff7c4f1967 100644 --- a/code/datums/components/mob_chain.dm +++ b/code/datums/components/mob_chain.dm @@ -43,7 +43,7 @@ RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_deletion)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) RegisterSignal(parent, COMSIG_ATOM_CAN_BE_PULLED, PROC_REF(on_pulled)) - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_MOB_ATTACK_RANGED), PROC_REF(on_attack)) + RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_MOB_ATTACK_RANGED), PROC_REF(on_attack)) RegisterSignal(parent, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(on_glide_size_changed)) if (vary_icon_state) RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(on_update_icon_state)) @@ -61,7 +61,6 @@ COMSIG_ATOM_CAN_BE_PULLED, COMSIG_ATOM_UPDATE_ICON_STATE, COMSIG_CARBON_LIMB_DAMAGED, - COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_LIVING_ADJUST_BRUTE_DAMAGE, COMSIG_LIVING_ADJUST_BURN_DAMAGE, COMSIG_LIVING_ADJUST_CLONE_DAMAGE, diff --git a/code/datums/components/punchcooldown.dm b/code/datums/components/punchcooldown.dm index 7c2ae1047fe..80a72784c09 100644 --- a/code/datums/components/punchcooldown.dm +++ b/code/datums/components/punchcooldown.dm @@ -1,6 +1,6 @@ ///Your favourite Jojoke. Used for the gloves of the north star. /datum/component/wearertargeting/punchcooldown - signals = list(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_LIVING_SLAP_MOB) + signals = list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_LIVING_SLAP_MOB) mobtype = /mob/living/carbon proctype = PROC_REF(reducecooldown) valid_slots = list(ITEM_SLOT_GLOVES) @@ -13,7 +13,7 @@ return RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(changewarcry)) -///Called on COMSIG_HUMAN_MELEE_UNARMED_ATTACK. Yells the warcry and and reduces punch cooldown. +///Called on COMSIG_LIVING_UNARMED_ATTACK. Yells the warcry and and reduces punch cooldown. /datum/component/wearertargeting/punchcooldown/proc/reducecooldown(mob/living/carbon/M, atom/target) if((M.combat_mode && isliving(target)) || istype(M.get_active_held_item(), /obj/item/hand_item/slapper)) M.changeNext_move(CLICK_CD_RAPID) diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index a546508e505..cf4dad61b5e 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -212,7 +212,7 @@ /datum/component/riding/creature/human/RegisterWithParent() . = ..() - RegisterSignal(parent, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_host_unarmed_melee)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_host_unarmed_melee)) RegisterSignal(parent, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(check_carrier_fall_over)) /datum/component/riding/creature/human/log_riding(mob/living/living_parent, mob/living/rider) @@ -234,12 +234,13 @@ return ..() /// If the carrier shoves the person they're carrying, force the carried mob off -/datum/component/riding/creature/human/proc/on_host_unarmed_melee(mob/living/carbon/human/human_parent, atom/target, proximity, modifiers) +/datum/component/riding/creature/human/proc/on_host_unarmed_melee(mob/living/source, atom/target, proximity, modifiers) SIGNAL_HANDLER - if(LAZYACCESS(modifiers, RIGHT_CLICK) && (target in human_parent.buckled_mobs)) + if(LAZYACCESS(modifiers, RIGHT_CLICK) && (target in source.buckled_mobs)) force_dismount(target) return COMPONENT_CANCEL_ATTACK_CHAIN + return NONE /// If the carrier gets knocked over, force the rider(s) off and see if someone got hurt /datum/component/riding/creature/human/proc/check_carrier_fall_over(mob/living/carbon/human/human_parent) diff --git a/code/datums/components/shovel_hands.dm b/code/datums/components/shovel_hands.dm index e4ee2d644d3..34eaf8a98b6 100644 --- a/code/datums/components/shovel_hands.dm +++ b/code/datums/components/shovel_hands.dm @@ -14,10 +14,10 @@ /datum/component/shovel_hands/RegisterWithParent() . = ..() - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(dig)) + RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(dig)) /datum/component/shovel_hands/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) return ..() /datum/component/shovel_hands/Destroy(force, silent) diff --git a/code/datums/components/shy.dm b/code/datums/components/shy.dm index 845da7e0f7d..5743322dea1 100644 --- a/code/datums/components/shy.dm +++ b/code/datums/components/shy.dm @@ -46,7 +46,7 @@ /datum/component/shy/RegisterWithParent() RegisterSignal(parent, COMSIG_MOB_CLICKON, PROC_REF(on_clickon)) RegisterSignal(parent, COMSIG_LIVING_TRY_PULL, PROC_REF(on_try_pull)) - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK), PROC_REF(on_unarmed_attack)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) RegisterSignal(parent, COMSIG_TRY_STRIP, PROC_REF(on_try_strip)) RegisterSignal(parent, COMSIG_TRY_ALT_ACTION, PROC_REF(on_try_alt_action)) @@ -54,7 +54,7 @@ UnregisterSignal(parent, list( COMSIG_MOB_CLICKON, COMSIG_LIVING_TRY_PULL, - COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, + COMSIG_LIVING_UNARMED_ATTACK, COMSIG_TRY_STRIP, COMSIG_TRY_ALT_ACTION, )) @@ -137,4 +137,3 @@ return is_shy(target) && COMPONENT_CANT_ALT_ACTION #undef SHY_COMPONENT_CACHE_TIME - diff --git a/code/datums/components/shy_in_room.dm b/code/datums/components/shy_in_room.dm index 2413c9abafd..023dbaff719 100644 --- a/code/datums/components/shy_in_room.dm +++ b/code/datums/components/shy_in_room.dm @@ -17,7 +17,7 @@ /datum/component/shy_in_room/RegisterWithParent() RegisterSignal(parent, COMSIG_MOB_CLICKON, PROC_REF(on_clickon)) RegisterSignal(parent, COMSIG_LIVING_TRY_PULL, PROC_REF(on_try_pull)) - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK), PROC_REF(on_unarmed_attack)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) RegisterSignal(parent, COMSIG_TRY_STRIP, PROC_REF(on_try_strip)) RegisterSignal(parent, COMSIG_TRY_ALT_ACTION, PROC_REF(on_try_alt_action)) @@ -27,7 +27,6 @@ COMSIG_MOB_CLICKON, COMSIG_LIVING_TRY_PULL, COMSIG_LIVING_UNARMED_ATTACK, - COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_TRY_STRIP, COMSIG_TRY_ALT_ACTION, )) @@ -73,4 +72,3 @@ /datum/component/shy_in_room/proc/on_try_alt_action(datum/source, atom/target) SIGNAL_HANDLER return is_shy(target) && COMPONENT_CANT_ALT_ACTION - diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm index 3894f77311e..abcc99574fe 100644 --- a/code/datums/components/style/style.dm +++ b/code/datums/components/style/style.dm @@ -105,7 +105,7 @@ RegisterSignal(parent, COMSIG_MOB_EMOTED("flip"), PROC_REF(on_flip)) RegisterSignal(parent, COMSIG_MOB_EMOTED("spin"), PROC_REF(on_spin)) RegisterSignal(parent, COMSIG_MOB_ITEM_ATTACK, PROC_REF(on_attack)) - RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(on_punch)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_punch)) RegisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH, PROC_REF(on_death)) RegisterSignal(parent, COMSIG_LIVING_RESONATOR_BURST, PROC_REF(on_resonator_burst)) RegisterSignal(parent, COMSIG_LIVING_PROJECTILE_PARRIED, PROC_REF(on_projectile_parry)) @@ -132,7 +132,7 @@ UnregisterSignal(parent, COMSIG_MOB_MINED) UnregisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE) UnregisterSignal(parent, list(COMSIG_MOB_EMOTED("flip"), COMSIG_MOB_EMOTED("spin"))) - UnregisterSignal(parent, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK)) + UnregisterSignal(parent, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_LIVING_UNARMED_ATTACK)) UnregisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH) UnregisterSignal(parent, COMSIG_LIVING_RESONATOR_BURST) UnregisterSignal(parent, COMSIG_LIVING_PROJECTILE_PARRIED) diff --git a/code/datums/elements/amputating_limbs.dm b/code/datums/elements/amputating_limbs.dm index 16a99e96f6c..8684a76f47f 100644 --- a/code/datums/elements/amputating_limbs.dm +++ b/code/datums/elements/amputating_limbs.dm @@ -32,16 +32,16 @@ src.minimum_stat = minimum_stat src.snip_chance = snip_chance src.target_zones = target_zones - RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(try_amputate)) + RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(try_amputate)) /datum/element/amputating_limbs/Detach(datum/source) - UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) return ..() /// Called when you click on literally anything with your hands, see if it is an injured carbon and then try to cut it up -/datum/element/amputating_limbs/proc/try_amputate(mob/living/surgeon, atom/victim) +/datum/element/amputating_limbs/proc/try_amputate(mob/living/surgeon, atom/victim, proximity, modifiers) SIGNAL_HANDLER - if (!iscarbon(victim) || HAS_TRAIT(victim, TRAIT_NODISMEMBER) || !prob(snip_chance)) + if (!proximity || !iscarbon(victim) || HAS_TRAIT(victim, TRAIT_NODISMEMBER) || !prob(snip_chance)) return var/mob/living/carbon/limbed_victim = victim diff --git a/code/datums/elements/basic_eating.dm b/code/datums/elements/basic_eating.dm index 86f4be63cac..08c2ed0c192 100644 --- a/code/datums/elements/basic_eating.dm +++ b/code/datums/elements/basic_eating.dm @@ -37,7 +37,12 @@ /datum/element/basic_eating/proc/on_unarm_attack(mob/living/eater, atom/target, proximity, modifiers) SIGNAL_HANDLER - try_eating(eater, target) + if(!proximity) + return NONE + + if(try_eating(eater, target)) + return COMPONENT_CANCEL_ATTACK_CHAIN + return NONE /datum/element/basic_eating/proc/on_pre_attackingtarget(mob/living/eater, atom/target) SIGNAL_HANDLER @@ -45,7 +50,7 @@ /datum/element/basic_eating/proc/try_eating(mob/living/eater, atom/target) if(!is_type_in_list(target, food_types)) - return + return FALSE var/eat_verb = pick("bite","chew","nibble","gnaw","gobble","chomp") if (heal_amt > 0) @@ -54,16 +59,17 @@ eater.heal_overall_damage(heal_amt) eater.visible_message(span_notice("[eater] [eat_verb]s [target]."), span_notice("You [eat_verb] [target][healed ? ", restoring some health" : ""].")) finish_eating(eater, target) - return + return TRUE if (damage_amount > 0 && damage_type) eater.apply_damage(damage_amount, damage_type) eater.visible_message(span_notice("[eater] [eat_verb]s [target], and seems to hurt itself."), span_notice("You [eat_verb] [target], hurting yourself in the process.")) finish_eating(eater, target) - return + return TRUE eater.visible_message(span_notice("[eater] [eat_verb]s [target]."), span_notice("You [eat_verb] [target].")) finish_eating(eater, target) + return TRUE /datum/element/basic_eating/proc/finish_eating(mob/living/eater, atom/target) playsound(eater.loc,'sound/items/eatfood.ogg', rand(10,50), TRUE) diff --git a/code/datums/elements/dextrous.dm b/code/datums/elements/dextrous.dm index 335c7c196d1..526dfa974af 100644 --- a/code/datums/elements/dextrous.dm +++ b/code/datums/elements/dextrous.dm @@ -50,8 +50,10 @@ /// Try picking up items /datum/element/dextrous/proc/on_hand_clicked(mob/living/hand_haver, atom/target, proximity, modifiers) SIGNAL_HANDLER + if(!proximity) + return NONE if (!isitem(target) && hand_haver.combat_mode) - return + return NONE if (LAZYACCESS(modifiers, RIGHT_CLICK)) INVOKE_ASYNC(target, TYPE_PROC_REF(/atom, attack_hand_secondary), hand_haver, modifiers) else diff --git a/code/datums/elements/door_pryer.dm b/code/datums/elements/door_pryer.dm index 5d807434e04..a17687407e3 100644 --- a/code/datums/elements/door_pryer.dm +++ b/code/datums/elements/door_pryer.dm @@ -16,20 +16,20 @@ return ELEMENT_INCOMPATIBLE src.pry_time = pry_time src.interaction_key = interaction_key - RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK), PROC_REF(on_attack)) + RegisterSignal(target, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_attack)) /datum/element/door_pryer/Detach(datum/source) . = ..() - UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK)) + UnregisterSignal(source, COMSIG_LIVING_UNARMED_ATTACK) /// If we're targetting an airlock, open it -/datum/element/door_pryer/proc/on_attack(mob/living/basic/attacker, atom/target) +/datum/element/door_pryer/proc/on_attack(mob/living/basic/attacker, atom/target, proximity_flag) SIGNAL_HANDLER - if(!istype(target, /obj/machinery/door/airlock)) - return + if(!proximity_flag || !istype(target, /obj/machinery/door/airlock)) + return NONE var/obj/machinery/door/airlock/airlock_target = target if (!airlock_target.density) - return // It's already open numbnuts + return NONE // It's already open numbnuts if(DOING_INTERACTION_WITH_TARGET(attacker, target) || (!isnull(interaction_key) && DOING_INTERACTION(attacker, interaction_key))) attacker.balloon_alert(attacker, "busy!") diff --git a/code/datums/elements/human_biter.dm b/code/datums/elements/human_biter.dm new file mode 100644 index 00000000000..852dea12320 --- /dev/null +++ b/code/datums/elements/human_biter.dm @@ -0,0 +1,28 @@ +/// Allows carbons with heads to attempt to bite mobs if attacking with cuffed hands / missing arms +/datum/element/human_biter + +/datum/element/human_biter/Attach(datum/target) + . = ..() + if(!iscarbon(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(try_bite)) + +/datum/element/human_biter/Detach(datum/source, ...) + . = ..() + UnregisterSignal(source, COMSIG_LIVING_EARLY_UNARMED_ATTACK) + +/datum/element/human_biter/proc/try_bite(mob/living/carbon/human/source, atom/target, proximity_flag, modifiers) + SIGNAL_HANDLER + + if(!proximity_flag || !source.combat_mode || LAZYACCESS(modifiers, RIGHT_CLICK) || !isliving(target)) + return NONE + + // If we can attack like normal, just go ahead and do that + if(source.can_unarmed_attack()) + return NONE + + if(target.attack_paw(source, modifiers)) + return COMPONENT_CANCEL_ATTACK_CHAIN // bite successful! + + return COMPONENT_SKIP_ATTACK // we will fail anyways if we try to attack normally, so skip the rest diff --git a/code/datums/elements/mob_grabber.dm b/code/datums/elements/mob_grabber.dm index a85c5dc48b2..cc766f24887 100644 --- a/code/datums/elements/mob_grabber.dm +++ b/code/datums/elements/mob_grabber.dm @@ -13,18 +13,19 @@ return ELEMENT_INCOMPATIBLE src.minimum_stat = minimum_stat src.steal_from_others = steal_from_others - RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(grab_mob)) + RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(grab_mob)) /datum/element/mob_grabber/Detach(datum/source) - UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) . = ..() /// Try and grab something we attacked -/datum/element/mob_grabber/proc/grab_mob(mob/living/source, mob/living/target) +/datum/element/mob_grabber/proc/grab_mob(mob/living/source, mob/living/target, proximity, modifiers) SIGNAL_HANDLER - if (!isliving(target) || !source.Adjacent(target) || target.stat < minimum_stat) - return + if (!isliving(target) || !proximity || target.stat < minimum_stat) + return NONE var/atom/currently_pulled = target.pulledby if (!isnull(currently_pulled) && (!steal_from_others || currently_pulled == source)) - return + return NONE INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living, grabbedby), source) + return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/datums/elements/structure_repair.dm b/code/datums/elements/structure_repair.dm index d3b26eed815..1f57a3d1730 100644 --- a/code/datums/elements/structure_repair.dm +++ b/code/datums/elements/structure_repair.dm @@ -25,11 +25,11 @@ return ..() /// If the target is of a valid type, interrupt the attack chain to repair it instead -/datum/element/structure_repair/proc/try_repair(mob/living/fixer, atom/target) +/datum/element/structure_repair/proc/try_repair(mob/living/fixer, atom/target, proximity) SIGNAL_HANDLER - if (!is_type_in_typecache(target, structure_types_typecache)) - return + if (!proximity || !is_type_in_typecache(target, structure_types_typecache)) + return NONE if (target.get_integrity() >= target.max_integrity) target.balloon_alert(fixer, "not damaged!") diff --git a/code/datums/elements/wall_smasher.dm b/code/datums/elements/wall_smasher.dm index 3c6c1d92da7..ba8a689253c 100644 --- a/code/datums/elements/wall_smasher.dm +++ b/code/datums/elements/wall_smasher.dm @@ -17,7 +17,7 @@ return ELEMENT_INCOMPATIBLE src.strength_flag = strength_flag - RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK), PROC_REF(on_unarm_attack)) // Players + RegisterSignal(target, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarm_attack)) // Players RegisterSignal(target, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_pre_attackingtarget)) // AI if (isanimal_or_basicmob(target)) @@ -25,7 +25,7 @@ animal_target.environment_smash = strength_flag /datum/element/wall_smasher/Detach(datum/target) - UnregisterSignal(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + UnregisterSignal(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) if (isanimal_or_basicmob(target)) var/mob/living/simple_animal/animal_target = target animal_target.environment_smash = initial(animal_target.environment_smash) @@ -34,19 +34,19 @@ /datum/element/wall_smasher/proc/on_unarm_attack(mob/living/puncher, atom/target, proximity, modifiers) SIGNAL_HANDLER - try_smashing(puncher, target) + return try_smashing(puncher, target) /datum/element/wall_smasher/proc/on_pre_attackingtarget(mob/living/puncher, atom/target) SIGNAL_HANDLER - try_smashing(puncher, target) + return try_smashing(puncher, target) /datum/element/wall_smasher/proc/try_smashing(mob/living/puncher, atom/target) if (!isturf(target)) - return + return NONE if (isfloorturf(target)) - return + return NONE if (isindestructiblewall(target)) - return + return NONE puncher.changeNext_move(CLICK_CD_MELEE) puncher.do_attack_animation(target) diff --git a/code/datums/elements/wall_tearer.dm b/code/datums/elements/wall_tearer.dm index 8499a161705..e7ca4b3be96 100644 --- a/code/datums/elements/wall_tearer.dm +++ b/code/datums/elements/wall_tearer.dm @@ -28,17 +28,17 @@ src.tear_time = tear_time src.reinforced_multiplier = reinforced_multiplier src.do_after_key = do_after_key - RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK), PROC_REF(on_attacked_wall)) + RegisterSignal(target, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_attacked_wall)) /datum/element/wall_tearer/Detach(datum/source) . = ..() - UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK)) + UnregisterSignal(source, COMSIG_LIVING_UNARMED_ATTACK) /// Try to tear up a wall /datum/element/wall_tearer/proc/on_attacked_wall(mob/living/tearer, atom/target, proximity_flag) SIGNAL_HANDLER if (!proximity_flag) - return + return NONE if (DOING_INTERACTION_WITH_TARGET(tearer, target) || (!isnull(do_after_key) && DOING_INTERACTION(tearer, do_after_key))) tearer.balloon_alert(tearer, "busy!") return COMPONENT_HOSTILE_NO_ATTACK diff --git a/code/datums/mutations/chameleon.dm b/code/datums/mutations/chameleon.dm index 9cd155594ec..3de361ba548 100644 --- a/code/datums/mutations/chameleon.dm +++ b/code/datums/mutations/chameleon.dm @@ -14,7 +14,7 @@ return owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) - RegisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + RegisterSignal(owner, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_attack_hand)) /datum/mutation/human/chameleon/on_life(seconds_per_tick, times_fired) owner.alpha = max(owner.alpha - (12.5 * (GET_MUTATION_POWER(src)) * seconds_per_tick), 0) @@ -54,4 +54,4 @@ if(..()) return owner.alpha = 255 - UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_HUMAN_EARLY_UNARMED_ATTACK)) + UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_UNARMED_ATTACK)) diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index ba04fc07c54..788b885bbce 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -29,26 +29,27 @@ part.variable_color = "#00aa00" owner.update_body_parts() owner.add_mood_event("hulk", /datum/mood_event/hulk) - RegisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + RegisterSignal(owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) RegisterSignal(owner, COMSIG_MOB_CLICKON, PROC_REF(check_swing)) /datum/mutation/human/hulk/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers) SIGNAL_HANDLER - if(!proximity) - return - if(!source.combat_mode || LAZYACCESS(modifiers, RIGHT_CLICK)) - return - if(target.attack_hulk(owner)) - if(world.time > (last_scream + scream_delay)) - last_scream = world.time - INVOKE_ASYNC(src, PROC_REF(scream_attack), source) - log_combat(source, target, "punched", "hulk powers") - source.do_attack_animation(target, ATTACK_EFFECT_SMASH) - source.changeNext_move(CLICK_CD_MELEE) - + if(!source.combat_mode || !proximity || LAZYACCESS(modifiers, RIGHT_CLICK)) + return NONE + if(!source.can_unarmed_attack()) return COMPONENT_CANCEL_ATTACK_CHAIN + if(!target.attack_hulk(owner)) + return NONE + + if(world.time > (last_scream + scream_delay)) + last_scream = world.time + INVOKE_ASYNC(src, PROC_REF(scream_attack), source) + log_combat(source, target, "punched", "hulk powers") + source.do_attack_animation(target, ATTACK_EFFECT_SMASH) + source.changeNext_move(CLICK_CD_MELEE) + return COMPONENT_CANCEL_ATTACK_CHAIN /datum/mutation/human/hulk/proc/scream_attack(mob/living/carbon/human/source) source.say("WAAAAAAAAAAAAAAGH!", forced="hulk") @@ -90,7 +91,7 @@ part.variable_color = null owner.update_body_parts() owner.clear_mood_event("hulk") - UnregisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) UnregisterSignal(owner, COMSIG_MOB_SAY) UnregisterSignal(owner, COMSIG_MOB_CLICKON) diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 9b8da5177ca..80c1c0a7557 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -61,9 +61,9 @@ /datum/wound/blunt/bone/set_victim(new_victim) if (victim) - UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(victim, COMSIG_LIVING_UNARMED_ATTACK) if (new_victim) - RegisterSignal(new_victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) + RegisterSignal(new_victim, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) return ..() @@ -114,8 +114,8 @@ /datum/wound/blunt/bone/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) SIGNAL_HANDLER - if(victim.get_active_hand() != limb || !victim.combat_mode || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) - return + if(victim.get_active_hand() != limb || !proximity || !victim.combat_mode || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) + return NONE // With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit if(prob((severity - 1) * 15)) @@ -131,6 +131,7 @@ limb.receive_damage(brute=rand(3,7)) return COMPONENT_CANCEL_ATTACK_CHAIN + return NONE /datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus) if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index f99b9f3cc94..c3d968dca8a 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -680,10 +680,25 @@ /obj/machinery/attack_paw(mob/living/user, list/modifiers) if(!user.combat_mode) return attack_hand(user) + user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - var/damage = take_damage(4, BRUTE, MELEE, 1) - user.visible_message(span_danger("[user] smashes [src] with [user.p_their()] paws[damage ? "." : ", without leaving a mark!"]"), null, null, COMBAT_MESSAGE_RANGE) + var/damage = take_damage(damage_amount = 4, damage_type = BRUTE, damage_flag = MELEE, sound_effect = TRUE, attack_dir = get_dir(user, src)) + + var/hit_with_what_noun = "paws" + var/obj/item/bodypart/arm/arm = user.get_active_hand() + if(!isnull(arm)) + hit_with_what_noun = arm.appendage_noun // hit with "their hand" + if(user.usable_hands > 1) + hit_with_what_noun += plural_s(hit_with_what_noun) // hit with "their hands" + + user.visible_message( + span_danger("[user] smashes [src] with [user.p_their()] [hit_with_what_noun][damage ? "." : ", without leaving a mark!"]"), + span_danger("You smash [src] with your [hit_with_what_noun][damage ? "." : ", without leaving a mark!"]"), + span_hear("You hear a [damage ? "smash" : "thud"]."), + COMBAT_MESSAGE_RANGE, + ) + return TRUE /obj/machinery/attack_hulk(mob/living/carbon/user) . = ..() diff --git a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm index 5ed7fcd4682..e52c5f8034c 100644 --- a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm +++ b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm @@ -343,7 +343,7 @@ if (!.) return FALSE var/mob/living/carbon/human/human_owner = owner - RegisterSignal(human_owner, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(on_punched)) + RegisterSignal(human_owner, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_punched)) human_owner.physiology.brute_mod *= brute_modifier for (var/obj/item/bodypart/arm/arm in human_owner.bodyparts) if (arm.limb_id != SPECIES_GOLEM) @@ -354,10 +354,10 @@ /datum/status_effect/golem/titanium/proc/on_punched(mob/living/puncher, atom/punchee, proximity) SIGNAL_HANDLER if (!proximity || !isliving(punchee)) - return + return NONE var/mob/living/victim = punchee if (victim.body_position == LYING_DOWN || (!(FACTION_MINING in victim.faction) && !(FACTION_BOSS in victim.faction))) - return + return NONE victim.apply_damage(mining_bonus, BRUTE) /// Make the targeted arm big and strong @@ -370,7 +370,7 @@ /datum/status_effect/golem/titanium/on_remove() var/mob/living/carbon/human/human_owner = owner - UnregisterSignal(human_owner, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) + UnregisterSignal(human_owner, COMSIG_LIVING_UNARMED_ATTACK) human_owner.physiology.brute_mod /= brute_modifier for (var/obj/item/bodypart/arm/arm as anything in modified_arms) debuff_arm(arm) diff --git a/code/modules/antagonists/traitor/objectives/hack_comm_console.dm b/code/modules/antagonists/traitor/objectives/hack_comm_console.dm index 52e0397cc60..93323e4e15f 100644 --- a/code/modules/antagonists/traitor/objectives/hack_comm_console.dm +++ b/code/modules/antagonists/traitor/objectives/hack_comm_console.dm @@ -23,7 +23,7 @@ /datum/traitor_objective/hack_comm_console/generate_objective(datum/mind/generating_for, list/possible_duplicates) AddComponent(/datum/component/traitor_objective_mind_tracker, generating_for, \ - signals = list(COMSIG_HUMAN_EARLY_UNARMED_ATTACK = PROC_REF(on_unarmed_attack))) + signals = list(COMSIG_LIVING_UNARMED_ATTACK = PROC_REF(on_unarmed_attack))) RegisterSignal(SSdcs, COMSIG_GLOB_TRAITOR_OBJECTIVE_COMPLETED, PROC_REF(on_global_obj_completed)) return TRUE diff --git a/code/modules/clothing/shoes/gunboots.dm b/code/modules/clothing/shoes/gunboots.dm index db24b2338cf..d8335b5fcb0 100644 --- a/code/modules/clothing/shoes/gunboots.dm +++ b/code/modules/clothing/shoes/gunboots.dm @@ -18,13 +18,13 @@ /obj/item/clothing/shoes/gunboots/equipped(mob/user, slot) . = ..() if(slot & ITEM_SLOT_FEET) - RegisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(check_kick)) + RegisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(check_kick)) else - UnregisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) + UnregisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK) /obj/item/clothing/shoes/gunboots/dropped(mob/user) if(user) - UnregisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) + UnregisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK) return ..() /// After each step, check if we randomly fire a shot @@ -38,8 +38,8 @@ /// Stomping on someone while wearing gunboots shoots them point blank /obj/item/clothing/shoes/gunboots/proc/check_kick(mob/living/carbon/human/kicking_person, atom/attacked_atom, proximity) SIGNAL_HANDLER - if(!isliving(attacked_atom)) - return + if(!proximity || !isliving(attacked_atom)) + return NONE var/mob/living/attacked_living = attacked_atom if(attacked_living.body_position == LYING_DOWN) INVOKE_ASYNC(src, PROC_REF(fire_shot), attacked_living) diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index d3d4b4b672f..e790a235549 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -632,7 +632,7 @@ . = ..() if(slot & ITEM_SLOT_GLOVES) tool_behaviour = TOOL_MINING - RegisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(rocksmash)) + RegisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(rocksmash)) RegisterSignal(user, COMSIG_MOVABLE_BUMP, PROC_REF(rocksmash)) else stopmining(user) @@ -643,13 +643,15 @@ /obj/item/clothing/gloves/gauntlets/proc/stopmining(mob/user) tool_behaviour = initial(tool_behaviour) - UnregisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK) UnregisterSignal(user, COMSIG_MOVABLE_BUMP) /obj/item/clothing/gloves/gauntlets/proc/rocksmash(mob/living/carbon/human/user, atom/rocks, proximity) SIGNAL_HANDLER + if(!proximity) + return NONE if(!ismineralturf(rocks) && !isasteroidturf(rocks)) - return + return NONE rocks.attackby(src, user) return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm b/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm index e52eb09ac0b..ed3c131949d 100644 --- a/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm +++ b/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm @@ -99,16 +99,19 @@ /mob/living/basic/demon/slaughter/proc/on_attack(mob/living/source, atom/attack_target, proximity_flag, list/modifiers) SIGNAL_HANDLER + if(!proximity_flag) + return NONE + if(LAZYACCESS(modifiers, RIGHT_CLICK)) bodyslam(attack_target) return COMPONENT_CANCEL_ATTACK_CHAIN if(!iscarbon(attack_target)) - return + return NONE var/mob/living/carbon/target = attack_target if(target.stat == DEAD || isnull(target.mind) || (current_hitstreak > wound_bonus_hitstreak_max)) - return + return NONE current_hitstreak++ wound_bonus += wound_bonus_per_hit diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 12e2bd7a053..af4f3b9ddf7 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1198,7 +1198,6 @@ GLOBAL_LIST_EMPTY(features_by_species) 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) @@ -1225,9 +1224,6 @@ GLOBAL_LIST_EMPTY(features_by_species) target.apply_effect(knockdown_duration, EFFECT_KNOCKDOWN, armor_block) log_combat(user, target, "got a stun punch with their previous punch") -/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(span_warning("[user]'s shove is blocked by [target]!"), \ @@ -1790,10 +1786,6 @@ GLOBAL_LIST_EMPTY(features_by_species) former_tail_owner.clear_mood_event("tail_balance_lost") former_tail_owner.clear_mood_event("wrong_tail_regained") -///Species override for unarmed attacks because the attack_hand proc was made by a mouth-breathing troglodyte on a tricycle. Also to whoever thought it would be a good idea to make it so the original spec_unarmedattack was not actually linked to unarmed attack needs to be checked by a doctor because they clearly have a vast empty space in their head. -/datum/species/proc/spec_unarmedattack(mob/living/carbon/human/user, atom/target, modifiers) - return FALSE - /// Returns a list of strings representing features this species has. /// Used by the preferences UI to know what buttons to show. /datum/species/proc/get_features() diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index f8aee4d83b1..81861d381a0 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -52,70 +52,13 @@ passtable_on(H, SPECIES_TRAIT) H.dna.add_mutation(/datum/mutation/human/race, MUT_NORMAL) H.dna.activate_mutation(/datum/mutation/human/race) + H.AddElement(/datum/element/human_biter) /datum/species/monkey/on_species_loss(mob/living/carbon/C) . = ..() passtable_off(C, SPECIES_TRAIT) C.dna.remove_mutation(/datum/mutation/human/race) - -/datum/species/monkey/spec_unarmedattack(mob/living/carbon/human/user, atom/target, modifiers) - // If our hands are not blocked, dont try to bite them - if(!HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) - // if we aren't an advanced tool user, we call attack_paw and cancel the preceeding attack chain - if(!ISADVANCEDTOOLUSER(user)) - target.attack_paw(user, modifiers) - return TRUE - return ..() - - // this shouldn't even be possible, but I'm sure the check was here for a reason - if(!iscarbon(target)) - stack_trace("HEY LISTEN! We are performing a species spec_unarmed attack with a non-carbon user. How did you fuck this up?") - return TRUE - var/mob/living/carbon/victim = target - if(user.is_muzzled()) - return TRUE // cannot bite them if we're muzzled - - var/obj/item/bodypart/affecting - if(ishuman(victim)) - var/mob/living/carbon/human/human_victim = victim - affecting = human_victim.get_bodypart(human_victim.get_random_valid_zone(even_weights = TRUE)) - var/armor = victim.run_armor_check(affecting, MELEE) - - if(prob(MONKEY_SPEC_ATTACK_BITE_MISS_CHANCE)) - victim.visible_message( - span_danger("[user]'s bite misses [victim]!"), - span_danger("You avoid [user]'s bite!"), - span_hear("You hear jaws snapping shut!"), - COMBAT_MESSAGE_RANGE, - user, - ) - to_chat(user, span_danger("Your bite misses [victim]!")) - return TRUE - - var/obj/item/bodypart/head/mouth = user.get_bodypart(BODY_ZONE_HEAD) - if(!mouth) // check for them having a head, ala HARS - return TRUE - - var/damage_roll = rand(mouth.unarmed_damage_low, mouth.unarmed_damage_high) - victim.apply_damage(damage_roll, BRUTE, affecting, armor) - - victim.visible_message( - span_danger("[name] bites [victim]!"), - span_userdanger("[name] bites you!"), - span_hear("You hear a chomp!"), - COMBAT_MESSAGE_RANGE, - name, - ) - to_chat(user, span_danger("You bite [victim]!")) - - if(armor >= 2) // if they have basic armor on the limb we bit, don't spread diseases - return TRUE - for(var/datum/disease/bite_infection as anything in user.diseases) - if(bite_infection.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS)) - continue // ignore diseases that have special spread logic, or are not contagious - victim.ForceContractDisease(bite_infection) - - return TRUE + C.RemoveElement(/datum/element/human_biter) /datum/species/monkey/check_roundstart_eligible() if(check_holidays(MONKEYDAY)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index f31fd60b131..cfc2208a1bc 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -309,10 +309,6 @@ return martial_result /mob/living/attack_paw(mob/living/carbon/human/user, list/modifiers) - if(isturf(loc) && istype(loc.loc, /area/misc/start)) - to_chat(user, "No attacking people at spawn, you jackass.") - return FALSE - var/martial_result = user.apply_martial_art(src, modifiers) if (martial_result != MARTIAL_ATTACK_INVALID) return martial_result @@ -327,6 +323,8 @@ to_chat(user, span_warning("You don't want to hurt anyone!")) return FALSE + if(!user.get_bodypart(BODY_ZONE_HEAD)) + return FALSE if(user.is_muzzled() || user.is_mouth_covered(ITEM_SLOT_MASK)) to_chat(user, span_warning("You can't bite with your mouth covered!")) return FALSE diff --git a/code/modules/mod/modules/modules_ninja.dm b/code/modules/mod/modules/modules_ninja.dm index 7a38238594d..31db6017609 100644 --- a/code/modules/mod/modules/modules_ninja.dm +++ b/code/modules/mod/modules/modules_ninja.dm @@ -24,7 +24,7 @@ return if(bumpoff) RegisterSignal(mod.wearer, COMSIG_LIVING_MOB_BUMP, PROC_REF(unstealth)) - RegisterSignal(mod.wearer, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) + RegisterSignal(mod.wearer, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) RegisterSignal(mod.wearer, COMSIG_ATOM_BULLET_ACT, PROC_REF(on_bullet_act)) RegisterSignals(mod.wearer, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED), PROC_REF(unstealth)) animate(mod.wearer, alpha = stealth_alpha, time = 1.5 SECONDS) @@ -36,7 +36,7 @@ return if(bumpoff) UnregisterSignal(mod.wearer, COMSIG_LIVING_MOB_BUMP) - UnregisterSignal(mod.wearer, list(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED)) + UnregisterSignal(mod.wearer, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED)) animate(mod.wearer, alpha = 255, time = 1.5 SECONDS) /obj/item/mod/module/stealth/proc/unstealth(datum/source) @@ -143,10 +143,10 @@ var/door_hack_counter = 0 /obj/item/mod/module/hacker/on_suit_activation() - RegisterSignal(mod.wearer, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(hack)) + RegisterSignal(mod.wearer, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(hack)) /obj/item/mod/module/hacker/on_suit_deactivation(deleting = FALSE) - UnregisterSignal(mod.wearer, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(mod.wearer, COMSIG_LIVING_UNARMED_ATTACK) /obj/item/mod/module/hacker/proc/hack(mob/living/carbon/human/source, atom/target, proximity, modifiers) SIGNAL_HANDLER diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index c3924163784..fc3c259fa92 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -113,6 +113,8 @@ var/datum/worn_feature_offset/worn_glove_offset /// Datum describing how to offset things held in the hands of this arm, the x offset IS functional here var/datum/worn_feature_offset/held_hand_offset + /// The noun to use when referring to this arm's appendage, e.g. "hand" or "paw" + var/appendage_noun = "hand" biological_state = BIO_STANDARD_JOINTED @@ -211,6 +213,7 @@ unarmed_damage_low = 1 /// monkey punches must be really weak, considering they bite people instead and their bites are weak as hell. unarmed_damage_high = 2 unarmed_stun_threshold = 3 + appendage_noun = "paw" /obj/item/bodypart/arm/left/alien icon = 'icons/mob/human/species/alien/bodyparts.dmi' @@ -224,6 +227,7 @@ can_be_disabled = FALSE max_damage = 100 should_draw_greyscale = FALSE + appendage_noun = "scythe-like hand" /obj/item/bodypart/arm/right @@ -314,6 +318,7 @@ unarmed_damage_low = 1 unarmed_damage_high = 2 unarmed_stun_threshold = 3 + appendage_noun = "paw" /obj/item/bodypart/arm/right/alien icon = 'icons/mob/human/species/alien/bodyparts.dmi' @@ -327,6 +332,7 @@ can_be_disabled = FALSE max_damage = 100 should_draw_greyscale = FALSE + appendage_noun = "scythe-like hand" /// Parent Type for legs, should not appear in game. /obj/item/bodypart/leg diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm index 86cdf855134..142cf8d5143 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm @@ -381,11 +381,11 @@ /obj/item/organ/internal/cyberimp/arm/muscle/Insert(mob/living/carbon/reciever, special = FALSE, drop_if_replaced = TRUE) . = ..() if(ishuman(reciever)) //Sorry, only humans - RegisterSignal(reciever, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + RegisterSignal(reciever, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) /obj/item/organ/internal/cyberimp/arm/muscle/Remove(mob/living/carbon/implant_owner, special = 0) . = ..() - UnregisterSignal(implant_owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(implant_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) /obj/item/organ/internal/cyberimp/arm/muscle/emp_act(severity) . = ..() @@ -402,15 +402,17 @@ /obj/item/organ/internal/cyberimp/arm/muscle/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers) SIGNAL_HANDLER - if(source.get_active_hand() != source.get_bodypart(check_zone(zone)) || !proximity) - return + if(source.get_active_hand() != hand || !proximity) + return NONE if(!source.combat_mode || LAZYACCESS(modifiers, RIGHT_CLICK)) - return + return NONE if(!isliving(target)) - return + return NONE var/datum/dna/dna = source.has_dna() if(dna?.check_mutation(/datum/mutation/human/hulk)) //NO HULK - return + return NONE + if(!source.can_unarmed_attack()) + return COMPONENT_CANCEL_ATTACK_CHAIN var/mob/living/living_target = target source.changeNext_move(CLICK_CD_MELEE) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index c6fdecbd29b..3f877d637aa 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -149,6 +149,7 @@ #include "heretic_rituals.dm" #include "high_five.dm" #include "holidays.dm" +#include "hulk.dm" #include "human_through_recycler.dm" #include "hunger_curse.dm" #include "hydroponics_extractor_storage.dm" diff --git a/code/modules/unit_tests/hulk.dm b/code/modules/unit_tests/hulk.dm new file mode 100644 index 00000000000..52706e9ac73 --- /dev/null +++ b/code/modules/unit_tests/hulk.dm @@ -0,0 +1,44 @@ +/// Tests hulk attacking over normal attacking +/datum/unit_test/hulk_attack + var/hulk_hits = 0 + var/hand_hits = 0 + +/datum/unit_test/hulk_attack/Run() + var/mob/living/carbon/human/hulk = allocate(/mob/living/carbon/human/consistent) + var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) + + + RegisterSignal(dummy, COMSIG_ATOM_HULK_ATTACK, PROC_REF(hulk_sig_fire)) + RegisterSignal(dummy, COMSIG_ATOM_ATTACK_HAND, PROC_REF(hand_sig_fire)) + + hulk.dna.add_mutation(/datum/mutation/human/hulk) + hulk.set_combat_mode(TRUE) + hulk.ClickOn(dummy) + + TEST_ASSERT_EQUAL(hulk_hits, 1, "Hulk should have hit the dummy once.") + TEST_ASSERT_EQUAL(hand_hits, 0, "Hulk should not have hit the dummy with attack_hand.") + TEST_ASSERT(dummy.getBruteLoss(), "Dummy should have taken brute damage from being hulk punched.") + +/datum/unit_test/hulk_attack/proc/hulk_sig_fire() + SIGNAL_HANDLER + hulk_hits += 1 + +/datum/unit_test/hulk_attack/proc/hand_sig_fire() + SIGNAL_HANDLER + hand_hits += 1 + +/// Tests that hulks aren't given rapid attacks from rapid attack gloves +/datum/unit_test/hulk_north_star + +/datum/unit_test/hulk_north_star/Run() + var/mob/living/carbon/human/hulk = allocate(/mob/living/carbon/human/consistent) + var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) + var/obj/item/clothing/gloves/rapid/fotns = allocate(/obj/item/clothing/gloves/rapid) + + hulk.equip_to_appropriate_slot(fotns) + hulk.dna.add_mutation(/datum/mutation/human/hulk) + hulk.set_combat_mode(TRUE) + hulk.ClickOn(dummy) + + TEST_ASSERT_NOTEQUAL(hulk.next_move, world.time + CLICK_CD_RAPID, "Hulk should not gain the effects of the Fists of the North Star.") + TEST_ASSERT_EQUAL(hulk.next_move, world.time + CLICK_CD_MELEE, "Hulk click cooldown was a value not expected.") diff --git a/tgstation.dme b/tgstation.dme index 366143b7aa0..640bda8c24c 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1326,6 +1326,7 @@ #include "code\datums\elements\haunted.dm" #include "code\datums\elements\high_fiver.dm" #include "code\datums\elements\honkspam.dm" +#include "code\datums\elements\human_biter.dm" #include "code\datums\elements\immerse.dm" #include "code\datums\elements\item_fov.dm" #include "code\datums\elements\item_scaling.dm"