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

Lurker invis toggling #6148

Merged
merged 4 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

if(xeno.crest_defense)
to_chat(xeno, SPAN_XENOWARNING("We lower our crest."))
xeno.balloon_alert(xeno, "crest lowered")

xeno.ability_speed_modifier += speed_debuff
xeno.armor_deflection_buff += armor_buff
Expand All @@ -26,7 +25,6 @@
xeno.update_icons()
else
to_chat(xeno, SPAN_XENOWARNING("We raise our crest."))
xeno.balloon_alert(xeno, "crest raised")

xeno.ability_speed_modifier -= speed_debuff
xeno.armor_deflection_buff -= armor_buff
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
macro_path = /datum/action/xeno_action/verb/verb_lurker_invisibility
ability_primacy = XENO_PRIMARY_ACTION_2
action_type = XENO_ACTION_CLICK
xeno_cooldown = 1 // This ability never goes off cooldown 'naturally'. Cooldown is applied manually as a super-large value in the use_ability proc
// and reset by the behavior_delegate whenever the ability ends (because it can be ended by things like slashes, that we can't easily track here)
plasma_cost = 20

var/duration = 30 SECONDS // 30 seconds base
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/datum/action/xeno_action/activable/pounce/lurker/additional_effects_always()
/datum/action/xeno_action/activable/pounce/lurker/additional_effects(mob/living/living_mob)
var/mob/living/carbon/xenomorph/xeno = owner
if(!istype(xeno))
return

RegisterSignal(xeno, COMSIG_XENO_SLASH_ADDITIONAL_EFFECTS_SELF, PROC_REF(remove_freeze), TRUE) // Suppresses runtime ever we pounce again before slashing

var/found = FALSE
for(var/mob/living/carbon/human/human in get_turf(xeno))
if(human.stat == DEAD)
Expand All @@ -12,14 +14,8 @@

if(found)
var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis = get_xeno_action_by_type(xeno, /datum/action/xeno_action/onclick/lurker_invisibility)
lurker_invis.invisibility_off()

/datum/action/xeno_action/activable/pounce/lurker/additional_effects(mob/living/living_mob)
var/mob/living/carbon/xenomorph/xeno = owner
if(!istype(xeno))
return

RegisterSignal(xeno, COMSIG_XENO_SLASH_ADDITIONAL_EFFECTS_SELF, PROC_REF(remove_freeze), TRUE) // Suppresses runtime ever we pounce again before slashing
if(lurker_invis)
lurker_invis.invisibility_off() // Full cooldown

/datum/action/xeno_action/activable/pounce/lurker/proc/remove_freeze(mob/living/carbon/xenomorph/xeno)
SIGNAL_HANDLER
Expand All @@ -32,18 +28,22 @@
/datum/action/xeno_action/onclick/lurker_invisibility/use_ability(atom/targeted_atom)
var/mob/living/carbon/xenomorph/xeno = owner

if (!istype(xeno))
if(!istype(xeno))
return

if (!action_cooldown_check())
if(!action_cooldown_check())
return

if (!check_and_use_plasma_owner())
if(!check_and_use_plasma_owner())
return

animate(xeno, alpha = alpha_amount, time = 0.1 SECONDS, easing = QUAD_EASING)
if(xeno.stealth)
invisibility_off(0.9) // Near full refund of remaining time
return ..()

button.icon_state = "template_active"
xeno.update_icons() // callback to make the icon_state indicate invisibility is in lurker/update_icon

animate(xeno, alpha = alpha_amount, time = 0.1 SECONDS, easing = QUAD_EASING)

xeno.speed_modifier -= speed_buff
xeno.recalculate_speed()

Expand All @@ -53,31 +53,44 @@
// if we go off early, this also works fine.
invis_timer_id = addtimer(CALLBACK(src, PROC_REF(invisibility_off)), duration, TIMER_STOPPABLE)

// Only resets when invisibility ends
apply_cooldown_override(1000000000)
return ..()

/datum/action/xeno_action/onclick/lurker_invisibility/proc/invisibility_off()
if(!owner || owner.alpha == initial(owner.alpha))
/// Implementation for disabling invisibility.
/// (refund_multiplier) indicates how much cooldown to refund based on time remaining
/// 0 indicates full cooldown; 0.5 indicates 50% of remaining time is refunded
/datum/action/xeno_action/onclick/lurker_invisibility/proc/invisibility_off(refund_multiplier = 0.0)
var/mob/living/carbon/xenomorph/xeno = owner

if(!istype(xeno))
return
if(owner.alpha == initial(owner.alpha) && !xeno.stealth)
return

if (invis_timer_id != TIMER_ID_NULL)
if(invis_timer_id != TIMER_ID_NULL)
deltimer(invis_timer_id)
invis_timer_id = TIMER_ID_NULL

var/mob/living/carbon/xenomorph/xeno = owner
if (istype(xeno))
animate(xeno, alpha = initial(xeno.alpha), time = 0.1 SECONDS, easing = QUAD_EASING)
to_chat(xeno, SPAN_XENOHIGHDANGER("We feel our invisibility end!"))
animate(xeno, alpha = initial(xeno.alpha), time = 0.1 SECONDS, easing = QUAD_EASING)
to_chat(xeno, SPAN_XENOHIGHDANGER("We feel our invisibility end!"))

button.icon_state = "template"
xeno.update_icons()

xeno.update_icons()
xeno.speed_modifier += speed_buff
xeno.recalculate_speed()

