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 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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 200
#define STAGE_THREE_BLOODTHIRST 300

// ***************************************
// *********** Charge
// ***************************************
Expand Down Expand Up @@ -29,10 +33,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++
if(X.plasma_stored >= STAGE_THREE_BLOODTHIRST)
multiplier++
Lumipharon marked this conversation as resolved.
Show resolved Hide resolved

X.throw_at(A, charge_range, 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 +84,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 @@ -123,6 +141,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 @@ -402,6 +432,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 +449,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 +609,109 @@
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"
Copy link
Contributor

Choose a reason for hiding this comment

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

hi todo

hidden = TRUE
var/last_fight_time
var/hit_zero_time
var/decay_delay = 30 SECONDS
var/damage_delay = 30 SECONDS
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)

/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

/datum/action/ability/xeno_action/bloodthirst/proc/on_take_damage(datum/source, damage)
SIGNAL_HANDLER
last_fight_time = world.time
Copy link
Contributor

Choose a reason for hiding this comment

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

autodoc and in the wrong place


/datum/action/ability/xeno_action/bloodthirst/process()
var/mob/living/carbon/xenomorph/xeno = owner
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)
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")
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
Copy link
Contributor

Choose a reason for hiding this comment

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

doc


/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 = 400
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,
/datum/action/ability/activable/xeno/ravage,
/datum/action/ability/xeno_action/endure,
/datum/action/ability/xeno_action/rage,
/datum/action/ability/xeno_action/bloodthirst,
)
plasma_damage_dealt_mult = 2
plasma_damage_recieved_mult = 0.5

/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,
/datum/action/ability/activable/xeno/ravage,
/datum/action/ability/xeno_action/endure,
/datum/action/ability/xeno_action/rage,
/datum/action/ability/xeno_action/bloodthirst,
/datum/action/ability/xeno_action/deathmark,
)
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,6 @@
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
4 changes: 4 additions & 0 deletions code/modules/mob/living/carbon/xenomorph/xenoupgrade.dm
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@
upgrade = XENO_UPGRADE_PRIMO
upgrade_stored = TIER_THREE_THRESHOLD

/mob/living/carbon/xenomorph/ravager/bloodthirster/primordial
upgrade = XENO_UPGRADE_PRIMO
upgrade_stored = TIER_THREE_THRESHOLD

//----RAVAGER END----//
//================//
//RAVAGER ERT START
Expand Down
Binary file modified icons/Xeno/64x64_Xeno_overlays.dmi
Binary file not shown.
Binary file modified icons/Xeno/actions/ravager.dmi
Binary file not shown.
Binary file modified icons/Xeno/castes/ravager.dmi
Binary file not shown.
Loading