Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored the attack proc #19908

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aurorastation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
#include "code\__DEFINES\dcs\signals\signals_spatial_grid.dm"
#include "code\__DEFINES\dcs\signals\signals_subsystem.dm"
#include "code\__DEFINES\dcs\signals\signals_turf.dm"
#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_attack.dm"
#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_main.dm"
#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movable.dm"
#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movement.dm"
Expand Down
17 changes: 17 additions & 0 deletions code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Atom attack signals. Format:
// When the signal is called: (signal arguments)
// All signals send the source datum of the signal as the first argument

///from base of atom/attackby(): (/obj/item, /mob/living, params)
#define COMSIG_ATOM_ATTACKBY "atom_attackby"

/// From [/item/attack()], sent by an atom which was just attacked by an item: (/obj/item/weapon, /mob/user, proximity_flag, click_parameters)
#define COMSIG_ATOM_AFTER_ATTACKEDBY "atom_after_attackby"

///Return this in response if you don't want afterattack to be called
#define COMPONENT_NO_AFTERATTACK (1<<0)

///Ends the attack chain. If sent early might cause posterior attacks not to happen.
#define COMPONENT_CANCEL_ATTACK_CHAIN (1<<0)
///Skips the specific attack step, continuing for the next one to happen.
#define COMPONENT_SKIP_ATTACK (1<<1)
3 changes: 3 additions & 0 deletions code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@
/// The arugment of move_args which dictates our movement direction
#define MOVE_ARG_DIRECTION 2

///from base of /obj/item/attack(): (mob/M, mob/user)
#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack"

///From base of mob/update_movespeed():area
#define COMSIG_MOB_MOVESPEED_UPDATED "mob_update_movespeed"
6 changes: 6 additions & 0 deletions code/__DEFINES/dcs/signals/signals_object/signals_object.dm
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@
#define COMSIG_ITEM_DROPPED "item_drop"
///from base of obj/item/pickup(): (mob/user)
#define COMSIG_ITEM_PICKUP "item_pickup"

///from base of /obj/item/attack(): (mob/living, mob/living, params)
#define COMSIG_ITEM_ATTACK "item_attack"

///from base of [obj/item/attack()]: (atom/target, mob/user, proximity_flag, click_parameters)
#define COMSIG_ITEM_AFTERATTACK "item_afterattack"
69 changes: 46 additions & 23 deletions code/_onclick/item_attack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ avoid code duplication. This includes items that may sometimes act as a standard
log_attack("[A] at [A?.loc]/[A.x]-[A.y]-[A.z] got ITEM attacked by [usr]/[usr?.ckey] on INTENT [usr?.a_intent] with [src]")
return A.attackby(src, user, click_parameters)

// attackby should return TRUE if all desired actions are resolved from that attack, within attackby. This prevents afterattack being called.
/**
* Called on an object being hit by an item
*
Expand All @@ -41,38 +40,46 @@ avoid code duplication. This includes items that may sometimes act as a standard
* * params - Click params such as alt/shift etc
*/
/atom/proc/attackby(obj/item/attacking_item, mob/user, params)
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACKBY, attacking_item, user, params) & COMPONENT_NO_AFTERATTACK)
return TRUE
return FALSE

/atom/movable/attackby(obj/item/attacking_item, mob/user, params)
if(..())
return TRUE

if((user?.a_intent == I_HURT) && !(attacking_item.item_flags & ITEM_FLAG_NO_BLUDGEON))
visible_message(SPAN_DANGER("[src] has been hit by [user] with [attacking_item]."))

/mob/living/attackby(obj/item/I, mob/user)
/mob/living/attackby(obj/item/attacking_item, mob/user, params)
if(..())
return TRUE

if(!ismob(user))
return FALSE

