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

refactor: reagent attacks & Unarmed attacks #5926

Open
wants to merge 25 commits into
base: master220
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
7 changes: 7 additions & 0 deletions code/__DEFINES/dcs/signals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,9 @@
/// from base of /client/proc/handle_popup_close() : (window_id)
#define COMSIG_POPUP_CLEARED "popup_cleared"

/// Source: /mob/living/UnarmedAttack(atom/atom, proximity_flag)
#define COMSIG_LIVING_UNARMED_ATTACK "living_unarmed_attack"

// /mob/living/carbon signals

///from base of mob/living/carbon/soundbang_act(): (list(intensity))
Expand Down Expand Up @@ -1131,6 +1134,10 @@
///from base of [/datum/element/light_eater/proc/devour]: (atom/eaten_light)
#define COMSIG_LIGHT_EATER_DEVOUR "light_eater_devour"

/// datum/element/reagent_attack
/// Source: /datum/element/reagent_attack/proc/inject(atom/source, mob/living/carbon/target)
#define COMSIG_REAGENT_INJECTED "reagent_inject"
// sends: datum/element/reagent_attack, mob/living/carbon/target, reagent_id, reagent_amount, target_zone

// /datum/element/movetype_handler signals
/// Called when the floating anim has to be temporarily stopped and restarted later: (timer)
Expand Down
8 changes: 6 additions & 2 deletions code/_onclick/click.dm
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,14 @@
proximity_flag is not currently passed to attack_hand, and is instead used
in human click code to allow glove touches only at melee range.
*/
/mob/proc/UnarmedAttack(atom/A, proximity_flag)
if(ismob(A))
/mob/proc/UnarmedAttack(atom/atom, proximity_flag)
if(ismob(atom))
changeNext_move(CLICK_CD_MELEE)

OnUnarmedAttack(atom, proximity_flag)

/mob/proc/OnUnarmedAttack(atom/atom, proximity_flag)
return

/*
Ranged unarmed attack:
Expand Down
7 changes: 4 additions & 3 deletions code/_onclick/cyborg.dm
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,12 @@
clicks, you can do so here, but you will have to
change attack_robot() above to the proper function
*/
/mob/living/silicon/robot/UnarmedAttack(atom/A)
if(!can_unarmed_attack())
return
/mob/living/silicon/robot/OnUnarmedAttack(atom/A)
A.attack_robot(src)

/mob/living/silicon/robot/pre_grab_attack(atom/atom, proximity_flag)
return FALSE

/mob/living/silicon/robot/RangedAttack(atom/A, params)
A.attack_robot(src)

Expand Down
80 changes: 44 additions & 36 deletions code/_onclick/other_mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@

Otherwise pretty standard.
*/
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity_flag)
if(!can_unarmed_attack())
return

if(proximity_flag && pulling && (!isnull(pull_hand) && (pull_hand == PULL_WITHOUT_HANDS || pull_hand == hand)))
if(A.grab_attack(src, pulling))
changeNext_move(grab_state > GRAB_PASSIVE ? CLICK_CD_GRABBING : CLICK_CD_PULLING)
return

/mob/living/carbon/human/OnUnarmedAttack(atom/A, proximity_flag)
// Special glove functions:
// If the gloves do anything, have them return 1 to stop
// normal attack_hand() here.
Expand All @@ -26,8 +18,15 @@
if(S.prevents_buckled_mobs_attacking())
return

A.attack_hand(src)
return A.attack_hand(src)

/mob/living/carbon/human/pre_grab_attack(atom/atom, proximity_flag)
if(proximity_flag && pulling && (!isnull(pull_hand) && (pull_hand == PULL_WITHOUT_HANDS || pull_hand == hand)))
if(atom.grab_attack(src, pulling))
changeNext_move(grab_state > GRAB_PASSIVE ? CLICK_CD_GRABBING : CLICK_CD_PULLING)
return TRUE

return FALSE

/mob/living/carbon/human/beforeAdjacentClick(atom/A, params)
if(prob(get_bones_symptom_prob() * 3))
Expand Down Expand Up @@ -98,25 +97,36 @@
/*
Animals & All Unspecified
*/
/mob/living/UnarmedAttack(atom/A, proximity_flag)
/mob/living/UnarmedAttack(atom/atom, proximity_flag)
if(!can_unarmed_attack())
return
if(proximity_flag && pulling && !isnull(pull_hand) && pull_hand != PULL_WITHOUT_HANDS && pull_hand == hand)
if(A.grab_attack(src, pulling))
changeNext_move(grab_state > GRAB_PASSIVE ? CLICK_CD_GRABBING : CLICK_CD_PULLING)
return
A.attack_animal(src)

/mob/living/simple_animal/hostile/UnarmedAttack(atom/A, proximity_flag)
if(!can_unarmed_attack())
var/signal = SEND_SIGNAL(src, COMSIG_LIVING_UNARMED_ATTACK, atom, proximity_flag)

