Skip to content

Commit

Permalink
Merge pull request #4204 from MistakeNot4892/tweak/windup
Browse files Browse the repository at this point in the history
Generalizes the simple_animal melee telegraph.
  • Loading branch information
out-of-phaze authored Jul 16, 2024
2 parents ae05d52 + 182a50f commit 808b3b8
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 29 deletions.
22 changes: 18 additions & 4 deletions code/_onclick/click.dm
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,18 @@
var/sdepth = A.storage_depth(src)
if((!isturf(A) && A == loc) || (sdepth != -1 && sdepth <= 1))
if(holding)

// AI driven mobs have a melee telegraph that needs to be handled here.
if(a_intent == I_HURT && istype(A) && (!do_attack_windup_checking(A) || holding != get_active_held_item()))
return TRUE

var/resolved = holding.resolve_attackby(A, src, params)
if(!resolved && A && holding)
holding.afterattack(A, src, 1, params) // 1 indicates adjacency
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
UnarmedAttack(A, TRUE)

trigger_aiming(TARGET_CAN_CLICK)
Expand All @@ -137,14 +142,19 @@
if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1))
if(A.Adjacent(src)) // see adjacent.dm
if(holding)

// AI driven mobs have a melee telegraph that needs to be handled here.
if(a_intent == I_HURT && istype(A) && (!do_attack_windup_checking(A) || holding != get_active_held_item()))
return TRUE

// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = holding.resolve_attackby(A,src, params)
if(!resolved && A && holding)
holding.afterattack(A, src, 1, params) // 1: clicking something Adjacent
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
UnarmedAttack(A, TRUE)

trigger_aiming(TARGET_CAN_CLICK)
Expand Down Expand Up @@ -211,6 +221,10 @@
if(check_dexterity(DEXTERITY_HOLD_ITEM, silent = TRUE))
return A.attack_hand(src)

// AI driven mobs have a melee telegraph that needs to be handled here.
if(a_intent == I_HURT && istype(A) && !do_attack_windup_checking(A))
return TRUE

return FALSE