var/selected_zone = user.zone_sel ? user.zone_sel.selecting : BP_CHEST
var/operating = can_operate(src)
if(operating == SURGERY_SUCCESS)
if(do_surgery(src, user, I))
if(do_surgery(src, user, attacking_item))
return TRUE
else
return I.attack(src, user, selected_zone) //This is necessary to make things like health analyzers work. -mattatlas
return attacking_item.attack(src, user, selected_zone) //This is necessary to make things like health analyzers work. -mattatlas
if(operating == SURGERY_FAIL)
if(do_surgery(src, user, I, TRUE))
if(do_surgery(src, user, attacking_item, TRUE))
return TRUE
else
return I.attack(src, user, selected_zone)
return attacking_item.attack(src, user, selected_zone)
else
return I.attack(src, user, selected_zone)
return attacking_item.attack(src, user, selected_zone)

/mob/living/carbon/human/attackby(obj/item/I, mob/user)
if(user == src && user.a_intent == I_GRAB && zone_sel?.selecting == BP_MOUTH && can_devour(I, silent = TRUE))
/mob/living/carbon/human/attackby(obj/item/attacking_item, mob/user, params)
if(user == src && user.a_intent == I_GRAB && zone_sel?.selecting == BP_MOUTH && can_devour(attacking_item, silent = TRUE))
var/obj/item/blocked = src.check_mouth_coverage()
if(blocked)
to_chat(user, SPAN_WARNING("\The [blocked] is in the way!"))
return TRUE
if(devour(I))
if(devour(attacking_item))
return TRUE
return ..()

Expand All @@ -88,12 +95,25 @@ avoid code duplication. This includes items that may sometimes act as a standard
else
return Clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100

//I would prefer to rename this attack_as_weapon(), but that would involve touching hundreds of files.
/obj/item/proc/attack(mob/living/M, mob/living/user, var/target_zone = BP_CHEST)
/**
* Called from [/mob/living/proc/attackby] (usually)
*
* Arguments:
* * mob/living/target_mob - The mob being hit by this item
* * mob/living/user - The mob hitting with this item
* * target_zone - The target zone aimed at, **THIS DIFFERS FROM TG WHERE IT TAKES THE CLICK PARAMS**
*/
/obj/item/proc/attack(mob/living/target_mob, mob/living/user, target_zone = BP_CHEST)
var/signal_return = SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, target_mob, user) || SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, target_mob, user)
if(signal_return & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
if(signal_return & COMPONENT_SKIP_ATTACK)
return FALSE

if(item_flags & ITEM_FLAG_NO_BLUDGEON)
return 0

if(M == user && user.a_intent != I_HURT)
if(target_mob == user && user.a_intent != I_HURT)
return 0

if(user.incapacitated(INCAPACITATION_STUNNED|INCAPACITATION_KNOCKOUT|INCAPACITATION_KNOCKDOWN|INCAPACITATION_FORCELYING))
Expand All @@ -104,11 +124,11 @@ avoid code duplication. This includes items that may sometimes act as a standard
return 0

user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.do_attack_animation(M, src)
user.do_attack_animation(target_mob, src)
if(!user.aura_check(AURA_TYPE_WEAPON, src, user))
return FALSE

var/mob/living/victim = M.get_attack_victim(src, user, target_zone)
var/mob/living/victim = target_mob.get_attack_victim(src, user, target_zone)
var/hit_zone
if(victim)
hit_zone = victim.resolve_item_attack(src, user, target_zone)
Expand All @@ -118,20 +138,23 @@ avoid code duplication. This includes items that may sometimes act as a standard
// Null hitzone means a miss.
if(hit_zone)
if(!force)
playsound(loc, 'sound/weapons/tap.ogg', get_clamped_volume(), 1, -1)
playsound(src, 'sound/weapons/tap.ogg', get_clamped_volume(), TRUE, -1)
else if(hitsound)
playsound(loc, hitsound, get_clamped_volume(), 1, -1)
playsound(src, hitsound, get_clamped_volume(), TRUE, -1, falloff_distance = 0)
else
playsound(loc, 'sound/weapons/punchmiss2.ogg', get_clamped_volume(), 1, -1)
playsound(src, 'sound/weapons/punchmiss2.ogg', get_clamped_volume(), TRUE, -1)

/////////////////////////
user.lastattacked = M
M.lastattacker = user
user.lastattacked = target_mob
target_mob.lastattacker = user

SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target_mob, user)
SEND_SIGNAL(target_mob, COMSIG_ATOM_AFTER_ATTACKEDBY, src, user)

