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

Adds bloodthirster Rav strain #16664

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions code/__DEFINES/movespeed_modification.dm
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define MOVESPEED_ID_WARRIOR_AGILITY "WARRIOR_AGILITY"
#define MOVESPEED_ID_FRENZY_AURA "FRENZY_AURA"
#define MOVESPEED_ID_XENO_HEMODILE "XENO_HEMODILE"
#define MOVESPEED_ID_RAVAGER_DEATHMARK "RAVAGER_DEATHMARK"
#define MOVESPEED_ID_RAVAGER_RAGE "RAVAGER_RAGE"
#define MOVESPEED_ID_GORGER_CARNAGE "GORGER_CARNAGE"
#define MOVESPEED_ID_GORGER_REJUVENATE "GORGER_REJUVENATE"
Expand Down
1 change: 1 addition & 0 deletions code/__DEFINES/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@
#define TRAIT_XENOMORPH_INVISIBLE_BLOOD "invisible_blood"
#define TRAIT_VALHALLA_XENO "valhalla_xeno"
#define TRAIT_BULWARKED_TURF "bulwarked_turf" // turf is affected by bulwark ability
#define TRAIT_BLOODTHIRSTER "bloodthirster" // xeno has the bloodthirster ability

//important_recursive_contents traits
/*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#define STAGE_ONE_BLOODTHIRST 100
#define STAGE_TWO_BLOODTHIRST 300
#define STAGE_THREE_BLOODTHIRST 400

// ***************************************
// *********** Charge
// ***************************************
Expand All @@ -14,6 +18,9 @@
///charge distance
var/charge_range = RAV_CHARGEDISTANCE

/datum/action/ability/activable/xeno/charge/nocost
ability_cost = 0

/datum/action/ability/activable/xeno/charge/use_ability(atom/A)
if(!A)
return
Expand All @@ -29,10 +36,18 @@
X.xeno_flags |= XENO_LEAPING //This has to come before throw_at, which checks impact. So we don't do end-charge specials when thrown
succeed_activate()

X.throw_at(A, charge_range, RAV_CHARGESPEED, X)
var/multiplier = 1
if(HAS_TRAIT(owner, TRAIT_BLOODTHIRSTER))
if(X.plasma_stored >= STAGE_TWO_BLOODTHIRST)
multiplier += 0.5
if(X.plasma_stored >= STAGE_THREE_BLOODTHIRST)
multiplier++ += 0.5

Check failure on line 44 in code/modules/mob/living/carbon/xenomorph/castes/ravager/abilities_ravager.dm

View workflow job for this annotation

GitHub Actions / Run Linters

OD0011: attempt to reference r-value
Lumipharon marked this conversation as resolved.
Show resolved Hide resolved

X.throw_at(A, charge_range*multiplier, RAV_CHARGESPEED*multiplier, X)

add_cooldown()


/datum/action/ability/activable/xeno/charge/on_cooldown_finish()
to_chat(owner, span_xenodanger("Our exoskeleton quivers as we get ready to use [name] again."))
playsound(owner, 'sound/effects/alien/new_larva.ogg', 50, 0, 1)
Expand Down Expand Up @@ -72,7 +87,13 @@
return

var/mob/living/carbon/xenomorph/xeno_owner = owner
living_target.attack_alien_harm(xeno_owner, xeno_owner.xeno_caste.melee_damage * xeno_owner.xeno_melee_damage_modifier * 0.25, FALSE, TRUE, FALSE, TRUE, INTENT_HARM) //Location is always random, cannot crit, harm only
var/multiplier = 1
if(HAS_TRAIT(xeno_owner, TRAIT_BLOODTHIRSTER))
if(xeno_owner.plasma_stored >= STAGE_TWO_BLOODTHIRST)
multiplier++
if(xeno_owner.plasma_stored >= STAGE_THREE_BLOODTHIRST)
multiplier++
Lumipharon marked this conversation as resolved.
Show resolved Hide resolved
living_target.attack_alien_harm(xeno_owner, xeno_owner.xeno_caste.melee_damage * xeno_owner.xeno_melee_damage_modifier * 0.25 * multiplier, FALSE, TRUE, FALSE, TRUE, INTENT_HARM) //Location is always random, cannot crit, harm only
var/target_turf = get_ranged_target_turf(living_target, get_dir(src, living_target), rand(1, 3)) //we blast our victim behind us
target_turf = get_step_rand(target_turf) //Scatter
if(iscarbon(living_target))
Expand Down Expand Up @@ -105,6 +126,9 @@
/// Used for particles. Holds the particles instead of the mob. See particle_holder for documentation.
var/obj/effect/abstract/particle_holder/particle_holder

/datum/action/ability/activable/xeno/ravage/nocost
ability_cost = 0

/datum/action/ability/activable/xeno/ravage/on_cooldown_finish()
to_chat(owner, span_xenodanger("We gather enough strength to Ravage again."))
playsound(owner, 'sound/effects/alien/new_larva.ogg', 50, 0, 1)
Expand All @@ -123,6 +147,18 @@
var/list/atom/movable/atoms_to_ravage = get_step(owner, owner.dir).contents.Copy()
atoms_to_ravage += get_step(owner, turn(owner.dir, -45)).contents
atoms_to_ravage += get_step(owner, turn(owner.dir, 45)).contents
if(HAS_TRAIT(owner, TRAIT_BLOODTHIRSTER))
if(X.plasma_stored >= STAGE_TWO_BLOODTHIRST)
var/turf/far = get_step(get_step(owner, owner.dir), owner.dir)
atoms_to_ravage += far.contents
atoms_to_ravage += get_step(far, turn(owner.dir, 90)).contents
atoms_to_ravage += get_step(far, turn(owner.dir, -90)).contents
if(X.plasma_stored >= STAGE_THREE_BLOODTHIRST)
far = get_step(far, owner.dir)
atoms_to_ravage += far.contents
atoms_to_ravage += get_step(far, turn(owner.dir, 90)).contents
atoms_to_ravage += get_step(far, turn(owner.dir, -90)).contents

for(var/atom/movable/ravaged AS in atoms_to_ravage)
if(ishitbox(ravaged) || isvehicle(ravaged))
ravaged.attack_alien(X, X.xeno_caste.melee_damage) //Handles APC/Tank stuff. Has to be before the !ishuman check or else ravage does work properly on vehicles.
Expand Down Expand Up @@ -212,6 +248,9 @@
///Timer for Endure's warning
var/endure_warning_duration

/datum/action/ability/xeno_action/endure/nocost
ability_cost = 0

/datum/action/ability/xeno_action/endure/on_cooldown_finish()
to_chat(owner, span_xenodanger("We feel able to imbue ourselves with plasma to Endure once again!"))
owner.playsound_local(owner, 'sound/effects/alien/new_larva.ogg', 25, 0, 1)
Expand Down Expand Up @@ -330,6 +369,9 @@
///Determines the Plasma to remove when Rage ends
var/rage_plasma

/datum/action/ability/xeno_action/rage/nocost
ability_cost = 0

/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/new_larva.ogg', 25, 0, 1)
Expand Down Expand Up @@ -402,6 +444,13 @@
animate(OT.get_filter("rage_outcry"), size = 0.12, time = 5, loop = -1)
addtimer(CALLBACK(GW, TYPE_PROC_REF(/datum, remove_filter), "rage_outcry"), 1 SECONDS)

var/multiplier = 1
if(HAS_TRAIT(owner, TRAIT_BLOODTHIRSTER))
if(X.plasma_stored >= STAGE_TWO_BLOODTHIRST)
multiplier++
if(X.plasma_stored >= STAGE_THREE_BLOODTHIRST)
multiplier++

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)
Expand All @@ -412,7 +461,7 @@

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
X.add_movespeed_modifier(MOVESPEED_ID_RAVAGER_RAGE, TRUE, 0, NONE, TRUE, X.xeno_caste.speed * (0.5 * multiplier * rage_power)) //Set rage speed bonus

//Too angry to be stunned/slowed/staggered/knocked down
ADD_TRAIT(X, TRAIT_STUNIMMUNE, RAGE_TRAIT)
Expand Down Expand Up @@ -572,3 +621,120 @@
particle_holder.pixel_y = 18
particle_holder.pixel_x = 18
timer_ref = QDEL_NULL_IN(src, particle_holder, heal_delay)

#define BLOODTHIRST_DECAY_PER_TICK 30
#define LOWEST_BLOODTHIRST_HP_ALLOWED 100
#define MAX_DAMAGE_PER_DISINTEGRATING 25

/datum/action/ability/xeno_action/bloodthirst
name = "bloodthirst"
desc = "tivi todo"
TiviPlus marked this conversation as resolved.
Show resolved Hide resolved
hidden = TRUE
///tick time of last time we attacked a human
var/last_fight_time
///time when we last hit 0 bloodthirst/plasma
var/hit_zero_time
/// delay until decaying starts
var/decay_delay = 30 SECONDS
///once bloodthirst hits 0 how long
var/damage_delay = 30 SECONDS
///used to track if effects played for disintegration start
var/disintegrating = FALSE

/datum/action/ability/xeno_action/bloodthirst/give_action(mob/living/L)
. = ..()
RegisterSignal(L, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_attack))
RegisterSignal(L, COMSIG_XENOMORPH_TAKING_DAMAGE, PROC_REF(on_take_damage))
ADD_TRAIT(L, TRAIT_BLOODTHIRSTER, TRAIT_GENERIC)
START_PROCESSING(SSprocessing, src)
last_fight_time = world.time

/datum/action/ability/xeno_action/bloodthirst/remove_action(mob/living/L)
. = ..()
REMOVE_TRAIT(L, TRAIT_BLOODTHIRSTER, TRAIT_GENERIC)
UnregisterSignal(L, list(COMSIG_XENOMORPH_ATTACK_LIVING, COMSIG_XENOMORPH_TAKING_DAMAGE))
STOP_PROCESSING(SSprocessing, src)

/// sig handler to track attacks for bloodthirst
/datum/action/ability/xeno_action/bloodthirst/proc/on_attack(datum/source, mob/living/attacked, damage)
SIGNAL_HANDLER
if(!ishuman(attacked) || attacked.stat == DEAD)
return
last_fight_time = world.time

///sig handler to track last attacked for bloodthirst
/datum/action/ability/xeno_action/bloodthirst/proc/on_take_damage(datum/source, damage)
SIGNAL_HANDLER
last_fight_time = world.time

/datum/action/ability/xeno_action/bloodthirst/process()
var/mob/living/carbon/xenomorph/xeno = owner
if(!last_fight_time) // you may live until first attack happens
return
if(last_fight_time + decay_delay > world.time)
return
if(xeno.use_plasma(BLOODTHIRST_DECAY_PER_TICK))
disintegrating = FALSE
return
if(!disintegrating)
hit_zero_time = world.time
owner.balloon_alert(owner, "disintegrating...")
xeno.playsound_local(xeno, 'sound/voice/hiss5.ogg', 50)
disintegrating = TRUE
return
if((hit_zero_time + damage_delay) < world.time)
//take damage per tick down to a minimum allowed hp
var/damage_taken = min(MAX_DAMAGE_PER_DISINTEGRATING, (xeno.health - xeno.health_threshold_crit - LOWEST_BLOODTHIRST_HP_ALLOWED))
xeno.take_overall_damage(damage_taken)


#define DEATHMARK_DAMAGE_OR_DIE 400
#define DEATHMARK_DURATION 40 SECONDS
#define DEATHMARK_MESSAGE_COOLDOWN 2 SECONDS

/datum/action/ability/xeno_action/deathmark
name = "deathmark"
desc = "Mark yourself for death, filling your bloodthirst, but failing to deal enough damage to living creatures while it is active instantly kills you."
cooldown_duration = DEATHMARK_DURATION*3
COOLDOWN_DECLARE(message_cooldown)
//tracker for damage dealt during deathmark
var/damage_dealt = 0

/datum/action/ability/xeno_action/deathmark/action_activate()
var/mob/living/carbon/xenomorph/xeno = owner
addtimer(CALLBACK(src, PROC_REF(on_deathmark_expire)), DEATHMARK_DURATION)

xeno.overlays_standing[SUIT_LAYER] = image('icons/Xeno/64x64_Xeno_overlays.dmi', icon_state = "deathmark")
xeno.apply_temp_overlay(SUIT_LAYER, DEATHMARK_DURATION)

RegisterSignal(owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_attack))
damage_dealt = 0
xeno.use_plasma(-xeno.xeno_caste.plasma_max) // fill it to the max so they can kill better
xeno.add_movespeed_modifier(MOVESPEED_ID_RAVAGER_DEATHMARK, TRUE, 0, NONE, TRUE, -1.5) //Extra speed so they can get to where to kill better
xeno.emote("roar")

/// on attack for deathmark, tracks the amount of dmg dealt
/datum/action/ability/xeno_action/deathmark/proc/on_attack(datum/source, mob/living/attacked, damage)
Copy link
Contributor

@Arturlang Arturlang Oct 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, assuming that the rav only really slashes to try to fulfill deathmark's 400 damage threshold, as COMSIG_XENOMORPH_ATTACK_LIVING outputs xeno's slash damage times whatever damage modifier it has, but I'll just assume it's 25 as it usually is, 400/25, means you need to do 16 slashes to not die, which means you'd probably have to kill two marines just to not die, unless they're incredibly tanky because of tyr 2.
Though i'm not really accounting for charge as that can multihit easily

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh 16 slashes isn't that much but might get fucky if you're focused - but full rage is really good since you well.. have full rage - FULL HEAL + temp sunder(like rage) would also be huge, but it might be bit far (but it is primo ability after all)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Means you have 2.5 seconds to do each slash or you'll simply run out of time.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think that 40 seconds is doable since you can slash prerty fast but only tm can show us - also timer in some way would be good - maybe same as time until endure/rage runs out? Screen effects too maybe? Or maybe a glowy aura changing on time - something so you aren't surprised how fast 40 seconds passed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use the screen timer thingy or do a similar thing on the mob itself

if(!ishuman(attacked) || attacked.stat == DEAD)
return
damage_dealt += damage
if(COOLDOWN_CHECK(src, message_cooldown))
var/percent_dealt = round((damage_dealt/DEATHMARK_DAMAGE_OR_DIE)*100)
owner.balloon_alert(owner, "[percent_dealt]%")
COOLDOWN_START(src, message_cooldown, DEATHMARK_MESSAGE_COOLDOWN)

/// on expire after the timer, execute the owner if they gambled bad
/datum/action/ability/xeno_action/deathmark/proc/on_deathmark_expire()
var/mob/living/carbon/xenomorph/xeno = owner
UnregisterSignal(owner, COMSIG_XENOMORPH_ATTACK_LIVING)
xeno.remove_movespeed_modifier(MOVESPEED_ID_RAVAGER_DEATHMARK)
if(damage_dealt < DEATHMARK_DAMAGE_OR_DIE)
to_chat(owner, span_highdanger("THE QUEEN MOTHER IS DISPLEASED WITH YOUR PERFORMANCE ([damage_dealt]/[DEATHMARK_DAMAGE_OR_DIE]). DEATH COMES TO TAKE ITS DUE."))
xeno.take_overall_damage(999)
var/turf/balloonloc = get_turf(xeno)
balloonloc.balloon_alert_to_viewers("JUDGEMENT")
return
xeno.playsound_local(xeno, 'sound/voice/hiss5.ogg', 50)
to_chat(owner, span_highdanger("THE QUEEN MOTHER IS PLEASED WITH YOUR PERFORMANCE ([damage_dealt]/[DEATHMARK_DAMAGE_OR_DIE])."))
owner.balloon_alert(owner, "deathmark expired")
add_cooldown()
Lumipharon marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,18 @@
/datum/action/ability/xeno_action/endure,
/datum/action/ability/xeno_action/rage,
)
var/plasma_damage_dealt_mult = 1.5
var/plasma_damage_recieved_mult = 0.5
TiviPlus marked this conversation as resolved.
Show resolved Hide resolved

/datum/xeno_caste/ravager/on_caste_applied(mob/xenomorph)
. = ..()
xenomorph.AddElement(/datum/element/plasma_on_attack, 1.5)
xenomorph.AddElement(/datum/element/plasma_on_attacked, 0.5)
xenomorph.AddElement(/datum/element/plasma_on_attack, plasma_damage_dealt_mult)
xenomorph.AddElement(/datum/element/plasma_on_attacked, plasma_damage_recieved_mult)

/datum/xeno_caste/ravager/on_caste_removed(mob/xenomorph)
. = ..()
xenomorph.RemoveElement(/datum/element/plasma_on_attack, 1.5)
xenomorph.RemoveElement(/datum/element/plasma_on_attacked, 0.5)
xenomorph.RemoveElement(/datum/element/plasma_on_attack, plasma_damage_dealt_mult)
xenomorph.RemoveElement(/datum/element/plasma_on_attacked, plasma_damage_recieved_mult)

/datum/xeno_caste/ravager/normal
upgrade = XENO_UPGRADE_NORMAL
Expand All @@ -82,3 +84,84 @@
/datum/action/ability/xeno_action/rage,
/datum/action/ability/xeno_action/vampirism,
)



/datum/xeno_caste/ravager/bloodthirster
caste_name = "Bloodthirster"
display_name = "Bloodthirster"
upgrade_name = ""
caste_desc = "A thirsting fighter that knows no rest."
caste_type_path = /mob/living/carbon/xenomorph/ravager
tier = XENO_TIER_THREE
upgrade = XENO_UPGRADE_BASETYPE
wound_type = "ravager" //used to match appropriate wound overlays

// *** Melee Attacks *** //
melee_damage = 25
melee_ap = 15
attack_delay = 7

// *** Speed *** //
speed = -1.0

// *** Plasma *** //
plasma_max = 500
plasma_gain = 0
plasma_regen_limit = 0.5 // tivi todo
plasma_icon_state = "fury"

// *** Health *** //
max_health = 400

// *** Evolution *** //
upgrade_threshold = TIER_THREE_THRESHOLD

deevolves_to = /datum/xeno_caste/hunter

// *** Flags *** //
caste_flags = CASTE_INNATE_PLASMA_REGEN|CASTE_PLASMADRAIN_IMMUNE|CASTE_EVOLUTION_ALLOWED
can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_LEADER
caste_traits = null

// *** Defense *** //
soft_armor = list(MELEE = 50, BULLET = 55, LASER = 50, ENERGY = 50, BOMB = 10, BIO = 40, FIRE = 70, ACID = 40)

// *** Minimap Icon *** //
minimap_icon = "ravager"

// *** Abilities *** //
actions = list(
/datum/action/ability/xeno_action/xeno_resting,
/datum/action/ability/xeno_action/watch_xeno,
/datum/action/ability/activable/xeno/psydrain,
/datum/action/ability/activable/xeno/charge/nocost,
/datum/action/ability/activable/xeno/ravage/nocost,
/datum/action/ability/xeno_action/endure/nocost,
/datum/action/ability/xeno_action/rage/nocost,
/datum/action/ability/xeno_action/bloodthirst,
)
plasma_damage_dealt_mult = 2
plasma_damage_recieved_mult = 0.5
TiviPlus marked this conversation as resolved.
Show resolved Hide resolved

/datum/xeno_caste/ravager/bloodthirster/normal
upgrade = XENO_UPGRADE_NORMAL

/datum/xeno_caste/ravager/bloodthirster/primordial
upgrade_name = "Primordial"
caste_desc = "A blood caked merciless killer."
primordial_message = "BLOOD FOR THE BLOOD GOD! SKULLS FOR THE SKULL THRONE!"
upgrade = XENO_UPGRADE_PRIMO

// *** Abilities *** //
actions = list(
/datum/action/ability/xeno_action/xeno_resting,
/datum/action/ability/xeno_action/watch_xeno,
/datum/action/ability/activable/xeno/psydrain,
/datum/action/ability/activable/xeno/charge/nocost,
/datum/action/ability/activable/xeno/ravage/nocost,
/datum/action/ability/xeno_action/endure/nocost,
/datum/action/ability/xeno_action/rage/nocost,
/datum/action/ability/xeno_action/bloodthirst,
/datum/action/ability/xeno_action/deathmark,
)
19 changes: 2 additions & 17 deletions code/modules/mob/living/carbon/xenomorph/castes/ravager/ravager.dm
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,5 @@
emote("roar")
to_chat(src, span_xenodanger("The heat of the fire roars in our veins! KILL! CHARGE! DESTROY!"))

// ***************************************
// *********** Ability related
// ***************************************
/mob/living/carbon/xenomorph/ravager/get_crit_threshold()
. = ..()
if(!endure)
return
var/datum/action/ability/xeno_action/endure/endure_ability = actions_by_path[/datum/action/ability/xeno_action/endure]
return endure_ability.endure_threshold

/mob/living/carbon/xenomorph/ravager/get_death_threshold()
. = ..()
if(!endure)
return
var/datum/action/ability/xeno_action/endure/endure_ability = actions_by_path[/datum/action/ability/xeno_action/endure]
return endure_ability.endure_threshold

/mob/living/carbon/xenomorph/ravager/bloodthirster
caste_base_type = /datum/xeno_caste/ravager/bloodthirster
Loading
Loading