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

Necro execution #175

Closed
wants to merge 13 commits into from
1 change: 1 addition & 0 deletions daedalus.dme
Original file line number Diff line number Diff line change
Expand Up @@ -4825,6 +4825,7 @@
#include "deadspace\code\necromorph\living.dm"
#include "deadspace\code\necromorph\abilities\ability.dm"
#include "deadspace\code\necromorph\abilities\charge.dm"
#include "deadspace\code\necromorph\abilities\finisher.dm"
#include "deadspace\code\necromorph\abilities\charge_exploder.dm"
#include "deadspace\code\necromorph\abilities\curl.dm"
#include "deadspace\code\necromorph\abilities\dodge.dm"
Expand Down
1 change: 1 addition & 0 deletions deadspace/code/__DEFINES/keybinding.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define COMSIG_KB_NECROMORPH_ABILITY_CHARGE_DOWN "keybinding_necromorph_ability_charge_down"
#define COMSIG_KB_NECROMORPH_ABILITY_DODGE_DOWN "keybinding_necromorph_ability_dodge_down"
#define COMSIG_KB_NECROMORPH_ABILITY_SHOUT_DOWN "keybinding_necromorph_ability_shout_down"
#define COMSIG_KB_NECROMORPH_ABILITY_FINISHER_DOWN "keybinding_necromorph_ability_finisher_down"
#define COMSIG_KB_NECROMORPH_ABILITY_SHOUT_LONG_DOWN "keybinding_necromorph_ability_shout_long_down"
#define COMSIG_KB_NECROMORPH_ABILITY_SCREAM_DOWN "keybinding_necromorph_ability_scream_down"
#define COMSIG_KB_NECROMORPH_ABILITY_SENSE_DOWN "keybind_necromorph_ability_sense_down"
Expand Down
7 changes: 7 additions & 0 deletions deadspace/code/datums/keybindingins/necromorph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
description = "Shout to disorientate the enemy."
keybind_signal = COMSIG_KB_NECROMORPH_ABILITY_SHOUT_DOWN

/datum/keybinding/necromorph/finisher
hotkey_keys = list("Unbound")
name = "use_finisher"
full_name = "Necromorph Finisher"
description = "Attempt a lethal takedown on the enemy."
keybind_signal = COMSIG_KB_NECROMORPH_ABILITY_FINISHER_DOWN

/datum/keybinding/necromorph/longshout
hotkey_keys = list("Unbound")
name = "use_long_shout"
Expand Down
193 changes: 193 additions & 0 deletions deadspace/code/necromorph/abilities/finisher.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/* This is a finisher, it's supposed to be used against vulnurable survivors that are incapable of resisting the onslaught of necromorphs*/


/// Every second the target hasn't broken out of the finisher grapple, this amount of damage is dealt to the cranium
#define FINISHER_DAMAGE_PER_SECOND 50
/datum/action/cooldown/necro/finisher
name = "finisher"
desc = "Allows you to deal extraordinary amounts of damage to weakened humans, guarantees death of its victims upon completion."
cooldown_time = 2 SECONDS
click_to_activate = TRUE
/// Delay before the finisher does a charge towards its target to force a grapple
var/charge_delay = 2 SECONDS
/// The maximum amount of time we're delaying chargeing the target for a finisher
var/charge_time = 3 SECONDS
/// Initial damage dealt to the target's head when starting the finisher
var/charge_damage = 30
/// If the victim breaks out of the finisher clutches
var/finisher_stagger = 3 SECONDS
/// If the current move is being triggered by us or not
var/actively_moving = FALSE
var/valid_steps_taken = 0
var/speed_per_step = 0.50
var/max_steps_buildup = 2
var/atom/target_atom
/// How long the execution is going to take compared to world.time
var/finisher_time = 5 SECONDS
//How long the animation to initiate a finisher grapple
var/exegrab_anim = 0.5 SECONDS
//How long the animation to finish actually takes
var/exe_anim = 1 SECONDS

/datum/action/cooldown/necro/finisher/PreActivate(atom/target)
var/turf/T = get_turf(target)
if(!T)
to_chat(owner, span_notice("You must target a human to finish them!"))
return FALSE
if(!ishuman(target))
for(var/mob/living/carbon/human/hummie in view(1, T))
if(!isnecromorph(hummie))
target = hummie
break
if(target == owner || isnecromorph(target))
to_chat(owner, span_notice("You can't peform a finisher on a necromorph!"))
return FALSE

target_atom = target

if(isturf(target))
RegisterSignal(target, COMSIG_ATOM_ENTERED, PROC_REF(on_target_loc_entered))
else
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_target_loc_entered),
)
AddComponent(/datum/component/connect_loc_behalf, target, loc_connections)

return ..()