if(!no_attack_log)
user.attack_log += "\[[time_stamp()]\]<span class='warning'> [hit_zone ? "Attacked" : "Missed"] [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</span>"
M.attack_log += "\[[time_stamp()]\]<font color='orange'> [hit_zone ? "Attacked" : "Missed"] by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
msg_admin_attack("[key_name(user, highlight_special = 1)] [hit_zone ? "attacked" : "missed"] [key_name(M, highlight_special = 1)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",ckey=key_name(user),ckey_target=key_name(M) )
user.attack_log += "\[[time_stamp()]\]<span class='warning'> [hit_zone ? "Attacked" : "Missed"] [target_mob.name] ([target_mob.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</span>"
target_mob.attack_log += "\[[time_stamp()]\]<font color='orange'> [hit_zone ? "Attacked" : "Missed"] by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
msg_admin_attack("[key_name(user, highlight_special = 1)] [hit_zone ? "attacked" : "missed"] [key_name(target_mob, highlight_special = 1)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",ckey=key_name(user),ckey_target=key_name(target_mob) )
/////////////////////////

return 1
Expand Down
86 changes: 43 additions & 43 deletions code/defines/obj/weapon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@
attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed")
var/can_support = TRUE

/obj/item/cane/attack(mob/living/target, mob/living/carbon/human/user, target_zone = BP_CHEST)
/obj/item/cane/attack(mob/living/target_mob, mob/living/user, target_zone)

if(!(istype(target) && istype(user)))
if(!(istype(target_mob) && istype(user)))
return ..()

var/targetIsHuman = ishuman(target)
var/mob/living/carbon/human/targetashuman = target
var/targetIsHuman = ishuman(target_mob)
var/mob/living/carbon/human/targetashuman = target_mob
var/wasselfattack = 0
var/verbtouse = pick(attack_verb)
var/punct = "!"
Expand All @@ -80,11 +80,11 @@
wasselfattack = 1

if (user.a_intent == I_HURT)
target_zone = get_zone_with_miss_chance(target_zone, target) //Vary the attack
target_zone = get_zone_with_miss_chance(target_zone, target_mob) //Vary the attack
damagetype = DAMAGE_BRUTE

if (targetIsHuman)
var/mob/living/carbon/human/targethuman = target
var/mob/living/carbon/human/targethuman = target_mob
armorpercent = targethuman.get_blocked_ratio(target_zone, DAMAGE_BRUTE, damage = force)*100
wasblocked = targethuman.check_shields(force, src, user, target_zone, null)