if(signal & COMPONENT_CANCEL_ATTACK_CHAIN)
return

if(pre_grab_attack(atom, proximity_flag))
return

OnUnarmedAttack(atom, proximity_flag)

/mob/living/proc/pre_grab_attack(atom/atom, proximity_flag)
if(proximity_flag && pulling && !isnull(pull_hand) && pull_hand != PULL_WITHOUT_HANDS && pull_hand == hand)
if(A.grab_attack(src, pulling))
if(atom.grab_attack(src, pulling))
changeNext_move(grab_state > GRAB_PASSIVE ? CLICK_CD_GRABBING : CLICK_CD_PULLING)
return
GiveTarget(A)
return TRUE

return FALSE

/mob/living/OnUnarmedAttack(atom/atom, proximity_flag)
return atom.attack_animal(src)

/mob/living/simple_animal/hostile/OnUnarmedAttack(atom/atom, proximity_flag)
GiveTarget(atom)

if(target)
AttackingTarget()
return AttackingTarget()

/atom/proc/attack_animal(mob/user)
return
Expand All @@ -128,14 +138,16 @@
Aliens
Defaults to same as monkey in most places
*/
/mob/living/carbon/alien/UnarmedAttack(atom/A, proximity_flag)
if(!can_unarmed_attack())
return
/mob/living/carbon/alien/OnUnarmedAttack(atom/atom, proximity_flag)
return atom.attack_alien(src)

/mob/living/carbon/alien/pre_grab_attack(atom/atom, proximity_flag)
if(proximity_flag && pulling && (!isnull(pull_hand) && (pull_hand == PULL_WITHOUT_HANDS || pull_hand == hand)))
if(A.grab_attack(src, pulling))
if(atom.grab_attack(src, pulling))
changeNext_move(grab_state > GRAB_PASSIVE ? CLICK_CD_GRABBING : CLICK_CD_PULLING)
return
A.attack_alien(src)
return TRUE

return FALSE

/atom/proc/attack_alien(mob/living/carbon/alien/user)
attack_hand(user)
Expand All @@ -144,10 +156,8 @@
return

// Babby aliens
/mob/living/carbon/alien/larva/UnarmedAttack(atom/A, proximity_flag)
if(!can_unarmed_attack())
return
A.attack_larva(src)
/mob/living/carbon/alien/larva/OnUnarmedAttack(atom/atom, proximity_flag)
return atom.attack_larva(src)

/atom/proc/attack_larva(mob/user)
return
Expand All @@ -156,10 +166,8 @@
Slimes
Nothing happening here
*/
/mob/living/simple_animal/slime/UnarmedAttack(atom/A, proximity_flag)
if(!can_unarmed_attack())
return
A.attack_slime(src)
/mob/living/simple_animal/slime/OnUnarmedAttack(atom/atom, proximity_flag)
return atom.attack_slime(src)

/atom/proc/attack_slime(mob/user)
return
Expand Down
144 changes: 144 additions & 0 deletions code/datums/elements/reagent_attack.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/datum/element/reagent_attack
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH_ON_HOST_DESTROY
id_arg_index = 2
/// Which reagent we will inject
var/reagent_id
/// How much reagent we will inject
var/reagent_amount
/// Will we inject anyway or check can_inject
var/piercing
/// Limitation of our reagent in target
var/reagent_limit
/// Override attacking zones
var/list/allowed_zones

/datum/element/reagent_attack/Attach(
atom/source,
reagent_id,
reagent_amount,
piercing,
reagent_limit,
list/allowed_zones
)
. = ..()

if(!isliving(source))
return ELEMENT_INCOMPATIBLE

src.reagent_id = reagent_id
src.reagent_amount = reagent_amount
src.piercing = piercing
src.reagent_limit = reagent_limit
src.allowed_zones = allowed_zones

RegisterSignal(source, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(mob_attack))

/datum/element/reagent_attack/Detach(atom/source)
. = ..()
UnregisterSignal(source, COMSIG_LIVING_UNARMED_ATTACK)

/datum/element/reagent_attack/proc/mob_attack(datum/source, mob/target, proximity_flag)
SIGNAL_HANDLER

var/mob/mob = source

if(!proximity_flag && mob.a_intent != INTENT_HARM)
return

var/picked_zone = allowed_zones ? pick(allowed_zones) : mob.zone_selected

if(!can_inject(target, picked_zone))
return

INVOKE_ASYNC(src, PROC_REF(pre_inject), mob, target, picked_zone)

/datum/element/reagent_attack/proc/can_inject(mob/living/carbon/target, target_zone)
if(!istype(target))
return FALSE

if(!target.reagents)
return FALSE

if(reagent_limit && target.reagents?.has_reagent(reagent_id, reagent_limit))
return FALSE