/*
Expand Down
4 changes: 2 additions & 2 deletions code/_onclick/cyborg.dm
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
var/resolved = holding.resolve_attackby(A, src, params)
if(!resolved && A && holding)
holding.afterattack(A, src, 1, params) // 1 indicates adjacency
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
return

if(!isturf(loc))
Expand All @@ -88,7 +88,7 @@
var/resolved = holding.resolve_attackby(A, src, params)
if(!resolved && A && holding)
holding.afterattack(A, src, 1, params) // 1 indicates adjacency
setClickCooldown(DEFAULT_QUICK_COOLDOWN)
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
else
holding.afterattack(A, src, 0, params)
return
Expand Down
24 changes: 4 additions & 20 deletions code/_onclick/other_mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -74,31 +74,15 @@
if(.)
return

setClickCooldown(attack_delay)
a_intent = I_HURT
var/attacking_with = get_natural_weapon()
if(a_intent == I_HELP || !attacking_with)
return A.attack_animal(src)

var/decl/pronouns/G = get_pronouns()
face_atom(A)
if(attack_delay)
stop_automove() // Cancel any baked-in movement.
do_windup_animation(A, attack_delay, no_reset = TRUE)
if(!do_after(src, attack_delay, A) || !Adjacent(A))
visible_message(SPAN_NOTICE("\The [src] misses [G.his] attack on \the [A]!"))
animate(src, pixel_x = default_pixel_x, pixel_y = default_pixel_y, time = 2) // reset wherever the attack animation got us to.
ai?.move_to_target(TRUE) // Restart hostile mob tracking.
return TRUE
ai?.move_to_target(TRUE) // Restart hostile mob tracking.

if(ismob(A)) // Clientless mobs are too dum to move away, so they can be missed.
var/mob/mob = A
if(!mob.ckey && !prob(get_melee_accuracy()))
visible_message(SPAN_NOTICE("\The [src] misses [G.his] attack on \the [A]!"))
return TRUE

. = A.attackby(attacking_with, src)
if(isliving(A))
if(!.)
reset_offsets(anim_time = 2)
else if(isliving(A))
apply_attack_effects(A)

// Attack hand but for simple animals
Expand Down
10 changes: 9 additions & 1 deletion code/game/objects/items/__item.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,15 @@ modules/mob/living/human/life.dm if you die, you will be zoomed out.
try_burn_wearer(user, slot, 1)

/obj/item/can_embed()
return !anchored && !is_robot_module(src)
. = !anchored && !is_robot_module(src)
if(. && isliving(loc))
var/mob/living/holder = loc
// Terrible check for if the mob is being driven by an AI or not.
// AI can't retrieve the weapon currently so this is unfair.
if(holder.get_attack_telegraph_delay() > 0)
return FALSE
// Skill check to avoid getting it stuck.
return holder.skill_fail_prob(SKILL_COMBAT, 100, no_more_fail = SKILL_EXPERT)

/obj/item/clear_matter()
..()
Expand Down
3 changes: 3 additions & 0 deletions code/modules/mob/living/human/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1213,3 +1213,6 @@
if(istype(limb.material, /decl/material/solid/organic/meat))
return TRUE
return FALSE

/mob/living/human/get_attack_telegraph_delay()
return client ? 0 : DEFAULT_ATTACK_COOLDOWN
39 changes: 39 additions & 0 deletions code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1691,3 +1691,42 @@ default behaviour is:
if(target.is_open() && target.has_gravity() && !can_overcome_gravity())
return FALSE
return TRUE

/mob/living/proc/get_attack_telegraph_delay()
return 0

/mob/living/proc/get_base_telegraphed_melee_accuracy()
return 85

/mob/living/proc/get_telegraphed_melee_accuracy()
return clamp(get_base_telegraphed_melee_accuracy() - melee_accuracy_mods(), 0, 100)

// This will generally only be invoked by AI driven mobs. Player humans do not show the windup.
/mob/living/do_attack_windup_checking(atom/target)

var/attack_delay = get_attack_telegraph_delay()
if(attack_delay <= 0)
return TRUE

var/decl/pronouns/G = get_pronouns()
setClickCooldown(attack_delay)
face_atom(target)

stop_automove() // Cancel any baked-in movement.
do_windup_animation(target, attack_delay, no_reset = TRUE)
if(!do_after(src, attack_delay, target) || !Adjacent(target))
visible_message(SPAN_NOTICE("\The [src] misses [G.his] attack on \the [target]!"))
reset_offsets(anim_time = 2)
ai?.move_to_target(TRUE) // Restart hostile mob tracking.
return FALSE

ai?.move_to_target(TRUE) // Restart hostile mob tracking.
if(ismob(target))
// Clientless mobs are too dum to move away, so they can be missed.
var/mob/mob = target
if(!mob.ckey && !prob(get_telegraphed_melee_accuracy()))
visible_message(SPAN_NOTICE("\The [src] misses [G.his] attack on \the [target]!"))
reset_offsets(anim_time = 2)
return FALSE

return TRUE
7 changes: 5 additions & 2 deletions code/modules/mob/living/simple_animal/_simple_animal.dm
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,8 @@ var/global/list/simplemob_icon_bitflag_cache = list()
bodytype_flag = 0
bodytype_category = "quadrupedal animal body"

/mob/living/simple_animal/proc/get_melee_accuracy()
return clamp(sa_accuracy - melee_accuracy_mods(), 0, 100)
/mob/living/simple_animal/get_base_telegraphed_melee_accuracy()
return sa_accuracy

/mob/living/simple_animal/check_has_mouth()
return TRUE
Expand Down Expand Up @@ -544,3 +544,6 @@ var/global/list/simplemob_icon_bitflag_cache = list()

/mob/living/simple_animal/can_eat_food_currently(obj/eating, mob/user, consumption_method)
return TRUE

/mob/living/simple_animal/get_attack_telegraph_delay()
return attack_delay
1 change: 1 addition & 0 deletions code/modules/mob/living/simple_animal/natural_weapons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
canremove = FALSE
obj_flags = OBJ_FLAG_CONDUCTIBLE //for intent of shocking checks, they're right inside the animal
is_spawnable_type = FALSE
needs_attack_dexterity = DEXTERITY_NONE
var/show_in_message // whether should we show up in attack message, e.g. 'urist has been bit with teeth by carp' vs 'urist has been bit by carp'

/obj/item/natural_weapon/attack_message_name()
Expand Down
11 changes: 11 additions & 0 deletions code/modules/mob/mob.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1371,3 +1371,14 @@
var/datum/movement_handler/mob/delay/delay = locate() in movement_handlers
if(istype(delay))
delay.next_move = world.time

/mob/proc/do_attack_windup_checking(atom/target)
return TRUE

/mob/living/human/debug_attack_windup
ai = /datum/mob_controller/aggressive
faction = "arsehole"

/mob/living/human/debug_attack_windup/Initialize(mapload, species_name, datum/mob_snapshot/supplied_appearance)
. = ..()
put_in_active_hand(new /obj/item/stamp/denied(src))

0 comments on commit 808b3b8

Please sign in to comment.