diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 6a806bdef74..0bd1629893d 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -610,9 +610,10 @@ GLOBAL_LIST_INIT(xenoupgradetiers, list(XENO_UPGRADE_BASETYPE, XENO_UPGRADE_INVA #define RAVAGER_RAGE_DURATION 10 SECONDS #define RAVAGER_RAGE_WARNING 0.7 -#define RAVAGER_RAGE_MIN_HEALTH_THRESHOLD 0.5 //The maximum % of HP we can have to trigger Rage +#define RAVAGER_RAGE_MIN_HEALTH_THRESHOLD 0.75 //The maximum % of HP we can have to trigger Rage +#define RAVAGER_RAGE_STAGGERSTUN_IMMUNE_THRESHOLD 0.5 #define RAVAGER_RAGE_ENDURE_INCREASE_PER_SLASH 2 SECONDS //The amount of time each slash during Rage increases Endure's duration -#define RAVAGER_RAGE_HEALTH_RECOVERY_PER_SLASH 80 //Maximum amount of healing from slash during Rage +#define RAVAGER_RAGE_HEALTH_RECOVERY_PER_SLASH 60 //Maximum amount of healing from slash during Rage //crusher defines #define CRUSHER_STOMP_LOWER_DMG 40 diff --git a/code/datums/keybinding/xeno.dm b/code/datums/keybinding/xeno.dm index 29e8bb276bf..0205a945324 100644 --- a/code/datums/keybinding/xeno.dm +++ b/code/datums/keybinding/xeno.dm @@ -742,13 +742,6 @@ keybind_signal = COMSIG_XENOABILITY_ENDURE hotkey_keys = list("F") -/datum/keybinding/xeno/ravager_rage - name = "ravager_rage" - full_name = "Ravager: Rage" - description = "While active, you will temporarily recover plasma and sunder and gain a bonus to speed and melee damage in proportion to the percentage of your missing health. At negative HP your ability cooldowns reset and your slash damage restores health." - keybind_signal = COMSIG_XENOABILITY_RAGE - hotkey_keys = list("Space") - /datum/keybinding/xeno/ravager_vampirism name = "togglevampirism" full_name = "Ravager: Toggle vampirism" diff --git a/code/modules/mob/living/carbon/xenomorph/castes/ravager/abilities_ravager.dm b/code/modules/mob/living/carbon/xenomorph/castes/ravager/abilities_ravager.dm index ec7e19ce68a..b1a1e2a7fe5 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/ravager/abilities_ravager.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/ravager/abilities_ravager.dm @@ -304,156 +304,6 @@ return FALSE return TRUE -// *************************************** -// *********** Rage -// *************************************** -/datum/action/ability/xeno_action/rage - name = "Rage" - action_icon_state = "rage" - desc = "Use while at 50% health or lower to gain extra slash damage, resistances and speed in proportion to your missing hit points. This bonus is increased and you regain plasma while your HP is negative." - ability_cost = 0 //We're limited by cooldowns, not plasma - cooldown_duration = 60 SECONDS - keybind_flags = ABILITY_KEYBIND_USE_ABILITY | ABILITY_IGNORE_SELECTED_ABILITY - keybinding_signals = list( - KEYBINDING_NORMAL = COMSIG_XENOABILITY_RAGE, - ) - ///Determines the power of Rage's many effects. Power scales inversely with the Ravager's HP; min 0.25 at 50% of Max HP, max 1 while in negative HP. 0.5 and above triggers especial effects. - var/rage_power - ///Determines the Plasma to remove when Rage ends - var/rage_plasma - -/datum/action/ability/xeno_action/rage/on_cooldown_finish() - to_chat(owner, span_xenodanger("We are able to enter our rage once again.")) - owner.playsound_local(owner, 'sound/effects/alien/newlarva.ogg', 25, 0, 1) - return ..() - -/datum/action/ability/xeno_action/rage/can_use_action(atom/A, silent = FALSE, override_flags) - . = ..() - if(!.) - return FALSE - - var/mob/living/carbon/xenomorph/rager = owner - - if(rager.health > rager.maxHealth * RAVAGER_RAGE_MIN_HEALTH_THRESHOLD) //Need to be at 50% of max hp or lower to rage - if(!silent) - to_chat(rager, span_xenodanger("Our health isn't low enough to rage! We must take [rager.health - (rager.maxHealth * RAVAGER_RAGE_MIN_HEALTH_THRESHOLD)] more damage!")) - return FALSE - - -/datum/action/ability/xeno_action/rage/action_activate() - var/mob/living/carbon/xenomorph/X = owner - - var/rage_threshold = X.maxHealth * (1 - RAVAGER_RAGE_MIN_HEALTH_THRESHOLD) - rage_power = max(0, (1 - ((X.health - RAVAGER_ENDURE_HP_LIMIT) / (X.maxHealth - RAVAGER_ENDURE_HP_LIMIT - rage_threshold)))) //Calculate the power of our rage; scales with difference between current and max HP - - var/rage_power_radius = CEILING(rage_power * 3, 1) //Define radius of the SFX - - X.visible_message(span_danger("\The [X] becomes frenzied, bellowing with a shuddering roar!"), \ - span_highdanger("We bellow as our fury overtakes us! RIP AND TEAR!")) - X.do_jitter_animation(1000) - - //Roar SFX; volume scales with rage - playsound(X.loc, 'sound/voice/alien/roar2.ogg', clamp(100 * rage_power, 25, 80), 0) - - var/bonus_duration - - var/datum/action/ability/xeno_action/endure/endure_ability = X.actions_by_path[/datum/action/ability/xeno_action/endure] - if(endure_ability.endure_duration) //Check if Endure is active - endure_ability.endure_threshold = RAVAGER_ENDURE_HP_LIMIT * (1 + rage_power) //Endure crit threshold scales with Rage Power; min -100, max -150 - RegisterSignal(X, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(drain_slash)) - - for(var/turf/affected_tiles AS in RANGE_TURFS(rage_power_radius * 0.5, X.loc)) - affected_tiles.Shake(duration = 1 SECONDS) //SFX - - for(var/mob/living/affected_mob in cheap_get_humans_near(X, rage_power_radius) + cheap_get_xenos_near(X, rage_power_radius)) //Roar that applies cool SFX - if(affected_mob.stat || affected_mob == X) //We don't care about the dead/unconsious || RUTGMC EDIT - continue - - shake_camera(affected_mob, 1 SECONDS, 1) - affected_mob.Shake(duration = 1 SECONDS) //SFX - - X.add_filter("ravager_rage_outline", 5, outline_filter(1.5, COLOR_RED)) //Set our cool aura; also confirmation we have the buff - - rage_plasma = min(X.xeno_caste.plasma_max - X.plasma_stored, X.xeno_caste.plasma_max * rage_power) //Calculate the plasma to restore (and take away later) - X.plasma_stored += rage_plasma //Regain a % of our maximum plasma scaling with rage - X.xeno_melee_damage_modifier += rage_power //Set rage melee damage bonus - - X.add_movespeed_modifier(MOVESPEED_ID_RAVAGER_RAGE, TRUE, 0, NONE, TRUE, X.xeno_caste.speed * 0.5 * rage_power) //Set rage speed bonus - - //Too angry to be stunned/slowed/staggered/knocked down - ADD_TRAIT(X, TRAIT_STUNIMMUNE, RAGE_TRAIT) - ADD_TRAIT(X, TRAIT_SLOWDOWNIMMUNE, RAGE_TRAIT) - ADD_TRAIT(X, TRAIT_STAGGERIMMUNE, RAGE_TRAIT) - - addtimer(CALLBACK(src, PROC_REF(rage_warning), bonus_duration), (RAVAGER_RAGE_DURATION + bonus_duration) * RAVAGER_RAGE_WARNING) //Warn the ravager when rage is about to expire. - addtimer(CALLBACK(src, PROC_REF(rage_deactivate)), (RAVAGER_RAGE_DURATION + bonus_duration)) - - succeed_activate() - add_cooldown() - - GLOB.round_statistics.ravager_rages++ //Statistics - SSblackbox.record_feedback("tally", "round_statistics", 1, "ravager_rages") - -///Warns the user when his rage is about to end. -/datum/action/ability/xeno_action/rage/proc/rage_warning(bonus_duration = 0) - if(QDELETED(owner)) - return - to_chat(owner,span_highdanger("Our rage begins to subside... [initial(name)] will only last for only [(RAVAGER_RAGE_DURATION + bonus_duration) * (1-RAVAGER_RAGE_WARNING) * 0.1] more seconds!")) - owner.playsound_local(owner, 'sound/voice/alien/hiss8.ogg', 50, 0, 1) - -///Warns the user when his rage is about to end. -/datum/action/ability/xeno_action/rage/proc/drain_slash(datum/source, mob/living/target, damage, list/damage_mod, list/armor_mod) - SIGNAL_HANDLER - var/mob/living/rager = owner - var/brute_damage = rager.getBruteLoss() - var/burn_damage = rager.getFireLoss() - if(!brute_damage && !burn_damage) //If we have no healable damage, don't bother proceeding - return - var/health_recovery = rage_power * RAVAGER_RAGE_HEALTH_RECOVERY_PER_SLASH //Amount of health we leech per slash - var/health_modifier - if(brute_damage) //First heal Brute damage, then heal Burn damage with remainder - health_modifier = min(brute_damage, health_recovery)*-1 //Get the lower of our Brute Loss or the health we're leeching - rager.adjustBruteLoss(health_modifier) - health_recovery += health_modifier //Decrement the amount healed from our total healing pool - if(burn_damage) - health_modifier = min(burn_damage, health_recovery)*-1 - rager.adjustFireLoss(health_modifier) - - var/datum/action/ability/xeno_action/endure/endure_ability = rager.actions_by_path[/datum/action/ability/xeno_action/endure] - if(endure_ability.endure_duration) //Check if Endure is active - var/new_duration = min(RAVAGER_ENDURE_DURATION, (timeleft(endure_ability.endure_duration) + RAVAGER_RAGE_ENDURE_INCREASE_PER_SLASH * rage_power)) //Increment Endure duration by 2 seconds per slash at maximum rage - deltimer(endure_ability.endure_duration) //Reset timers - deltimer(endure_ability.endure_warning_duration) - endure_ability.endure_duration = addtimer(CALLBACK(endure_ability, TYPE_PROC_REF(/datum/action/ability/xeno_action/endure, endure_deactivate)), new_duration, TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_OVERRIDE) //Reset Endure timers if active - if(new_duration > 3 SECONDS) //Check timing - endure_ability.endure_warning_duration = addtimer(CALLBACK(endure_ability, TYPE_PROC_REF(/datum/action/ability/xeno_action/endure, endure_warning)), new_duration - 3 SECONDS, TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_OVERRIDE) //Reset Endure timers if active - -///Called when we want to end the Rage effect -/datum/action/ability/xeno_action/rage/proc/rage_deactivate() - if(QDELETED(owner)) - return - var/mob/living/carbon/xenomorph/X = owner - - X.do_jitter_animation(1000) - - X.remove_filter("ravager_rage_outline") - X.visible_message(span_warning("[X] seems to calm down."), \ - span_highdanger("Our rage subsides and its power leaves our body, leaving us exhausted.")) - - X.xeno_melee_damage_modifier = initial(X.xeno_melee_damage_modifier) //Reset rage melee damage bonus - X.remove_movespeed_modifier(MOVESPEED_ID_RAVAGER_RAGE) //Reset speed - X.use_plasma(rage_plasma) //Remove the temporary Plasma - - REMOVE_TRAIT(X, TRAIT_STUNIMMUNE, RAGE_TRAIT) - REMOVE_TRAIT(X, TRAIT_SLOWDOWNIMMUNE, RAGE_TRAIT) - REMOVE_TRAIT(X, TRAIT_STAGGERIMMUNE, RAGE_TRAIT) - UnregisterSignal(X, COMSIG_XENOMORPH_ATTACK_LIVING) - - rage_power = 0 - rage_plasma = 0 - X.playsound_local(X, 'sound/voice/alien/hiss8.ogg', 50) //Audio cue - - // *************************************** // *********** Vampirism // *************************************** diff --git a/code/modules/mob/living/carbon/xenomorph/castes/ravager/castedatum_ravager.dm b/code/modules/mob/living/carbon/xenomorph/castes/ravager/castedatum_ravager.dm index 9d867db42a0..fc9e794f642 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/ravager/castedatum_ravager.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/ravager/castedatum_ravager.dm @@ -46,7 +46,6 @@ /datum/action/ability/activable/xeno/charge, /datum/action/ability/activable/xeno/ravage, /datum/action/ability/xeno_action/endure, - /datum/action/ability/xeno_action/rage, ) /datum/xeno_caste/ravager/on_caste_applied(mob/xenomorph) @@ -76,6 +75,5 @@ /datum/action/ability/activable/xeno/charge, /datum/action/ability/activable/xeno/ravage, /datum/action/ability/xeno_action/endure, - /datum/action/ability/xeno_action/rage, /datum/action/ability/xeno_action/vampirism, ) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/ravager/ravager.dm b/code/modules/mob/living/carbon/xenomorph/castes/ravager/ravager.dm index a704b4cd440..0bd4b534a2b 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/ravager/ravager.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/ravager/ravager.dm @@ -14,11 +14,94 @@ pixel_x = -16 old_x = -16 bubble_icon = "alienroyal" + var/rage_power + var/rage = FALSE + var/staggerstun_immune = FALSE + var/on_cooldown = FALSE /mob/living/carbon/xenomorph/ravager/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_LIGHT_STEP, XENO_TRAIT) +/mob/living/carbon/xenomorph/ravager/Life() + . = ..() + if(health > maxHealth * RAVAGER_RAGE_MIN_HEALTH_THRESHOLD) + if(!rage) + return + rage = FALSE + on_cooldown = FALSE + rage_power = 0 + remove_filter("ravager_rage_outline") + xeno_melee_damage_modifier = initial(xeno_melee_damage_modifier) + remove_movespeed_modifier(MOVESPEED_ID_RAVAGER_RAGE) + REMOVE_TRAIT(src, TRAIT_STUNIMMUNE, RAGE_TRAIT) + REMOVE_TRAIT(src, TRAIT_SLOWDOWNIMMUNE, RAGE_TRAIT) + REMOVE_TRAIT(src, TRAIT_STAGGERIMMUNE, RAGE_TRAIT) + UnregisterSignal(src, COMSIG_XENOMORPH_ATTACK_LIVING) + playsound_local(src, 'sound/voice/alien/hiss8.ogg', 50) + balloon_alert(src, "We are rested enough") + return + + var/rage_threshold = maxHealth * (1 - RAVAGER_RAGE_MIN_HEALTH_THRESHOLD) + rage_power = max(0, (1 - ((health - RAVAGER_ENDURE_HP_LIMIT) / (maxHealth - RAVAGER_ENDURE_HP_LIMIT - rage_threshold)))) + + add_filter("ravager_rage_outline", 5, outline_filter(rage_power, COLOR_RED)) + + if(!rage) + RegisterSignal(src, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(drain_slash)) + rage = TRUE + + if(!staggerstun_immune && (health <= maxHealth * RAVAGER_RAGE_STAGGERSTUN_IMMUNE_THRESHOLD)) + ADD_TRAIT(src, TRAIT_STUNIMMUNE, RAGE_TRAIT) + ADD_TRAIT(src, TRAIT_SLOWDOWNIMMUNE, RAGE_TRAIT) + ADD_TRAIT(src, TRAIT_STAGGERIMMUNE, RAGE_TRAIT) + staggerstun_immune = TRUE + else if (health > maxHealth * RAVAGER_RAGE_STAGGERSTUN_IMMUNE_THRESHOLD) + REMOVE_TRAIT(src, TRAIT_STUNIMMUNE, RAGE_TRAIT) + REMOVE_TRAIT(src, TRAIT_SLOWDOWNIMMUNE, RAGE_TRAIT) + REMOVE_TRAIT(src, TRAIT_STAGGERIMMUNE, RAGE_TRAIT) + staggerstun_immune = FALSE + + xeno_melee_damage_modifier = initial(xeno_melee_damage_modifier) + rage_power + add_movespeed_modifier(MOVESPEED_ID_RAVAGER_RAGE, TRUE, 0, NONE, TRUE, xeno_caste.speed * 0.5 * rage_power) + + if((health < 0) && !on_cooldown && stat == CONSCIOUS) + playsound(loc, 'sound/voice/alien/roar2.ogg', clamp(100 * rage_power, 25, 80), 0) + balloon_alert(src, "RIP AND TEAR") + plasma_stored += xeno_caste.plasma_max + var/datum/action/ability/xeno_action/charge = actions_by_path[/datum/action/ability/activable/xeno/charge] + var/datum/action/ability/xeno_action/ravage = actions_by_path[/datum/action/ability/activable/xeno/ravage] + if(charge) + charge.clear_cooldown() + if(ravage) + ravage.clear_cooldown() + on_cooldown = TRUE + +/mob/living/carbon/xenomorph/ravager/proc/drain_slash(datum/source, mob/living/target, damage, list/damage_mod, list/armor_mod) + SIGNAL_HANDLER + var/brute_damage = getBruteLoss() + var/burn_damage = getFireLoss() + if(!brute_damage && !burn_damage) + return + var/health_recovery = rage_power * RAVAGER_RAGE_HEALTH_RECOVERY_PER_SLASH + var/health_modifier + if(brute_damage) + health_modifier = min(brute_damage, health_recovery)*-1 + adjustBruteLoss(health_modifier) + health_recovery += health_modifier + if(burn_damage) + health_modifier = min(burn_damage, health_recovery)*-1 + adjustFireLoss(health_modifier) + + var/datum/action/ability/xeno_action/endure/endure_ability = actions_by_path[/datum/action/ability/xeno_action/endure] + if(endure_ability.endure_duration) //Check if Endure is active + var/new_duration = min(RAVAGER_ENDURE_DURATION, (timeleft(endure_ability.endure_duration) + RAVAGER_RAGE_ENDURE_INCREASE_PER_SLASH * rage_power)) + deltimer(endure_ability.endure_duration) //Reset timers + deltimer(endure_ability.endure_warning_duration) + endure_ability.endure_duration = addtimer(CALLBACK(endure_ability, TYPE_PROC_REF(/datum/action/ability/xeno_action/endure, endure_deactivate)), new_duration, TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_OVERRIDE) + if(new_duration > 3 SECONDS) //Check timing + endure_ability.endure_warning_duration = addtimer(CALLBACK(endure_ability, TYPE_PROC_REF(/datum/action/ability/xeno_action/endure, endure_warning)), new_duration - 3 SECONDS, TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_OVERRIDE) + // *************************************** // *********** Mob overrides // ***************************************