Expand All @@ -105,19 +105,19 @@
soundname = "punch"
if(targetIsHuman)
user.visible_message("<span class='[class]'>[user] flips [user.get_pronoun("his")] [name]...</span>", "<span class='[class]'>You flip [src], preparing a disarm...</span>")
if (do_mob(user,target,chargedelay,display_progress=0))
if (do_mob(user,target_mob,chargedelay,display_progress=0))
if(!wasblocked && damageamount)
var/chancemod = (100 - armorpercent)*0.05*damageamount // Lower chance if lower damage + high armor. Base chance is 50% at 10 damage.
if(target_zone == BP_L_HAND || target_zone == BP_L_ARM)
if (prob(chancemod) && target.l_hand && target.l_hand != src)
if (prob(chancemod) && target_mob.l_hand && target_mob.l_hand != src)
shoulddisarm = 1
else if(target_zone == BP_R_HAND || target_zone == BP_R_ARM)
if (prob(chancemod) && target.r_hand && target.r_hand != src)
if (prob(chancemod) && target_mob.r_hand && target_mob.r_hand != src)
shoulddisarm = 2
else
if (prob(chancemod*0.5) && target.l_hand && target.l_hand != src)
if (prob(chancemod*0.5) && target_mob.l_hand && target_mob.l_hand != src)
shoulddisarm = 1
if (prob(chancemod*0.5) && target.r_hand && target.r_hand != src)
if (prob(chancemod*0.5) && target_mob.r_hand && target_mob.r_hand != src)
shoulddisarm += 2
else
user.visible_message("<span class='[class]'>[user] flips [user.get_pronoun("his")] [name] back to its original position.</span>", "<span class='[class]'>You flip [src] back to its original position.</span>")
Expand All @@ -128,9 +128,9 @@
soundname = "punch"
if(targetIsHuman)
user.visible_message("<span class='[class]'>[user] flips [user.get_pronoun("his")] [name]...</span>", "<span class='[class]'>You flip [src], preparing a grab...</span>")
if (do_mob(user,target,chargedelay,display_progress=0))
if (do_mob(user,target_mob,chargedelay,display_progress=0))
if(!wasblocked && damageamount)
user.start_pulling(target)
user.start_pulling(target_mob)
else
verbtouse = pick("awkwardly tries to hook","fails to grab")
else
Expand All @@ -142,80 +142,80 @@

// Damage Logs
/////////////////////////
user.lastattacked = target
target.lastattacker = user
user.lastattacked = target_mob
target_mob.lastattacker = user
if(!no_attack_log)
user.attack_log += "\[[time_stamp()]\]<span class='warning'> Attacked [target.name] ([target.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damagetype)])</span>"
target.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damagetype)])</font>"
msg_admin_attack("[key_name(user, highlight_special = 1)] attacked [key_name(target, highlight_special = 1)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damagetype)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",ckey=key_name(user),ckey_target=key_name(target) )
user.attack_log += "\[[time_stamp()]\]<span class='warning'> Attacked [target_mob.name] ([target_mob.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damagetype)])</span>"
target_mob.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damagetype)])</font>"
msg_admin_attack("[key_name(user, highlight_special = 1)] attacked [key_name(target_mob, highlight_special = 1)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damagetype)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",ckey=key_name(user),ckey_target=key_name(target_mob) )
/////////////////////////

var/washit = 0
var/endmessage1st
var/endmessage3rd

if(!target_zone || get_dist(user,target) > 1) //Dodged
endmessage1st = "Your [name] was dodged by [target]"
endmessage3rd = "[target] dodged the [name]"
if(!target_zone || get_dist(user,target_mob) > 1) //Dodged
endmessage1st = "Your [name] was dodged by [target_mob]"
endmessage3rd = "[target_mob] dodged the [name]"
soundname = "punchmiss"
else if(wasblocked) // Blocked by Shield
endmessage1st = "Your [name] was blocked by [target]"
endmessage3rd = "[target] blocks the [name]"
endmessage1st = "Your [name] was blocked by [target_mob]"
endmessage3rd = "[target_mob] blocks the [name]"
soundname = "punchmiss"
else

washit = 1
var/noun = "[target]"
var/noun = "[target_mob]"
var/selfnoun = "your"