/datum/action/cooldown/necro/finisher/Activate(atom/target)
. = TRUE
// Start pre-cooldown so that the ability can't come up while the finisher is happening
StartCooldown(charge_time+charge_delay+1)
addtimer(CALLBACK(src, PROC_REF(do_charge)), charge_delay)

/datum/action/cooldown/necro/finisher/proc/do_charge()
var/mob/living/carbon/human/necromorph/finisher = owner

actively_moving = FALSE
finisher.charging = TRUE
RegisterSignal(finisher, COMSIG_MOVABLE_BUMP, PROC_REF(on_bump))
RegisterSignal(finisher, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_move))
RegisterSignal(finisher, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
finisher.setDir(get_dir(finisher, target_atom))
do_rush_indicator(target_atom)

var/datum/move_loop/new_loop = SSmove_manager.move_towards(finisher, target_atom, priority = MOVEMENT_ABOVE_SPACE_PRIORITY)
if(!new_loop)
UnregisterSignal(finisher, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED))
return
RegisterSignal(new_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(pre_move))
RegisterSignal(new_loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(post_move))
RegisterSignal(new_loop, COMSIG_MOVELOOP_STOP, PROC_REF(charge_end))
RegisterSignal(finisher, COMSIG_MOB_STATCHANGE, PROC_REF(stat_changed))
RegisterSignal(finisher, COMSIG_LIVING_UPDATED_RESTING, PROC_REF(update_resting))

SEND_SIGNAL(finisher, COMSIG_STARTED_CHARGE)

/datum/action/cooldown/necro/finisher/proc/on_target_loc_entered(atom/loc, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
SIGNAL_HANDLER
if(arrived != owner)
return
on_bump(owner, target_atom)

/datum/action/cooldown/necro/finisher/proc/pre_move(datum)
SIGNAL_HANDLER
actively_moving = TRUE

/datum/action/cooldown/necro/finisher/proc/post_move(datum)
SIGNAL_HANDLER
actively_moving = FALSE

/datum/action/cooldown/necro/finisher/proc/charge_end(datum/move_loop/source)
SIGNAL_HANDLER
var/mob/living/carbon/human/necromorph/finisher = source.moving
UnregisterSignal(finisher, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_STATCHANGE, COMSIG_LIVING_UPDATED_RESTING))
finisher.charging = FALSE
finisher.remove_movespeed_modifier(/datum/movespeed_modifier/necro_charge)
StartCooldown()
SEND_SIGNAL(owner, COMSIG_FINISHED_CHARGE)

qdel(GetComponent(/datum/component/connect_loc_behalf))
target_atom = null

/datum/action/cooldown/necro/finisher/proc/stat_changed(mob/source, new_stat, old_stat)
SIGNAL_HANDLER
if(new_stat > CONSCIOUS)
SSmove_manager.stop_looping(owner)

/datum/action/cooldown/necro/finisher/proc/do_rush_indicator(atom/charge_target)
return

/datum/action/cooldown/necro/finisher/proc/on_move(atom/source, atom/new_loc)
SIGNAL_HANDLER
if(!actively_moving)
return COMPONENT_MOVABLE_BLOCK_PRE_MOVE

/datum/action/cooldown/necro/finisher/proc/on_moved(atom/source)
SIGNAL_HANDLER
var/mob/living/carbon/human/necromorph/finisher = source
if(++valid_steps_taken <= max_steps_buildup)
finisher.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/necro_charge, TRUE, -CHARGE_SPEED(src))

//Light shake with each step
shake_camera(source, 1.5, 0.5)

return

/datum/action/cooldown/necro/finisher/proc/on_bump(atom/movable/source, atom/target)
SIGNAL_HANDLER
if(ismob(target) || target.uses_integrity)
start_finish(source, target)
SSmove_manager.stop_looping(owner)

/datum/action/cooldown/necro/finisher/proc/start_finish(mob/living/carbon/human/necromorph/source, mob/living/target, delta_time)
target.attack_necromorph(source, dealt_damage = charge_damage)
if(isliving(target))
if(ishuman(target))
var/mob/living/carbon/human/human_target = target
if(human_target.check_shields(source, 0, "the [source.name]", attack_type = LEAP_ATTACK))
source.Stun(6)
shake_camera(source, 4, 3)
shake_camera(target, 2, 1)
return
/// Do an aggro grab
target.grabbedby(source)
target.grippedby(source, instant = TRUE)
target.visible_message("<span class='danger'>[source] clasps [target] in its grasp! Teeth ripping into the base of [target]'s neck!</span>", "<span class='userdanger'>[source] clasps you in its arms! You feel a sharp pain coming from your neck as [source] digs in!</span>")
shake_camera(target, 4, 3)
shake_camera(source, 2, 3)
///
if(target.grab_state == GRAB_AGGRESSIVE)
var/finisher_end = world.time + finisher_time
var/obj/item/bodypart/target_head = target.get_bodypart(BODY_ZONE_HEAD)
if(finisher_end > world.time && target.stat != DEAD)
target.adjustBruteLoss(FINISHER_DAMAGE_PER_SECOND * delta_time, BRUTE, target_head)
/// do slasher finisher animation
do_finisher_indicator(source, target)
/// do exe_anim to kill off the target
if(finisher_end <= world.time && target.stat != DEAD)
target.apply_damage(400, BRUTE, target_head)
return
else
shake_camera(source, 4, 3)
target.visible_message("<span class='danger'>[target] writhes out of the grasp by [source]! [source] has lost its footing!</span>", "<span class='userdanger'>You wriggle out of [source]'s restraint! Your neck relaxes as teeth of [source] are no longer in.</span>")
source.Stun(6)

