[MIRROR] Refactors UnarmedAttack so we don't have like 4 Unarmed Attack signals, kills two more snowflake species procs [MDB IGNORE] (#24356)

* Refactors `UnarmedAttack` so we don't have like 4 Unarmed Attack signals, kills two more snowflake species procs

* Update chameleon.dm

* Update _species.dm

* Modular

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-10-16 12:37:49 -04:00
committed by GitHub
co-authored by MrMelbert Bloop
parent e4ce355747
commit 22943b9449
43 changed files with 284 additions and 217 deletions
@@ -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)
@@ -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"
@@ -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)
+4 -1
View File
@@ -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
+51 -31
View File
@@ -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.
+4 -4
View File
@@ -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)
+2 -2
View File
@@ -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)
+1 -2
View File
@@ -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,
+2 -2
View File
@@ -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)
+4 -3
View File
@@ -218,7 +218,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)
@@ -240,12 +240,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)
+2 -2
View File
@@ -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)
+2 -3
View File
@@ -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
+1 -3
View File
@@ -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
+2 -2
View File
@@ -107,7 +107,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))
@@ -134,7 +134,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)
+4 -4
View File
@@ -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
+10 -4
View File
@@ -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)
+3 -1
View File
@@ -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
+6 -6
View File
@@ -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!")
+28
View File
@@ -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
+7 -6
View File
@@ -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
+3 -3
View File
@@ -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!")
+7 -7
View File
@@ -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)
+3 -3
View File
@@ -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
+2 -2
View File
@@ -19,7 +19,7 @@
/// SKYRAT EDIT END
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)
/// SKYRAT EDIT BEGIN
@@ -73,7 +73,7 @@
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))
/// SKYRAT EDIT BEGIN
REMOVE_TRAIT(owner, TRAIT_CHAMELEON_SKIN, GENETIC_MUTATION)
/// SKYRAT EDIT END
+15 -14
View File
@@ -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)
+5 -4
View File
@@ -60,9 +60,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 ..()
@@ -113,8 +113,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))
@@ -130,6 +130,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)
+17 -2
View File
@@ -681,10 +681,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)
. = ..()
@@ -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)
@@ -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
+5 -5
View File
@@ -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)
+5 -3
View File
@@ -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
@@ -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
@@ -1218,7 +1218,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)
@@ -1250,9 +1249,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
target.StaminaKnockdown(20) //SKYRAT EDIT ADDITION
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]!"), \
@@ -1829,11 +1825,8 @@ 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
/* SKYRAT EDIT REMOVAL - MOVED TO MODULAR
/// 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()
@@ -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))
+2 -4
View File
@@ -321,10 +321,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
@@ -339,6 +335,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
+4 -4
View File
@@ -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
+6
View File
@@ -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
@@ -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)
+1
View File
@@ -148,6 +148,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"
+44
View File
@@ -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.")
@@ -76,7 +76,7 @@
/datum/gunpoint/Destroy()
UnregisterSignal(aimed_gun, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED))
UnregisterSignal(target, list(COMSIG_QDELETING, COMSIG_MOB_ITEM_AFTERATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_MOVABLE_RADIO_TALK_INTO, COMSIG_MOB_FIRED_GUN, COMSIG_MOVABLE_MOVED))
UnregisterSignal(target, list(COMSIG_QDELETING, COMSIG_MOB_ITEM_AFTERATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_MOVABLE_RADIO_TALK_INTO, COMSIG_MOB_FIRED_GUN, COMSIG_MOVABLE_MOVED))
UnregisterSignal(source, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIVING_STATUS_STUN, COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_LIVING_STATUS_PARALYZE, COMSIG_LIVING_UPDATED_RESTING))
REMOVE_TRAIT(source, TRAIT_NORUNNING, "gunpoint")
@@ -46,10 +46,10 @@
/datum/wound/muscle/set_victim(new_victim)
if (victim)
UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK)
UnregisterSignal(victim, COMSIG_LIVING_EARLY_UNARMED_ATTACK)
if (new_victim)
RegisterSignal(new_victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand))
RegisterSignal(new_victim, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand))
return ..()
+1
View File
@@ -1413,6 +1413,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"