diff --git a/code/__DEFINES/dcs/signals/signals_keybindings.dm b/code/__DEFINES/dcs/signals/signals_keybindings.dm index 15a0ee0c3f7d1..9dc44c8bed31f 100644 --- a/code/__DEFINES/dcs/signals/signals_keybindings.dm +++ b/code/__DEFINES/dcs/signals/signals_keybindings.dm @@ -142,6 +142,9 @@ #define COMSIG_XENOABILITY_CORROSIVE_ACID "xenoability_corrosive_acid" #define COMSIG_XENOABILITY_SPRAY_ACID "xenoability_spray_acid" #define COMSIG_XENOABILITY_ACID_DASH "xenoability_acid_dash" +#define COMSIG_XENOABILITY_DODGE "xenoability_dodge" +#define COMSIG_XENOABILITY_IMPALE "xenoability_impale" +#define COMSIG_XENOABILITY_TAIL_TRIP "xenoability_tail_trip" #define COMSIG_XENOABILITY_XENO_SPIT "xenoability_xeno_spit" #define COMSIG_XENOABILITY_HIDE "xenoability_hide" #define COMSIG_XENOABILITY_NEUROTOX_STING "xenoability_neurotox_sting" diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm index e62b7e8be31af..b8e4deeb20b35 100644 --- a/code/__DEFINES/movespeed_modification.dm +++ b/code/__DEFINES/movespeed_modification.dm @@ -32,6 +32,7 @@ #define MOVESPEED_ID_WARLOCK_CHANNELING "WARLOCK_CHANNELING" #define MOVESPEED_ID_XENO_DREAD "DREADXENO" #define MOVESPEED_ID_BEHEMOTH_PRIMAL_WRATH "BEHEMOTH_PRIMAL_WRATH" +#define MOVESPEED_ID_PRAETORIAN_DANCER_DODGE_SPEED "PRAETORIAN_DANCER_DODGE_SPEED" #define MOVESPEED_ID_SIMPLEMOB_VARSPEED "SIMPLEMOB_VARSPEED_MODIFIER" diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 93e24916fad5b..64fb57c8ba1af 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -74,6 +74,8 @@ #define STATUS_EFFECT_INTOXICATED /datum/status_effect/stacking/intoxicated //Damage over time +#define STATUS_EFFECT_DANCER_TAGGED /datum/status_effect/incapacitating/dancer_tagged //Additional damage/effects by Praetorian Dancer's abilities. + #define STATUS_EFFECT_REPAIR_MODE /datum/status_effect/incapacitating/repair_mode //affected is blinded and stunned, but heals over time ///damage and sunder over time #define STATUS_EFFECT_MELTING /datum/status_effect/stacking/melting diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 1acf370017593..84894e726efbb 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -93,6 +93,8 @@ GLOBAL_LIST_INIT(all_xeno_types, list( /mob/living/carbon/xenomorph/ravager/primordial, /mob/living/carbon/xenomorph/praetorian, /mob/living/carbon/xenomorph/praetorian/primordial, + /mob/living/carbon/xenomorph/praetorian/dancer, + /mob/living/carbon/xenomorph/praetorian/dancer/primordial, /mob/living/carbon/xenomorph/boiler, /mob/living/carbon/xenomorph/boiler/primordial, /mob/living/carbon/xenomorph/defiler, diff --git a/code/datums/keybinding/xeno.dm b/code/datums/keybinding/xeno.dm index 0b87b9151b542..ac844fe221578 100644 --- a/code/datums/keybinding/xeno.dm +++ b/code/datums/keybinding/xeno.dm @@ -687,6 +687,24 @@ keybind_signal = COMSIG_XENOABILITY_ACID_DASH hotkey_keys = list("E") +/datum/keybinding/xeno/dodge + name = "Dodge" + full_name = "Praetorian: Dodge" + description = "Gain a speed boost upon activation and the ability to pass through mobs. Enemies automatically receive bump attacks when passed." + keybind_signal = COMSIG_XENOABILITY_DODGE + +/datum/keybinding/xeno/impale + name = "Impale" + full_name = "Praetorian: Impale" + description = "Impale a marine next to you with your tail for moderate damage. Marked enemies are impaled twice." + keybind_signal = COMSIG_XENOABILITY_IMPALE + +/datum/keybinding/xeno/tail_trip + name = "Tail Trip" + full_name = "Praetorian: Tail Trip" + description = "Target a marine within two tiles of you to disorient and slows them. Marked enemies receive stronger debuffs and are stunned for a second." + keybind_signal = COMSIG_XENOABILITY_TAIL_TRIP + /datum/keybinding/xeno/screech name = "screech" full_name = "Queen: Screech" diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index c42fe47239a9c..7b89a51b59884 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -917,4 +917,8 @@ desc = "Space is very very cold, who would've thought?" icon_state = "cold3" - +// *************************************** +// *********** Dancer Tagged +// *************************************** +/datum/status_effect/incapacitating/dancer_tagged + id = "dancer_tagged" diff --git a/code/modules/mob/living/carbon/xenomorph/castes/praetorian/abilities_praetorian.dm b/code/modules/mob/living/carbon/xenomorph/castes/praetorian/abilities_praetorian.dm index 77fe575cfa3fe..1bd29f9713950 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/praetorian/abilities_praetorian.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/praetorian/abilities_praetorian.dm @@ -197,3 +197,206 @@ GLOBAL_LIST_INIT(acid_spray_hit, typecacheof(list(/obj/structure/barricade, /obj new /obj/effect/xenomorph/spray(get_turf(xeno_owner), 5 SECONDS, xeno_owner.xeno_caste.acid_spray_damage) //Add a modifier here to buff the damage if needed for(var/obj/O in get_turf(xeno_owner)) O.acid_spray_act(xeno_owner) + +// *************************************** +// *********** Dodge +// *************************************** +/datum/action/ability/xeno_action/dodge + name = "Dodge" + action_icon_state = "dodge" + action_icon = 'icons/Xeno/actions/praetorian.dmi' + desc = "Gain a speed boost upon activation and the ability to pass through mobs. Enemies automatically receive bump attacks when passed." + ability_cost = 100 + cooldown_duration = 12 SECONDS + use_state_flags = ABILITY_USE_BUSY + keybind_flags = ABILITY_KEYBIND_USE_ABILITY + keybinding_signals = list( + KEYBINDING_NORMAL = COMSIG_XENOABILITY_DODGE, + ) + /// The increase of speed when ability is active. + var/speed_buff = -0.4 + /// How long the ability will last? + var/duration = 6 SECONDS + +/datum/action/ability/xeno_action/dodge/action_activate(atom/A) + owner.balloon_alert(owner, "Dodge ready!") + + owner.add_movespeed_modifier(MOVESPEED_ID_PRAETORIAN_DANCER_DODGE_SPEED, TRUE, 0, NONE, TRUE, speed_buff) + owner.allow_pass_flags |= (PASS_MOB|PASS_XENO) + owner.pass_flags |= (PASS_MOB|PASS_XENO) + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + addtimer(CALLBACK(src, PROC_REF(remove_effects)), duration) + + succeed_activate() + add_cooldown() + +/// Automatically bumps living non-xenos if bump attacks are on. +/datum/action/ability/xeno_action/dodge/proc/on_move(datum/source) + if(!isxeno(owner)) + return FALSE + var/mob/living/carbon/xenomorph/xeno_owner = owner + if(xeno_owner.stat == DEAD) + return FALSE + var/datum/action/bump_attack_toggle/bump_attack_action = xeno_owner.actions_by_path[/datum/action/bump_attack_toggle] + if(bump_attack_action == null || bump_attack_action.attacking) // Bump attacks are off if attacking is true, apparently. + return FALSE + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_BUMP_ATTACK)) + return FALSE + + var/turf/current_turf = get_turf(owner) + for(var/mob/living/living_mob in current_turf) + if(living_mob.stat == DEAD) + continue + if(isxeno(living_mob)) + var/mob/living/carbon/xenomorph/xenomorph_mob = living_mob + if(owner.issamexenohive(xenomorph_mob)) + continue + xeno_owner.Bump(living_mob) + return + +/// Removes the movespeed modifier and various pass_flags that was given by the dodge ability. +/datum/action/ability/xeno_action/dodge/proc/remove_effects() + owner.balloon_alert(owner, "Dodge inactive!") + + owner.remove_movespeed_modifier(MOVESPEED_ID_PRAETORIAN_DANCER_DODGE_SPEED) + owner.allow_pass_flags &= ~(PASS_MOB|PASS_XENO) + owner.pass_flags &= ~(PASS_MOB|PASS_XENO) + UnregisterSignal(owner, COMSIG_MOVABLE_MOVED) + +// *************************************** +// *********** Impale +// *************************************** +/datum/action/ability/activable/xeno/impale + name = "Impale" + action_icon_state = "impale" + action_icon = 'icons/Xeno/actions/praetorian.dmi' + desc = "Impale a marine next to you with your tail for moderate damage. Marked enemies are impaled twice." + ability_cost = 100 + cooldown_duration = 8 SECONDS + keybinding_signals = list( + KEYBINDING_NORMAL = COMSIG_XENOABILITY_IMPALE, + ) + target_flags = ABILITY_MOB_TARGET + +/datum/action/ability/activable/xeno/impale/can_use_ability(atom/A, silent = FALSE, override_flags) + . = ..() + if(!.) + return FALSE + if(!iscarbon(A)) + if(!silent) + A.balloon_alert(owner, "cannot impale") + return FALSE + if(isxeno(A)) + var/mob/living/carbon/xenomorph/xenomorph_target = A + if(owner.issamexenohive(xenomorph_target)) + A.balloon_alert(owner, "cannot impale ally") + return FALSE + var/mob/living/carbon/carbon_target = A + if(!owner.Adjacent(carbon_target)) + carbon_target.balloon_alert(owner, "too far") + return FALSE + if(carbon_target.stat == DEAD) + carbon_target.balloon_alert(owner, "already dead") + return FALSE + +/datum/action/ability/activable/xeno/impale/use_ability(atom/target_atom) + . = ..() + + var/mob/living/carbon/xenomorph/xeno_owner = owner + if(!iscarbon(target_atom)) + return + var/mob/living/carbon/living_target = target_atom + var/buffed = living_target.has_status_effect(STATUS_EFFECT_DANCER_TAGGED) + xeno_owner.visible_message(span_danger("\The [xeno_owner] violently slices [living_target] with its tail [buffed ? "twice" : ""]!"), \ + span_danger("We slice [living_target] with our tail[buffed ? " twice" : ""]!")) + + try_impale(living_target) + if(buffed) + xeno_owner.emote("roar") + addtimer(CALLBACK(src, PROC_REF(try_impale), living_target), 0.1 SECONDS) // A short delay for animation coolness (and also if they're dead). + + succeed_activate() + add_cooldown() + +/// Performs the main effect of impale ability like animating and attacking. +/datum/action/ability/activable/xeno/impale/proc/try_impale(mob/living/carbon/living_target) + var/mob/living/carbon/xenomorph/xeno_owner = owner + var/damage = (xeno_owner.xeno_caste.melee_damage * xeno_owner.xeno_melee_damage_modifier) + xeno_owner.face_atom(living_target) + xeno_owner.do_attack_animation(living_target, ATTACK_EFFECT_REDSLASH) + xeno_owner.spin(4, 1) + playsound(living_target, get_sfx(SFX_ALIEN_TAIL_ATTACK), 30, TRUE) + if(living_target.stat != DEAD) // If they drop dead from the first impale, keep the effects but do no damage. + living_target.apply_damage(damage, BRUTE, blocked = MELEE) + +// *************************************** +// *********** Tail Trip +// *************************************** +/datum/action/ability/activable/xeno/tail_trip + name = "Tail Trip" + action_icon_state = "tail_trip" + action_icon = 'icons/Xeno/actions/praetorian.dmi' + desc = "Target a marine within two tiles of you to disorient and slows them. Marked enemies receive stronger debuffs and are stunned for a second." + ability_cost = 50 + cooldown_duration = 8 SECONDS + keybinding_signals = list( + KEYBINDING_NORMAL = COMSIG_XENOABILITY_TAIL_TRIP, + ) + target_flags = ABILITY_MOB_TARGET + +/datum/action/ability/activable/xeno/tail_trip/can_use_ability(atom/A, silent = FALSE, override_flags) + . = ..() + if(!.) + return FALSE + if(!iscarbon(A)) + if(!silent) + A.balloon_alert(owner, "cannot tail trip") + return FALSE + if(isxeno(A)) + var/mob/living/carbon/xenomorph/xenomorph_target = A + if(owner.issamexenohive(xenomorph_target)) + A.balloon_alert(owner, "cannot tail trip ally") + return FALSE + var/mob/living/carbon/carbon_target = A + if(get_dist(owner, carbon_target) > 2) + if(!silent) + carbon_target.balloon_alert(owner, "too far") + return FALSE + if(!line_of_sight(owner, carbon_target, 2)) + if(!silent) + carbon_target.balloon_alert(owner, "need line of sight") + return FALSE + if(carbon_target.stat == DEAD) + carbon_target.balloon_alert(owner, "already dead") + return FALSE + if(carbon_target.stat == UNCONSCIOUS) + carbon_target.balloon_alert(owner, "not standing") + return FALSE + +/datum/action/ability/activable/xeno/tail_trip/use_ability(atom/target_atom) + . = ..() + + var/mob/living/carbon/xenomorph/xeno_owner = owner + if(!iscarbon(target_atom)) + return + + var/mob/living/carbon/living_target = target_atom + + var/damage = (xeno_owner.xeno_caste.melee_damage * xeno_owner.xeno_melee_damage_modifier) + var/buffed = living_target.has_status_effect(STATUS_EFFECT_DANCER_TAGGED) + + xeno_owner.visible_message(span_danger("\The [xeno_owner] sweeps [living_target]'s legs with its tail!"), \ + span_danger("We trip [living_target] with our tail!")) + shake_camera(living_target, 2, 1) + xeno_owner.face_atom(living_target) + xeno_owner.spin(4, 1) + xeno_owner.emote("tail") + playsound(living_target,'sound/weapons/alien_claw_block.ogg', 50, 1) + + living_target.Paralyze(buffed ? 1 SECONDS : 0.1 SECONDS) + living_target.adjust_stagger(buffed ? 5 SECONDS : 4 SECONDS) + living_target.adjust_slowdown(buffed ? 1.2 : 0.9) + living_target.apply_damage(damage, STAMINA, updating_health = TRUE) + + succeed_activate() + add_cooldown() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/praetorian/castedatum_praetorian.dm b/code/modules/mob/living/carbon/xenomorph/castes/praetorian/castedatum_praetorian.dm index 627eb7817f8ae..a154c24acd73d 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/praetorian/castedatum_praetorian.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/praetorian/castedatum_praetorian.dm @@ -87,3 +87,59 @@ /datum/action/ability/xeno_action/pheromones/emit_warding, /datum/action/ability/xeno_action/pheromones/emit_frenzy, ) + +/datum/xeno_caste/praetorian/dancer + caste_type_path = /mob/living/carbon/xenomorph/praetorian/dancer + upgrade_name = "" + caste_name = "Dancer Praetorian" + display_name = "Praetorian" + upgrade = XENO_UPGRADE_BASETYPE + caste_desc = "A giant melee monster. It looks pretty strong." + + // +2 melee damage + melee_damage = 25 + + // Loses some common armor (-5) for more speed (-0.3). + speed = -0.8 + soft_armor = list(MELEE = 40, BULLET = 45, LASER = 45, ENERGY = 45, BOMB = 10, BIO = 40, FIRE = 45, ACID = 40) + + // Loses ranged spit abilities for close combat combo 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/xeno_action/place_acidwell, + /datum/action/ability/activable/xeno/corrosive_acid, + /datum/action/ability/xeno_action/dodge, + /datum/action/ability/activable/xeno/impale, + /datum/action/ability/activable/xeno/tail_trip, + /datum/action/ability/xeno_action/pheromones, + /datum/action/ability/xeno_action/pheromones/emit_recovery, + /datum/action/ability/xeno_action/pheromones/emit_warding, + /datum/action/ability/xeno_action/pheromones/emit_frenzy, + ) + +/datum/xeno_caste/praetorian/dancer/normal + upgrade = XENO_UPGRADE_NORMAL + +/datum/xeno_caste/praetorian/dancer/primordial + upgrade_name = "Primordial" + caste_desc = "An aberrant creature extremely proficient with its body and tail. Keep your distance if you don't wish to be finessed." + upgrade = XENO_UPGRADE_PRIMO + primordial_message = "With a flick of our tail, we dance through the shadows, striking with lethal precision." + + 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/xeno_action/place_acidwell, + /datum/action/ability/activable/xeno/corrosive_acid, + /datum/action/ability/xeno_action/dodge, + /datum/action/ability/activable/xeno/impale, + /datum/action/ability/activable/xeno/tail_trip, + /datum/action/ability/activable/xeno/charge/acid_dash, // No unique primordial ability at the moment. Replace eventually with something cooler! + /datum/action/ability/xeno_action/pheromones, + /datum/action/ability/xeno_action/pheromones/emit_recovery, + /datum/action/ability/xeno_action/pheromones/emit_warding, + /datum/action/ability/xeno_action/pheromones/emit_frenzy, + ) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/praetorian/praetorian.dm b/code/modules/mob/living/carbon/xenomorph/castes/praetorian/praetorian.dm index c442f12c193af..2eb581849953c 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/praetorian/praetorian.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/praetorian/praetorian.dm @@ -13,3 +13,16 @@ tier = XENO_TIER_THREE upgrade = XENO_UPGRADE_NORMAL bubble_icon = "alienroyal" + +/mob/living/carbon/xenomorph/praetorian/dancer + caste_base_type = /datum/xeno_caste/praetorian/dancer + +/mob/living/carbon/xenomorph/praetorian/dancer/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_XENOMORPH_POSTATTACK_LIVING, PROC_REF(on_postattack)) + +/// Applies the dancer mark status effect to those that they slash and damage. +/mob/living/carbon/xenomorph/praetorian/dancer/proc/on_postattack(mob/living/source, mob/living/target, damage) + SIGNAL_HANDLER + target.apply_status_effect(STATUS_EFFECT_DANCER_TAGGED, 4 SECONDS) + diff --git a/code/modules/mob/living/carbon/xenomorph/xenoupgrade.dm b/code/modules/mob/living/carbon/xenomorph/xenoupgrade.dm index 794afdc1a2e37..98bd4d3324840 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoupgrade.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoupgrade.dm @@ -153,6 +153,10 @@ upgrade = XENO_UPGRADE_PRIMO upgrade_stored = TIER_THREE_THRESHOLD +/mob/living/carbon/xenomorph/praetorian/dancer/primordial + upgrade = XENO_UPGRADE_PRIMO + upgrade_stored = TIER_THREE_THRESHOLD + //----PRAETORIAN END----// //================// //----RAVAGER START----// diff --git a/icons/Xeno/actions/praetorian.dmi b/icons/Xeno/actions/praetorian.dmi new file mode 100644 index 0000000000000..899c0301e6a9b Binary files /dev/null and b/icons/Xeno/actions/praetorian.dmi differ diff --git a/icons/Xeno/castes/praetorian.dmi b/icons/Xeno/castes/praetorian.dmi index 3c58bafc0aa27..9ce4213cef180 100644 Binary files a/icons/Xeno/castes/praetorian.dmi and b/icons/Xeno/castes/praetorian.dmi differ