if(!piercing && !target.can_inject(null, FALSE, target_zone, FALSE))
return FALSE

return TRUE

/datum/element/reagent_attack/proc/pre_inject(
mob/source,
mob/living/carbon/target,
target_zone,
reagent_id,
reagent_amount
)

if(!inject(source, target, target_zone))
return FALSE

SEND_SIGNAL(source, COMSIG_REAGENT_INJECTED, target, reagent_id, reagent_amount, target_zone)
return TRUE

/datum/element/reagent_attack/proc/inject(
mob/source,
mob/living/carbon/target,
target_zone,
reagent_id,
reagent_amount
)
if(target.reagents.add_reagent(reagent_id ? reagent_id : src.reagent_id, reagent_amount ? reagent_amount : src.reagent_amount))
return TRUE

return FALSE

/datum/element/reagent_attack/bee
reagent_id = "beetoxin"
reagent_amount = 5

/datum/element/reagent_attack/bee/pre_inject(
mob/source,
mob/living/carbon/target,
target_zone,
reagent_id,
reagent_amount
)
var/mob/living/simple_animal/hostile/poison/bees/bee = source

if(!bee.beegent)
return ..()

reagent_id = bee.beegent.id // Set parameters and send them into parent without initial()
reagent_amount = rand(1, 5)

if(!..())
return FALSE

bee.beegent.reaction_mob(target, REAGENT_INGEST)
return TRUE

/datum/element/reagent_attack/widow
reagent_id = "terror_black_toxin"
reagent_limit = 100
reagent_amount = 20
allowed_zones = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)

/datum/element/reagent_attack/widow/pre_inject(
mob/source,
mob/living/carbon/target,
target_zone,
reagent_id,
reagent_amount
)
if(!HAS_TRAIT(target, TRAIT_INCAPACITATED))
source.visible_message(span_danger("[src] pierces armour and buries its long fangs deep into the [target_zone] of [target]!"))
return ..()

reagent_amount = 33

if(!..())
return FALSE

source.visible_message(span_danger("[src] buries its long fangs deep into the [target_zone] of [target]!"))
return TRUE
10 changes: 5 additions & 5 deletions code/game/gamemodes/devil/true_devil/_true_devil.dm
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,15 @@
return ATTACK_CHAIN_BLOCKED_ALL


/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity)
if(!can_unarmed_attack())
return
if(!ishuman(A))
/mob/living/carbon/true_devil/OnUnarmedAttack(atom/atom, proximity)
if(!ishuman(atom))
// `attack_hand` on mobs assumes the attacker is a human
// I am the worst
A.attack_hand(src)
return atom.attack_hand(src)
// If the devil wants to actually attack, they have the pitchfork.

/mob/living/carbon/true_devil/pre_grab_attack(atom/atom, proximity_flag)
return FALSE

/mob/living/carbon/true_devil/Process_Spacemove(movement_dir = NONE, continuous_move = FALSE)
return TRUE
Expand Down
13 changes: 8 additions & 5 deletions code/game/gamemodes/miniantags/borer/borer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,15 @@
else
return ..()

/mob/living/simple_animal/borer/UnarmedAttack(mob/living/carbon/human/M)
if(!can_unarmed_attack())
/mob/living/simple_animal/borer/OnUnarmedAttack(mob/living/carbon/human/human)
if(!istype(human))
return
if(istype(M))
to_chat(src, span_notice("Вы анализируете жизненные показатели [M]."))
healthscan(src, M, 1, TRUE)

to_chat(src, span_notice("Вы анализируете жизненные показатели [human]."))
healthscan(src, human, 1, TRUE)

/mob/living/simple_animal/borer/pre_grab_attack(atom/atom, proximity_flag)
return FALSE

/mob/living/simple_animal/borer/proc/secrete_chemicals()
if(!host)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -774,9 +774,7 @@
do_attack_animation(L)
try_shock_mob(L)

/mob/living/simple_animal/demon/pulse_demon/UnarmedAttack(atom/A)
if(!can_unarmed_attack())
return
/mob/living/simple_animal/demon/pulse_demon/OnUnarmedAttack(atom/A)
if(isliving(A))
try_attack_mob(A)
else if(isitem(A) && !is_under_tile())
Expand All @@ -787,6 +785,9 @@
adjust_charge(min(C.charge, power_drain_rate))
visible_message(span_notice("[src] touches [O] and drains its power!"), span_notice("You touch [O] and drain it's power!"))

/mob/living/simple_animal/demon/pulse_demon/pre_grab_attack(atom/atom, proximity_flag)
return FALSE

/mob/living/simple_animal/demon/pulse_demon/attack_hand(mob/living/carbon/human/M)
if(is_under_tile())
to_chat(M, span_danger(">You can't interact with something that's under the floor!"))
Expand Down
Loading