var/datum/behavior_delegate/lurker_base/behavior = xeno.behavior_delegate
if(!istype(behavior))
CRASH("lurker_base behavior_delegate missing/invalid for [xeno]!")

xeno.speed_modifier += speed_buff
xeno.recalculate_speed()
var/recharge_time = behavior.invis_recharge_time
if(behavior.invis_start_time > 0) // Sanity
refund_multiplier = clamp(refund_multiplier, 0, 1)
var/remaining = 1 - (world.time - behavior.invis_start_time) / behavior.invis_duration
recharge_time = behavior.invis_recharge_time - remaining * refund_multiplier * behavior.invis_recharge_time
apply_cooldown_override(recharge_time)

var/datum/behavior_delegate/lurker_base/behavior = xeno.behavior_delegate
if (istype(behavior))
behavior.on_invisibility_off()
behavior.on_invisibility_off()

/datum/action/xeno_action/onclick/lurker_invisibility/ability_cooldown_over()
to_chat(owner, SPAN_XENOHIGHDANGER("We are ready to use our invisibility again!"))
Expand Down
34 changes: 9 additions & 25 deletions code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,14 @@
name = "Base Lurker Behavior Delegate"

// Config
var/invis_recharge_time = 150 // 15 seconds to recharge invisibility.
var/invis_recharge_time = 20 SECONDS
var/invis_start_time = -1 // Special value for when we're not invisible
var/invis_duration = 300 // so we can display how long the lurker is invisible to it
var/invis_duration = 30 SECONDS // so we can display how long the lurker is invisible to it
var/buffed_slash_damage_ratio = 1.2
var/slash_slow_duration = 35

// State
var/next_slash_buffed = FALSE
var/can_go_invisible = TRUE

/datum/behavior_delegate/lurker_base/melee_attack_modify_damage(original_damage, mob/living/carbon/target_carbon)
if (!isxeno_human(target_carbon))
Expand Down Expand Up @@ -116,51 +115,36 @@

var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility)
if (lurker_invis_action)
lurker_invis_action.invisibility_off()
lurker_invis_action.invisibility_off() // Full cooldown

/datum/behavior_delegate/lurker_base/proc/decloak_handler(mob/source)
SIGNAL_HANDLER
var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility)
if(istype(lurker_invis_action))
lurker_invis_action.invisibility_off()
lurker_invis_action.invisibility_off(0.5) // Partial refund of remaining time

// What to do when we go invisible
/// Implementation for enabling invisibility.
/datum/behavior_delegate/lurker_base/proc/on_invisibility()
var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker)
if (lurker_pounce_action)
if(lurker_pounce_action)
lurker_pounce_action.knockdown = TRUE // pounce knocks down
lurker_pounce_action.freeze_self = TRUE
ADD_TRAIT(bound_xeno, TRAIT_CLOAKED, TRAIT_SOURCE_ABILITY("cloak"))
RegisterSignal(bound_xeno, COMSIG_MOB_EFFECT_CLOAK_CANCEL, PROC_REF(decloak_handler))
bound_xeno.stealth = TRUE
can_go_invisible = FALSE
invis_start_time = world.time

/// Implementation for disabling invisibility.
/datum/behavior_delegate/lurker_base/proc/on_invisibility_off()
var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker)
if (lurker_pounce_action)
if(lurker_pounce_action)
lurker_pounce_action.knockdown = FALSE // pounce no longer knocks down
lurker_pounce_action.freeze_self = FALSE
bound_xeno.stealth = FALSE
REMOVE_TRAIT(bound_xeno, TRAIT_CLOAKED, TRAIT_SOURCE_ABILITY("cloak"))
UnregisterSignal(bound_xeno, COMSIG_MOB_EFFECT_CLOAK_CANCEL)

// SLIGHTLY hacky because we need to maintain lots of other state on the lurker
// whenever invisibility is on/off CD and when it's active.
addtimer(CALLBACK(src, PROC_REF(regen_invisibility)), invis_recharge_time)

invis_start_time = -1

/datum/behavior_delegate/lurker_base/proc/regen_invisibility()
if (can_go_invisible)
return

can_go_invisible = TRUE
if(bound_xeno)
var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility)
if(lurker_invisibility_action)
lurker_invisibility_action.end_cooldown()

/datum/behavior_delegate/lurker_base/append_to_stat()
. = list()
var/invis_message = (invis_start_time == -1) ? "N/A" : "[(invis_duration-(world.time - invis_start_time))/10] seconds."
Expand All @@ -184,4 +168,4 @@
return

to_chat(bound_xeno, SPAN_XENOHIGHDANGER("We bumped into someone and lost our invisibility!"))
lurker_invisibility_action.invisibility_off()
lurker_invisibility_action.invisibility_off(0.5) // partial refund of remaining time
1 change: 1 addition & 0 deletions code/modules/mob/mob_grab.dm
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
if(user.action_busy)
to_chat(xeno, SPAN_WARNING("We are already busy with something."))
return
SEND_SIGNAL(xeno, COMSIG_MOB_EFFECT_CLOAK_CANCEL)
xeno.visible_message(SPAN_DANGER("[xeno] starts to devour [pulled]!"), \
SPAN_DANGER("We start to devour [pulled]!"), null, 5)
if(HAS_TRAIT(xeno, TRAIT_CLOAKED)) //cloaked don't show the visible message, so we gotta work around
Expand Down
Loading