Files
Bubberstation/code/modules/mob/living/basic/basic_defense.dm
Jacquerel f47b29a392 Basic Mob Carp Part II: Regenerator (#71437)
## About The Pull Request

<details>
  <summary>Video</summary>
  

https://user-images.githubusercontent.com/7483112/203324325-5bf46e0f-b294-4832-9016-aec275036ca9.mp4

</details>


Adds a "Regenerator" component, applies it to carp, and removes the
previous implementation from megacarp.
The function of this component is that any time you take damage a timer
is reset, when that timer expires you will begin regenerating health and
display an animated border for visual feedback.
This was previously a function of mega carp but was extremely obscure
because there was _no_ feedback, so it would only be visible that it was
happening if you were wearing a medical hud.

Additionally because mega carp will pursue a target until it dies you
probably wouldn't notice it even then, it had to survive a fight in
order to gain any value from this.
This will still be true for all carp until AI changes are pushed, so
until then this isn't going to do very much for NPCs but might be a
small buff to player controlled carp (though those can all retreat to a
carp rift for a similar effect).

This also modifies a few "defence" procs which were either directly
setting HP or neglecting to call signals from a base proc, as they would
bypass triggering the effect. This should make them more reliable for
other things which rely on those signals too.

## Why It's Good For The Game

Gives an iconic creature some more unique behaviour than "moves directly
towards you and bites".
Gives visual feedback to some behaviour which has existed invisibly for
a long time.

## Changelog
🆑
add: All Space Carp will now start regenerating health after 6 seconds
of not taking any damage, until they're back to full health. This
behaviour was previously unique to mega carp.
/🆑
2022-11-23 09:40:59 -08:00

205 lines
7.3 KiB
Plaintext

/mob/living/basic/attack_hand(mob/living/carbon/human/user, list/modifiers)
// so that martial arts don't double dip
if (..())
return TRUE
if(LAZYACCESS(modifiers, RIGHT_CLICK))
if(user.move_force < move_resist)
return
user.do_attack_animation(src, ATTACK_EFFECT_DISARM)
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
var/shove_dir = get_dir(user, src)
if(!Move(get_step(src, shove_dir), shove_dir))
log_combat(user, src, "shoved", "failing to move it")
user.visible_message(span_danger("[user.name] shoves [src]!"),
span_danger("You shove [src]!"), span_hear("You hear aggressive shuffling!"), COMBAT_MESSAGE_RANGE, list(src))
to_chat(src, span_userdanger("You're shoved by [user.name]!"))
return TRUE
log_combat(user, src, "shoved", "pushing it")
user.visible_message(span_danger("[user.name] shoves [src], pushing [p_them()]!"),
span_danger("You shove [src], pushing [p_them()]!"), span_hear("You hear aggressive shuffling!"), COMBAT_MESSAGE_RANGE, list(src))
to_chat(src, span_userdanger("You're pushed by [user.name]!"))
return TRUE
if(!user.combat_mode)
if (stat == DEAD)
return
visible_message(span_notice("[user] [response_help_continuous] [src]."), \
span_notice("[user] [response_help_continuous] you."), null, null, user)
to_chat(user, span_notice("You [response_help_simple] [src]."))
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
else
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, span_warning("You don't want to hurt [src]!"))
return
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
visible_message(span_danger("[user] [response_harm_continuous] [src]!"),\
span_userdanger("[user] [response_harm_continuous] you!"), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You [response_harm_simple] [src]!"))
playsound(loc, attacked_sound, 25, TRUE, -1)
var/obj/item/bodypart/arm/active_arm = user.get_active_hand()
var/damage = rand(active_arm.unarmed_damage_low, active_arm.unarmed_damage_high)
attack_threshold_check(damage)
log_combat(user, src, "attacked")
updatehealth()
return TRUE
/mob/living/basic/attack_hulk(mob/living/carbon/human/user)
. = ..()
if(!.)
return
playsound(loc, SFX_PUNCH, 25, TRUE, -1)
visible_message(span_danger("[user] punches [src]!"), \
span_userdanger("You're punched by [user]!"), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You punch [src]!"))
apply_damage(15, damagetype = BRUTE)
/mob/living/basic/attack_paw(mob/living/carbon/human/user, list/modifiers)
if(..()) //successful monkey bite.
if(stat != DEAD)
var/damage = rand(1, 3)
attack_threshold_check(damage)
return 1
if (!user.combat_mode)
if (health > 0)
visible_message(span_notice("[user.name] [response_help_continuous] [src]."), \
span_notice("[user.name] [response_help_continuous] you."), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_notice("You [response_help_simple] [src]."))
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
/mob/living/basic/attack_alien(mob/living/carbon/alien/adult/user, list/modifiers)
if(..()) //if harm or disarm intent.
if(LAZYACCESS(modifiers, RIGHT_CLICK))
playsound(loc, 'sound/weapons/pierce.ogg', 25, TRUE, -1)
visible_message(span_danger("[user] [response_disarm_continuous] [name]!"), \
span_userdanger("[user] [response_disarm_continuous] you!"), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You [response_disarm_simple] [name]!"))
log_combat(user, src, "disarmed")
else
var/damage = rand(15, 30)
visible_message(span_danger("[user] slashes at [src]!"), \
span_userdanger("You're slashed at by [user]!"), null, COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_danger("You slash at [src]!"))
playsound(loc, 'sound/weapons/slice.ogg', 25, TRUE, -1)
attack_threshold_check(damage)
log_combat(user, src, "attacked")
return 1
/mob/living/basic/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers)
. = ..()
if(. && stat != DEAD) //successful larva bite
var/damage = rand(5, 10)
. = attack_threshold_check(damage)
if(.)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
/mob/living/basic/attack_basic_mob(mob/living/basic/user, list/modifiers)
. = ..()
if(.)
var/damage = rand(user.melee_damage_lower, user.melee_damage_upper)
return attack_threshold_check(damage, user.melee_damage_type)
/mob/living/basic/attack_animal(mob/living/simple_animal/user, list/modifiers)
. = ..()
if(.)
var/damage = rand(user.melee_damage_lower, user.melee_damage_upper)
return attack_threshold_check(damage, user.melee_damage_type)
/mob/living/basic/attack_slime(mob/living/simple_animal/slime/M, list/modifiers)
if(..()) //successful slime attack
var/damage = rand(15, 25)
if(M.is_adult)
damage = rand(20, 35)
return attack_threshold_check(damage)
/mob/living/basic/attack_drone(mob/living/simple_animal/drone/M)
if(M.combat_mode) //No kicking dogs even as a rogue drone. Use a weapon.
return
return ..()
/mob/living/basic/attack_drone_secondary(mob/living/simple_animal/drone/M)
if(M.combat_mode)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
return ..()
/mob/living/basic/proc/attack_threshold_check(damage, damagetype = BRUTE, armorcheck = MELEE, actuallydamage = TRUE)
var/temp_damage = damage
if(!damage_coeff[damagetype])
temp_damage = 0
else
temp_damage *= damage_coeff[damagetype]
if(actuallydamage)
apply_damage(damage, damagetype, null, getarmor(null, armorcheck))
return TRUE
/mob/living/basic/check_projectile_armor(def_zone, obj/projectile/impacting_projectile, is_silent)
return 0
/mob/living/basic/ex_act(severity, target, origin)
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
return FALSE
. = ..()
if(QDELETED(src))
return
var/bomb_armor = getarmor(null, BOMB)
switch (severity)
if (EXPLODE_DEVASTATE)
if(prob(bomb_armor))
apply_damage(500, damagetype = BRUTE)
else
investigate_log("has been gibbed by an explosion.", INVESTIGATE_DEATHS)
gib()
return
if (EXPLODE_HEAVY)
var/bloss = 60
if(prob(bomb_armor))
bloss = bloss / 1.5
apply_damage(bloss, damagetype = BRUTE)
if (EXPLODE_LIGHT)
var/bloss = 30
if(prob(bomb_armor))
bloss = bloss / 1.5
apply_damage(bloss, damagetype = BRUTE)
/mob/living/basic/blob_act(obj/structure/blob/B)
apply_damage(20, damagetype = BRUTE)
return
/mob/living/basic/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
if(!no_effect && !visual_effect_icon && melee_damage_upper)
if(attack_vis_effect && !iswallturf(A)) // override the standard visual effect.
visual_effect_icon = attack_vis_effect
else if(melee_damage_upper < 10)
visual_effect_icon = ATTACK_EFFECT_PUNCH
else
visual_effect_icon = ATTACK_EFFECT_SMASH
..()
/mob/living/basic/update_stat()
if(status_flags & GODMODE)
return
if(stat != DEAD)
if(health <= 0)
death()
else
set_stat(CONSCIOUS)
med_hud_set_status()
/mob/living/basic/emp_act(severity)
. = ..()
if(mob_biotypes & MOB_ROBOTIC)
switch (severity)
if (EMP_LIGHT)
visible_message(span_danger("[src] shakes violently, its parts coming loose!"))
apply_damage(maxHealth * 0.6)
Shake(5, 5, 1 SECONDS)
if (EMP_HEAVY)
visible_message(span_danger("[src] suddenly bursts apart!"))
apply_damage(maxHealth)