else
source.visible_message(span_danger("[source] smashes into [target]!"))
shake_camera(source, 4, 3)
source.Stun(6)
/// Finisher deals progressive damage

/datum/action/cooldown/necro/finisher/proc/do_finisher_indicator(atom/finisher_source, atom/finish_target)
return

/datum/action/cooldown/necro/finisher/proc/update_resting(atom/movable/source, resting)
SIGNAL_HANDLER
if(resting)
SSmove_manager.stop_looping(source)


/// RegisterSignal(target, COMSIG_LIVING_START_PULL, PROC_REF(do_finisher))????????????
/// target.attack_necromorph(source, dealt_damage = charge_damage)
/// /datum/action/cooldown/necro/finisher/proc/do_finisher(mob/living/carbon/human/target, mob/living/carbon/human/necromorph/source, delta_time)
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
/datum/action/cooldown/necro/dodge/enhanced = COMSIG_KB_NECROMORPH_ABILITY_DODGE_DOWN,
/datum/action/cooldown/necro/shout = COMSIG_KB_NECROMORPH_ABILITY_SHOUT_DOWN,
/datum/action/cooldown/necro/scream = COMSIG_KB_NECROMORPH_ABILITY_SCREAM_DOWN,
/datum/action/cooldown/necro/finisher = COMSIG_KB_NECROMORPH_ABILITY_FINISHER_DOWN,
)
minimap_icon = "e_slasher"
implemented = TRUE
Expand Down
25 changes: 25 additions & 0 deletions deadspace/code/necromorph/necromorphs/subtypes/slasher.dm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/datum/action/cooldown/necro/charge/slasher = COMSIG_KB_NECROMORPH_ABILITY_CHARGE_DOWN,
/datum/action/cooldown/necro/dodge = COMSIG_KB_NECROMORPH_ABILITY_DODGE_DOWN,
/datum/action/cooldown/necro/shout = COMSIG_KB_NECROMORPH_ABILITY_SHOUT_DOWN,
/datum/action/cooldown/necro/finisher = COMSIG_KB_NECROMORPH_ABILITY_FINISHER_DOWN,
)
minimap_icon = "slasher"
implemented = TRUE
Expand Down Expand Up @@ -61,3 +62,27 @@
animate(source, transform = new_matrix, pixel_x = source.pixel_x + 5*shake_dir, time = 1)
animate(transform = matrix(), pixel_x = source.pixel_x-5*shake_dir, time = 9, easing = ELASTIC_EASING)
source.play_necro_sound(SOUND_SHOUT_LONG, VOLUME_HIGH, TRUE, 3)

/datum/action/cooldown/necro/finisher/slasher
cooldown_time = 12 SECONDS
charge_delay = 2 SECONDS
charge_time = 4 SECONDS

/datum/action/cooldown/necro/finisher/slasher/do_rush_indicator(atom/charge_target)
var/mob/living/carbon/human/necromorph/source = owner
var/matrix/new_matrix = matrix(source.transform)
var/shake_dir = pick(-3, 2)
new_matrix.Turn(16*shake_dir)
animate(source, transform = new_matrix, pixel_x = source.pixel_x + 5*shake_dir, time = 1)
animate(transform = matrix(), pixel_x = source.pixel_x-5*shake_dir, time = 9, easing = ELASTIC_EASING)
source.play_necro_sound(SOUND_SHOUT_LONG, VOLUME_HIGH, TRUE, 3)

//bwuh, how
/datum/action/cooldown/necro/finisher/slasher/do_finisher_indicator(atom/finish_target)
var/mob/living/carbon/human/necromorph/source = owner
var/matrix/new_matrix = matrix(source.transform)
var/shake_dir = pick(-1, 1)
new_matrix.Turn(16*shake_dir)
animate(source, transform = new_matrix, pixel_x = source.pixel_x + 5*shake_dir, time = 1)
animate(transform = matrix(), pixel_x = source.pixel_x-5*shake_dir, time = 9, easing = ELASTIC_EASING)
source.play_necro_sound(SOUND_SHOUT_LONG, VOLUME_HIGH, TRUE, 3)