if(shoulddisarm)
if(wasselfattack)
selfnoun = "your grip"
noun = "[target.get_pronoun("his")] grip"
noun = "[target_mob.get_pronoun("his")] grip"
else
noun = "[target]'s grip"
noun = "[target_mob]'s grip"
selfnoun = noun
if (targetIsHuman && shoulddisarm != 3) // Query: Can non-humans hold objects in hands?
var/mob/living/carbon/human/targethuman = target
var/mob/living/carbon/human/targethuman = target_mob
var/obj/item/organ/external/O = targethuman.get_organ(target_zone)
if (O.is_stump())
if(wasselfattack)
selfnoun = "your missing [O.name]"
noun = "[target.get_pronoun("his")] missing [O.name]"
noun = "[target_mob.get_pronoun("his")] missing [O.name]"
else
noun = "[target]'s missing [O.name]"
noun = "[target_mob]'s missing [O.name]"
selfnoun = noun
else
if(wasselfattack)
selfnoun = "your [O.name]"
noun = "[target.get_pronoun("his")] [O.name]"
noun = "[target_mob.get_pronoun("his")] [O.name]"
else
noun = "[target]'s [O.name]"
noun = "[target_mob]'s [O.name]"
selfnoun = noun

switch(shoulddisarm)
if(1)
endmessage1st = "You [verbtouse] the [target.l_hand.name] out of [selfnoun]"
endmessage3rd = "[user] [verbtouse] the [target.l_hand.name] out of [noun]"
target.drop_l_hand()
endmessage1st = "You [verbtouse] the [target_mob.l_hand.name] out of [selfnoun]"
endmessage3rd = "[user] [verbtouse] the [target_mob.l_hand.name] out of [noun]"
target_mob.drop_l_hand()
if(2)
endmessage1st = "You [verbtouse] the [target.r_hand.name] out of [selfnoun]"
endmessage3rd = "[user] [verbtouse] the [target.r_hand.name] out of [noun]"
target.drop_r_hand()
endmessage1st = "You [verbtouse] the [target_mob.r_hand.name] out of [selfnoun]"
endmessage3rd = "[user] [verbtouse] the [target_mob.r_hand.name] out of [noun]"
target_mob.drop_r_hand()
if(3)
endmessage1st = "You [verbtouse] both the [target.r_hand.name] and the [target.l_hand.name] out of [selfnoun]"
endmessage3rd = "[user] [verbtouse] both the [target.r_hand.name] and the [target.l_hand.name] out of [noun]"
target.drop_l_hand()
target.drop_r_hand()
endmessage1st = "You [verbtouse] both the [target_mob.r_hand.name] and the [target_mob.l_hand.name] out of [selfnoun]"
endmessage3rd = "[user] [verbtouse] both the [target_mob.r_hand.name] and the [target_mob.l_hand.name] out of [noun]"
target_mob.drop_l_hand()
target_mob.drop_r_hand()
else
endmessage1st = "You [verbtouse] [selfnoun] with the [name]"
endmessage3rd = "[user] [verbtouse] [noun] with the [name]"

if(damageamount > 0) // Poking will no longer do damage until there is some fix that makes it so that 0.0001 HALLOS doesn't cause bleed.
target.standard_weapon_hit_effects(src, user, damageamount, armorpercent, target_zone)
target_mob.standard_weapon_hit_effects(src, user, damageamount, armorpercent, target_zone)

user.visible_message("<span class='[class]'>[endmessage3rd][punct]</span>", "<span class='[class]'>[endmessage1st][punct]</span>")
user.do_attack_animation(target)
user.do_attack_animation(target_mob)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)

if(soundname)
Expand Down
4 changes: 2 additions & 2 deletions code/game/atoms_movable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,9 @@
master = null
. = ..()

/atom/movable/overlay/attackby(a, b)
/atom/movable/overlay/attackby(obj/item/attacking_item, mob/user, params)
if (src.master)
return src.master.attackby(a, b)
return src.master.attackby(arglist(args))
return

/atom/movable/overlay/attack_hand(a, b, c)
Expand Down
2 changes: 1 addition & 1 deletion code/game/gamemodes/cult/items/sword.dm
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
/obj/item/melee/cultblade/cultify()
return

/obj/item/melee/cultblade/attack(mob/living/M, mob/living/user, var/target_zone)
/obj/item/melee/cultblade/attack(mob/living/target_mob, mob/living/user, target_zone)
if(iscultist(user) || !does_cult_check)
return ..()

Expand Down
Loading
Loading