diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 3df635790a5e2..c178353ece1cc 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -258,7 +258,7 @@
/// If the mob won't drop items held in face slot when downed
#define TRAIT_IRON_TEETH "t_iron_teeth"
-// -- ability traits --
+// -- general ability traits --
/// Xenos with this trait cannot have plasma transferred to them
#define TRAIT_ABILITY_NO_PLASMA_TRANSFER "t_ability_no_plasma_transfer"
/// Shows that the xeno queen is on ovi
@@ -267,9 +267,31 @@
#define TRAIT_ABILITY_BURROWED "t_ability_burrowed"
/// Xenos with this trait can toggle long sight while resting.
#define TRAIT_ABILITY_SIGHT_IGNORE_REST "t_ability_sight_ignore_rest"
-/// Used by shielder to check stance.
+/// Xenos with this trait cannot spit multiple times.
+#define TRAIT_ABILITY_SPITTING "t_ability_charge_spitting"
+
+
+// -- specific ability traits --
+#define TRAIT_ABILITY_POUNCE "t_ability_pounce"
+#define TRAIT_ABILITY_ASSASINATE "t_ability_assasinate"
+#define TRAIT_ABILITY_INVIS "t_ability_invis"
+#define TRAIT_ABILITY_LUNGE "t_ability_lunge"
+#define TRAIT_ABILITY_BURROW_DIGGING "t_ability_burrow_digging"
+#define TRAIT_ABILITY_BURROW_UNDERGROUND "t_ability_burrow_underground"
+#define TRAIT_ABILITY_CREST "t_ability_burrower_crest"
+#define TRAIT_ABILITY_FORTIFY "t_ability_fortify"
+#define TRAIT_ABILITY_POUNCE_CHARGE "t_ability_pounce_charge"
+#define TRAIT_ABILITY_PRE_EMPOWER "t_ability_pre_empower"
+#define TRAIT_ABILITY_EMPOWER "t_ability_empower"
+#define TRAIT_ABILITY_CATALYZE_EMPOWER "t_ability_catalyze_empower"
+#define TRAIT_ABILITY_CLEAVE_ROOT "t_ability_cleave_root"
+#define TRAIT_ABILITY_CLEAVE_BUFFED "t_ability_cleave_buffed"
+#define TRAIT_ABILITY_PRE_DASH "t_ability_pre_dash"
+#define TRAIT_ABILITY_DODGE "t_ability_dodge"
+#define TRAIT_ABILITY_RED_TAG "t_ability_red_tag"
+#define TRAIT_ABILITY_YELLOW_TAG "t_ability_yellow_tag"
+#define TRAIT_ABILITY_SHED_SPIKES "t_ability_shed_spikes"
#define TRAIT_ABILITY_ENCLOSED_PLATES "t_ability_enclosed_plates"
-/// Used by shielder for reflective plates.
#define TRAIT_ABILITY_REFLECTIVE_PLATES "t_ability_reflective_plates"
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 05c0dfc563ff8..ebea5c56e83f0 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -89,6 +89,7 @@
if(!new_maptext)
return
maptext_overlay = image(null, null, null, layer + 0.1)
+ maptext_overlay.appearance_flags |= RESET_COLOR
maptext_overlay.maptext = new_maptext
if(new_maptext_x)
maptext_overlay.maptext_x = new_maptext_x
diff --git a/code/datums/action.dm b/code/datums/action.dm
index ad77899663428..3ab28917e559c 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -663,3 +663,5 @@
if(reload_screen)
client.add_to_screen(hud_used.hide_actions_toggle)
+#define XENO_ACTION_CHECK(X) if(!X.check_state() || !action_cooldown_check() || !check_plasma_owner(src.plasma_cost)) return
+#define XENO_ACTION_CHECK_USE_PLASMA(X) if(!X.check_state() || !action_cooldown_check() || !check_and_use_plasma_owner(src.plasma_cost)) return
diff --git a/code/modules/mob/living/carbon/xenomorph/Evolution.dm b/code/modules/mob/living/carbon/xenomorph/Evolution.dm
index ff5348756c8ae..4e26134fe77fa 100644
--- a/code/modules/mob/living/carbon/xenomorph/Evolution.dm
+++ b/code/modules/mob/living/carbon/xenomorph/Evolution.dm
@@ -285,7 +285,7 @@ GLOBAL_LIST_EMPTY(deevolved_ckeys)
to_chat(src, SPAN_WARNING("We must be at full health to evolve."))
return FALSE
- if(fortify || crest_defense || stealth || HAS_TRAIT(src, TRAIT_ABILITY_ENCLOSED_PLATES) || HAS_TRAIT(src, TRAIT_ABILITY_REFLECTIVE_PLATES))
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY) || HAS_TRAIT(src, TRAIT_ABILITY_CREST) || HAS_TRAIT(src, TRAIT_ABILITY_INVIS) || HAS_TRAIT(src, TRAIT_ABILITY_ENCLOSED_PLATES) || HAS_TRAIT(src, TRAIT_ABILITY_REFLECTIVE_PLATES))
to_chat(src, SPAN_WARNING("We cannot evolve while in this stance."))
return FALSE
@@ -326,7 +326,7 @@ GLOBAL_LIST_EMPTY(deevolved_ckeys)
if(tier == 0 || tier == 4)
to_chat(src, SPAN_XENOWARNING("We can't transmute."))
return
- if(fortify || crest_defense || stealth)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY) || HAS_TRAIT(src, TRAIT_ABILITY_CREST) || HAS_TRAIT(src, TRAIT_ABILITY_INVIS) || HAS_TRAIT(src, TRAIT_ABILITY_ENCLOSED_PLATES) || HAS_TRAIT(src, TRAIT_ABILITY_REFLECTIVE_PLATES))
to_chat(src, SPAN_XENOWARNING("We can't transmute while in this stance."))
return
if(lock_evolve)
diff --git a/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm b/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm
index 816ba1fb8c7f4..b8356f5aefdf3 100644
--- a/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm
+++ b/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm
@@ -24,6 +24,9 @@
if(..())
return TRUE
+ if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
+ return
+
switch(M.a_intent)
if(INTENT_HELP)
@@ -109,7 +112,7 @@
//Hot hot Aliens on Aliens action.
//Actually just used for eating people.
/mob/living/carbon/xenomorph/attack_alien(mob/living/carbon/xenomorph/xeno)
- if(xeno.fortify || HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED) || HAS_TRAIT(xeno, TRAIT_ABILITY_REFLECTIVE_PLATES))
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY) || HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
return XENO_NO_DELAY_ACTION
if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
index ce4d8f9c4af50..28024c8522f50 100644
--- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
+++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
@@ -293,11 +293,6 @@
//
//////////////////////////////////////////////////////////////////
- var/tunnel = FALSE
- /// for check on lurker invisibility
- var/stealth = FALSE
- var/fortify = FALSE
- var/crest_defense = FALSE
/// For drones/hivelords. Extends the maximum build range they have
var/extra_build_dist = 0
/// tiles from self you can plant eggs.
@@ -362,14 +357,6 @@
// Vars that should be deleted
//
//////////////////////////////////////////////////////////////////
- var/burrow_timer = 200
- var/tunnel_timer = 20
-
- //Burrower Vars
- var/used_tremor = 0
- // Burrowers
- var/used_burrow = 0
- var/used_tunnel = 0
//Taken from update_icon for all xeno's
var/list/overlays_standing[X_TOTAL_LAYERS]
@@ -827,7 +814,7 @@
return TRUE
playsound(puller.loc, 'sound/weapons/pierce.ogg', 25, 1)
puller.visible_message(SPAN_WARNING("[puller] tried to pull [src] but instead gets a tail swipe to the head!"))
- if(stealth)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_INVIS))
puller.apply_effect(caste.tacklestrength_min, WEAKEN)
return FALSE
puller.apply_effect(rand(caste.tacklestrength_min,caste.tacklestrength_max), WEAKEN)
@@ -854,7 +841,6 @@
pulledby.stop_pulling()
. = 1
-
/mob/living/carbon/xenomorph/proc/rename_tunnel(obj/structure/tunnel/tunnel_target in oview(1))
set name = "Rename Tunnel"
set desc = "Rename the tunnel."
@@ -872,7 +858,6 @@
tunnel_target.tunnel_desc = "[new_name]"
return
-
/mob/living/carbon/xenomorph/prepare_huds()
..()
//updating all the mob's hud images
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm
index 0ea27be28d18d..933bd6effe86c 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm
@@ -8,17 +8,12 @@
action_type = XENO_ACTION_CLICK
ability_primacy = XENO_PRIMARY_ACTION_3
-/datum/action/xeno_action/activable/burrow/use_ability(atom/A)
- var/mob/living/carbon/xenomorph/xenomorph = owner
+ var/used_digging = FALSE
+ var/digging_timer = 2 SECONDS
+ var/burrow_timer = 20 SECONDS
- if(!action_cooldown_check())
- return
-
- if(HAS_TRAIT(xenomorph, TRAIT_ABILITY_BURROWED))
- xenomorph.tunnel(get_turf(A))
- else
- xenomorph.burrow()
- return ..()
+ var/burrow_cooldown = 2 SECONDS
+ var/digging_cooldown = 7 SECONDS
/datum/action/xeno_action/onclick/tremor
name = "Tremor (100)"
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/carrier/carrier_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/carrier/carrier_abilities.dm
index ed9ad321ce4b0..c4add8fcc7d91 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/carrier/carrier_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/carrier/carrier_abilities.dm
@@ -5,12 +5,6 @@
action_type = XENO_ACTION_CLICK
ability_primacy = XENO_PRIMARY_ACTION_3
-/datum/action/xeno_action/activable/throw_hugger/action_cooldown_check()
- if(owner)
- var/mob/living/carbon/xenomorph/carrier/alien = owner
- return world.time >= alien.hugger_throw_cooldown // i think
- return TRUE //When we first add the ability we still do this check, but owner is null, so a workaround
-
/datum/action/xeno_action/activable/retrieve_egg
name = "Retrieve Egg"
action_icon_state = "retrieve_egg"
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/crusher/crusher_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/crusher/crusher_abilities.dm
index eae9b09a18551..5bdd9d05646ee 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/crusher/crusher_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/crusher/crusher_abilities.dm
@@ -24,14 +24,6 @@
// Object types that don't reduce cooldown when hit
var/list/not_reducing_objects = list()
-
-/datum/action/xeno_action/activable/pounce/crusher_charge/New()
- . = ..()
- not_reducing_objects = typesof(/obj/structure/barricade) + typesof(/obj/structure/machinery/defenses)
-
-/datum/action/xeno_action/activable/pounce/crusher_charge/initialize_pounce_pass_flags()
- pounce_pass_flags = PASS_CRUSHER_CHARGE
-
/datum/action/xeno_action/onclick/crusher_stomp
name = "Stomp"
action_icon_state = "stomp"
@@ -119,137 +111,6 @@
var/momentum = 0
-/datum/action/xeno_action/onclick/charger_charge/proc/handle_position_change(mob/living/carbon/xenomorph/xeno, body_position)
- SIGNAL_HANDLER
- if(body_position == LYING_DOWN)
- handle_movement(xeno)
-
-/datum/action/xeno_action/onclick/charger_charge/proc/handle_movement(mob/living/carbon/xenomorph/Xeno, atom/oldloc, dir, forced)
- SIGNAL_HANDLER
- if(Xeno.pulling)
- if(!momentum)
- steps_taken = 0
- return
- else
- Xeno.stop_pulling()
-
- if(Xeno.is_mob_incapacitated())
- if(!momentum)
- return
- var/distance_to_throw = get_ranged_target_turf(Xeno, charge_dir, momentum/2)
- INVOKE_ASYNC(Xeno, TYPE_PROC_REF(/atom/movable, throw_atom), distance_to_throw, momentum/2, SPEED_FAST, null, TRUE)
- stop_momentum()
- return
- if(!isturf(Xeno.loc))
- stop_momentum()
- return
- // Don't build up charge if you move via getting propelled by something
- if(Xeno.throwing)
- stop_momentum()
- return
-
- var/do_stop_momentum = FALSE
-
- // Need to be constantly moving in order to maintain charge
- if(world.time > last_charge_move + 0.5 SECONDS)
- do_stop_momentum = TRUE
- if(dir != charge_dir)
- charge_dir = dir
- do_stop_momentum = TRUE
-
- if(do_stop_momentum)
- stop_momentum()
- if(Xeno.plasma_stored <= plasma_per_step)
- stop_momentum()
- return
- last_charge_move = world.time
- steps_taken++
- if(steps_taken < steps_to_charge)
- return
- if(momentum < max_momentum)
- momentum++
- ADD_TRAIT(Xeno, TRAIT_CHARGING, TRAIT_SOURCE_XENO_ACTION_CHARGE)
- Xeno.update_icons()
- if(momentum == max_momentum)
- Xeno.emote("roar")
- //X.use_plasma(plasma_per_step) // take if you are in toggle charge mode
- if(momentum > 0)
- Xeno.use_plasma(plasma_per_step) // take plasma when you have momentum
-
- noise_timer = noise_timer ? --noise_timer : 3
- if(noise_timer == 3)
- playsound(Xeno, 'sound/effects/alien_footstep_charge1.ogg', 50)
-
- for(var/mob/living/carbon/human/Mob in Xeno.loc)
- if(Mob.body_position == LYING_DOWN && Mob.stat != DEAD)
- Xeno.visible_message(SPAN_DANGER("[Xeno] runs [Mob] over!"),
- SPAN_DANGER("We run [Mob] over!")
- )
- var/ram_dir = pick(get_perpen_dir(Xeno.dir))
- var/dist = 1
- if(momentum == max_momentum)
- dist = momentum * 0.25
- step(Mob, ram_dir, dist)
- Mob.take_overall_armored_damage(momentum * 6)
- INVOKE_ASYNC(Mob, TYPE_PROC_REF(/mob/living/carbon/human, emote),"pain")
- shake_camera(Mob, 7,3)
- animation_flash_color(Mob)
-
- Xeno.recalculate_speed()
-
-/datum/action/xeno_action/onclick/charger_charge/proc/handle_dir_change(datum/source, old_dir, new_dir)
- SIGNAL_HANDLER
- if(new_dir != charge_dir)
- charge_dir = new_dir
- if(momentum)
- stop_momentum()
-
-/datum/action/xeno_action/onclick/charger_charge/proc/handle_river(datum/source, covered)
- SIGNAL_HANDLER
- if(!covered)
- stop_momentum()
-
-/datum/action/xeno_action/onclick/charger_charge/proc/update_speed(mob/living/carbon/xenomorph/Xeno)
- SIGNAL_HANDLER
- Xeno.speed += momentum * speed_per_momentum
-
-/datum/action/xeno_action/onclick/charger_charge/proc/stop_momentum(datum/source)
- SIGNAL_HANDLER
- var/mob/living/carbon/xenomorph/Xeno = owner
- if(momentum == max_momentum)
- Xeno.visible_message(SPAN_DANGER("[Xeno] skids to a halt!"))
-
- REMOVE_TRAIT(Xeno, TRAIT_CHARGING, TRAIT_SOURCE_XENO_ACTION_CHARGE)
- steps_taken = 0
- momentum = 0
- Xeno.recalculate_speed()
- Xeno.update_icons()
-
-/datum/action/xeno_action/onclick/charger_charge/proc/lose_momentum(amount)
- if(amount >= momentum)
- stop_momentum()
- else
- momentum -= amount
- var/mob/living/carbon/xenomorph/Xeno = owner
- Xeno.recalculate_speed()
-
-/datum/action/xeno_action/onclick/charger_charge/proc/handle_collision(mob/living/carbon/xenomorph/Xeno, atom/tar)
- SIGNAL_HANDLER
- if(!momentum)
- stop_momentum()
- return
-
- var/result = tar.handle_charge_collision(Xeno, src)
- switch(result)
- if(XENO_CHARGE_TRY_MOVE)
- if(step(Xeno, charge_dir))
- return COMPONENT_LIVING_COLLIDE_HANDLED
-
-/datum/action/xeno_action/onclick/charger_charge/proc/start_charging(datum/source)
- SIGNAL_HANDLER
- steps_taken = steps_to_charge
-
-
/datum/action/xeno_action/activable/tumble
name = "Tumble"
action_icon_state = "tumble"
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm
index 13cacd7929595..e92eccd9393fb 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm
@@ -261,6 +261,21 @@
/datum/action/xeno_action/activable/pounce/proc/pre_pounce_effects()
return
+/**
+ * Effects to apply before "thrown" xeno to choosen tile.
+ */
+/datum/action/xeno_action/activable/pounce/proc/start_airbone()
+ return
+
+/**
+ * Effects to apply after xeno is "thrown" to choosen tile.
+ */
+/datum/action/xeno_action/activable/pounce/proc/end_airbone()
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_POUNCE))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_POUNCE, TRAIT_SOURCE_ABILITY("pounce"))
+
/datum/action/xeno_action/activable/pounce/proc/end_pounce_freeze()
if(freeze_timer_id == TIMER_ID_NULL)
return
@@ -461,8 +476,6 @@
no_cooldown_msg = TRUE // Currently [14.6.25], every xeno that uses this save Boiler has a cooldown far too fast for messages to be worth it
ability_uses_acid_overlay = TRUE
- /// Var that keeps track of in-progress wind-up spits like Bombard to prevent spitting multiple spits at the same time
- var/spitting = FALSE
var/sound_to_play = "acid_spit"
var/aim_turf = FALSE
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm
index ec981e3d9ce13..170ba0b96150d 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm
@@ -3,12 +3,11 @@
// and abilities files hold the object declarations for the abilities
// Plant weeds
-/datum/action/xeno_action/onclick/plant_weeds/use_ability(atom/atom)
+/datum/action/xeno_action/onclick/plant_weeds/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if(!action_cooldown_check())
- return
- if(!xeno.check_state())
- return
+
+ XENO_ACTION_CHECK(xeno)
+
if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
return
@@ -70,8 +69,7 @@
to_chat(xeno, SPAN_XENOWARNING("It's too early to spread the hive this far."))
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
var/list/to_convert
if(node)
@@ -98,7 +96,7 @@
to_chat(src, SPAN_WARNING("No time to rest, must KILL!"))
return
- if(fortify)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY))
to_chat(src, SPAN_WARNING("We cannot rest while fortified!"))
return
@@ -106,7 +104,7 @@
to_chat(src, SPAN_WARNING("We cannot rest while burrowed!"))
return
- if(crest_defense)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_CREST))
to_chat(src, SPAN_WARNING("We cannot rest while our crest is down!"))
return
@@ -128,17 +126,16 @@
return ..()
-/datum/action/xeno_action/onclick/xeno_resting/use_ability(atom/target)
+/datum/action/xeno_action/onclick/xeno_resting/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
xeno.lay_down()
button.icon_state = xeno.resting ? "template_active" : "template_xeno"
return ..()
// Shift spits
-/datum/action/xeno_action/onclick/shift_spits/use_ability(atom/atom)
+/datum/action/xeno_action/onclick/shift_spits/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if(!xeno.check_state())
- return
+ XENO_ACTION_CHECK(xeno)
for(var/i in 1 to length(xeno.caste.spit_types))
if(xeno.ammo == GLOB.ammo_list[xeno.caste.spit_types[i]])
if(i == length(xeno.caste.spit_types))
@@ -151,10 +148,10 @@
button.overlays += image('icons/mob/hud/actions_xeno.dmi', button, "shift_spit_[xeno.ammo.icon_state]")
return ..()
-/datum/action/xeno_action/onclick/release_haul/use_ability(atom/atom)
+/datum/action/xeno_action/onclick/release_haul/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if(!xeno.check_state())
- return
+
+ XENO_ACTION_CHECK(xeno)
if(!isturf(xeno.loc))
to_chat(xeno, SPAN_WARNING("We cannot put them down here."))
@@ -167,11 +164,10 @@
/datum/action/xeno_action/onclick/release_haul/can_use_action()
return TRUE //we should always be able to do this
-/datum/action/xeno_action/onclick/choose_resin/use_ability(atom/atom)
+/datum/action/xeno_action/onclick/choose_resin/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if(!xeno.check_state())
- return
+ XENO_ACTION_CHECK(xeno)
tgui_interact(xeno)
return ..()
@@ -190,13 +186,13 @@
var/list/constructions = list()
for(var/type in xeno.resin_build_order)
var/list/entry = list()
- var/datum/resin_construction/RC = GLOB.resin_constructions_list[type]
+ var/datum/resin_construction/resin_const = GLOB.resin_constructions_list[type]
- entry["name"] = RC.name
- entry["desc"] = RC.desc
- entry["image"] = replacetext(RC.construction_name, " ", "-")
- entry["plasma_cost"] = RC.cost
- entry["max_per_xeno"] = RC.max_per_xeno
+ entry["name"] = resin_const.name
+ entry["desc"] = resin_const.desc
+ entry["image"] = replacetext(resin_const.construction_name, " ", "-")
+ entry["plasma_cost"] = resin_const.cost
+ entry["max_per_xeno"] = resin_const.max_per_xeno
entry["id"] = "[type]"
constructions += list(entry)
@@ -257,21 +253,21 @@
button.overlays += image('icons/mob/hud/xeno_building.dmi', button, resin_construction.construction_name)
// Resin
-/datum/action/xeno_action/activable/secrete_resin/use_ability(atom/target)
+/datum/action/xeno_action/activable/secrete_resin/use_ability(atom/target_atom)
if(!..())
return FALSE
var/mob/living/carbon/xenomorph/xeno_owner = owner
- if(isstorage(target.loc))
+ if(isstorage(target_atom.loc))
return FALSE
- if(xeno_owner.contains(target))
+ if(xeno_owner.contains(target_atom))
return FALSE
- if(istype(target, /atom/movable/screen))
+ if(istype(target_atom, /atom/movable/screen))
return FALSE
- if(!SSmapping.same_z_map(target.z, xeno_owner.z))
+ if(!SSmapping.same_z_map(target_atom.z, xeno_owner.z))
to_chat(owner, SPAN_XENOWARNING("This area is too far away to affect!"))
return
apply_cooldown()
- switch(xeno_owner.build_resin(target, thick, make_message, plasma_cost != 0, build_speed_mod))
+ switch(xeno_owner.build_resin(target_atom, thick, make_message, plasma_cost != 0, build_speed_mod))
if(SECRETE_RESIN_INTERRUPT)
if(xeno_cooldown || xeno_cooldown_interrupt_penalty)
apply_cooldown_override(xeno_cooldown + xeno_cooldown_interrupt_penalty)
@@ -284,27 +280,26 @@
// leader Marker
-/datum/action/xeno_action/activable/info_marker/use_ability(atom/atom, mods)
+/datum/action/xeno_action/activable/info_marker/use_ability(atom/target_atom, mods)
+ var/mob/living/carbon/xenomorph/xeno = owner
if(!..())
return FALSE
if(mods[CLICK_CATCHER])
return
- if(!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(xeno)
- var/mob/living/carbon/xenomorph/xeno = owner
if(!xeno.check_state(TRUE))
- return FALSE
+ return
- if(ismob(atom)) //anticheese : if they click a mob, it will cancel.
+ if(ismob(target_atom)) //anticheese : if they click a mob, it will cancel.
to_chat(xeno, SPAN_XENOWARNING("We can't place resin markers on living things!"))
return FALSE //this is because xenos have thermal vision and can see mobs through walls - which would negate not being able to place them through walls
- if(isstorage(atom.loc) || xeno.contains(atom) || istype(atom, /atom/movable/screen))
+ if(isstorage(target_atom.loc) || xeno.contains(target_atom) || istype(target_atom, /atom/movable/screen))
return FALSE
- var/turf/target_turf = get_turf(atom)
+ var/turf/target_turf = get_turf(target_atom)
if(!SSmapping.same_z_map(xeno.loc.z, target_turf.loc.z))
to_chat(xeno, SPAN_XENOWARNING("Our mind cannot reach that far."))
@@ -316,24 +311,24 @@
var/tally = 0
- for(var/obj/effect/alien/resin/marker/MRK in xeno.hive.resin_marks)
- if(MRK.createdby == xeno.nicknumber)
+ for(var/obj/effect/alien/resin/marker/target_marker in xeno.hive.resin_marks)
+ if(target_marker.createdby == xeno.nicknumber)
tally++
if(tally >= max_markers)
to_chat(xeno, SPAN_XENOWARNING("We have reached the maximum number of resin marks."))
var/list/promptlist = list("Yes", "No")
- var/obj/effect/alien/resin/marker/Goober = null
+ var/obj/effect/alien/resin/marker/target_marker = null
var/promptuser = null
for(var/i=1, i<=length(xeno.hive.resin_marks))
- Goober = xeno.hive.resin_marks[i]
- if(Goober.createdby == xeno.nicknumber)
- promptuser = tgui_input_list(xeno, "Remove oldest placed mark: '[Goober.mark_meaning.name]!'?", "Mark limit reached.", promptlist, theme="hive_status")
+ target_marker = xeno.hive.resin_marks[i]
+ if(target_marker.createdby == xeno.nicknumber)
+ promptuser = tgui_input_list(xeno, "Remove oldest placed mark: '[target_marker.mark_meaning.name]!'?", "Mark limit reached.", promptlist, theme="hive_status")
break
i++
if(promptuser == "No")
return
else if(promptuser == "Yes")
- qdel(Goober)
+ qdel(target_marker)
if(xeno.make_marker(target_turf))
apply_cooldown()
return TRUE
@@ -344,10 +339,10 @@
// Destructive Acid
-/datum/action/xeno_action/activable/corrosive_acid/use_ability(atom/target)
+/datum/action/xeno_action/activable/corrosive_acid/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- xeno.corrosive_acid(target, acid_type, acid_plasma_cost)
- for(var/obj/item/explosive/plastic/explosive in target.contents)
+ xeno.corrosive_acid(target_atom, acid_type, acid_plasma_cost)
+ for(var/obj/item/explosive/plastic/explosive in target_atom.contents)
xeno.corrosive_acid(explosive,acid_type,acid_plasma_cost)
return ..()
@@ -357,17 +352,17 @@
/// Attempt to fill the target trap (called when xeno attacks with an empty hand)
/// Returns TRUE if the trap was filled
-/mob/living/carbon/xenomorph/proc/try_fill_trap(obj/effect/alien/resin/trap/target)
- if(!istype(target))
+/mob/living/carbon/xenomorph/proc/try_fill_trap(obj/effect/alien/resin/trap/target_trap)
+ if(!istype(target_trap))
return FALSE
if(!acid_level)
- to_chat(src, SPAN_XENONOTICE("You can't secrete any acid into [target]."))
+ to_chat(src, SPAN_XENONOTICE("You can't secrete any acid into [target_trap]."))
return FALSE
var/trap_acid_level = 0
- if(target.trap_type >= RESIN_TRAP_ACID1)
- trap_acid_level = 1 + target.trap_type - RESIN_TRAP_ACID1
+ if(target_trap.trap_type >= RESIN_TRAP_ACID1)
+ trap_acid_level = 1 + target_trap.trap_type - RESIN_TRAP_ACID1
if(trap_acid_level >= acid_level)
to_chat(src, SPAN_XENONOTICE("It already has good acid in."))
@@ -388,8 +383,8 @@
if(!do_after(src, 3 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE, src))
return FALSE
- if(target.trap_type >= RESIN_TRAP_ACID1)
- trap_acid_level = 1 + target.trap_type - RESIN_TRAP_ACID1
+ if(target_trap.trap_type >= RESIN_TRAP_ACID1)
+ trap_acid_level = 1 + target_trap.trap_type - RESIN_TRAP_ACID1
if(trap_acid_level >= acid_level)
return FALSE
@@ -399,11 +394,11 @@
use_plasma(acid_cost)
- target.cause_data = create_cause_data("resin acid trap", src)
- target.setup_tripwires()
- target.set_state(RESIN_TRAP_ACID1 + acid_level - 1)
+ target_trap.cause_data = create_cause_data("resin acid trap", src)
+ target_trap.setup_tripwires()
+ target_trap.set_state(RESIN_TRAP_ACID1 + acid_level - 1)
- playsound(target, 'sound/effects/refill.ogg', 25, 1)
+ playsound(target_trap, 'sound/effects/refill.ogg', 25, 1)
visible_message(SPAN_XENOWARNING("[src] pressurises the resin trap with acid!"),
SPAN_XENOWARNING("You pressurise the resin trap with acid!"), null, 5)
return TRUE
@@ -412,7 +407,7 @@
#undef ACID_COST_LEVEL_2
#undef ACID_COST_LEVEL_3
-/datum/action/xeno_action/onclick/emit_pheromones/use_ability(atom/target)
+/datum/action/xeno_action/onclick/emit_pheromones/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
if(!istype(xeno))
return
@@ -439,7 +434,7 @@
if(pheromone == "help")
to_chat(src, SPAN_NOTICE("
Pheromones provide a buff to all Xenos in range at the cost of some stored plasma every second, as follows:
Frenzy - Increased run speed, damage and chance to knock off headhunter masks.
Warding - While in critical state, increased maximum negative health and slower off weed bleedout.
Recovery - Increased plasma and health regeneration.
"))
return
- if(!pheromone || pheromone == "cancel" || current_aura || !check_state(1)) //If they are stacking windows, disable all input
+ if(!pheromone || pheromone == "cancel" || current_aura || !check_state(TRUE)) //If they are stacking windows, disable all input
return
else
var/static/list/phero_selections = list("Help" = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_help"), "Frenzy" = image(icon = 'icons/mob/radial.dmi', icon_state = "phero_frenzy"), "Warding" = image(icon = 'icons/mob/radial.dmi', icon_state = "phero_warding"), "Recovery" = image(icon = 'icons/mob/radial.dmi', icon_state = "phero_recov"))
@@ -447,7 +442,7 @@
if(pheromone == "help")
to_chat(src, SPAN_XENONOTICE("
Pheromones provide a buff to all Xenos in range at the cost of some stored plasma every second, as follows:
Frenzy (Red) - Increased run speed, damage and chance to knock off headhunter masks.
Warding (Green) - While in critical state, increased maximum negative health and slower off weed bleedout.
Recovery (Blue) - Increased plasma and health regeneration.
"))
return
- if(!pheromone || current_aura || !check_state(1)) //If they are stacking windows, disable all input
+ if(!pheromone || current_aura || !check_state(TRUE)) //If they are stacking windows, disable all input
return
if(pheromone)
if(pheromone == current_aura)
@@ -464,37 +459,35 @@
playsound(loc, "alien_drool", 25)
if(isqueen(src) && hive && length(hive.xeno_leader_list) && anchored)
- for(var/mob/living/carbon/xenomorph/L in hive.xeno_leader_list)
- L.handle_xeno_leader_pheromones()
+ for(var/mob/living/carbon/xenomorph/leader_xeno in hive.xeno_leader_list)
+ leader_xeno.handle_xeno_leader_pheromones()
-/datum/action/xeno_action/activable/pounce/use_ability(atom/target)
+/datum/action/xeno_action/activable/pounce/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if(!action_cooldown_check())
+ if(!istype(xeno))
return
- if(!target)
+ XENO_ACTION_CHECK(xeno)
+
+ if(!target_atom)
return
- while(istype(target, /turf/open_space))
- target = SSmapping.get_turf_below(target)
+ while(istype(target_atom, /turf/open_space))
+ target_atom = SSmapping.get_turf_below(target_atom)
- if(target.layer >= FLY_LAYER)//anything above that shouldn't be pounceable (hud stuff)
+ if(target_atom.layer >= FLY_LAYER)//anything above that shouldn't be pounceable (hud stuff)
return
if(!isturf(xeno.loc))
to_chat(xeno, SPAN_XENOWARNING("We can't [action_text] from here!"))
return
- if(!xeno.check_state())
- return
-
if(xeno.legcuffed)
to_chat(xeno, SPAN_XENODANGER("We can't [action_text] with that thing on our leg!"))
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
if(xeno.layer == XENO_HIDING_LAYER) //Xeno is currently hiding, unhide him
var/datum/action/xeno_action/onclick/xenohide/hide = get_action(xeno, /datum/action/xeno_action/onclick/xenohide)
@@ -504,13 +497,13 @@
if(isravager(xeno))
xeno.emote("roar")
- if (!tracks_target)
- target = get_turf(target)
+ if(!tracks_target)
+ target_atom = get_turf(target_atom)
//everyone gets (extra) timer to pounce up
- if(target.z != xeno.z)
- var/maximum_z = max(target.z, xeno.z)
- var/list/turf/path = get_line(locate(xeno.x, xeno.y, maximum_z), locate(target.x, target.y, maximum_z))
+ if(target_atom.z != xeno.z)
+ var/maximum_z = max(target_atom.z, xeno.z)
+ var/list/turf/path = get_line(locate(xeno.x, xeno.y, maximum_z), locate(target_atom.x, target_atom.y, maximum_z))
for(var/turf/turf_in_path in path)
while(istype(turf_in_path, /turf/open_space))
turf_in_path = SSmapping.get_turf_below(turf_in_path)
@@ -524,43 +517,45 @@
to_chat(xeno, SPAN_WARNING("You can't jump over an object in your path."))
return
- if (!do_after(xeno, 0.5 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
+ if(!do_after(xeno, 0.5 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
return
- if(target.z != xeno.z && xeno.mob_size >= MOB_SIZE_BIG)
- if (!do_after(xeno, 2 SECONDS, INTERRUPT_ALL, BUSY_ICON_HOSTILE))
+ if(target_atom.z != xeno.z && xeno.mob_size >= MOB_SIZE_BIG)
+ if(!do_after(xeno, 2 SECONDS, INTERRUPT_ALL, BUSY_ICON_HOSTILE))
return
apply_cooldown()
- if (windup)
- xeno.set_face_dir(get_cardinal_dir(xeno, target))
- if (!windup_interruptable)
+ if(windup)
+ xeno.set_face_dir(get_cardinal_dir(xeno, target_atom))
+ if(!windup_interruptable)
ADD_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Pounce"))
xeno.anchored = TRUE
pre_windup_effects()
- if (!do_after(xeno, windup_duration, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
+ if(!do_after(xeno, windup_duration, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
to_chat(xeno, SPAN_XENODANGER("We cancel our [action_text]!"))
- if (!windup_interruptable)
+ if(!windup_interruptable)
REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Pounce"))
xeno.anchored = FALSE
post_windup_effects(interrupted = TRUE)
return
- if (!windup_interruptable)
+ if(!windup_interruptable)
REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Pounce"))
xeno.anchored = FALSE
post_windup_effects()
- xeno.visible_message(SPAN_XENOWARNING("[xeno] [action_text][findtext(action_text, "e", -1) || findtext(action_text, "p", -1) ? "s" : "es"] at [target]!"), SPAN_XENOWARNING("We [action_text] at [target]!"))
+ xeno.visible_message(SPAN_XENOWARNING("[xeno] [action_text][findtext(action_text, "e", -1) || findtext(action_text, "p", -1) ? "s" : "es"] at [target_atom]!"), SPAN_XENOWARNING("We [action_text] at [target_atom]!"))
pre_pounce_effects()
- xeno.pounce_distance = get_dist(xeno, target)
- if(xeno.z != target.z)
+ xeno.pounce_distance = get_dist(xeno, target_atom)
+ if(xeno.z != target_atom.z)
xeno.pounce_distance += 2
- xeno.throw_atom(target, distance, throw_speed, xeno, launch_type = LOW_LAUNCH, pass_flags = pounce_pass_flags, collision_callbacks = pounce_callbacks, tracking=TRUE)
+ start_airbone()
+ xeno.throw_atom(target_atom, distance, throw_speed, xeno, launch_type = LOW_LAUNCH, pass_flags = pounce_pass_flags, collision_callbacks = pounce_callbacks, tracking=TRUE)
+ end_airbone()
xeno.update_icons()
additional_effects_always()
@@ -569,59 +564,51 @@
return TRUE
// Massive, customizable spray_acid
-/datum/action/xeno_action/activable/spray_acid/use_ability(atom/atom)
+/datum/action/xeno_action/activable/spray_acid/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if(!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(xeno)
- if(!atom)
+ if(!target_atom)
return
- if(atom.layer >= FLY_LAYER)
+ if(target_atom.layer >= FLY_LAYER)
return
if(!isturf(xeno.loc))
to_chat(xeno, SPAN_XENOWARNING("We can't [action_text] from here!"))
return
- if(!xeno.check_state() || xeno.action_busy)
+ if(xeno.action_busy)
return
- if (activation_delay)
+ if(activation_delay)
if(!do_after(xeno, activation_delay_length, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
to_chat(xeno, SPAN_XENOWARNING("We decide to cancel our acid spray."))
end_cooldown()
return
- if (!action_cooldown_check())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
apply_cooldown()
- if(!check_and_use_plasma_owner())
- return
-
playsound(get_turf(xeno), 'sound/effects/refill.ogg', 25, 1)
xeno.visible_message(SPAN_XENOWARNING("[xeno] vomits a flood of acid!"), SPAN_XENOWARNING("We vomit a flood of acid!"), null, 5)
- apply_cooldown()
-
// Build our list of target turfs based on
- if (spray_type == ACID_SPRAY_LINE)
- xeno.do_acid_spray_line(get_line(xeno, atom, include_start_atom = FALSE), spray_effect_type, spray_distance)
+ if(spray_type == ACID_SPRAY_LINE)
+ xeno.do_acid_spray_line(get_line(xeno, target_atom, include_start_atom = FALSE), spray_effect_type, spray_distance)
- else if (spray_type == ACID_SPRAY_CONE)
- xeno.do_acid_spray_cone(get_turf(atom), spray_effect_type, spray_distance)
+ else if(spray_type == ACID_SPRAY_CONE)
+ xeno.do_acid_spray_cone(get_turf(target_atom), spray_effect_type, spray_distance)
return ..()
-/datum/action/xeno_action/onclick/xenohide/use_ability(atom/target)
+/datum/action/xeno_action/onclick/xenohide/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
if(!xeno.check_state(TRUE))
return
- if(!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(xeno)
if(xeno.action_busy)
return
if(xeno.layer != XENO_HIDING_LAYER)
@@ -643,10 +630,9 @@
if(!QDELETED(source) && (new_stat >= UNCONSCIOUS && old_stat <= UNCONSCIOUS))
post_attack()
-/datum/action/xeno_action/onclick/place_trap/use_ability(atom/target)
+/datum/action/xeno_action/onclick/place_trap/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if(!xeno.check_state())
- return
+ XENO_ACTION_CHECK(xeno)
if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
return
@@ -655,6 +641,7 @@
if(!istype(turf))
to_chat(xeno, SPAN_XENOWARNING("We can't do that here."))
return
+
var/area/area = turf.loc
if(!area?.is_resin_allowed)
if(!area || area.flags_area & AREA_UNWEEDABLE)
@@ -665,13 +652,14 @@
if(istype(area,/area/shuttle/drop1/lz1) || istype(area,/area/shuttle/drop2/lz2) || SSinterior.in_interior(owner))
to_chat(xeno, SPAN_WARNING("We sense this is not a suitable area for creating a resin hole."))
return
+
var/obj/effect/alien/weeds/alien_weeds = turf.check_xeno_trap_placement(xeno)
if(!alien_weeds)
return
if(istype(alien_weeds, /obj/effect/alien/weeds/node))
to_chat(xeno, SPAN_NOTICE("We start uprooting the node so we can put the resin hole in its place..."))
- if(!do_after(xeno, 1 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC, target, INTERRUPT_ALL))
+ if(!do_after(xeno, 1 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC, target_atom, INTERRUPT_ALL))
return
if(!turf.check_xeno_trap_placement(xeno))
return
@@ -745,12 +733,11 @@
return alien_weeds
-/datum/action/xeno_action/activable/place_construction/use_ability(atom/target)
+/datum/action/xeno_action/activable/place_construction/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if(!xeno.check_state())
- return FALSE
+ XENO_ACTION_CHECK(xeno)
- if(isstorage(target.loc) || xeno.contains(target) || istype(target, /atom/movable/screen))
+ if(isstorage(target_atom.loc) || xeno.contains(target_atom) || istype(target_atom, /atom/movable/screen))
return FALSE
if(!xeno.hive)
@@ -777,7 +764,7 @@
to_chat(xeno, SPAN_DANGER("Something went wrong!"))
CRASH("Something went wrong determining hive_pos during place_construction!")
- var/turf/target_turf = get_turf(target)
+ var/turf/target_turf = get_turf(target_atom)
var/area/target_area = get_area(target_turf)
if(isnull(target_area) || !(target_area.is_resin_allowed))
@@ -787,7 +774,7 @@
to_chat(xeno, SPAN_XENOWARNING("It's too early to spread the hive this far."))
return FALSE
- if(!SSmapping.same_z_map(target_turf.z, xeno.z))
+ if(target_turf.z != xeno.z)
to_chat(xeno, SPAN_XENOWARNING("This area is too far away to affect!"))
return FALSE
@@ -795,7 +782,6 @@
to_chat(xeno, SPAN_XENOWARNING("It's too tight in here to build."))
return FALSE
-
if(!xeno.check_alien_construction(target_turf))
return FALSE
@@ -814,12 +800,12 @@
message += "[capitalize_first_letters(structure_name)] - [initial(structure_type.description)]
"
to_chat(xeno, SPAN_NOTICE(message))
return TRUE
- if(!xeno.check_state(TRUE) || !xeno.check_plasma(400))
+ XENO_ACTION_CHECK(xeno)
+ if(!xeno.check_plasma(400))
return FALSE
var/structure_type = xeno.hive.hive_structure_types[choice]
var/datum/construction_template/xenomorph/structure_template = new structure_type()
-
if(!spacecheck(xeno, target_turf, structure_template))
// spacecheck already cleans up the template
return FALSE
@@ -889,74 +875,70 @@
// XSS Spacecheck
-/datum/action/xeno_action/activable/place_construction/proc/spacecheck(mob/living/carbon/xenomorph/xeno, turf/turf, datum/construction_template/xenomorph/tem)
+/datum/action/xeno_action/activable/place_construction/proc/spacecheck(mob/living/carbon/xenomorph/xeno, turf/target_turf, datum/construction_template/xenomorph/tem)
if(tem.block_range)
- for(var/turf/TA in range(tem.block_range, turf))
- if(!xeno.check_alien_construction(TA, FALSE, TRUE, ignore_nest = TRUE))
+ for(target_turf in range(tem.block_range, target_turf))
+ if(!xeno.check_alien_construction(target_turf, FALSE, TRUE, ignore_nest = TRUE))
to_chat(xeno, SPAN_WARNING("We need more open space to build here."))
qdel(tem)
return FALSE
- if(!xeno.check_alien_construction(turf, ignore_nest = TRUE))
+ if(!xeno.check_alien_construction(target_turf, ignore_nest = TRUE))
to_chat(xeno, SPAN_WARNING("We need more open space to build here."))
qdel(tem)
return FALSE
- var/obj/effect/alien/weeds/alien_weeds = locate() in turf
+ var/obj/effect/alien/weeds/alien_weeds = locate() in target_turf
if(!alien_weeds || alien_weeds.weed_strength < WEED_LEVEL_HIVE || alien_weeds.linked_hive.hivenumber != xeno.hivenumber)
to_chat(xeno, SPAN_WARNING("We can only shape on [lowertext(GLOB.hive_datum[xeno.hivenumber].prefix)]hive weeds. We must find a hive node or core before we start building!"))
qdel(tem)
return FALSE
- if(turf.density)
+ if(target_turf.density)
qdel(tem)
to_chat(xeno, SPAN_WARNING("We need empty space to build this."))
return FALSE
return TRUE
-/datum/action/xeno_action/activable/xeno_spit/use_ability(atom/atom)
+/datum/action/xeno_action/activable/xeno_spit/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- var/spit_target = aim_turf ? get_turf(atom) : atom
- if(!xeno.check_state())
- return
+ var/spit_target = aim_turf ? get_turf(target_atom) : target_atom
- if(spitting)
- to_chat(src, SPAN_WARNING("We are already preparing a spit!"))
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_SPITTING))
+ to_chat(xeno, SPAN_WARNING("We are already preparing a spit!"))
return
if(!isturf(xeno.loc))
- to_chat(src, SPAN_WARNING("We can't spit from here!"))
+ to_chat(xeno, SPAN_WARNING("We can't spit from here!"))
return
if(!action_cooldown_check())
- to_chat(src, SPAN_WARNING("We must wait for our spit glands to refill."))
+ to_chat(xeno, SPAN_WARNING("We must wait for our spit glands to refill."))
return
var/turf/current_turf = get_turf(xeno)
-
if(!current_turf)
return
- if (!check_plasma_owner())
- return
+ XENO_ACTION_CHECK(xeno)
if(xeno.ammo.spit_windup)
- spitting = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_SPITTING, TRAIT_SOURCE_ABILITY("spitting"))
if(xeno.ammo.pre_spit_warn)
playsound(xeno.loc,"alien_drool", 55, 1)
to_chat(xeno, SPAN_WARNING("We begin to prepare a large spit!"))
xeno.visible_message(SPAN_WARNING("[xeno] prepares to spit a massive glob!"),
SPAN_WARNING("We begin to spit [xeno.ammo.name]!"))
- if (!do_after(xeno, xeno.ammo.spit_windup, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_HOSTILE))
+ if(!do_after(xeno, xeno.ammo.spit_windup, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_HOSTILE))
to_chat(xeno, SPAN_XENODANGER("We decide to cancel our spit."))
- spitting = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_SPITTING, TRAIT_SOURCE_ABILITY("spitting"))
return
plasma_cost = xeno.ammo.spit_cost
if(!check_and_use_plasma_owner())
- spitting = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_SPITTING, TRAIT_SOURCE_ABILITY("spitting"))
return
- xeno.visible_message(SPAN_XENOWARNING("[xeno] spits at [atom]!"),
+ xeno.visible_message(SPAN_XENOWARNING("[xeno] spits at [target_atom]!"),
- SPAN_XENOWARNING("We spit [xeno.ammo.name] at [atom]!") )
+ SPAN_XENOWARNING("We spit [xeno.ammo.name] at [target_atom]!") )
playsound(xeno.loc, sound_to_play, 25, 1)
var/obj/projectile/proj = new (current_turf, create_cause_data(xeno.ammo.name, xeno))
@@ -965,13 +947,13 @@
proj.def_zone = xeno.get_limbzone_target()
proj.fire_at(spit_target, xeno, xeno, xeno.ammo.max_range, xeno.ammo.shell_speed)
- spitting = FALSE
-
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_SPITTING, TRAIT_SOURCE_ABILITY("spitting"))
SEND_SIGNAL(xeno, COMSIG_XENO_POST_SPIT)
apply_cooldown()
return ..()
+
/datum/action/xeno_action/activable/tail_stab/use_ability(atom/targetted_atom)
var/mob/living/carbon/xenomorph/stabbing_xeno = owner
if(HAS_TRAIT(targetted_atom, TRAIT_HAULED))
@@ -981,7 +963,7 @@
to_chat(stabbing_xeno, SPAN_XENOWARNING("We must be above ground to do this."))
return
- if(!stabbing_xeno.check_state() || stabbing_xeno.cannot_slash)
+ if(stabbing_xeno.cannot_slash)
return FALSE
var/pre_result = pre_ability_act(stabbing_xeno, targetted_atom)
@@ -989,10 +971,9 @@
if(pre_result)
return FALSE
- if(!action_cooldown_check())
- return FALSE
+ XENO_ACTION_CHECK(stabbing_xeno)
- if (world.time <= stabbing_xeno.next_move)
+ if(world.time <= stabbing_xeno.next_move)
return FALSE
if(stabbing_xeno.z != targetted_atom.z)
@@ -1045,20 +1026,19 @@
if(stabbing_xeno.can_not_harm(targetted_atom))
return FALSE
- var/mob/living/carbon/target = targetted_atom
+ var/mob/living/carbon/target_carbon = targetted_atom
- if(target.stat == DEAD || HAS_TRAIT(target, TRAIT_NESTED))
+ if(target_carbon.stat == DEAD || HAS_TRAIT(target_carbon, TRAIT_NESTED))
return FALSE
- var/obj/limb/limb = target.get_limb(check_zone(stabbing_xeno.zone_selected))
- if (ishuman(target) && (!limb || (limb.status & LIMB_DESTROYED)))
+ var/obj/limb/limb = target_carbon.get_limb(check_zone(stabbing_xeno.zone_selected))
+ if(ishuman(target_carbon) && (!limb || (limb.status & LIMB_DESTROYED)))
to_chat(stabbing_xeno, (SPAN_WARNING("What [limb.display_name]?")))
return FALSE
- if(!check_and_use_plasma_owner())
- return FALSE
+ XENO_ACTION_CHECK_USE_PLASMA(stabbing_xeno)
- var/result = ability_act(stabbing_xeno, target, limb)
+ var/result = ability_act(stabbing_xeno, target_carbon, limb)
apply_cooldown()
xeno_attack_delay(stabbing_xeno)
@@ -1091,45 +1071,45 @@
if(new_dir == dir)
setDir(last_dir)
-/datum/action/xeno_action/activable/tail_stab/proc/ability_act(mob/living/carbon/xenomorph/stabbing_xeno, mob/living/carbon/target, obj/limb/limb, apply_behavior_delagate = TRUE)
+/datum/action/xeno_action/activable/tail_stab/proc/ability_act(mob/living/carbon/xenomorph/stabbing_xeno, mob/living/carbon/target_carbon, obj/limb/limb, apply_behavior_delagate = TRUE)
- target.last_damage_data = create_cause_data(initial(stabbing_xeno.caste_type), stabbing_xeno)
+ target_carbon.last_damage_data = create_cause_data(initial(stabbing_xeno.caste_type), stabbing_xeno)
var/stab_overlay
if(blunt_stab)
- stabbing_xeno.visible_message(SPAN_XENOWARNING("\The [stabbing_xeno] swipes its tail into [target]'s [limb ? limb.display_name : "chest"], bashing it!"), SPAN_XENOWARNING("We swipe our tail into [target]'s [limb? limb.display_name : "chest"], bashing it!"))
+ stabbing_xeno.visible_message(SPAN_XENOWARNING("\The [stabbing_xeno] swipes its tail into [target_carbon]'s [limb ? limb.display_name : "chest"], bashing it!"), SPAN_XENOWARNING("We swipe our tail into [target_carbon]'s [limb? limb.display_name : "chest"], bashing it!"))
if(prob(1))
- playsound(target, 'sound/effects/comical_bonk.ogg', 50, TRUE)
+ playsound(target_carbon, 'sound/effects/comical_bonk.ogg', 50, TRUE)
else
- playsound(target, "punch", 50, TRUE)
+ playsound(target_carbon, "punch", 50, TRUE)
stab_overlay = "slam"
else
- stabbing_xeno.visible_message(SPAN_XENOWARNING("\The [stabbing_xeno] skewers [target] through the [limb ? limb.display_name : "chest"] with its razor sharp tail!"), SPAN_XENOWARNING("We skewer [target] through the [limb? limb.display_name : "chest"] with our razor sharp tail!"))
- playsound(target, "alien_bite", 50, TRUE)
+ stabbing_xeno.visible_message(SPAN_XENOWARNING("\The [stabbing_xeno] skewers [target_carbon] through the [limb ? limb.display_name : "chest"] with its razor sharp tail!"), SPAN_XENOWARNING("We skewer [target_carbon] through the [limb? limb.display_name : "chest"] with our razor sharp tail!"))
+ playsound(target_carbon, "alien_bite", 50, TRUE)
stab_overlay = "tail"
- log_attack("[key_name(stabbing_xeno)] tailstabbed [key_name(target)] at [get_area_name(stabbing_xeno)]")
- target.attack_log += text("\[[time_stamp()]\] was tailstabbed by [key_name(stabbing_xeno)]")
- stabbing_xeno.attack_log += text("\[[time_stamp()]\] tailstabbed [key_name(target)]")
+ log_attack("[key_name(stabbing_xeno)] tailstabbed [key_name(target_carbon)] at [get_area_name(stabbing_xeno)]")
+ target_carbon.attack_log += text("\[[time_stamp()]\] was tailstabbed by [key_name(stabbing_xeno)]")
+ stabbing_xeno.attack_log += text("\[[time_stamp()]\] tailstabbed [key_name(target_carbon)]")
- stabbing_xeno.tail_stab_animation(target, blunt_stab)
- stabbing_xeno.animation_attack_on(target)
- stabbing_xeno.flick_attack_overlay(target, stab_overlay)
+ stabbing_xeno.tail_stab_animation(target_carbon, blunt_stab)
+ stabbing_xeno.animation_attack_on(target_carbon)
+ stabbing_xeno.flick_attack_overlay(target_carbon, stab_overlay)
var/damage = (stabbing_xeno.melee_damage_upper + stabbing_xeno.frenzy_aura * FRENZY_DAMAGE_MULTIPLIER) * damage_multiplier
if(stabbing_xeno.behavior_delegate && apply_behavior_delagate)
- stabbing_xeno.behavior_delegate.melee_attack_additional_effects_target(target)
+ stabbing_xeno.behavior_delegate.melee_attack_additional_effects_target(target_carbon)
stabbing_xeno.behavior_delegate.melee_attack_additional_effects_self()
- damage = stabbing_xeno.behavior_delegate.melee_attack_modify_damage(damage, target)
+ damage = stabbing_xeno.behavior_delegate.melee_attack_modify_damage(damage, target_carbon)
- target.apply_armoured_damage(get_xeno_damage_slash(target, damage), ARMOR_MELEE, BRUTE, limb ? limb.name : "chest")
+ target_carbon.apply_armoured_damage(get_xeno_damage_slash(target_carbon, damage), ARMOR_MELEE, BRUTE, limb ? limb.name : "chest")
if(stabbing_xeno.mob_size >= MOB_SIZE_BIG)
- target.apply_effect(3, DAZE)
+ target_carbon.apply_effect(3, DAZE)
else if(stabbing_xeno.mob_size == MOB_SIZE_XENO)
- target.apply_effect(1, DAZE)
- shake_camera(target, 2, 1)
+ target_carbon.apply_effect(1, DAZE)
+ shake_camera(target_carbon, 2, 1)
- target.handle_blood_splatter(get_dir(owner.loc, target.loc))
- return target
+ target_carbon.handle_blood_splatter(get_dir(owner.loc, target_carbon.loc))
+ return target_carbon
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_abilities.dm
index d4fb390f14f92..99f8a67f17234 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_abilities.dm
@@ -19,10 +19,12 @@
action_type = XENO_ACTION_CLICK
plasma_cost = 20
- var/duration = 30 SECONDS // 30 seconds base
var/invis_timer_id = TIMER_ID_NULL
var/alpha_amount = 25
var/speed_buff = 0.20
+ var/invis_recharge_time = 20 SECONDS
+ var/invis_start_time = -1 // Special value for when we're not invisible
+ var/invis_duration = 30 SECONDS
// tightly coupled 'buff next slash' action
/datum/action/xeno_action/onclick/lurker_assassinate
@@ -35,6 +37,8 @@
plasma_cost = 20
var/buff_duration = 50
+ var/buffed_slash_damage_ratio = 1.2
+ var/slash_slow_duration = 35
// VAMP LURKER ABILITIES
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_abilities.dm
index 282b6f6c52d00..6abdf6d126617 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_abilities.dm
@@ -35,8 +35,6 @@
var/buff_duration = 12
var/damage = 40
var/shield_regen_threshold = 1
-
- var/activated_once = FALSE
var/time_until_timeout = 20
/datum/action/xeno_action/activable/pounce/prae_dash/initialize_pounce_pass_flags()
@@ -58,8 +56,6 @@
var/fling_dist_unbuffed = 3
var/fling_dist_buffed = 6
- // Root or do a punch-like-effect.
- var/root_toggle = TRUE
var/buffed = FALSE // Are we buffed
/datum/action/xeno_action/onclick/toggle_cleave
@@ -70,39 +66,6 @@
action_type = XENO_ACTION_CLICK
ability_primacy = XENO_PRIMARY_ACTION_4
-/datum/action/xeno_action/onclick/toggle_cleave/can_use_action()
- var/mob/living/carbon/xenomorph/X = owner
- if(X && !X.buckled && !X.is_mob_incapacitated())
- return TRUE
-
-/datum/action/xeno_action/onclick/toggle_cleave/use_ability(atom/A)
- var/mob/living/carbon/xenomorph/X = owner
-
- if (!istype(X))
- return
-
- if(!X.check_state(1))
- return
-
- var/datum/action/xeno_action/activable/cleave/cAction = get_action(X, /datum/action/xeno_action/activable/cleave)
-
- if (!istype(cAction))
- return
-
- cAction.root_toggle = !cAction.root_toggle
-
- var/action_icon_result
- if (cAction.root_toggle)
- action_icon_result = "prae_cleave_root"
- to_chat(X, SPAN_WARNING("We will now root marines with our cleave."))
- else
- action_icon_result = "prae_cleave_fling" // TODO: update
- to_chat(X, SPAN_WARNING("We will now throw marines with our cleave."))
-
- button.overlays.Cut()
- button.overlays += image('icons/mob/hud/actions_xeno.dmi', button, action_icon_result)
- return ..()
-
////////// Oppressor powers
/datum/action/xeno_action/activable/tail_stab/tail_seize //no verbmacrohotkey, its just tail stab.
@@ -172,6 +135,11 @@
action_type = XENO_ACTION_CLICK
ability_primacy = XENO_TAIL_STAB
+ /// How much damage Harpoon Tail on DISARM mode do. (pierces armor)
+ var/blunt_damage = 8
+ /// Harpoon Tail mode, used only to display in status.
+ var/tail_mode = null
+
/datum/action/xeno_action/activable/prae_impale
name = "Impale"
action_icon_state = "prae_impale"
@@ -197,6 +165,15 @@
var/speed_buff_amount = 0.5
var/afterimage_interval = 1 DECISECONDS
+ /// Used to countdown DANCER_DODGE_TIME.
+ var/dodge_start_time = -1
+ /// How much refund we want to get back? 1.0 is 1s used to 1s cooldown, 2.0 is 1s used 2s cooldown.
+ var/refund_multiplier = 2.0
+ /// Used in calculation, finalized number will be displayed as cooldown.
+ var/recharge_time = null
+ /// Cooldown after activation to prevent accidental double click.
+ var/safe_click_cooldown = 0
+
/datum/action/xeno_action/activable/prae_tail_trip
name = "Tail Trip"
action_icon_state = "prae_tail_trip"
@@ -249,7 +226,7 @@
plasma_cost = 80
var/activation_delay = 1 SECONDS
- var/prime_delay = 1 SECONDS
+ var/prime_delay = 1.5 SECONDS
/datum/action/xeno_action/activable/prae_acid_ball/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/acid_ball_user = owner
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_abilities.dm
index 5a181a5b1990f..998da49b5c2eb 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_abilities.dm
@@ -156,29 +156,29 @@
var/datum/hive_status/hive
var/list/transported_xenos
-/datum/action/xeno_action/activable/place_queen_beacon/give_to(mob/living/carbon/xenomorph/queen/Q)
+/datum/action/xeno_action/activable/place_queen_beacon/give_to(mob/living/carbon/xenomorph/queen/queen_user)
. = ..()
- hive = Q.hive
- if(!Q.ovipositor)
- hide_from(Q)
- RegisterSignal(Q, COMSIG_QUEEN_MOUNT_OVIPOSITOR, PROC_REF(handle_mount_ovipositor))
- RegisterSignal(Q, COMSIG_QUEEN_DISMOUNT_OVIPOSITOR, PROC_REF(handle_dismount_ovipositor))
+ hive = queen_user.hive
+ if(!queen_user.ovipositor)
+ hide_from(queen_user)
+ RegisterSignal(queen_user, COMSIG_QUEEN_MOUNT_OVIPOSITOR, PROC_REF(handle_mount_ovipositor))
+ RegisterSignal(queen_user, COMSIG_QUEEN_DISMOUNT_OVIPOSITOR, PROC_REF(handle_dismount_ovipositor))
-/datum/action/xeno_action/activable/place_queen_beacon/remove_from(mob/living/carbon/xenomorph/X)
+/datum/action/xeno_action/activable/place_queen_beacon/remove_from(mob/living/carbon/xenomorph/xeno)
. = ..()
hive = null
- UnregisterSignal(X, list(
+ UnregisterSignal(xeno, list(
COMSIG_QUEEN_MOUNT_OVIPOSITOR,
COMSIG_QUEEN_DISMOUNT_OVIPOSITOR,
))
-/datum/action/xeno_action/activable/place_queen_beacon/proc/handle_mount_ovipositor(mob/living/carbon/xenomorph/queen/Q)
+/datum/action/xeno_action/activable/place_queen_beacon/proc/handle_mount_ovipositor(mob/living/carbon/xenomorph/queen/queen_user)
SIGNAL_HANDLER
- unhide_from(Q)
+ unhide_from(queen_user)
-/datum/action/xeno_action/activable/place_queen_beacon/proc/handle_dismount_ovipositor(mob/living/carbon/xenomorph/queen/Q)
+/datum/action/xeno_action/activable/place_queen_beacon/proc/handle_dismount_ovipositor(mob/living/carbon/xenomorph/queen/queen_user)
SIGNAL_HANDLER
- hide_from(Q)
+ hide_from(queen_user)
/datum/action/xeno_action/activable/blockade
@@ -194,24 +194,24 @@
var/brittle_time = 45 SECONDS
var/decay_time = 45 SECONDS
-/datum/action/xeno_action/activable/blockade/give_to(mob/living/carbon/xenomorph/queen/Q)
+/datum/action/xeno_action/activable/blockade/give_to(mob/living/carbon/xenomorph/queen/queen_user)
. = ..()
- if(!Q.ovipositor)
- hide_from(Q)
- RegisterSignal(Q, COMSIG_QUEEN_MOUNT_OVIPOSITOR, PROC_REF(handle_mount_ovipositor))
- RegisterSignal(Q, COMSIG_QUEEN_DISMOUNT_OVIPOSITOR, PROC_REF(handle_dismount_ovipositor))
+ if(!queen_user.ovipositor)
+ hide_from(queen_user)
+ RegisterSignal(queen_user, COMSIG_QUEEN_MOUNT_OVIPOSITOR, PROC_REF(handle_mount_ovipositor))
+ RegisterSignal(queen_user, COMSIG_QUEEN_DISMOUNT_OVIPOSITOR, PROC_REF(handle_dismount_ovipositor))
-/datum/action/xeno_action/activable/blockade/remove_from(mob/living/carbon/xenomorph/X)
+/datum/action/xeno_action/activable/blockade/remove_from(mob/living/carbon/xenomorph/xeno)
. = ..()
- UnregisterSignal(X, list(
+ UnregisterSignal(xeno, list(
COMSIG_QUEEN_MOUNT_OVIPOSITOR,
COMSIG_QUEEN_DISMOUNT_OVIPOSITOR,
))
-/datum/action/xeno_action/activable/blockade/proc/handle_mount_ovipositor(mob/living/carbon/xenomorph/queen/Q)
+/datum/action/xeno_action/activable/blockade/proc/handle_mount_ovipositor(mob/living/carbon/xenomorph/queen/queen_user)
SIGNAL_HANDLER
- unhide_from(Q)
+ unhide_from(queen_user)
-/datum/action/xeno_action/activable/blockade/proc/handle_dismount_ovipositor(mob/living/carbon/xenomorph/queen/Q)
+/datum/action/xeno_action/activable/blockade/proc/handle_dismount_ovipositor(mob/living/carbon/xenomorph/queen/queen_user)
SIGNAL_HANDLER
- hide_from(Q)
+ hide_from(queen_user)
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/ravager/ravager_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/ravager/ravager_abilities.dm
index c676fff618263..3c62418cb3f14 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/ravager/ravager_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/ravager/ravager_abilities.dm
@@ -17,6 +17,9 @@
freeze_self = FALSE // Should we freeze ourselves after the lunge?
should_destroy_objects = TRUE // Only used for ravager charge
+ var/knockdown_amount = 1.6
+ var/fling_distance = 3
+
// Base ravager shield ability
/datum/action/xeno_action/onclick/empower
name = "Empower"
@@ -34,9 +37,8 @@
var/initial_activation_shield = 50
var/shield_per_human = 50
var/time_until_timeout = 6 SECONDS
-
- // State
- var/activated_once = FALSE
+ var/empower_targets = 0
+ var/super_empower_threshold = 3
// Rav "Scissor Cut"
/datum/action/xeno_action/activable/scissor_cut
@@ -149,4 +151,6 @@
var/ammo_type = /datum/ammo/xeno/bone_chips/spread
var/shrapnel_amount = 40
+ var/shard_lock_duration = 15 SECONDS
+ var/shard_lock_speed_mod = 0.45
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_abilities.dm
index 528dc9767a139..158cf0a43da44 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_abilities.dm
@@ -38,6 +38,7 @@
macro_path = /datum/action/xeno_action/verb/verb_acider_acid
ability_primacy = XENO_PRIMARY_ACTION_1
action_type = XENO_ACTION_CLICK
+
var/acid_cost = 100
/datum/action/xeno_action/activable/acider_for_the_hive
@@ -46,4 +47,19 @@
macro_path = /datum/action/xeno_action/verb/verb_acider_sacrifice
action_type = XENO_ACTION_CLICK
ability_primacy = XENO_PRIMARY_ACTION_2
+
var/minimal_acid = 200
+ var/caboom_timer = 20
+ var/caboom_left = 20
+ var/caboom_loop = 1
+
+ var/caboom_left_display = 20 SECONDS
+
+ var/caboom_trigger
+ var/caboom_last_proc
+ var/list/caboom_sound = list('sound/effects/runner_charging_1.ogg','sound/effects/runner_charging_2.ogg')
+
+ var/caboom_acid_ratio = 200
+ var/caboom_burn_damage_ratio = 5
+ var/caboom_burn_range_ratio = 100
+ var/caboom_struct_acid_type = /obj/effect/xenomorph/acid
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm b/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm
index d2cd1e6615566..e452ef8a37f3d 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm
@@ -13,12 +13,16 @@
var/cooldown_message = null
var/no_cooldown_msg = FALSE
- var/cooldown_timer_id = TIMER_ID_NULL // holds our timer ID
+ var/cooldown_timer_id = TIMER_ID_NULL // holds cooldown timer ID
// Track state so we can effectively REDUCE xeno_cooldown by removing and replacing timers.
var/current_cooldown_start_time = 0
var/current_cooldown_duration = 0
+ var/duration_timer_id = TIMER_ID_NULL // holds duration timer ID
+ var/current_duration_start_time = 0
+ var/current_duration_duration = 0
+
// Charging
/// When set, an ability has to be charged up by being the active ability before it can be used
var/charge_time = null
@@ -43,6 +47,9 @@
. = ..()
/datum/action/xeno_action/process(delta_time)
+ if(duration_timer_id != TIMER_ID_NULL)
+ return update_duration_visual()
+
return update_cooldown_visual()
/datum/action/xeno_action/proc/remove_charge()
@@ -472,19 +479,42 @@
if(action_start_message)
to_chat(owner, SPAN_NOTICE(action_start_message))
+///Use to display duration time of active ability.
+/datum/action/xeno_action/proc/start_duration_display(duration)
+ if(duration_timer_id != TIMER_ID_NULL)
+ deltimer(duration_timer_id)
+
+ duration_timer_id = addtimer(CALLBACK(src, PROC_REF(end_duration_display)), duration, TIMER_STOPPABLE)
+
+ current_duration_start_time = world.time
+ current_duration_duration = duration
+
+ START_PROCESSING(SSfasteffects, src)
+
+///Use to stop display duration time of active ability.
+/datum/action/xeno_action/proc/end_duration_display()
+ duration_timer_id = TIMER_ID_NULL
+ current_duration_start_time = 0
+ current_duration_duration = 0
+
+ update_button_icon()
+
+/datum/action/xeno_action/proc/update_duration_visual()
+ var/time_left = max(current_duration_start_time + current_duration_duration - world.time, 0)
+ if(!owner || time_left <= 0 || duration_timer_id == TIMER_ID_NULL)
+ button.set_maptext()
+ return PROCESS_KILL
+ button.set_maptext(SMALL_FONTS(7, round(time_left/10, 0.1)), 4, 4)
+
/datum/action/xeno_action/proc/update_cooldown_visual()
var/time_left = max(current_cooldown_start_time + current_cooldown_duration - world.time, 0)
if(!owner || time_left <= 0 || cooldown_timer_id == TIMER_ID_NULL)
button.set_maptext()
return PROCESS_KILL
- else
- button.set_maptext(SMALL_FONTS(7, round(time_left/10, 0.1)), 4, 4)
+ button.set_maptext(SMALL_FONTS_COLOR(7, round(time_left/10, 0.1), "#fffb00"), 4, 4)
/datum/action/xeno_action/proc/on_select(mob/user)
return
/datum/action/xeno_action/proc/on_deselect(mob/user)
return
-
-#define XENO_ACTION_CHECK(X) if(!X.check_state() || !action_cooldown_check() || !check_plasma_owner(src.plasma_cost)) return
-#define XENO_ACTION_CHECK_USE_PLASMA(X) if(!X.check_state() || !action_cooldown_check() || !check_and_use_plasma_owner(src.plasma_cost)) return
diff --git a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm
index 3a2098f14bea3..375dd3ce124f8 100644
--- a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm
+++ b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm
@@ -9,7 +9,7 @@
// this proc could use refactoring at some point
/mob/living/carbon/human/attack_alien(mob/living/carbon/xenomorph/attacking_xeno, dam_bonus, unblockable = FALSE)
- if(attacking_xeno.fortify || HAS_TRAIT(attacking_xeno, TRAIT_ABILITY_BURROWED) || HAS_TRAIT(attacking_xeno, TRAIT_ABILITY_REFLECTIVE_PLATES))
+ if(HAS_TRAIT(attacking_xeno, TRAIT_ABILITY_FORTIFY) || HAS_TRAIT(attacking_xeno, TRAIT_ABILITY_BURROWED) || HAS_TRAIT(attacking_xeno, TRAIT_ABILITY_REFLECTIVE_PLATES))
return XENO_NO_DELAY_ACTION
if(HAS_TRAIT(src, TRAIT_HAULED))
@@ -253,7 +253,7 @@
//Every other type of nonhuman mob
/mob/living/attack_alien(mob/living/carbon/xenomorph/xeno)
- if(xeno.fortify || HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY) || HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
return XENO_NO_DELAY_ACTION
switch(xeno.a_intent)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Boiler.dm b/code/modules/mob/living/carbon/xenomorph/castes/Boiler.dm
index 95483880fa51b..97579461284d5 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Boiler.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Boiler.dm
@@ -100,11 +100,11 @@
/datum/action/xeno_action/activable/xeno_spit/bombard/use_ability(atom/affected_atom)
. = ..()
- var/mob/living/carbon/xenomorph/xeno = owner
+ var/mob/living/carbon/xenomorph/bombard_user = owner
if(!action_cooldown_check()) // activate c/d only if we already spit
- for (var/action_type in action_types_to_cd)
- var/datum/action/xeno_action/xeno_action = get_action(xeno, action_type)
- if (!istype(xeno_action))
+ for(var/action_type in action_types_to_cd)
+ var/datum/action/xeno_action/xeno_action = get_action(bombard_user, action_type)
+ if(!istype(xeno_action))
continue
xeno_action.apply_cooldown_override(cooldown_duration)
@@ -113,21 +113,17 @@
/datum/action/xeno_action/onclick/acid_shroud/use_ability(atom/affected_atom)
var/datum/effect_system/smoke_spread/xeno_acid/spicy_gas
var/mob/living/carbon/xenomorph/xeno = owner
- if (!isxeno(owner))
+ if(!isxeno(owner))
return
- if (!action_cooldown_check())
- return
-
- if (!xeno.check_state())
- return
+ XENO_ACTION_CHECK(xeno)
if(sound_play)
playsound(xeno,"acid_strike", 35, 1)
sound_play = FALSE
addtimer(VARSET_CALLBACK(src, sound_play, TRUE), 2 SECONDS)
- if (!do_after(xeno, xeno.ammo.spit_windup/6.5, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_HOSTILE, numticks = 2)) /// 0.7 seconds
+ if(!do_after(xeno, xeno.ammo.spit_windup / 6.5, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_HOSTILE, numticks = 2)) /// 0.7 seconds
to_chat(xeno, SPAN_XENODANGER("We decide to cancel our gas shroud."))
return
@@ -144,9 +140,9 @@
spicy_gas.start()
to_chat(xeno, SPAN_XENOHIGHDANGER("We dump our acid through our pores, creating a shroud of gas!"))
- for (var/action_type in action_types_to_cd)
+ for(var/action_type in action_types_to_cd)
var/datum/action/xeno_action/xeno_action = get_action(xeno, action_type)
- if (!istype(xeno_action))
+ if(!istype(xeno_action))
continue
xeno_action.apply_cooldown_override(cooldown_duration)
@@ -159,21 +155,21 @@
apply_cooldown()
/datum/action/xeno_action/activable/tail_stab/boiler/use_ability(atom/affected_atom)
- var/mob/living/carbon/xenomorph/stabbing_xeno = owner
+ var/mob/living/carbon/xenomorph/xeno = owner
var/target = ..()
if(iscarbon(target))
var/mob/living/carbon/carbon_target = target
- if(stabbing_xeno.ammo == GLOB.ammo_list[/datum/ammo/xeno/boiler_gas/acid])
+ if(xeno.ammo == GLOB.ammo_list[/datum/ammo/xeno/boiler_gas/acid])
carbon_target.reagents.add_reagent("molecularacid", 6)
carbon_target.reagents.set_source_mob(owner, /datum/reagent/toxin/molecular_acid)
- else if(stabbing_xeno.ammo == GLOB.ammo_list[/datum/ammo/xeno/boiler_gas])
+ else if(xeno.ammo == GLOB.ammo_list[/datum/ammo/xeno/boiler_gas])
var/datum/effects/neurotoxin/neuro_effect = locate() in carbon_target.effects_list
if(!neuro_effect)
neuro_effect = new(carbon_target, owner)
neuro_effect.duration += 20
- to_chat(carbon_target,SPAN_HIGHDANGER("You are injected with something from [stabbing_xeno]'s tailstab!"))
+ to_chat(carbon_target,SPAN_HIGHDANGER("You are injected with something from [xeno]'s tailstab!"))
else
- CRASH("Globber has unknown ammo [stabbing_xeno.ammo]! Oh no!")
+ CRASH("Globber has unknown ammo [xeno.ammo]! Oh no!")
return TRUE
#define ACID_COST_BOILER 200 // ACID_COST_LEVEL_3
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm b/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm
index 574c191d32b35..7b66d6e8ac411 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm
@@ -28,9 +28,6 @@
tacklestrength_min = 4
tacklestrength_max = 5
- burrow_cooldown = 2 SECONDS
- tunnel_cooldown = 7 SECONDS
-
minimum_evolve_time = 7 MINUTES
minimap_icon = "burrower"
@@ -85,232 +82,229 @@
skull = /obj/item/skull/burrower
pelt = /obj/item/pelt/burrower
-/mob/living/carbon/xenomorph/burrower/ex_act(severity, direction, datum/cause_data/cause_data, pierce=0, enviro=FALSE)
- if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
- return
- ..()
+/datum/behavior_delegate/burrower_base
+ name = "Base Burrower Behavior Delegate"
-/mob/living/carbon/xenomorph/burrower/attack_hand()
- if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
- return
- ..()
+/datum/action/xeno_action/activable/burrow/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
-/mob/living/carbon/xenomorph/burrower/attackby()
- if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
- return
- . = ..()
+ XENO_ACTION_CHECK(xeno)
-/mob/living/carbon/xenomorph/burrower/get_projectile_hit_chance()
- . = ..()
- if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
- return 0
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
+ digging(get_turf(target_atom))
+ else
+ burrow()
+ return ..()
-/datum/behavior_delegate/burrower_base
- name = "Base Burrower Behavior Delegate"
+/datum/action/xeno_action/activable/burrow/proc/burrow()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ XENO_ACTION_CHECK(xeno)
-//Burrower Abilities
-/mob/living/carbon/xenomorph/proc/burrow()
- if(!check_state())
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROW_UNDERGROUND) || HAS_TRAIT(xeno, TRAIT_ABILITY_BURROW_DIGGING))
return
- if(used_burrow || tunnel || is_ventcrawling || action_busy)
+ if(xeno.is_ventcrawling || xeno.action_busy)
return
- var/turf/current_turf = get_turf(src)
+ var/turf/current_turf = get_turf(xeno)
if(!current_turf)
return
var/area/current_area = get_area(current_turf)
if(current_area.flags_area & AREA_NOBURROW)
- to_chat(src, SPAN_XENOWARNING("There's no way to burrow here."))
+ to_chat(xeno, SPAN_XENOWARNING("There's no way to burrow here."))
return
if(istype(current_turf, /turf/open/floor/almayer/research/containment) || istype(current_turf, /turf/closed/wall/almayer/research/containment))
- to_chat(src, SPAN_XENOWARNING("We can't escape this cell!"))
+ to_chat(xeno, SPAN_XENOWARNING("We can't escape this cell!"))
return
- if(clone) //Prevents burrowing on stairs
- to_chat(src, SPAN_XENOWARNING("We can't burrow here!"))
+ if(xeno.clone) //Prevents burrowing on stairs
+ to_chat(xeno, SPAN_XENOWARNING("We can't burrow here!"))
return
- if(caste_type && GLOB.xeno_datum_list[caste_type])
- caste = GLOB.xeno_datum_list[caste_type]
+ if(xeno.caste_type && GLOB.xeno_datum_list[xeno.caste_type])
+ xeno.caste = GLOB.xeno_datum_list[xeno.caste_type]
- used_burrow = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_BURROW_UNDERGROUND, TRAIT_SOURCE_ABILITY("burrow_underground"))
- to_chat(src, SPAN_XENOWARNING("We begin burrowing ourselves into the ground."))
- if(!do_after(src, 1.5 SECONDS, INTERRUPT_ALL, BUSY_ICON_HOSTILE))
- addtimer(CALLBACK(src, PROC_REF(do_burrow_cooldown)), (caste ? caste.burrow_cooldown : 5 SECONDS))
+ to_chat(xeno, SPAN_XENOWARNING("We begin burrowing ourselves into the ground."))
+ if(!do_after(xeno, 1.5 SECONDS, INTERRUPT_ALL, BUSY_ICON_HOSTILE))
+ addtimer(CALLBACK(src, PROC_REF(do_burrow_cooldown)), burrow_cooldown)
return
// TODO Make immune to all damage here.
- to_chat(src, SPAN_XENOWARNING("We burrow ourselves into the ground."))
- QDEL_NULL(observed_atom)
- invisibility = 101
- alpha = 100
- anchored = TRUE
+ to_chat(xeno, SPAN_XENOWARNING("We burrow ourselves into the ground."))
+ QDEL_NULL(xeno.observed_atom)
+ xeno.invisibility = 101
+ xeno.alpha = 100
+ xeno.anchored = TRUE
- var/mob/living/carbon/human/hauled = hauled_mob?.resolve()
+ var/mob/living/carbon/human/hauled = xeno.hauled_mob?.resolve()
if(hauled)
- hauled.forceMove(src)
+ hauled.forceMove(xeno)
- add_traits(list(TRAIT_ABILITY_BURROWED, TRAIT_UNDENSE, TRAIT_IMMOBILIZED), TRAIT_SOURCE_ABILITY("Burrow"))
- playsound(src.loc, 'sound/effects/burrowing_b.ogg', 25)
- update_icons()
- addtimer(CALLBACK(src, PROC_REF(do_burrow_cooldown)), (caste ? caste.burrow_cooldown : 5 SECONDS))
+ xeno.add_traits(list(TRAIT_ABILITY_BURROWED, TRAIT_UNDENSE, TRAIT_IMMOBILIZED), TRAIT_SOURCE_ABILITY("Burrow"))
+ playsound(xeno.loc, 'sound/effects/burrowing_b.ogg', 25)
+ xeno.update_icons()
+ start_duration_display(10 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(do_burrow_cooldown)), burrow_cooldown)
burrow_timer = world.time + 90 // How long we can be burrowed
process_burrow()
-/mob/living/carbon/xenomorph/proc/process_burrow()
- if(!HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
+/datum/action/xeno_action/activable/burrow/proc/process_burrow()
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
return
- if(world.time > burrow_timer && !tunnel)
+ if(world.time > burrow_timer && !HAS_TRAIT(xeno, TRAIT_ABILITY_BURROW_DIGGING))
burrow_off()
- if(observed_xeno)
- overwatch(observed_xeno, TRUE)
- if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
+ if(xeno.observed_xeno)
+ xeno.overwatch(xeno.observed_xeno, TRUE)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
addtimer(CALLBACK(src, PROC_REF(process_burrow)), 1 SECONDS)
-/mob/living/carbon/xenomorph/proc/burrow_off()
- if(caste_type && GLOB.xeno_datum_list[caste_type])
- caste = GLOB.xeno_datum_list[caste_type]
- to_chat(src, SPAN_NOTICE("You resurface."))
- remove_traits(list(TRAIT_ABILITY_BURROWED, TRAIT_UNDENSE, TRAIT_IMMOBILIZED), TRAIT_SOURCE_ABILITY("Burrow"))
- invisibility = FALSE
- alpha = initial(alpha)
- anchored = FALSE
+/datum/action/xeno_action/activable/burrow/proc/burrow_off()
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ to_chat(xeno, SPAN_NOTICE("You resurface."))
+ xeno.remove_traits(list(TRAIT_ABILITY_BURROWED, TRAIT_UNDENSE, TRAIT_IMMOBILIZED), TRAIT_SOURCE_ABILITY("Burrow"))
+ xeno.invisibility = FALSE
+ xeno.alpha = initial(xeno.alpha)
+ xeno.anchored = FALSE
+ end_duration_display()
- var/mob/living/carbon/human/hauled = hauled_mob?.resolve()
+ var/mob/living/carbon/human/hauled = xeno.hauled_mob?.resolve()
if(hauled)
- hauled.forceMove(loc)
+ hauled.forceMove(xeno.loc)
- playsound(loc, 'sound/effects/burrowoff.ogg', 25)
- for(var/mob/living/carbon/mob in loc)
- if(!can_not_harm(mob))
+ playsound(xeno.loc, 'sound/effects/burrowoff.ogg', 25)
+ for(var/mob/living/carbon/mob in xeno.loc)
+ if(!xeno.can_not_harm(mob))
mob.apply_effect(1.5, WEAKEN)
- addtimer(CALLBACK(src, PROC_REF(do_burrow_cooldown)), (caste ? caste.burrow_cooldown : 5 SECONDS))
- update_icons()
+ addtimer(CALLBACK(src, PROC_REF(do_burrow_cooldown)), burrow_cooldown)
+ xeno.update_icons()
-/mob/living/carbon/xenomorph/proc/do_burrow_cooldown()
- used_burrow = FALSE
- if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
- to_chat(src, SPAN_NOTICE("We can now surface."))
- for(var/X in actions)
- var/datum/action/act = X
- act.update_button_icon()
+/datum/action/xeno_action/activable/burrow/proc/do_burrow_cooldown()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_BURROW_UNDERGROUND, TRAIT_SOURCE_ABILITY("burrow_underground"))
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
+ to_chat(xeno, SPAN_NOTICE("We can now surface."))
+ update_button_icon()
-/mob/living/carbon/xenomorph/proc/tunnel(turf/target)
- if(!check_state())
- return
- if(!HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
- to_chat(src, SPAN_NOTICE("We must be burrowed to do this."))
+
+/datum/action/xeno_action/activable/burrow/proc/digging(turf/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ XENO_ACTION_CHECK(xeno)
+
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
+ to_chat(xeno, SPAN_NOTICE("We must be burrowed to do this."))
return
- if(tunnel)
- tunnel = FALSE
- to_chat(src, SPAN_NOTICE("We stop tunneling."))
- used_tunnel = TRUE
- addtimer(CALLBACK(src, PROC_REF(do_tunnel_cooldown)), (caste ? caste.tunnel_cooldown : 5 SECONDS))
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROW_DIGGING))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_BURROW_DIGGING, TRAIT_SOURCE_ABILITY("burrow_digging"))
+ to_chat(xeno, SPAN_NOTICE("We stop tunneling."))
+ used_digging = TRUE
+ addtimer(CALLBACK(src, PROC_REF(do_digging_cooldown)), digging_cooldown)
return
- if(used_tunnel)
- to_chat(src, SPAN_NOTICE("We must wait some time to do this."))
+ if(used_digging)
+ to_chat(xeno, SPAN_NOTICE("We must wait some time to do this."))
return
- if(!target)
- to_chat(src, SPAN_NOTICE("We can't tunnel there!"))
+ if(!target_atom)
+ to_chat(xeno, SPAN_NOTICE("We can't tunnel there!"))
return
- if(target.density)
- to_chat(src, SPAN_XENOWARNING("We can't tunnel into a solid wall!"))
+ if(target_atom.density)
+ to_chat(xeno, SPAN_XENOWARNING("We can't tunnel into a solid wall!"))
return
- if(istype(target, /turf/open/space))
- to_chat(src, SPAN_XENOWARNING("We make tunnels, not wormholes!"))
+ if(istype(target_atom, /turf/open/space))
+ to_chat(xeno, SPAN_XENOWARNING("We make tunnels, not wormholes!"))
return
- if(clone) //Prevents tunnels in Z transition areas
- to_chat(src, SPAN_XENOWARNING("We make tunnels, not wormholes!"))
+ if(xeno.clone) //Prevents tunnels in Z transition areas
+ to_chat(xeno, SPAN_XENOWARNING("We make tunnels, not wormholes!"))
return
- var/area/area_to_get = get_area(target)
- if(area_to_get.flags_area & AREA_NOBURROW || get_dist(src, target) > 15)
- to_chat(src, SPAN_XENOWARNING("There's no way to tunnel over there."))
+ var/area/area_to_get = get_area(target_atom)
+ if(area_to_get.flags_area & AREA_NOBURROW || get_dist(xeno, target_atom) > 15)
+ to_chat(xeno, SPAN_XENOWARNING("There's no way to tunnel over there."))
return
- for(var/obj/objects_in_turf in target.contents)
+ for(var/obj/objects_in_turf in target_atom.contents)
if(objects_in_turf.density)
if(objects_in_turf.flags_atom & ON_BORDER)
continue
- to_chat(src, SPAN_WARNING("There's something solid there to stop us from emerging."))
+ to_chat(xeno, SPAN_WARNING("There's something solid there to stop us from emerging."))
return
- if(!target || target.density)
- to_chat(src, SPAN_NOTICE("We cannot tunnel to there!"))
- tunnel = TRUE
- to_chat(src, SPAN_NOTICE("We start tunneling!"))
- var/target_distance = max(get_dist(src, target), 1) // Min distance of 1 is to prevent stunlocking
- tunnel_timer = (target_distance*10) + world.time
- process_tunnel(target)
+ if(!target_atom || target_atom.density)
+ to_chat(xeno, SPAN_NOTICE("We cannot tunnel to there!"))
+ ADD_TRAIT(xeno, TRAIT_ABILITY_BURROW_DIGGING, TRAIT_SOURCE_ABILITY("burrow_digging"))
+ to_chat(xeno, SPAN_NOTICE("We start tunneling!"))
+ var/target_distance = max(get_dist(xeno, target_atom), 1) // Min distance of 1 is to prevent stunlocking
+ digging_timer = (target_distance * 10) + world.time
+ process_digging(target_atom)
+/datum/action/xeno_action/activable/burrow/proc/process_digging(turf/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
-/mob/living/carbon/xenomorph/proc/process_tunnel(turf/target)
- if(!tunnel)
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_BURROW_DIGGING))
return
- if(world.time > tunnel_timer)
- tunnel = FALSE
- do_tunnel(target)
- if(tunnel && target)
- addtimer(CALLBACK(src, PROC_REF(process_tunnel), target), 1 SECONDS)
+ if(world.time > digging_timer)
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_BURROW_DIGGING, TRAIT_SOURCE_ABILITY("burrow_digging"))
+ do_digging(target_atom)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROW_DIGGING) && target_atom)
+ addtimer(CALLBACK(src, PROC_REF(process_digging), target_atom), 1 SECONDS)
-/mob/living/carbon/xenomorph/proc/do_tunnel(turf/target)
- to_chat(src, SPAN_NOTICE("We tunnel to the destination."))
- anchored = FALSE
- forceMove(target)
+/datum/action/xeno_action/activable/burrow/proc/do_digging(turf/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ to_chat(xeno, SPAN_NOTICE("We tunnel to the destination."))
+ xeno.anchored = FALSE
+ xeno.forceMove(target_atom)
+ end_duration_display()
burrow_off()
-/mob/living/carbon/xenomorph/proc/do_tunnel_cooldown()
- used_tunnel = FALSE
- to_chat(src, SPAN_NOTICE("We can now tunnel while burrowed."))
- for(var/X in actions)
- var/datum/action/act = X
- act.update_button_icon()
+/datum/action/xeno_action/activable/burrow/proc/do_digging_cooldown()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ used_digging = FALSE
+ to_chat(xeno, SPAN_NOTICE("We can now tunnel while burrowed."))
+ update_button_icon()
-/datum/action/xeno_action/onclick/tremor/use_ability(atom/target)
- var/mob/living/carbon/xenomorph/burrower_tremor = owner
- if(HAS_TRAIT(burrower_tremor, TRAIT_ABILITY_BURROWED))
- to_chat(burrower_tremor, SPAN_XENOWARNING("We must be above ground to do this."))
- return
- if(burrower_tremor.is_ventcrawling)
- to_chat(burrower_tremor, SPAN_XENOWARNING("We must be above ground to do this."))
- return
- if(!action_cooldown_check())
- return
+/datum/action/xeno_action/onclick/tremor/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
- if(!burrower_tremor.check_state())
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED))
+ to_chat(xeno, SPAN_XENOWARNING("We must be above ground to do this."))
return
- if(!check_and_use_plasma_owner())
+ if(xeno.is_ventcrawling)
+ to_chat(xeno, SPAN_XENOWARNING("We must be above ground to do this."))
return
- playsound(burrower_tremor, 'sound/effects/alien_footstep_charge3.ogg', 75, 0)
- to_chat(burrower_tremor, SPAN_XENOWARNING("We dig ourselves into the ground and cause tremors."))
- burrower_tremor.create_stomp()
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
+ playsound(xeno, 'sound/effects/alien_footstep_charge3.ogg', 75, 0)
+ to_chat(xeno, SPAN_XENOWARNING("We dig ourselves into the ground and cause tremors."))
+ xeno.create_stomp()
- for(var/mob/living/carbon/carbon_target in range(7, burrower_tremor))
+ for(var/mob/living/carbon/carbon_target in range(7, xeno))
to_chat(carbon_target, SPAN_WARNING("You struggle to remain on your feet as the ground shakes beneath your feet!"))
shake_camera(carbon_target, 2, 3)
- if(get_dist(burrower_tremor, carbon_target) <= 3 && !burrower_tremor.can_not_harm(carbon_target))
+ if(get_dist(xeno, carbon_target) <= 3 && !xeno.can_not_harm(carbon_target))
if(carbon_target.mob_size >= MOB_SIZE_BIG)
carbon_target.apply_effect(1, SLOW)
else
@@ -320,96 +314,97 @@
apply_cooldown()
return ..()
-/datum/action/xeno_action/onclick/build_tunnel/use_ability(atom/A)
- var/mob/living/carbon/xenomorph/xenomorph = owner
- if(!xenomorph.check_state())
- return
- if(xenomorph.action_busy)
- to_chat(xenomorph, SPAN_XENOWARNING("We should finish up what we're doing before digging."))
+
+/datum/action/xeno_action/onclick/build_tunnel/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ XENO_ACTION_CHECK(xeno)
+
+ if(xeno.action_busy)
+ to_chat(xeno, SPAN_XENOWARNING("We should finish up what we're doing before digging."))
return
- var/turf/turf = xenomorph.loc
+ var/turf/turf = xeno.loc
if(!istype(turf)) //logic
- to_chat(xenomorph, SPAN_XENOWARNING("We can't do that from there."))
+ to_chat(xeno, SPAN_XENOWARNING("We can't do that from there."))
return
var/area/current_area = get_area(turf)
if(!turf.can_dig_xeno_tunnel() || !is_ground_level(turf.z) || current_area.flags_area & AREA_NOTUNNEL)
- to_chat(xenomorph, SPAN_XENOWARNING("We scrape around, but we can't seem to dig through that kind of floor."))
+ to_chat(xeno, SPAN_XENOWARNING("We scrape around, but we can't seem to dig through that kind of floor."))
return
- if(locate(/obj/structure/tunnel) in xenomorph.loc)
- to_chat(xenomorph, SPAN_XENOWARNING("There already is a tunnel here."))
+ if(locate(/obj/structure/tunnel) in xeno.loc)
+ to_chat(xeno, SPAN_XENOWARNING("There already is a tunnel here."))
return
- if(locate(/obj/structure/machinery/sentry_holder/landing_zone) in xenomorph.loc)
- to_chat(xenomorph, SPAN_XENOWARNING("We can't dig a tunnel with this object in the way."))
+ if(locate(/obj/structure/machinery/sentry_holder/landing_zone) in xeno.loc)
+ to_chat(xeno, SPAN_XENOWARNING("We can't dig a tunnel with this object in the way."))
return
- if(xenomorph.tunnel_delay)
- to_chat(xenomorph, SPAN_XENOWARNING("We are not ready to dig a tunnel again."))
+ if(xeno.tunnel_delay)
+ to_chat(xeno, SPAN_XENOWARNING("We are not ready to dig a tunnel again."))
return
- if(xenomorph.get_active_hand())
- to_chat(xenomorph, SPAN_XENOWARNING("We need an empty claw for this!"))
+ if(xeno.get_active_hand())
+ to_chat(xeno, SPAN_XENOWARNING("We need an empty claw for this!"))
return
- if(!xenomorph.check_plasma(plasma_cost))
+ if(!xeno.check_plasma(plasma_cost))
return
- var/area/AR = get_area(turf)
+ var/area/target_area = get_area(turf)
- if(isnull(AR) || !(AR.is_resin_allowed))
- if(!AR || AR.flags_area & AREA_UNWEEDABLE)
- to_chat(xenomorph, SPAN_XENOWARNING("This area is unsuited to host the hive!"))
+ if(isnull(target_area) || !(target_area.is_resin_allowed))
+ if(!target_area || target_area.flags_area & AREA_UNWEEDABLE)
+ to_chat(xeno, SPAN_XENOWARNING("This area is unsuited to host the hive!"))
return
- to_chat(xenomorph, SPAN_XENOWARNING("It's too early to spread the hive this far."))
+ to_chat(xeno, SPAN_XENOWARNING("It's too early to spread the hive this far."))
return
- xenomorph.visible_message(SPAN_XENONOTICE("[xenomorph] begins digging out a tunnel entrance."),
+ xeno.visible_message(SPAN_XENONOTICE("[xeno] begins digging out a tunnel entrance."),
SPAN_XENONOTICE("We begin digging out a tunnel entrance."), null, 5)
- if(!do_after(xenomorph, 10 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
- to_chat(xenomorph, SPAN_WARNING("Our tunnel caves in as we stop digging it."))
+ if(!do_after(xeno, 10 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
+ to_chat(xeno, SPAN_WARNING("Our tunnel caves in as we stop digging it."))
return
- if(!xenomorph.check_plasma(plasma_cost))
+ if(!xeno.check_plasma(plasma_cost))
return
- xenomorph.visible_message(SPAN_XENONOTICE("\The [xenomorph] digs out a tunnel entrance."),
+ xeno.visible_message(SPAN_XENONOTICE("\The [xeno] digs out a tunnel entrance."),
SPAN_XENONOTICE("We dig out an entrance to the tunnel network."), null, 5)
- var/obj/structure/tunnel/tunnelobj = new(turf, xenomorph.hivenumber)
- xenomorph.tunnel_delay = 1
- addtimer(CALLBACK(src, PROC_REF(cooldown_end)), 4 MINUTES)
+ var/obj/structure/tunnel/tunnelobj = new(turf, xeno.hivenumber)
+ xeno.tunnel_delay = 1
+ addtimer(CALLBACK(xeno, PROC_REF(cooldown_end)), 4 MINUTES)
var/msg = strip_html(input("Add a description to the tunnel:", "Tunnel Description") as text|null)
msg = replace_non_alphanumeric_plus(msg)
var/description
if(msg)
description = msg
msg = "[msg] ([get_area_name(tunnelobj)])"
- log_admin("[key_name(xenomorph)] has named a new tunnel \"[msg]\".")
- msg_admin_niche("[xenomorph]/([key_name(xenomorph)]) has named a new tunnel \"[msg]\".")
+ log_admin("[key_name(xeno)] has named a new tunnel \"[msg]\".")
+ msg_admin_niche("[xeno]/([key_name(xeno)]) has named a new tunnel \"[msg]\".")
tunnelobj.tunnel_desc = "[msg]"
- if(xenomorph.hive.living_xeno_queen || xenomorph.hive.allow_no_queen_actions)
- for(var/mob/living/carbon/xenomorph/target_for_message as anything in xenomorph.hive.totalXenos)
+ if(xeno.hive.living_xeno_queen || xeno.hive.allow_no_queen_actions)
+ for(var/mob/living/carbon/xenomorph/target_for_message as anything in xeno.hive.totalXenos)
var/overwatch_target = XENO_OVERWATCH_TARGET_HREF
var/overwatch_src = XENO_OVERWATCH_SRC_HREF
- to_chat(target_for_message, SPAN_XENOANNOUNCE("Hive: A new tunnel[description ? " ([description])" : ""] has been created by [xenomorph] (watch) at [get_area_name(tunnelobj)]."))
+ to_chat(target_for_message, SPAN_XENOANNOUNCE("Hive: A new tunnel[description ? " ([description])" : ""] has been created by [xeno] (watch) at [get_area_name(tunnelobj)]."))
- xenomorph.use_plasma(plasma_cost)
- to_chat(xenomorph, SPAN_NOTICE("We will be ready to dig a new tunnel in 4 minutes."))
- playsound(xenomorph.loc, 'sound/weapons/pierce.ogg', 25, 1)
+ xeno.use_plasma(plasma_cost)
+ to_chat(xeno, SPAN_NOTICE("We will be ready to dig a new tunnel in 4 minutes."))
+ playsound(xeno.loc, 'sound/weapons/pierce.ogg', 25, 1)
apply_cooldown()
return ..()
-
/datum/action/xeno_action/onclick/build_tunnel/proc/cooldown_end()
- var/mob/living/carbon/xenomorph/xenomorph = owner
- to_chat(xenomorph, SPAN_NOTICE("We are ready to dig a tunnel again."))
- xenomorph.tunnel_delay = 0
+ var/mob/living/carbon/xenomorph/xeno = owner
+ to_chat(xeno, SPAN_NOTICE("We are ready to dig a tunnel again."))
+ xeno.tunnel_delay = 0
-/mob/living/carbon/xenomorph/burrower/try_fill_trap(obj/effect/alien/resin/trap/target)
+/mob/living/carbon/xenomorph/burrower/try_fill_trap(obj/effect/alien/resin/trap/target_trap)
. = ..()
if(.)
- target.set_state(RESIN_TRAP_ACID3)
+ target_trap.set_state(RESIN_TRAP_ACID3)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm b/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm
index 8196ea906bbf2..d47a1073161af 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm
@@ -247,7 +247,6 @@
else
to_chat(src, SPAN_WARNING("We can't carry more facehuggers on you."))
-
/mob/living/carbon/xenomorph/carrier/proc/throw_hugger(atom/object)
if(!object)
return
@@ -318,8 +317,8 @@
SPAN_XENOWARNING("We throw a facehugger towards \the [object]!"))
addtimer(CALLBACK(src, PROC_REF(update_action_buttons)), caste.hugger_throw_delay) // no idea why hugger_throw_delay is a parent since its only really used by this file but whatever
-/mob/living/carbon/xenomorph/carrier/proc/store_egg(obj/item/xeno_egg/E)
- if(E.hivenumber != hivenumber)
+/mob/living/carbon/xenomorph/carrier/proc/store_egg(obj/item/xeno_egg/target_egg)
+ if(target_egg.hivenumber != hivenumber)
to_chat(src, SPAN_WARNING("That egg is tainted!"))
return
if(eggs_cur < eggs_max)
@@ -327,9 +326,9 @@
eggs_cur++
behavior_delegate?.on_update_icons()
to_chat(src, SPAN_NOTICE("We store the egg and carry it for safekeeping. Now sheltering: [eggs_cur] / [eggs_max]."))
- qdel(E)
+ qdel(target_egg)
else
- to_chat(src, SPAN_WARNING("This [E.name] looks too unhealthy."))
+ to_chat(src, SPAN_WARNING("This [target_egg.name] looks too unhealthy."))
else
to_chat(src, SPAN_WARNING("We can't carry more eggs on ourselves."))
@@ -342,35 +341,35 @@
//target a hugger on the ground to store it directly
if(istype(object, /obj/item/xeno_egg))
- var/obj/item/xeno_egg/E = object
- if(isturf(E.loc) && Adjacent(E))
- var/turf/egg_turf = E.loc
- store_egg(E)
+ var/obj/item/xeno_egg/target_egg = object
+ if(isturf(target_egg.loc) && Adjacent(target_egg))
+ var/turf/egg_turf = target_egg.loc
+ store_egg(target_egg)
//Grab all the eggs from the turf
if(eggs_cur < eggs_max)
- for(E in egg_turf)
+ for(target_egg in egg_turf)
if(eggs_cur < eggs_max)
- store_egg(E)
+ store_egg(target_egg)
return
if(istype(object, /obj/effect/alien/resin/special/eggmorph))
store_eggs_into_egg_morpher(object)
return
- var/obj/item/xeno_egg/E = get_active_hand()
- if(!E) //empty active hand
+ var/obj/item/xeno_egg/target_egg = get_active_hand()
+ if(!target_egg) //empty active hand
//if no hugger in active hand, we take one from our storage
if(eggs_cur <= 0)
to_chat(src, SPAN_WARNING("We don't have any eggs to use!"))
return
- E = new(src, hivenumber)
+ target_egg = new(src, hivenumber)
eggs_cur--
behavior_delegate?.on_update_icons()
- put_in_active_hand(E)
+ put_in_active_hand(target_egg)
to_chat(src, SPAN_XENONOTICE("We grab one of the eggs in our storage. Now sheltering: [eggs_cur] / [eggs_max]."))
return
- if(!istype(E)) //something else in our hand
+ if(!istype(target_egg)) //something else in our hand
to_chat(src, SPAN_WARNING("We need an empty hand to grab one of our stored eggs!"))
return
@@ -454,6 +453,12 @@
carrier_owner.throw_hugger(target)
return ..()
+/datum/action/xeno_action/activable/throw_hugger/action_cooldown_check()
+ if(owner)
+ var/mob/living/carbon/xenomorph/carrier/alien = owner
+ return world.time >= alien.hugger_throw_cooldown // i think
+ return TRUE //When we first add the ability we still do this check, but owner is null, so a workaround
+
/datum/action/xeno_action/activable/retrieve_egg/use_ability(atom/target)
var/mob/living/carbon/xenomorph/carrier/carrier_owner = owner
carrier_owner.retrieve_egg(target)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm b/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm
index d38205214a601..a828c922c714b 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Crusher.dm
@@ -76,140 +76,130 @@
pelt = /obj/item/pelt/crusher
// Refactored to handle all of crusher's interactions with object during charge.
-/mob/living/carbon/xenomorph/proc/handle_collision(atom/target)
- if(!target)
+/mob/living/carbon/xenomorph/proc/handle_collision(atom/target_atom)
+ if(!target_atom)
return FALSE
- var/handled = FALSE
+ //Barricade collision
+ else if(istype(target_atom, /obj/structure/barricade))
+ var/obj/structure/barricade/blockade_in_path = target_atom
+ visible_message(SPAN_DANGER("[src] rams into [blockade_in_path] and skids to a halt!"), SPAN_XENOWARNING("We ram into [blockade_in_path] and skid to a halt!"))
- //Check all machinery first
- if(istype(target, /obj/structure/machinery))
- if(istype(target, /obj/structure/machinery/m56d_hmg))
- handled = TRUE
- var/obj/structure/machinery/m56d_hmg/weapon_in_path = target
- visible_message(SPAN_DANGER("[src] rams [weapon_in_path]!"), SPAN_XENODANGER("We ram [weapon_in_path]!"))
- playsound(loc, "punch", 25, 1)
- weapon_in_path.CrusherImpact()
+ blockade_in_path.Collided(src)
+ . = FALSE
+
+ else if(istype(target_atom, /obj/vehicle/multitile))
+ var/obj/vehicle/multitile/vehicle_in_path = target_atom
+ visible_message(SPAN_DANGER("[src] rams into [vehicle_in_path] and skids to a halt!"), SPAN_XENOWARNING("We ram into [vehicle_in_path] and skid to a halt!"))
+
+ vehicle_in_path.Collided(src)
+ . = FALSE
+
+ else if(istype(target_atom, /obj/structure/machinery/m56d_hmg))
+ var/obj/structure/machinery/m56d_hmg/weapon_in_path = target_atom
+ visible_message(SPAN_DANGER("[src] rams [weapon_in_path]!"), SPAN_XENODANGER("We ram [weapon_in_path]!"))
+ playsound(loc, "punch", 25, 1)
+ weapon_in_path.CrusherImpact()
+ . = FALSE
+
+ else if(istype(target_atom, /obj/structure/window))
+ var/obj/structure/window/window_in_path = target_atom
+ if (window_in_path.unacidable)
. = FALSE
- else if(istype(target, /obj/structure/machinery/door/airlock))
- handled = TRUE
- var/obj/structure/machinery/door/airlock/airlock_in_path = target
- if(airlock_in_path.unacidable)
- . = FALSE
- else
- airlock_in_path.deconstruct()
-
- else if(istype(target, /obj/structure/machinery/defenses))
- handled = TRUE
- var/obj/structure/machinery/defenses/defenses_in_path = target
- visible_message(SPAN_DANGER("[src] rams [defenses_in_path]!"), SPAN_XENODANGER("We ram [defenses_in_path]!"))
- if(!defenses_in_path.unacidable)
- playsound(loc, "punch", 25, 1)
- defenses_in_path.stat |= DEFENSE_DAMAGED
- defenses_in_path.update_health(melee_damage_upper)
+ else if (istype(target_atom, /obj/structure/machinery/door/airlock))
+ var/obj/structure/machinery/door/airlock/airlock_in_path = target_atom
+
+ if(airlock_in_path.unacidable)
. = FALSE
+ else
+ airlock_in_path.deconstruct()
- else if(istype(target, /obj/structure/machinery/vending))
- handled = TRUE
- var/obj/structure/machinery/vending/vending_in_path = target
- if(vending_in_path.unslashable)
- . = FALSE
- else
- visible_message(SPAN_DANGER("[src] smashes straight into [vending_in_path]!"), SPAN_XENODANGER("We smash straight into [vending_in_path]!"))
- playsound(loc, "punch", 25, 1)
- vending_in_path.tip_over()
- var/turf/turfs_charged_at = get_diagonal_step(vending_in_path, dir)
- turfs_charged_at = get_step_away(turfs_charged_at, src)
- throw_atom(turfs_charged_at, range=1, speed=2)
- . = TRUE
+ else if(istype(target_atom, /obj/structure/grille))
+ var/obj/structure/grille/grille_in_path = target_atom
+ if(grille_in_path.unacidable)
+ . = FALSE
+ else
+ grille_in_path.health -= 80 //Usually knocks it down.
+ grille_in_path.healthcheck()
+ . = TRUE
- else if(istype(target, /obj/structure/machinery/cm_vending))
- handled = TRUE
- var/obj/structure/machinery/cm_vending/vending_in_path = target
- if(vending_in_path.unslashable)
- . = FALSE
- else
- visible_message(SPAN_DANGER("[src] smashes straight into [vending_in_path]!"), SPAN_XENODANGER("We smash straight into [vending_in_path]!"))
- playsound(loc, "punch", 25, 1)
- vending_in_path.tip_over()
- var/turf/turfs_charged_at = get_diagonal_step(vending_in_path, dir)
- turfs_charged_at = get_step_away(turfs_charged_at, src)
- throw_atom(turfs_charged_at, range=1, speed=2)
- . = TRUE
+ else if(istype(target_atom, /obj/structure/surface/table))
+ var/obj/structure/surface/table/table_in_path = target_atom
+ table_in_path.Crossed(src)
+ . = TRUE
+
+ else if(istype(target_atom, /obj/structure/machinery/defenses))
+ var/obj/structure/machinery/defenses/defenses_in_path = target_atom
+ visible_message(SPAN_DANGER("[src] rams [defenses_in_path]!"), SPAN_XENODANGER("We ram [defenses_in_path]!"))
- else if(istype(target, /obj/structure/machinery/fuelpump))
- handled = TRUE
- var/obj/structure/machinery/fuelpump/pump_in_path = target
- visible_message(SPAN_DANGER("[src] rams [pump_in_path]!"), SPAN_XENODANGER("We ram [pump_in_path]!"))
+ if (!defenses_in_path.unacidable)
playsound(loc, "punch", 25, 1)
- pump_in_path.update_health(melee_damage_upper)
- . = FALSE
+ defenses_in_path.stat = 1
+ defenses_in_path.update_icon()
+ defenses_in_path.update_health(40)
- // Check all structures next
- else if(istype(target, /obj/structure))
- if(istype(target, /obj/structure/barricade))
- handled = TRUE
- var/obj/structure/barricade/blockade_in_path = target
- visible_message(SPAN_DANGER("[src] rams into [blockade_in_path] and skids to a halt!"), SPAN_XENOWARNING("We ram into [blockade_in_path] and skid to a halt!"))
- blockade_in_path.Collided(src)
- . = FALSE
+ . = FALSE
- else if(istype(target, /obj/structure/window))
- handled = TRUE
- var/obj/structure/window/window_in_path = target
- if (window_in_path.unacidable)
- . = FALSE
- else
- window_in_path.deconstruct(FALSE)
- . = TRUE // Continue throw
- playsound(loc, 'sound/effects/Glassbr1.ogg')
-
- else if(istype(target, /obj/structure/grille))
- handled = TRUE
- var/obj/structure/grille/grille_in_path = target
- if(grille_in_path.unacidable)
- . = FALSE
- else
- grille_in_path.health -= 80 //Usually knocks it down.
- grille_in_path.healthcheck()
- . = TRUE
+ else if(istype(target_atom, /obj/structure/machinery/vending))
+ var/obj/structure/machinery/vending/vending_in_path = target_atom
- else if(istype(target, /obj/structure/surface/table))
- handled = TRUE
- var/obj/structure/surface/table/table_in_path = target
- table_in_path.Crossed(src)
- . = TRUE
+ if(vending_in_path.unslashable)
+ . = FALSE
+ else
+ visible_message(SPAN_DANGER("[src] smashes straight into [vending_in_path]!"), SPAN_XENODANGER("We smash straight into [vending_in_path]!"))
+ playsound(loc, "punch", 25, 1)
+ vending_in_path.tip_over()
- else if(istype(target, /obj/structure/fence/electrified))
- handled = TRUE
- var/obj/structure/fence/electrified/fence = target
- if(fence.cut)
- . = FALSE
- else
- visible_message(SPAN_DANGER("[src] smashes into [fence]!"))
- fence.cut_grille()
- . = TRUE
+ var/impact_range = 1
+ var/turf/turfs_charged_at = get_diagonal_step(vending_in_path, dir)
+ turfs_charged_at = get_step_away(turfs_charged_at, src)
+ var/launch_speed = 2
+ launch_towards(turfs_charged_at, impact_range, launch_speed)
- // Vehicle?
- else if(istype(target, /obj/vehicle/multitile))
- handled = TRUE
- var/obj/vehicle/multitile/vehicle_in_path = target
- visible_message(SPAN_DANGER("[src] rams into [vehicle_in_path] and skids to a halt!"), SPAN_XENOWARNING("We ram into [vehicle_in_path] and skid to a halt!"))
- vehicle_in_path.Collided(src)
- . = FALSE
+ . = TRUE
- // Is it atleast an object?
- if(!handled && isobj(target))
- var/obj/object_in_path = target
- if(object_in_path.unacidable)
+ else if(istype(target_atom, /obj/structure/machinery/cm_vending))
+ var/obj/structure/machinery/cm_vending/vending_in_path = target_atom
+ if(vending_in_path.unslashable)
. = FALSE
- else if(object_in_path.anchored)
- visible_message(SPAN_DANGER("[src] crushes [object_in_path]!"), SPAN_XENODANGER("We crush [object_in_path]!"))
+ else
+ visible_message(SPAN_DANGER("[src] smashes straight into [vending_in_path]!"), SPAN_XENODANGER("We smash straight into [vending_in_path]!"))
playsound(loc, "punch", 25, 1)
- object_in_path.deconstruct(FALSE)
+ vending_in_path.tip_over()
+
+ var/impact_range = 1
+ var/turf/turfs_charged_at = get_diagonal_step(vending_in_path, dir)
+ turfs_charged_at = get_step_away(turfs_charged_at, src)
+ var/launch_speed = 2
+ throw_atom(turfs_charged_at, impact_range, launch_speed)
+
+ . = TRUE
+
+ else if(istype(target_atom, /obj/structure/fence/electrified))
+ var/obj/structure/fence/electrified/fence = target_atom
+ if(fence.cut)
+ . = FALSE
+ else
+ src.visible_message(SPAN_DANGER("[src] smashes into [fence]!"))
+ fence.cut_grille()
. = TRUE
+ // Anything else?
+ else
+ if(isobj(target_atom))
+ var/obj/objects_in_path = target_atom
+ if(objects_in_path.unacidable)
+ . = FALSE
+ else if(objects_in_path.anchored)
+ visible_message(SPAN_DANGER("[src] crushes [objects_in_path]!"), SPAN_XENODANGER("We crush [objects_in_path]!"))
+ if(length(objects_in_path.contents)) //Hopefully won't auto-delete things inside crushed stuff.
+ var/turf/turf_for_obj = get_turf(src)
+ for(var/atom/movable/stuff_to_move in turf_for_obj.contents) stuff_to_move.forceMove(turf_for_obj)
+
+ qdel(objects_in_path)
+ . = TRUE
+
else
if(object_in_path.buckled_mob)
object_in_path.unbuckle()
@@ -232,25 +222,24 @@
/// Utilized to update charging animation.
var/is_charging = FALSE
-/datum/behavior_delegate/crusher_base/melee_attack_additional_effects_target(mob/living/carbon/target)
-
- if (!isxeno_human(target))
+/datum/behavior_delegate/crusher_base/melee_attack_additional_effects_target(mob/living/carbon/target_carbon)
+ if(!isxeno_human(target_carbon))
return
- new /datum/effects/xeno_slow(target, bound_xeno, ttl = 2 SECONDS)
+ new /datum/effects/xeno_slow(target_carbon, bound_xeno, ttl = 2 SECONDS)
var/damage = bound_xeno.melee_damage_upper * aoe_slash_damage_reduction
var/base_cdr_amount = 1.5 SECONDS
var/cdr_amount = base_cdr_amount
- for (var/mob/living/carbon/aoe_targets in orange(1, target))
- if (aoe_targets.stat == DEAD)
+ for(var/mob/living/carbon/aoe_targets in orange(1, target_carbon))
+ if(aoe_targets.stat == DEAD)
continue
if(!isxeno_human(aoe_targets) || bound_xeno.can_not_harm(aoe_targets))
continue
- if (HAS_TRAIT(aoe_targets, TRAIT_NESTED))
+ if(HAS_TRAIT(aoe_targets, TRAIT_NESTED))
continue
cdr_amount += 0.5 SECONDS
@@ -273,19 +262,19 @@
aoe_targets.apply_armoured_damage(get_xeno_damage_slash(aoe_targets, damage), ARMOR_MELEE, BRUTE, bound_xeno.zone_selected)
var/datum/action/xeno_action/activable/pounce/crusher_charge/cAction = get_action(bound_xeno, /datum/action/xeno_action/activable/pounce/crusher_charge)
- if (!cAction.action_cooldown_check())
+ if(!cAction.action_cooldown_check())
cAction.reduce_cooldown(cdr_amount)
var/datum/action/xeno_action/onclick/crusher_shield/sAction = get_action(bound_xeno, /datum/action/xeno_action/onclick/crusher_shield)
- if (!sAction.action_cooldown_check())
+ if(!sAction.action_cooldown_check())
sAction.reduce_cooldown(base_cdr_amount)
/datum/behavior_delegate/crusher_base/append_to_stat()
. = list()
var/shield_total = 0
- for (var/datum/xeno_shield/XS in bound_xeno.xeno_shields)
- if (XS.shield_source == XENO_SHIELD_SOURCE_CRUSHER)
- shield_total += XS.amount
+ for(var/datum/xeno_shield/shielded_xeno in bound_xeno.xeno_shields)
+ if(shielded_xeno.shield_source == XENO_SHIELD_SOURCE_CRUSHER)
+ shield_total += shielded_xeno.amount
. += "Shield: [shield_total]"
@@ -294,29 +283,36 @@
bound_xeno.icon_state = "[bound_xeno.get_strain_icon()] Crusher Charging"
return TRUE
+/datum/action/xeno_action/activable/pounce/crusher_charge/New()
+ . = ..()
+ not_reducing_objects = typesof(/obj/structure/barricade) + typesof(/obj/structure/machinery/defenses)
+
+/datum/action/xeno_action/activable/pounce/crusher_charge/initialize_pounce_pass_flags()
+ pounce_pass_flags = PASS_CRUSHER_CHARGE
+
/datum/action/xeno_action/activable/pounce/crusher_charge/additional_effects_always()
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
+ if(!istype(xeno))
return
- for (var/mob/living/carbon/target in orange(1, get_turf(xeno)))
- if(xeno.can_not_harm(target))
+ for(var/mob/living/carbon/target_carbon in orange(1, get_turf(xeno)))
+ if(xeno.can_not_harm(target_carbon))
continue
- new /datum/effects/xeno_slow(target, xeno, ttl = 3.5 SECONDS)
- to_chat(target, SPAN_XENODANGER("You are slowed as the impact of [xeno] shakes the ground!"))
+ new /datum/effects/xeno_slow(target_carbon, xeno, ttl = 3.5 SECONDS)
+ to_chat(target_carbon, SPAN_XENODANGER("You are slowed as the impact of [xeno] shakes the ground!"))
-/datum/action/xeno_action/activable/pounce/crusher_charge/additional_effects(mob/living/target)
+/datum/action/xeno_action/activable/pounce/crusher_charge/additional_effects(mob/living/target_living)
var/mob/living/carbon/xenomorph/xeno = owner
- var/mob/living/carbon/target_to_check = target
- if (!isxeno_human(target))
+ var/mob/living/carbon/target_to_check = target_living
+ if(!isxeno_human(target_living))
return
- if (target_to_check.stat == DEAD)
+ if(target_to_check.stat == DEAD)
return
xeno.emote("roar")
- target.apply_effect(2, WEAKEN)
+ target_living.apply_effect(2, WEAKEN)
xeno.visible_message(SPAN_XENODANGER("[xeno] overruns [target_to_check], brutally trampling them underfoot!"), SPAN_XENODANGER("We brutalize [target_to_check] as we crush them underfoot!"))
target_to_check.apply_armoured_damage(get_xeno_damage_slash(target_to_check, direct_hit_damage), ARMOR_MELEE, BRUTE)
@@ -326,7 +322,7 @@
return
/datum/action/xeno_action/activable/pounce/crusher_charge/pre_windup_effects()
- RegisterSignal(owner, COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE, PROC_REF(check_directional_armor))
+ RegisterSignal(owner, COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE, PROC_REF(check_directional_projectile_armor))
var/mob/living/carbon/xenomorph/xeno_owner = owner
if(!istype(xeno_owner))
@@ -352,6 +348,7 @@
addtimer(CALLBACK(src, PROC_REF(undo_charging_icon)), 0.5 SECONDS) // let the icon be here for a bit, it looks cool
+
/datum/action/xeno_action/activable/pounce/crusher_charge/proc/undo_charging_icon()
var/mob/living/carbon/xenomorph/xeno_owner = owner
if(!istype(xeno_owner))
@@ -364,10 +361,10 @@
crusher_delegate.is_charging = FALSE
xeno_owner.update_icons()
-/datum/action/xeno_action/activable/pounce/crusher_charge/proc/check_directional_armor(mob/living/carbon/xenomorph/X, list/damagedata)
+/datum/action/xeno_action/activable/pounce/crusher_charge/proc/check_directional_projectile_armor(mob/living/carbon/xenomorph/xeno, list/damagedata)
SIGNAL_HANDLER
var/projectile_direction = damagedata["direction"]
- if(X.dir & REVERSE_DIR(projectile_direction))
+ if(xeno.dir & REVERSE_DIR(projectile_direction))
// During the charge windup, crusher gets an extra 15 directional armor in the direction its charging
damagedata["armor"] += frontal_armor
@@ -375,38 +372,31 @@
// This ties the pounce/throwing backend into the old collision backend
/mob/living/carbon/xenomorph/crusher/pounced_obj(obj/pounced_object)
var/datum/action/xeno_action/activable/pounce/crusher_charge/crusher_charge_action = get_action(src, /datum/action/xeno_action/activable/pounce/crusher_charge)
- if (istype(crusher_charge_action) && !crusher_charge_action.action_cooldown_check() && !(pounced_object.type in crusher_charge_action.not_reducing_objects))
+ if(istype(crusher_charge_action) && !crusher_charge_action.action_cooldown_check() && !(pounced_object.type in crusher_charge_action.not_reducing_objects))
crusher_charge_action.reduce_cooldown(50)
gain_plasma(10)
- if (!handle_collision(pounced_object)) // Check old backend
+ if(!handle_collision(pounced_object)) // Check old backend
obj_launch_collision(pounced_object)
/mob/living/carbon/xenomorph/crusher/pounced_turf(turf/pounced_turf)
pounced_turf.ex_act(EXPLOSION_THRESHOLD_VLOW, , create_cause_data(caste_type, src))
..(pounced_turf)
-/datum/action/xeno_action/onclick/crusher_stomp/use_ability(atom/Atom)
+/datum/action/xeno_action/onclick/crusher_stomp/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!action_cooldown_check())
- return
-
- if (!xeno.check_state())
- return
-
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
playsound(xeno, 'sound/effects/bang.ogg', 25)
xeno.visible_message(SPAN_XENODANGER("[xeno] smashes into the ground!"), SPAN_XENODANGER("We smash into the ground!"))
xeno.create_stomp()
- for (var/mob/living/carbon/targets in orange(distance, xeno))
+ for(var/mob/living/carbon/targets in orange(distance, xeno))
- if (targets.stat == DEAD || xeno.can_not_harm(targets))
+ if(targets.stat == DEAD || xeno.can_not_harm(targets))
continue
if(targets in get_turf(xeno))
@@ -426,24 +416,17 @@
var/mob/living/carbon/xenomorph/xeno = owner
var/mob/living/carbon/stomped_carbon
- if (!istype(xeno))
- return
-
- if (!action_cooldown_check())
+ if(!istype(xeno))
return
- if (!xeno.check_state())
- return
-
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
playsound(get_turf(xeno), 'sound/effects/bang.ogg', 25, 0)
xeno.visible_message(SPAN_XENODANGER("[xeno] smashes into the ground!"), SPAN_XENODANGER("We smash into the ground!"))
xeno.create_stomp()
- for (var/mob/living/carbon/target_to_stomp in get_turf(xeno)) // MOBS ONTOP
- if (target_to_stomp.stat == DEAD || xeno.can_not_harm(target_to_stomp))
+ for(var/mob/living/carbon/target_to_stomp in get_turf(xeno)) // MOBS ONTOP
+ if(target_to_stomp.stat == DEAD || xeno.can_not_harm(target_to_stomp))
continue
new effect_type_base(target_to_stomp, xeno, null, null, get_xeno_stun_duration(target_to_stomp, effect_duration))
@@ -457,8 +440,8 @@
target_to_stomp.last_damage_data = create_cause_data(xeno.caste_type, xeno)
target_to_stomp.emote("pain")
target_to_stomp = stomped_carbon
- for (var/mob/living/carbon/targets_to_get in orange(distance, get_turf(xeno))) // MOBS AROUND
- if (targets_to_get.stat == DEAD || xeno.can_not_harm(targets_to_get))
+ for(var/mob/living/carbon/targets_to_get in orange(distance, get_turf(xeno))) // MOBS AROUND
+ if(targets_to_get.stat == DEAD || xeno.can_not_harm(targets_to_get))
continue
if(targets_to_get.client)
shake_camera(targets_to_get, 10, 2)
@@ -469,20 +452,13 @@
apply_cooldown()
return ..()
-/datum/action/xeno_action/onclick/crusher_shield/use_ability(atom/Target)
+/datum/action/xeno_action/onclick/crusher_shield/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
- return
-
- if (!action_cooldown_check())
+ if(!istype(xeno))
return
- if (!xeno.check_state())
- return
-
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
xeno.visible_message(SPAN_XENOWARNING("[xeno] hunkers down and bolsters its defenses!"), SPAN_XENOHIGHDANGER("We hunker down and bolster our defenses!"))
button.icon_state = "template_active"
@@ -503,7 +479,7 @@
/datum/action/xeno_action/onclick/crusher_shield/proc/remove_explosion_immunity()
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
+ if(!istype(xeno))
return
xeno.explosivearmor_modifier -= 1000
@@ -512,16 +488,16 @@
/datum/action/xeno_action/onclick/crusher_shield/proc/remove_shield()
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
+ if(!istype(xeno))
return
var/datum/xeno_shield/found
- for (var/datum/xeno_shield/shield in xeno.xeno_shields)
- if (shield.shield_source == XENO_SHIELD_SOURCE_CRUSHER)
+ for(var/datum/xeno_shield/shield in xeno.xeno_shields)
+ if(shield.shield_source == XENO_SHIELD_SOURCE_CRUSHER)
found = shield
break
- if (istype(found))
+ if(istype(found))
found.on_removal()
qdel(found)
to_chat(xeno, SPAN_XENOHIGHDANGER("We feel our enhanced shield end!"))
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm b/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm
index c14045216b4ed..d325fde650445 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Defender.dm
@@ -64,26 +64,50 @@
pelt = /obj/item/pelt/defender
/mob/living/carbon/xenomorph/defender/handle_special_state()
- if(fortify)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY))
return TRUE
- if(crest_defense)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_CREST))
return TRUE
return FALSE
/mob/living/carbon/xenomorph/defender/handle_special_wound_states(severity)
. = ..()
- if(fortify)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY))
return "Defender_fortify_[severity]"
- if(crest_defense)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_CREST))
return "Defender_crest_[severity]"
/mob/living/carbon/xenomorph/defender/handle_special_backpack_states()
. = ..()
- if(fortify)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY))
return " Fortify"
- if(crest_defense)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_CREST))
return " Crest"
+/mob/living/carbon/xenomorph/defender/ex_act()
+ . = ..()
+ if(HAS_TRAIT(src, TRAIT_INCAPACITATED) && HAS_TRAIT(src, TRAIT_FLOORED))
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY))
+ var/datum/action/xeno_action/activable/fortify/fortify_used = get_action(src, /datum/action/xeno_action/activable/fortify)
+ fortify_used.stop_fortify()
+
+ if(HAS_TRAIT(src, TRAIT_ABILITY_CREST))
+ var/datum/action/xeno_action/onclick/toggle_crest/crest_used = get_action(src, /datum/action/xeno_action/onclick/toggle_crest)
+ crest_used.stop_crest()
+
+
+/mob/living/carbon/xenomorph/defender/death()
+ var/datum/action/xeno_action/activable/fortify/fortify_used = get_action(src, /datum/action/xeno_action/activable/fortify)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY))
+ fortify_used.stop_fortify()
+
+ var/datum/action/xeno_action/onclick/toggle_crest/crest_used = get_action(src, /datum/action/xeno_action/onclick/toggle_crest)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_CREST))
+ crest_used.stop_crest()
+
+ return ..()
+
+
/datum/behavior_delegate/defender_base
name = "Base Defender Behavior Delegate"
@@ -91,159 +115,149 @@
if(bound_xeno.stat == DEAD)
return
- if(bound_xeno.fortify && bound_xeno.health > 0)
- bound_xeno.icon_state = "[bound_xeno.get_strain_icon()] Defender Fortify"
- return TRUE
- if(bound_xeno.crest_defense && bound_xeno.health > 0)
- bound_xeno.icon_state = "[bound_xeno.get_strain_icon()] Defender Crest"
- return TRUE
+ if(!HAS_TRAIT(bound_xeno, TRAIT_INCAPACITATED) && !HAS_TRAIT(bound_xeno, TRAIT_FLOORED))
+ if(HAS_TRAIT(bound_xeno, TRAIT_ABILITY_FORTIFY) && bound_xeno.health > 0)
+ bound_xeno.icon_state = "[bound_xeno.get_strain_icon()] Defender Fortify"
+ return TRUE
+ if(HAS_TRAIT(bound_xeno, TRAIT_ABILITY_CREST) && bound_xeno.health > 0)
+ bound_xeno.icon_state = "[bound_xeno.get_strain_icon()] Defender Crest"
+ return TRUE
-/datum/action/xeno_action/onclick/toggle_crest/use_ability(atom/target)
- var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
- return
+ else
+ bound_xeno.icon_state = "[bound_xeno.get_strain_icon()] Defender Knocked Down"
- if(xeno.fortify)
- to_chat(xeno, SPAN_XENOWARNING("We cannot use abilities while fortified."))
- return
- if(!xeno.check_state())
+/datum/action/xeno_action/onclick/toggle_crest/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!istype(xeno))
return
- if(!action_cooldown_check())
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY))
+ to_chat(xeno, SPAN_XENOWARNING("We cannot use crest while fortified."))
return
- if(!xeno.crest_defense)
- RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(unconscious_check))
- headcrest_switch(xeno, TRUE)
- if(xeno.selected_ability != src)
- button.icon_state = "template_active"
+ XENO_ACTION_CHECK(xeno)
+
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CREST))
+ stop_crest()
else
- UnregisterSignal(owner, COMSIG_MOB_STATCHANGE)
- headcrest_switch(xeno, FALSE)
- if(xeno.selected_ability != src)
- button.icon_state = "template_xeno"
+ start_crest()
- apply_cooldown()
return ..()
-/datum/action/xeno_action/onclick/toggle_crest/proc/headcrest_switch(mob/living/carbon/xenomorph/xeno, crest_state)
- if(xeno.crest_defense == crest_state)
- return
-
- if(crest_state)
- to_chat(xeno, SPAN_XENOWARNING("We lower our crest."))
+/datum/action/xeno_action/onclick/toggle_crest/proc/start_crest()
+ var/mob/living/carbon/xenomorph/xeno = owner
- xeno.ability_speed_modifier += speed_debuff
- xeno.armor_deflection_buff += armor_buff
- xeno.crest_defense = TRUE
- xeno.mob_size = MOB_SIZE_BIG //knockback immune
- button.icon_state = "template_active"
- else
- to_chat(xeno, SPAN_XENOWARNING("We raise our crest."))
+ ADD_TRAIT(xeno, TRAIT_ABILITY_CREST, TRAIT_SOURCE_ABILITY("crest"))
+ to_chat(xeno, SPAN_XENOWARNING("We lower our crest."))
+ xeno.ability_speed_modifier += speed_debuff
+ xeno.armor_deflection_buff += armor_buff
+ xeno.mob_size = MOB_SIZE_BIG //knockback immune
+ button.icon_state = "template_active"
+ xeno.update_icons()
+ apply_cooldown()
- xeno.ability_speed_modifier -= speed_debuff
- xeno.armor_deflection_buff -= armor_buff
- xeno.crest_defense = FALSE
- xeno.mob_size = MOB_SIZE_XENO //no longer knockback immune
- button.icon_state = "template_xeno"
+/datum/action/xeno_action/onclick/toggle_crest/proc/stop_crest()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_CREST, TRAIT_SOURCE_ABILITY("crest"))
+ to_chat(xeno, SPAN_XENOWARNING("We raise our crest."))
+ xeno.ability_speed_modifier -= speed_debuff
+ xeno.armor_deflection_buff -= armor_buff
+ xeno.mob_size = MOB_SIZE_XENO //no longer knockback immune
+ button.icon_state = "template_xeno"
xeno.update_icons()
+ apply_cooldown()
+
+
// Defender Headbutt
/datum/action/xeno_action/activable/headbutt/use_ability(atom/target_atom)
- var/mob/living/carbon/xenomorph/fendy = owner
- if(!istype(fendy))
- return
-
- if(!isxeno_human(target_atom) || fendy.can_not_harm(target_atom))
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!istype(xeno))
return
- if(!fendy.check_state())
+ if(!isxeno_human(target_atom) || xeno.can_not_harm(target_atom))
return
- if(!action_cooldown_check())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- if(!check_and_use_plasma_owner())
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY) && !usable_while_fortified)
+ to_chat(xeno, SPAN_XENOWARNING("We cannot use headbutt while fortified."))
return
- if(fendy.fortify && !usable_while_fortified)
- to_chat(fendy, SPAN_XENOWARNING("We cannot use headbutt while fortified."))
+ var/mob/living/carbon/target_carbon = target_atom
+ if(target_carbon.stat == DEAD)
return
- var/mob/living/carbon/carbone = target_atom
- if(carbone.stat == DEAD)
- return
+ var/fortify = HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY)
+ var/crest_defense = HAS_TRAIT(xeno, TRAIT_ABILITY_CREST)
- var/distance = get_dist(fendy, carbone)
+ var/distance = get_dist(xeno, target_carbon)
- var/max_distance = 3 - (fendy.crest_defense * 2)
+ var/max_distance = 3 - (crest_defense ? 2 : 0)
if(distance > max_distance)
return
- if(!fendy.crest_defense)
+ if(!crest_defense)
apply_cooldown()
- fendy.throw_atom(get_step_towards(carbone, fendy), 3, SPEED_SLOW, fendy, tracking=TRUE)
- if(!fendy.Adjacent(carbone))
+ xeno.throw_atom(get_step_towards(target_carbon, xeno), 3, SPEED_SLOW, xeno, tracking=TRUE)
+ if(!xeno.Adjacent(target_carbon))
on_cooldown_end()
return
- carbone.last_damage_data = create_cause_data(fendy.caste_type, fendy)
- fendy.visible_message(SPAN_XENOWARNING("[fendy] rams [carbone] with its armored crest!"),
- SPAN_XENOWARNING("We ram [carbone] with our armored crest!"))
+ target_carbon.last_damage_data = create_cause_data(xeno.caste_type, xeno)
+ xeno.visible_message(SPAN_XENOWARNING("[xeno] rams [target_carbon] with its armored crest!"),
+ SPAN_XENOWARNING("We ram [target_carbon] with our armored crest!"))
- if(carbone.stat != DEAD && (!(carbone.status_flags & XENO_HOST) || !HAS_TRAIT(carbone, TRAIT_NESTED)))
+ if(target_carbon.stat != DEAD && (!(target_carbon.status_flags & XENO_HOST) || !HAS_TRAIT(target_carbon, TRAIT_NESTED)))
// -10 damage if their crest is down.
- var/damage = base_damage - (fendy.crest_defense * 10)
- carbone.apply_armoured_damage(get_xeno_damage_slash(carbone, damage), ARMOR_MELEE, BRUTE, "chest", 5)
+ var/damage = base_damage - (crest_defense ? 10 : 0)
+ target_carbon.apply_armoured_damage(get_xeno_damage_slash(target_carbon, damage), ARMOR_MELEE, BRUTE, "chest", 5)
- var/facing = get_dir(fendy, carbone)
- var/headbutt_distance = 1 + (fendy.crest_defense * 2) + (fendy.fortify * 2)
+ var/facing = get_dir(xeno, target_carbon)
+ var/headbutt_distance = 1 + (crest_defense ? 2 : 0) + (fortify ? 2 : 0)
// Hmm today I will kill a marine while looking away from them
- fendy.face_atom(carbone)
- fendy.animation_attack_on(carbone)
- fendy.flick_attack_overlay(carbone, "punch")
- fendy.throw_carbon(carbone, facing, headbutt_distance, SPEED_SLOW, shake_camera = FALSE, immobilize = FALSE)
- playsound(carbone,'sound/weapons/alien_claw_block.ogg', 50, 1)
+ xeno.face_atom(target_carbon)
+ xeno.animation_attack_on(target_carbon)
+ xeno.flick_attack_overlay(target_carbon, "punch")
+ xeno.throw_carbon(target_carbon, facing, headbutt_distance, SPEED_SLOW, shake_camera = FALSE, immobilize = FALSE)
+ playsound(target_carbon,'sound/weapons/alien_claw_block.ogg', 50, 1)
apply_cooldown()
return ..()
+
+
// Defender Tail Sweep
-/datum/action/xeno_action/onclick/tail_sweep/use_ability(atom/A)
+/datum/action/xeno_action/onclick/tail_sweep/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
+ if(!istype(xeno))
return
- if(!xeno.check_state())
- return
-
- if (!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(xeno)
- if(xeno.fortify)
- to_chat(src, SPAN_XENOWARNING("We cannot use tail swipe while fortified."))
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY))
+ to_chat(xeno, SPAN_XENOWARNING("We cannot use tail swipe while fortified."))
return
- if(xeno.crest_defense)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CREST))
xeno.balloon_alert(xeno, "our crest is lowered!", text_color = "#7d32bb", delay = 1 SECONDS)
return
xeno.visible_message(SPAN_XENOWARNING("[xeno] sweeps its tail in a wide circle!"),
SPAN_XENOWARNING("We sweep our tail in a wide circle!"))
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
xeno.spin_circle()
xeno.emote("tail")
var/sweep_range = 1
for(var/mob/living/carbon/human in orange(sweep_range, get_turf(xeno)))
- if (!isxeno_human(human) || xeno.can_not_harm(human))
+ if(!isxeno_human(human) || xeno.can_not_harm(human))
continue
if(human.stat == DEAD)
continue
@@ -264,74 +278,66 @@
apply_cooldown()
return ..()
+
+
// Defender Fortify
-/datum/action/xeno_action/activable/fortify/use_ability(atom/target)
+/datum/action/xeno_action/activable/fortify/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
+ if(!istype(xeno))
return
- if(xeno.crest_defense)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CREST))
xeno.balloon_alert(xeno, "our crest is lowered!", text_color = "#7d32bb", delay = 1 SECONDS)
return
- if(!xeno.check_state())
- return
-
- if (!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(xeno)
playsound(get_turf(xeno), 'sound/effects/stonedoor_openclose.ogg', 30, 1)
- if(!xeno.fortify)
- RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(unconscious_check))
- fortify_switch(xeno, TRUE)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY))
+ stop_fortify()
if(xeno.selected_ability != src)
- button.icon_state = "template_active"
+ button.icon_state = "template_xeno"
else
- UnregisterSignal(owner, COMSIG_MOB_STATCHANGE)
- fortify_switch(xeno, FALSE)
+ start_fortify()
if(xeno.selected_ability != src)
- button.icon_state = "template_xeno"
+ button.icon_state = "template_active"
+ xeno.update_icons()
apply_cooldown()
return ..()
-/datum/action/xeno_action/activable/fortify/action_activate()
- . = ..()
- ..()
+/datum/action/xeno_action/activable/fortify/proc/start_fortify()
var/mob/living/carbon/xenomorph/xeno = owner
- if(xeno.fortify && xeno.selected_ability != src)
- button.icon_state = "template_active"
-/datum/action/xeno_action/activable/fortify/action_deselect()
- ..()
+ RegisterSignal(xeno, COMSIG_XENO_ENTER_CRIT, PROC_REF(unconscious_check))
+ RegisterSignal(xeno, COMSIG_MOB_DEATH, PROC_REF(unconscious_check))
+ RegisterSignal(xeno, COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE, PROC_REF(check_directional_projectile_armor))
+
+ ADD_TRAIT(xeno, TRAIT_ABILITY_FORTIFY, TRAIT_SOURCE_ABILITY("fortify"))
+ to_chat(xeno, SPAN_XENOWARNING("We tuck ourself into a defensive stance."))
+
+ apply_modifiers(xeno, TRUE)
+ xeno.mob_size = MOB_SIZE_IMMOBILE //knockback immune
+ xeno.mob_flags &= ~SQUEEZE_UNDER_VEHICLES
+
+/datum/action/xeno_action/activable/fortify/proc/stop_fortify()
var/mob/living/carbon/xenomorph/xeno = owner
- if(xeno.fortify)
- button.icon_state = "template_active"
-/datum/action/xeno_action/activable/fortify/proc/fortify_switch(mob/living/carbon/xenomorph/xeno, fortify_state)
- if(xeno.fortify == fortify_state)
- return
+ UnregisterSignal(xeno, COMSIG_XENO_ENTER_CRIT)
+ UnregisterSignal(xeno, COMSIG_MOB_DEATH)
+ UnregisterSignal(xeno, COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE)
- if(fortify_state)
- to_chat(xeno, SPAN_XENOWARNING("We tuck ourself into a defensive stance."))
- RegisterSignal(owner, COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE, PROC_REF(check_directional_armor))
- xeno.mob_size = MOB_SIZE_IMMOBILE //knockback immune
- xeno.mob_flags &= ~SQUEEZE_UNDER_VEHICLES
- xeno.fortify = TRUE
- else
- to_chat(xeno, SPAN_XENOWARNING("We resume our normal stance."))
- REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Fortify"))
- xeno.anchored = FALSE
- UnregisterSignal(owner, COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE)
- xeno.mob_size = MOB_SIZE_XENO //no longer knockback immune
- xeno.mob_flags |= SQUEEZE_UNDER_VEHICLES
- xeno.fortify = FALSE
-
- apply_modifiers(xeno, fortify_state)
- xeno.update_icons()
+ REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Fortify"))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_FORTIFY, TRAIT_SOURCE_ABILITY("fortify"))
+ to_chat(xeno, SPAN_XENOWARNING("We resume our normal stance."))
-/datum/action/xeno_action/activable/fortify/proc/apply_modifiers(mob/living/carbon/xenomorph/xeno, fortify_state)
+ apply_modifiers(xeno, FALSE)
+ xeno.anchored = FALSE
+ xeno.mob_size = MOB_SIZE_XENO //no longer knockback immune
+ xeno.mob_flags |= SQUEEZE_UNDER_VEHICLES
+
+/datum/action/xeno_action/activable/fortify/proc/apply_modifiers(mob/living/carbon/xenomorph/xeno, fortify_state = FALSE)
if(fortify_state)
xeno.armor_deflection_buff += 30
xeno.armor_explosive_buff += 60
@@ -343,21 +349,16 @@
xeno.armor_explosive_buff -= 60
xeno.small_explosives_stun = TRUE
-/datum/action/xeno_action/activable/fortify/proc/check_directional_armor(mob/living/carbon/xenomorph/defendy, list/damagedata)
- SIGNAL_HANDLER
- var/projectile_direction = damagedata["direction"]
- // If the defender is facing the projectile.
- if(defendy.dir & REVERSE_DIR(projectile_direction))
- damagedata["armor"] += frontal_armor
-
-/datum/action/xeno_action/activable/fortify/proc/unconscious_check()
- SIGNAL_HANDLER
-
- UnregisterSignal(owner, COMSIG_MOB_STATCHANGE)
- fortify_switch(owner, FALSE)
+/datum/action/xeno_action/activable/fortify/action_activate()
+ . = ..()
+ ..()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY) && xeno.selected_ability != src)
+ button.icon_state = "template_active"
-/datum/action/xeno_action/onclick/toggle_crest/proc/unconscious_check()
- SIGNAL_HANDLER
+/datum/action/xeno_action/activable/fortify/action_deselect()
+ ..()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_FORTIFY))
+ button.icon_state = "template_active"
- UnregisterSignal(owner, COMSIG_MOB_STATCHANGE)
- headcrest_switch(owner, FALSE)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Despoiler.dm b/code/modules/mob/living/carbon/xenomorph/castes/Despoiler.dm
index 8f5f78f493127..26637675c50e3 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Despoiler.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Despoiler.dm
@@ -71,7 +71,7 @@
/mob/living/carbon/xenomorph/despoiler/proc/update_hypertension()
var/image/holder = hud_list[SPECIAL_HUD]
holder.overlays.Cut()
- if (stat == DEAD)
+ if(stat == DEAD)
return
var/datum/behavior_delegate/despoiler_base/delegate = behavior_delegate
@@ -98,7 +98,6 @@
/datum/behavior_delegate/despoiler_base
name = "Base Despoiler Behavior Delegate"
- var/next_ability_empowered = FALSE
var/image/empowered_overlay
// State
@@ -119,7 +118,7 @@
xeno.update_hypertension()
/datum/behavior_delegate/despoiler_base/on_life()
- if (last_hypertension_loss_time <= last_combat_time && last_combat_time + hypertension_loss_time <= world.time)
+ if(last_hypertension_loss_time <= last_combat_time && last_combat_time + hypertension_loss_time <= world.time)
hypertension_stacks = max(0, hypertension_stacks - 1)
var/mob/living/carbon/xenomorph/despoiler/xeno = bound_xeno
xeno.update_hypertension()
@@ -129,7 +128,7 @@
last_combat_time = world.time
/datum/behavior_delegate/despoiler_base/melee_attack_modify_burn_damage(original_damage, mob/living/carbon/target_carbon)
- if (!isxeno_human(target_carbon))
+ if(!isxeno_human(target_carbon))
return original_damage
increase_hypertension(100)
@@ -149,33 +148,32 @@
return original_damage + burn_damage
-/datum/action/xeno_action/activable/tail_stab/despoiler/ability_act(mob/living/carbon/xenomorph/stabbing_xeno, mob/living/carbon/target, obj/limb/limb, apply_behavior_delagate = FALSE)
+/datum/action/xeno_action/activable/tail_stab/despoiler/ability_act(mob/living/carbon/xenomorph/stabbing_xeno, mob/living/carbon/target_carbon, obj/limb/target_limb, apply_behavior_delagate = FALSE)
. = ..()
- var/datum/effects/acid/acid_effect = locate() in target.effects_list
+ var/datum/effects/acid/acid_effect = locate() in target_carbon.effects_list
if(!acid_effect)
return
- target.apply_armoured_damage(acid_effect.acid_level * 15, ARMOR_BIO, BURN, limb ? limb.name : "chest", acid_effect.acid_level * 10)
+ target_carbon.apply_armoured_damage(acid_effect.acid_level * 15, ARMOR_BIO, BURN, target_limb ? target_limb.name : "chest", acid_effect.acid_level * 10)
/datum/action/xeno_action/activable/acid_barrage/on_select(mob/user)
RegisterSignal(user, COMSIG_MOB_MOUSEDOWN, PROC_REF(on_mouse_down))
-/datum/action/xeno_action/activable/acid_barrage/proc/on_mouse_down(mob/source, atom/target, turf, skin_ctl, params)
+/datum/action/xeno_action/activable/acid_barrage/proc/on_mouse_down(mob/source, atom/target_atom, target_turf, skin_ctl, params)
SIGNAL_HANDLER
var/list/mods = params2list(params)
- source.click(target, mods)
+ source.click(target_atom, mods)
/datum/action/xeno_action/activable/acid_barrage/on_deselect(mob/user)
UnregisterSignal(user, COMSIG_MOB_MOUSEDOWN)
-/datum/action/xeno_action/activable/acid_barrage/use_ability(atom/target)
+/datum/action/xeno_action/activable/acid_barrage/use_ability(atom/target_atom)
. = ..()
var/mob/living/carbon/xenomorph/despoiler/xeno = owner
if(!action_cooldown_check())
to_chat(xeno, SPAN_WARNING("We must wait for our spit glands to refill."))
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
// Prevent some mouse down shenangians
apply_cooldown()
@@ -202,7 +200,7 @@
/datum/action/xeno_action/activable/acid_barrage/proc/notify_max_charge()
to_chat(owner, SPAN_XENOHIGHDANGER("Our acid barrage is full!"))
-/datum/action/xeno_action/activable/acid_barrage/proc/release_barrage(atom/source, atom/target, turf, skin_ctl, params)
+/datum/action/xeno_action/activable/acid_barrage/proc/release_barrage(atom/source, atom/target_atom, turf, skin_ctl, params)
SIGNAL_HANDLER
// The real cooldown starts here
apply_cooldown_override(xeno_cooldown)
@@ -220,8 +218,8 @@
var/datum/behavior_delegate/despoiler_base/delegate = xeno.behavior_delegate
var/time_charged = min(world.time - start_time, max_charge_time)
var/modifier = 0
- if(delegate.next_ability_empowered)
- delegate.next_ability_empowered = FALSE
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER, TRAIT_SOURCE_ABILITY("catalyze_empower"))
modifier += empower_modifier
xeno.overlays -= delegate.empowered_overlay
@@ -229,7 +227,7 @@
playsound(xeno, "alien_roarhiss", 30, 0, status = 0)
playsound(xeno.loc, "acid_spit", 25, 1)
for(var/index in 1 to barrage_size)
- var/initial_angle = Get_Angle(xeno, target)
+ var/initial_angle = Get_Angle(xeno, target_atom)
var/rand_angle = rand(-scatter, scatter)
var/turf/new_target = get_angle_target_turf(xeno, initial_angle + rand_angle, rand(1, 6))
var/obj/projectile/proj = new (get_turf(xeno), create_cause_data(xeno.ammo.name, xeno))
@@ -242,10 +240,11 @@
proj.def_zone = xeno.get_limbzone_target()
proj.fire_at(new_target, xeno, xeno, xeno.ammo.max_range, xeno.ammo.shell_speed)
-/datum/action/xeno_action/activable/pounce/caustic_embrace/use_ability(atom/target)
+
+
+/datum/action/xeno_action/activable/pounce/caustic_embrace/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/despoiler/xeno = owner
- var/datum/behavior_delegate/despoiler_base/delegate = xeno.behavior_delegate
- if(delegate.next_ability_empowered)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER))
distance = empowered_distance
else
distance = initial(distance)
@@ -257,46 +256,46 @@
var/datum/behavior_delegate/despoiler_base/delegate = xeno.behavior_delegate
xeno.emote("roar")
- if(delegate.next_ability_empowered)
- delegate.next_ability_empowered = FALSE
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER, TRAIT_SOURCE_ABILITY("catalyze_empower"))
xeno.overlays -= delegate.empowered_overlay
return // Handled in additional_effects()
var/list/turfs = orange(1, get_turf(xeno)) - get_step(xeno.loc, REVERSE_DIR(xeno.dir))
- for(var/turf/turf in turfs)
- for(var/mob/living/carbon/human/target in turf)
- playsound(target.loc, "acid_strike", 25, 1)
- var/armor_block_acid = target.getarmor("chest", ARMOR_BIO)
+ for(var/turf/target_turf in turfs)
+ for(var/mob/living/carbon/human/target_human in target_turf)
+ playsound(target_human.loc, "acid_strike", 25, 1)
+ var/armor_block_acid = target_human.getarmor("chest", ARMOR_BIO)
var/n_acid_damage = armor_damage_reduction(GLOB.marine_melee, damage, armor_block_acid)
if(n_acid_damage <= 0.34*damage)
- to_chat(target, SPAN_WARNING("Your armor absorbs the acid!"))
+ to_chat(target_human, SPAN_WARNING("Your armor absorbs the acid!"))
else if(n_acid_damage <= 0.67*damage)
- to_chat(target, SPAN_WARNING("Your armor softens the acid!"))
- target.apply_damage(n_acid_damage, BURN, "chest")
+ to_chat(target_human, SPAN_WARNING("Your armor softens the acid!"))
+ target_human.apply_damage(n_acid_damage, BURN, "chest")
if(prob(30))
- new /obj/effect/lingering_acid(turf, xeno.hivenumber)
- new /obj/effect/xenomorph/xeno_telegraph/yellow(turf, 2)
+ new /obj/effect/lingering_acid(target_turf, xeno.hivenumber)
+ new /obj/effect/xenomorph/xeno_telegraph/yellow(target_turf, 2)
-/datum/action/xeno_action/activable/pounce/caustic_embrace/additional_effects(mob/living/carbon/target)
+/datum/action/xeno_action/activable/pounce/caustic_embrace/additional_effects(mob/living/carbon/target_carbon)
var/mob/living/carbon/xenomorph/despoiler/xeno = owner
- var/datum/behavior_delegate/despoiler_base/delegate = xeno.behavior_delegate
- if(!delegate.next_ability_empowered)
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER))
return
- xeno.visible_message(SPAN_XENODANGER("[xeno] ravages [target] as it charges at them!"), SPAN_XENODANGER("We ruthlessly ravage [target] as we charge at them!"))
- target.apply_effect(weaken_duration, WEAKEN)
- target.attack_alien(xeno, rand(xeno.melee_damage_lower, xeno.melee_damage_upper))
- xeno.flick_attack_overlay(target, "embrace_slash")
+ xeno.visible_message(SPAN_XENODANGER("[xeno] ravages [target_carbon] as it charges at them!"), SPAN_XENODANGER("We ruthlessly ravage [target_carbon] as we charge at them!"))
+ target_carbon.apply_effect(weaken_duration, WEAKEN)
+ target_carbon.attack_alien(xeno, rand(xeno.melee_damage_lower, xeno.melee_damage_upper))
+ xeno.flick_attack_overlay(target_carbon, "embrace_slash")
- var/datum/effects/acid/acid_effect = locate() in target.effects_list
+ var/datum/effects/acid/acid_effect = locate() in target_carbon.effects_list
if(!acid_effect)
- acid_effect = new /datum/effects/acid(target)
+ acid_effect = new /datum/effects/acid(target_carbon)
acid_effect.enhance_acid()
acid_effect.enhance_acid(TRUE)
+
/datum/action/xeno_action/onclick/oozing_wounds/use_ability()
. = ..()
@@ -307,35 +306,35 @@
to_chat(xeno, SPAN_WARNING("We must wait for our acid glands to refill."))
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
apply_cooldown()
playsound(xeno, "alien_roarhiss", 30, 0, status = 0)
var/severity = (xeno.health <= (0.7 * xeno.maxHealth)) + (xeno.health <= (0.3 * xeno.maxHealth))
var/acid_range = severity + 1
- var/empowered = delegate.next_ability_empowered
- if(empowered)
- delegate.next_ability_empowered = FALSE
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER, TRAIT_SOURCE_ABILITY("catalyze_empower"))
xeno.overlays -= delegate.empowered_overlay
- for(var/turf/turf in orange(acid_range, get_turf(xeno)))
- if(get_dist_sqrd(turf, xeno) > acid_range ** 2)
+ for(var/turf/target_turf in orange(acid_range, get_turf(xeno)))
+ if(get_dist_sqrd(target_turf, xeno) > acid_range ** 2)
continue
- addtimer(CALLBACK(src, PROC_REF(spawn_acid), xeno, turf, empowered), 0.2 SECONDS * get_dist(turf, xeno))
+ addtimer(CALLBACK(src, PROC_REF(spawn_acid), xeno, target_turf), 0.2 SECONDS * get_dist(target_turf, xeno))
-/datum/action/xeno_action/onclick/oozing_wounds/proc/spawn_acid(mob/living/carbon/xenomorph/xeno, turf/turf, empowered)
- if(empowered)
- new /obj/effect/xenomorph/spray/despoiler/empowered(turf, create_cause_data(initial(xeno.caste_type), src), xeno.hivenumber)
+/datum/action/xeno_action/onclick/oozing_wounds/proc/spawn_acid(mob/living/carbon/xenomorph/xeno, turf/target_turf)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER))
+ new /obj/effect/xenomorph/spray/despoiler/empowered(target_turf, create_cause_data(initial(xeno.caste_type), src), xeno.hivenumber)
else
- new /obj/effect/xenomorph/spray/despoiler(turf, create_cause_data(initial(xeno.caste_type), src), xeno.hivenumber)
+ new /obj/effect/xenomorph/spray/despoiler(target_turf, create_cause_data(initial(xeno.caste_type), src), xeno.hivenumber)
if(prob(20))
- new /obj/effect/lingering_acid(turf, xeno.hivenumber)
+ new /obj/effect/lingering_acid(target_turf, xeno.hivenumber)
+
-/datum/action/xeno_action/onclick/catalyze/use_ability(atom/target)
+
+/datum/action/xeno_action/onclick/catalyze/use_ability(atom/target_atom)
. = ..()
var/mob/living/carbon/xenomorph/despoiler/xeno = owner
var/datum/behavior_delegate/despoiler_base/delegate = xeno.behavior_delegate
@@ -344,8 +343,7 @@
to_chat(xeno, SPAN_WARNING("We must wait before empowering an ability again."))
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
if(delegate.hypertension_stacks < 1)
to_chat(xeno, SPAN_WARNING("We don't enough acid to do that."))
@@ -354,7 +352,7 @@
apply_cooldown()
delegate.hypertension_stacks--
- delegate.next_ability_empowered = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER, TRAIT_SOURCE_ABILITY("catalyze_empower"))
delegate.empowered_overlay = image('icons/mob/xenos/castes/tier_3/despoiler.dmi', "hypertension")
delegate.empowered_overlay.layer = FLY_LAYER
delegate.empowered_overlay.plane = ABOVE_GAME_PLANE
@@ -366,10 +364,12 @@
/datum/action/xeno_action/onclick/catalyze/proc/debuff_next_ability()
var/mob/living/carbon/xenomorph/despoiler/xeno = owner
var/datum/behavior_delegate/despoiler_base/delegate = xeno.behavior_delegate
- if(delegate.next_ability_empowered)
- to_chat(owner, SPAN_XENOHIGHDANGER("We waited too long, our next ability is no longer empowered!"))
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER))
+ to_chat(xeno, SPAN_XENOHIGHDANGER("We waited too long, our next ability is no longer empowered!"))
xeno.overlays -= delegate.empowered_overlay
- delegate.next_ability_empowered = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_CATALYZE_EMPOWER, TRAIT_SOURCE_ABILITY("catalyze_empower"))
+
+
/obj/effect/lingering_acid
name = "acid"
@@ -393,30 +393,31 @@
/obj/effect/lingering_acid/Initialize(mapload, hive)
. = ..()
- if (hive)
+ if(hive)
hivenumber = hive
var/decay_time = rand(15 SECONDS, 20 SECONDS)
animate(src, alpha = 127, time = decay_time)
QDEL_IN(src, decay_time)
-/obj/effect/lingering_acid/Crossed(atom/movable/movable)
+/obj/effect/lingering_acid/Crossed(atom/movable/target_movable)
. = ..()
- var/mob/living/carbon/carbon = movable
- if(!istype(carbon))
+ var/mob/living/carbon/target_carbon = target_movable
+ if(!istype(target_carbon))
return
- if(carbon.ally_of_hivenumber(hivenumber))
+ if(target_carbon.ally_of_hivenumber(hivenumber))
return
- if(HAS_TRAIT(carbon, TRAIT_HAULED))
+ if(HAS_TRAIT(target_carbon, TRAIT_HAULED))
return
playsound(loc, "sound/bullets/acid_impact1.ogg", 15)
- if(!isliving(movable))
+ if(!isliving(target_movable))
return
- var/mob/living/target_mob = movable
+ var/mob/living/target_mob = target_movable
if(!target_mob.ally_of_hivenumber(hivenumber))
target_mob.next_move_slowdown = max(target_mob.next_move_slowdown, slow_amt)
- carbon.apply_armoured_damage(damage, damage_type = BURN, def_zone = pick(target_limbs))
+ target_carbon.apply_armoured_damage(damage, damage_type = BURN, def_zone = pick(target_limbs))
+
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Hellhound.dm b/code/modules/mob/living/carbon/xenomorph/castes/Hellhound.dm
index f9b1ca723478e..498f871497751 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Hellhound.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Hellhound.dm
@@ -93,7 +93,7 @@
/mob/living/carbon/xenomorph/hellhound/initialize_pass_flags(datum/pass_flags_container/PF)
..()
- if (PF)
+ if(PF)
PF.flags_pass = PASS_FLAGS_CRAWLER
/mob/living/carbon/xenomorph/hellhound/Login()
@@ -173,7 +173,7 @@
playsound(hellhound_gorger, "giant_lizard_growl", 30)
playsound(carbon, "alien_bite", 30)
-/datum/action/xeno_action/onclick/sense_owner/use_ability(atom/layer)
+/datum/action/xeno_action/onclick/sense_owner/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/hellhound/xeno = owner
var/datum/behavior_delegate/hellhound_base/hound_owner = xeno.behavior_delegate
var/direction = -3
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm
index 9bd5e35cb8e34..e68296254a020 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm
@@ -71,28 +71,18 @@
/datum/behavior_delegate/lurker_base
name = "Base Lurker Behavior Delegate"
- // Config
- var/invis_recharge_time = 20 SECONDS
- var/invis_start_time = -1 // Special value for when we're not invisible
- 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
-
/datum/behavior_delegate/lurker_base/melee_attack_modify_damage(original_damage, mob/living/carbon/target_carbon)
- if (!isxeno_human(target_carbon))
+ if(!isxeno_human(target_carbon))
return original_damage
- if (next_slash_buffed)
+ if(HAS_TRAIT(bound_xeno, TRAIT_ABILITY_ASSASINATE))
to_chat(bound_xeno, SPAN_XENOHIGHDANGER("We significantly strengthen our attack, slowing [target_carbon]!"))
to_chat(target_carbon, SPAN_XENOHIGHDANGER("You feel a sharp pain as [bound_xeno] slashes you, slowing you down!"))
- original_damage *= buffed_slash_damage_ratio
- target_carbon.set_effect(get_xeno_stun_duration(target_carbon, 3), SUPERSLOW)
- next_slash_buffed = FALSE
var/datum/action/xeno_action/onclick/lurker_assassinate/ability = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_assassinate)
- if (ability)
+ original_damage *= ability.buffed_slash_damage_ratio
+ target_carbon.set_effect(get_xeno_stun_duration(target_carbon, 3), SUPERSLOW)
+ REMOVE_TRAIT(bound_xeno, TRAIT_ABILITY_ASSASINATE, TRAIT_SOURCE_ABILITY("assasinate"))
+ if(ability)
ability.button.icon_state = "template_xeno"
return original_damage
@@ -103,15 +93,19 @@
if(!isxeno_human(target_carbon))
return
- if(next_slash_buffed && target_carbon)
+ if(HAS_TRAIT(bound_xeno, TRAIT_ABILITY_ASSASINATE) && target_carbon)
return INTENT_HARM
/datum/behavior_delegate/lurker_base/melee_attack_additional_effects_target(mob/living/carbon/target_carbon)
- if (!isxeno_human(target_carbon))
+ if(!isxeno_human(target_carbon))
+ return
+
+ var/datum/action/xeno_action/onclick/lurker_assassinate/lurker_ass = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_assassinate)
+ if(!lurker_ass)
return
- if (HAS_TRAIT(target_carbon, TRAIT_FLOORED))
- new /datum/effects/xeno_slow(target_carbon, bound_xeno, null, null, get_xeno_stun_duration(target_carbon, slash_slow_duration))
+ if(HAS_TRAIT(target_carbon, TRAIT_FLOORED))
+ new /datum/effects/xeno_slow(target_carbon, bound_xeno, null, null, get_xeno_stun_duration(target_carbon, lurker_ass.slash_slow_duration))
return
@@ -119,69 +113,19 @@
..()
var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility)
- if (lurker_invis_action)
+ if(lurker_invis_action)
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_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility)
- if(istype(lurker_invis_action))
- lurker_invis_action.invisibility_off(0.5) // Partial refund of remaining time
-
-/// Implementation for enabling invisibility.
-/datum/behavior_delegate/lurker_base/proc/on_invisibility()
- var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_action(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker)
- 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
- 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_action(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker)
- 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)
- invis_start_time = -1
-
-/datum/behavior_delegate/lurker_base/append_to_stat()
- . = list()
-
- // Invisible
- if(invis_start_time != -1)
- var/time_left = (invis_duration-(world.time - invis_start_time)) / 10
- . += "Invisibility Remaining: [time_left] second\s."
- return
-
- var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility)
- if(!lurker_invisibility_action)
- return
-
- if(!bound_xeno.client?.prefs.show_cooldown_messages)
- return
-
- // Recharged
- if(lurker_invisibility_action.cooldown_timer_id == TIMER_ID_NULL)
- . += "Invisibility Recharge: Ready."
- return
-
- // Recharging
- var/time_left = timeleft(lurker_invisibility_action.cooldown_timer_id) / 10
- . += "Invisibility Recharge: [time_left] second\s."
-
/datum/behavior_delegate/lurker_base/on_collide(atom/movable/movable_atom)
. = ..()
if(!ishuman(movable_atom))
return
- if(!bound_xeno || !bound_xeno.stealth)
+ if(!bound_xeno)
+ return
+
+ if(!HAS_TRAIT(bound_xeno, TRAIT_ABILITY_INVIS))
return
var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility)
@@ -195,7 +139,6 @@
to_chat(bound_xeno, SPAN_XENOHIGHDANGER("We bumped into someone and lost our invisibility!"))
lurker_invisibility_action.invisibility_off(0.5) // partial refund of remaining time
-
/datum/action/xeno_action/activable/pounce/lurker/additional_effects(mob/living/living_mob)
var/mob/living/carbon/xenomorph/xeno = owner
if(!istype(xeno))
@@ -215,6 +158,11 @@
if(lurker_invis)
lurker_invis.invisibility_off() // Full cooldown
+/datum/action/xeno_action/activable/pounce/lurker/start_airbone()
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ ADD_TRAIT(xeno, TRAIT_ABILITY_POUNCE, TRAIT_SOURCE_ABILITY("pounce"))
+
/datum/action/xeno_action/activable/pounce/lurker/proc/remove_freeze(mob/living/carbon/xenomorph/xeno)
SIGNAL_HANDLER
@@ -229,19 +177,17 @@
var/mob/living/carbon/xenomorph/xeno = owner
return xeno.deselect_timer < world.time // We clicked the same ability in a very short time
-/datum/action/xeno_action/onclick/lurker_invisibility/use_ability(atom/targeted_atom)
+/datum/action/xeno_action/onclick/lurker_invisibility/use_ability()
var/mob/living/carbon/xenomorph/xeno = owner
if(!istype(xeno))
return
- if(!action_cooldown_check())
- return
- if(!check_and_use_plasma_owner())
- return
+
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
xeno.deselect_timer = world.time + 5 // Half a second to prevent double clicks
- if(xeno.stealth)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_INVIS))
invisibility_off(0.9) // Near full refund of remaining time
return ..()
@@ -252,14 +198,26 @@
xeno.speed_modifier -= speed_buff
xeno.recalculate_speed()
- var/datum/behavior_delegate/lurker_base/behavior = xeno.behavior_delegate
- behavior.on_invisibility()
+ on_invisibility()
// if we go off early, this also works fine.
- invis_timer_id = addtimer(CALLBACK(src, PROC_REF(invisibility_off)), duration, TIMER_STOPPABLE)
+ invis_timer_id = addtimer(CALLBACK(src, PROC_REF(invisibility_off)), invis_duration, TIMER_STOPPABLE)
return ..()
+/// Implementation for enabling invisibility.
+/datum/action/xeno_action/onclick/lurker_invisibility/proc/on_invisibility()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_action(xeno, /datum/action/xeno_action/activable/pounce/lurker)
+ if(lurker_pounce_action)
+ lurker_pounce_action.knockdown = TRUE // pounce knocks down
+ lurker_pounce_action.freeze_self = TRUE
+ ADD_TRAIT(xeno, TRAIT_CLOAKED, TRAIT_SOURCE_ABILITY("cloak"))
+ ADD_TRAIT(xeno, TRAIT_ABILITY_INVIS, TRAIT_SOURCE_ABILITY("invis"))
+ RegisterSignal(xeno, COMSIG_MOB_EFFECT_CLOAK_CANCEL, PROC_REF(decloak_handler))
+ invis_start_time = world.time
+ start_duration_display(invis_duration)
+
/// 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
@@ -268,7 +226,11 @@
if(!istype(xeno))
return
- if(owner.alpha == initial(owner.alpha) && !xeno.stealth)
+
+ if(owner.alpha == initial(owner.alpha))
+ return
+
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_INVIS))
return
if(invis_timer_id != TIMER_ID_NULL)
@@ -283,39 +245,41 @@
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]!")
-
- var/recharge_time = behavior.invis_recharge_time
- if(behavior.invis_start_time > 0) // Sanity
+ if(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/remaining = 1 - (world.time - invis_start_time) / invis_duration
+ invis_recharge_time = invis_recharge_time - remaining * refund_multiplier * invis_recharge_time
- behavior.on_invisibility_off()
+ apply_cooldown_override(invis_recharge_time)
+ end_duration_display()
+
+ var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_action(xeno, /datum/action/xeno_action/activable/pounce/lurker)
+ if(lurker_pounce_action)
+ lurker_pounce_action.knockdown = FALSE // pounce no longer knocks down
+ lurker_pounce_action.freeze_self = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_CLOAKED, TRAIT_SOURCE_ABILITY("cloak"))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_INVIS, TRAIT_SOURCE_ABILITY("invis"))
+ UnregisterSignal(xeno, COMSIG_MOB_EFFECT_CLOAK_CANCEL)
+ invis_start_time = -1
+
+/datum/action/xeno_action/onclick/lurker_invisibility/proc/decloak_handler()
+ SIGNAL_HANDLER
+ invisibility_off(0.5) // Partial refund of remaining time
/datum/action/xeno_action/onclick/lurker_invisibility/ability_cooldown_over()
if(owner.client?.prefs.show_cooldown_messages)
to_chat(owner, SPAN_XENOHIGHDANGER("We are ready to use our invisibility again!"))
..()
-/datum/action/xeno_action/onclick/lurker_assassinate/use_ability(atom/targeted_atom)
+/datum/action/xeno_action/onclick/lurker_assassinate/use_ability()
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
- return
-
- if (!action_cooldown_check())
+ if(!istype(xeno))
return
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- var/datum/behavior_delegate/lurker_base/behavior = xeno.behavior_delegate
- if (istype(behavior))
- behavior.next_slash_buffed = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_ASSASINATE, TRAIT_SOURCE_ABILITY("assasinate"))
to_chat(xeno, SPAN_XENOHIGHDANGER("Our next slash will deal increased damage!"))
@@ -327,13 +291,11 @@
/datum/action/xeno_action/onclick/lurker_assassinate/proc/unbuff_slash()
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
+ if(!istype(xeno))
+ return
+
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_ASSASINATE))
return
- var/datum/behavior_delegate/lurker_base/behavior = xeno.behavior_delegate
- if (istype(behavior))
- // In case slash has already landed
- if (!behavior.next_slash_buffed)
- return
- behavior.next_slash_buffed = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_ASSASINATE, TRAIT_SOURCE_ABILITY("assasinate"))
to_chat(xeno, SPAN_XENODANGER("We have waited too long, our slash will no longer deal increased damage!"))
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Praetorian.dm b/code/modules/mob/living/carbon/xenomorph/castes/Praetorian.dm
index fac0fcd724f89..4b1af4557d040 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Praetorian.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Praetorian.dm
@@ -107,3 +107,8 @@
bound_xeno.add_xeno_shield(reward_shield, XENO_SHIELD_SOURCE_BASE_PRAE, add_shield_on = TRUE, max_shield = 45)
to_chat(bound_xeno, SPAN_NOTICE("Your exoskeleton shimmers for a fraction of a second as the acid coats your target."))
return
+
+/datum/action/xeno_action/activable/pounce/base_prae_dash/start_airbone()
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ ADD_TRAIT(xeno, TRAIT_ABILITY_POUNCE, TRAIT_SOURCE_ABILITY("pounce"))
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm b/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm
index 262e7c1e1b88b..15352fa40452a 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Predalien.dm
@@ -154,7 +154,7 @@ You must still listen to the queen.
. = list()
. += "Kills: [kills]/[max_kills]"
-/datum/behavior_delegate/predalien_base/on_kill_mob(mob/M)
+/datum/behavior_delegate/predalien_base/on_kill_mob(mob/target_mob)
. = ..()
kills = min(kills + 1, max_kills)
@@ -184,6 +184,9 @@ You must still listen to the queen.
if(isyautja(target_human) && yautja_glove)
if(HAS_TRAIT(target_human, TRAIT_CLOAKED))
yautja_glove.decloak(target_human, TRUE, DECLOAK_PREDALIEN)
+ target_human.add_filter("uncloack", 1, list("type" = "outline", "color" = "#32fff58c", "size" = 1.5))
+ addtimer(CALLBACK(src, PROC_REF(disable_filter), target_human), 3 SECONDS)
+ playsound(target_human.loc, 'sound/effects/pred_force_decloak.ogg', 100, 1, 10)
yautja_glove.cloak_timer = xeno_cooldown * 0.1
else if(isxeno(target_carbon) && xeno.can_not_harm(target_carbon))
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm
index 462fb168d5dd0..f4d9d1b6cda6b 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Queen.dm
@@ -58,9 +58,9 @@
if(hive.living_xeno_queen)
if(hive.living_xeno_queen.hivenumber == hive.hivenumber)
continue
- for(var/mob/living/carbon/xenomorph/queen/Q in GLOB.living_xeno_list)
- if(Q.hivenumber == hive.hivenumber && !should_block_game_interaction(Q))
- hive.living_xeno_queen = Q
+ for(var/mob/living/carbon/xenomorph/queen/queen_user in GLOB.living_xeno_list)
+ if(queen_user.hivenumber == hive.hivenumber && !should_block_game_interaction(queen_user))
+ hive.living_xeno_queen = queen_user
xeno_message(SPAN_XENOANNOUNCE("A new Queen has risen to lead the Hive! Rejoice!"),3,hive.hivenumber)
continue outer_loop
hive.living_xeno_queen = null
@@ -73,7 +73,6 @@
color = "#a800a8"
hud_possible = list(XENO_STATUS_HUD)
-
var/mob/is_watching
var/hivenumber = XENO_HIVE_NORMAL
@@ -82,40 +81,40 @@
var/point_delay = 1 SECONDS
-/mob/hologram/queen/Initialize(mapload, mob/living/carbon/xenomorph/queen/Q)
- if(!Q)
+/mob/hologram/queen/Initialize(mapload, mob/living/carbon/xenomorph/queen/queen_user)
+ if(!queen_user)
return INITIALIZE_HINT_QDEL
- if(!istype(Q))
- stack_trace("Tried to initialize a /mob/hologram/queen on type ([Q.type])")
+ if(!istype(queen_user))
+ stack_trace("Tried to initialize a /mob/hologram/queen on type ([queen_user.type])")
return INITIALIZE_HINT_QDEL
- if(!Q.ovipositor)
+ if(!queen_user.ovipositor)
return INITIALIZE_HINT_QDEL
// Make sure to turn off any previous overwatches
- Q.overwatch(stop_overwatch = TRUE)
+ queen_user.overwatch(stop_overwatch = TRUE)
. = ..()
- RegisterSignal(Q, COMSIG_MOB_PRE_CLICK, PROC_REF(handle_overwatch))
- RegisterSignal(Q, COMSIG_QUEEN_DISMOUNT_OVIPOSITOR, PROC_REF(exit_hologram))
- RegisterSignal(Q, COMSIG_XENO_OVERWATCH_XENO, PROC_REF(start_watching))
- RegisterSignal(Q, list(
+ RegisterSignal(queen_user, COMSIG_MOB_PRE_CLICK, PROC_REF(handle_overwatch))
+ RegisterSignal(queen_user, COMSIG_QUEEN_DISMOUNT_OVIPOSITOR, PROC_REF(exit_hologram))
+ RegisterSignal(queen_user, COMSIG_XENO_OVERWATCH_XENO, PROC_REF(start_watching))
+ RegisterSignal(queen_user, list(
COMSIG_XENO_STOP_OVERWATCH,
COMSIG_XENO_STOP_OVERWATCH_XENO
), PROC_REF(stop_watching))
- RegisterSignal(Q, COMSIG_MOB_REAL_NAME_CHANGED, PROC_REF(on_name_changed))
+ RegisterSignal(queen_user, COMSIG_MOB_REAL_NAME_CHANGED, PROC_REF(on_name_changed))
RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTER, PROC_REF(turf_weed_only))
// Default color
- if(Q.hive.color)
- color = Q.hive.color
+ if(queen_user.hive.color)
+ color = queen_user.hive.color
- hivenumber = Q.hivenumber
+ hivenumber = queen_user.hivenumber
med_hud_set_status()
add_to_all_mob_huds()
- Q.sight |= SEE_TURFS|SEE_OBJS
+ queen_user.sight |= SEE_TURFS|SEE_OBJS
/mob/hologram/queen/proc/exit_hologram()
SIGNAL_HANDLER
@@ -131,43 +130,43 @@
qdel(src)
-/mob/hologram/queen/handle_move(mob/living/carbon/xenomorph/X, NewLoc, direct)
+/mob/hologram/queen/handle_move(mob/living/carbon/xenomorph/xeno, NewLoc, direct)
if(is_watching && (turf_weed_only(src, is_watching.loc) & COMPONENT_TURF_DENY_MOVEMENT))
return COMPONENT_OVERRIDE_MOVE
- X.overwatch(stop_overwatch = TRUE)
+ xeno.overwatch(stop_overwatch = TRUE)
return ..()
-/mob/hologram/queen/proc/start_watching(mob/living/carbon/xenomorph/X, mob/living/carbon/xenomorph/target)
+/mob/hologram/queen/proc/start_watching(mob/living/carbon/xenomorph/xeno, mob/living/carbon/xenomorph/target_xeno)
SIGNAL_HANDLER
- forceMove(target)
- is_watching = target
+ forceMove(target_xeno)
+ is_watching = target_xeno
- RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(target_watching_qdeleted))
+ RegisterSignal(target_xeno, COMSIG_PARENT_QDELETING, PROC_REF(target_watching_qdeleted))
return
// able to stop watching here before the loc is set to null
-/mob/hologram/queen/proc/target_watching_qdeleted(mob/living/carbon/xenomorph/target)
+/mob/hologram/queen/proc/target_watching_qdeleted(mob/living/carbon/xenomorph/target_xeno)
SIGNAL_HANDLER
- stop_watching(linked_mob, target)
+ stop_watching(linked_mob, target_xeno)
-/mob/hologram/queen/proc/stop_watching(mob/living/carbon/xenomorph/X, mob/living/carbon/xenomorph/target)
+/mob/hologram/queen/proc/stop_watching(mob/living/carbon/xenomorph/xeno, mob/living/carbon/xenomorph/target_xeno)
SIGNAL_HANDLER
- if(target)
- if(loc == target)
- var/turf/T = get_turf(target)
+ if(target_xeno)
+ if(loc == target_xeno)
+ var/turf/target_turf = get_turf(target_xeno)
- if(T)
- forceMove(T)
- UnregisterSignal(target, COMSIG_PARENT_QDELETING)
+ if(target_turf)
+ forceMove(target_turf)
+ UnregisterSignal(target_xeno, COMSIG_PARENT_QDELETING)
if(!isturf(loc) || (turf_weed_only(src, loc) & COMPONENT_TURF_DENY_MOVEMENT))
- forceMove(X.loc)
+ forceMove(xeno.loc)
is_watching = null
- X.reset_view()
+ xeno.reset_view()
return
/mob/hologram/queen/proc/on_name_changed(mob/parent, old_name, new_name)
@@ -196,11 +195,11 @@
return COMPONENT_TURF_DENY_MOVEMENT
-/mob/hologram/queen/proc/handle_overwatch(mob/living/carbon/xenomorph/queen/Q, atom/A, mods)
+/mob/hologram/queen/proc/handle_overwatch(mob/living/carbon/xenomorph/queen/queen_user, atom/target_atom, mods)
SIGNAL_HANDLER
- var/turf/T = get_turf(A)
- if(!istype(T))
+ var/turf/target_turf = get_turf(target_atom)
+ if(!istype(target_turf))
return
if(mods[SHIFT_CLICK] && mods[MIDDLE_CLICK])
@@ -209,15 +208,15 @@
next_point = world.time + point_delay
- var/message = SPAN_XENONOTICE("[Q] points at [A].")
+ var/message = SPAN_XENONOTICE("[queen_user] points at [target_atom].")
- to_chat(Q, message)
- for(var/mob/living/carbon/xenomorph/X in viewers(7, src))
- if(X == Q)
+ to_chat(queen_user, message)
+ for(var/mob/living/carbon/xenomorph/xeno in viewers(7, src))
+ if(xeno == queen_user)
continue
- to_chat(X, message)
+ to_chat(xeno, message)
- var/obj/effect/overlay/temp/point/big/queen/point = new(T, src, A)
+ var/obj/effect/overlay/temp/point/big/queen/point = new(target_turf, src, target_atom)
point.color = color
return COMPONENT_INTERRUPT_CLICK
@@ -225,36 +224,36 @@
if(!mods[CTRL_CLICK])
return
- if(isxeno(A))
- var/mob/living/carbon/xenomorph/X = A
- if(X.ally_of_hivenumber(hivenumber))
- Q.overwatch(A)
+ if(isxeno(target_atom))
+ var/mob/living/carbon/xenomorph/xeno = target_atom
+ if(xeno.ally_of_hivenumber(hivenumber))
+ queen_user.overwatch(target_atom)
return COMPONENT_INTERRUPT_CLICK
- if(!(turf_weed_only(src, T) & COMPONENT_TURF_ALLOW_MOVEMENT))
+ if(!(turf_weed_only(src, target_turf) & COMPONENT_TURF_ALLOW_MOVEMENT))
return
- forceMove(T)
+ forceMove(target_turf)
if(is_watching)
- Q.overwatch(stop_overwatch = TRUE)
+ queen_user.overwatch(stop_overwatch = TRUE)
return COMPONENT_INTERRUPT_CLICK
-/mob/hologram/queen/handle_view(mob/M, atom/target)
- if(M.client)
- M.client.perspective = EYE_PERSPECTIVE
+/mob/hologram/queen/handle_view(mob/target_mob, atom/target_atom)
+ if(target_mob.client)
+ target_mob.client.perspective = EYE_PERSPECTIVE
if(is_watching)
- M.client.set_eye(is_watching)
+ target_mob.client.set_eye(is_watching)
else
- M.client.set_eye(src)
+ target_mob.client.set_eye(src)
return COMPONENT_OVERRIDE_VIEW
/mob/hologram/queen/Destroy()
if(linked_mob)
- var/mob/living/carbon/xenomorph/queen/Q = linked_mob
- if(Q.ovipositor)
+ var/mob/living/carbon/xenomorph/queen/queen_user = linked_mob
+ if(queen_user.ovipositor)
give_action(linked_mob, /datum/action/xeno_action/onclick/eye)
linked_mob.sight &= ~(SEE_TURFS|SEE_OBJS)
@@ -643,8 +642,8 @@
egg_amount += 0.07 //one egg approximately every 30 seconds
if(egg_amount >= 1)
if(isturf(loc))
- var/turf/T = loc
- if(length(T.contents) <= 25) //so we don't end up with a million object on that turf.
+ var/turf/target_turf = loc
+ if(length(target_turf.contents) <= 25) //so we don't end up with a million object on that turf.
egg_amount--
new /obj/item/xeno_egg(loc, hivenumber)
overlays -= acid_overlay
@@ -679,17 +678,17 @@
/mob/living/carbon/xenomorph/queen/proc/screech_ready()
to_chat(src, SPAN_WARNING("You feel your throat muscles vibrate. You are ready to screech again."))
- for(var/Z in actions)
- var/datum/action/A = Z
- A.update_button_icon()
+ for(var/xeno_ability in actions)
+ var/datum/action/target_action = xeno_ability
+ target_action.update_button_icon()
-/mob/living/carbon/xenomorph/queen/proc/queen_gut(atom/target)
- if(!iscarbon(target))
+/mob/living/carbon/xenomorph/queen/proc/queen_gut(atom/target_atom)
+ if(!iscarbon(target_atom))
return FALSE
- if(HAS_TRAIT(target, TRAIT_HAULED))
- to_chat(src, SPAN_XENOWARNING("[target] needs to be released first."))
+ if(HAS_TRAIT(target_atom, TRAIT_HAULED))
+ to_chat(src, SPAN_XENOWARNING("[target_atom] needs to be released first."))
return FALSE
- var/mob/living/carbon/victim = target
+ var/mob/living/carbon/victim = target_atom
if(get_dist(src, victim) > 1)
return FALSE
@@ -873,8 +872,8 @@
break
anchored = FALSE
- for(var/mob/living/carbon/xenomorph/L in hive.xeno_leader_list)
- L.handle_xeno_leader_pheromones()
+ for(var/mob/living/carbon/xenomorph/xeno_leader in hive.xeno_leader_list)
+ xeno_leader.handle_xeno_leader_pheromones()
if(!instant_dismount)
xeno_message(SPAN_XENOANNOUNCE("The Queen has shed her ovipositor, evolution progress paused."), 3, hivenumber)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm b/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm
index 85472a71a63ad..05f775d4096bd 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Ravager.dm
@@ -78,45 +78,44 @@
/datum/behavior_delegate/ravager_base
var/shield_decay_time = 15 SECONDS // Time in deciseconds before our shield decays
var/slash_charge_cdr = 3 SECONDS // Amount to reduce charge cooldown by per slash
- var/knockdown_amount = 1.6
- var/fling_distance = 3
- var/empower_targets = 0
- var/super_empower_threshold = 3
var/dmg_buff_per_target = 2
- var/mid_charge = FALSE
-/datum/behavior_delegate/ravager_base/melee_attack_modify_damage(original_damage, mob/living/carbon/carbon)
+/datum/behavior_delegate/ravager_base/melee_attack_modify_damage(original_damage)
var/damage_plus
- if(empower_targets)
- damage_plus = dmg_buff_per_target * empower_targets
+
+ var/datum/action/xeno_action/onclick/empower/empower_used = get_action(bound_xeno, /datum/action/xeno_action/onclick/empower)
+ if(empower_used.empower_targets)
+ damage_plus = dmg_buff_per_target * empower_used.empower_targets
return original_damage + damage_plus
/datum/behavior_delegate/ravager_base/melee_attack_additional_effects_self()
..()
- var/datum/action/xeno_action/activable/pounce/charge/cAction = get_action(bound_xeno, /datum/action/xeno_action/activable/pounce/charge)
- if (!cAction.action_cooldown_check())
- cAction.reduce_cooldown(slash_charge_cdr)
+ var/datum/action/xeno_action/activable/pounce/charge/charge_used = get_action(bound_xeno, /datum/action/xeno_action/activable/pounce/charge)
+ if(!charge_used.action_cooldown_check())
+ charge_used.reduce_cooldown(slash_charge_cdr)
/datum/behavior_delegate/ravager_base/append_to_stat()
. = list()
var/shield_total = 0
- for (var/datum/xeno_shield/xeno_shield in bound_xeno.xeno_shields)
- if (xeno_shield.shield_source == XENO_SHIELD_SOURCE_RAVAGER)
+ for(var/datum/xeno_shield/xeno_shield in bound_xeno.xeno_shields)
+ if(xeno_shield.shield_source == XENO_SHIELD_SOURCE_RAVAGER)
shield_total += xeno_shield.amount
. += "Empower Shield: [shield_total]"
- . += "Bonus Slash Damage: [dmg_buff_per_target * empower_targets]"
+
+ var/datum/action/xeno_action/onclick/empower/empower_used = get_action(bound_xeno, /datum/action/xeno_action/onclick/empower)
+ . += "Bonus Slash Damage: [dmg_buff_per_target * empower_used.empower_targets]"
/datum/behavior_delegate/ravager_base/on_life()
var/datum/xeno_shield/rav_shield
- for (var/datum/xeno_shield/xeno_shield in bound_xeno.xeno_shields)
- if (xeno_shield.shield_source == XENO_SHIELD_SOURCE_RAVAGER)
+ for(var/datum/xeno_shield/xeno_shield in bound_xeno.xeno_shields)
+ if(xeno_shield.shield_source == XENO_SHIELD_SOURCE_RAVAGER)
rav_shield = xeno_shield
break
- if (rav_shield && ((rav_shield.last_damage_taken + shield_decay_time) < world.time))
+ if(rav_shield && ((rav_shield.last_damage_taken + shield_decay_time) < world.time))
QDEL_NULL(rav_shield)
to_chat(bound_xeno, SPAN_XENODANGER("We feel our shield decay!"))
bound_xeno.overlay_shields()
@@ -127,23 +126,26 @@
if(!isxeno_human(target_carbon))
return
- if(mid_charge && target_carbon)
+ if(HAS_TRAIT(bound_xeno, TRAIT_ABILITY_POUNCE_CHARGE) && target_carbon)
return INTENT_HARM
-/datum/action/xeno_action/onclick/empower/use_ability(atom/target)
+
+/datum/action/xeno_action/activable/pounce/charge/start_airbone()
var/mob/living/carbon/xenomorph/xeno = owner
- if(!xeno.check_state())
- return
- if(!action_cooldown_check())
- return
+ ADD_TRAIT(xeno, TRAIT_ABILITY_POUNCE, TRAIT_SOURCE_ABILITY("pounce"))
+
+
+/datum/action/xeno_action/onclick/empower/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ XENO_ACTION_CHECK(xeno)
- if(!activated_once)
- if (!check_and_use_plasma_owner())
- return
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_PRE_EMPOWER))
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
xeno.visible_message(SPAN_XENODANGER("[xeno] starts empowering!"), SPAN_XENODANGER("We start empowering ourself!"))
- activated_once = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_PRE_EMPOWER, TRAIT_SOURCE_ABILITY("pre_empower"))
button.icon_state = "template_active"
get_initial_shield()
addtimer(CALLBACK(src, PROC_REF(timeout)), time_until_timeout)
@@ -153,10 +155,17 @@
actual_empower(xeno)
return TRUE
-/datum/action/xeno_action/onclick/empower/proc/actual_empower(mob/living/carbon/xenomorph/xeno)
- var/datum/behavior_delegate/ravager_base/behavior = xeno.behavior_delegate
+/datum/action/xeno_action/onclick/empower/action_cooldown_check()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(cooldown_timer_id == TIMER_ID_NULL)
+ return TRUE
+ else if(HAS_TRAIT(xeno, TRAIT_ABILITY_PRE_EMPOWER))
+ return TRUE
+ else
+ return FALSE
- activated_once = FALSE
+/datum/action/xeno_action/onclick/empower/proc/actual_empower(mob/living/carbon/xenomorph/xeno)
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_PRE_EMPOWER, TRAIT_SOURCE_ABILITY("pre_empower"))
button.icon_state = "template_xeno"
xeno.visible_message(SPAN_XENOWARNING("[xeno] gets empowered by the surrounding enemies!"), SPAN_XENOWARNING("We feel a rush of power from the surrounding enemies!"))
xeno.create_empower()
@@ -168,7 +177,6 @@
var/accumulative_health = 0
var/list/telegraph_atom_list = list()
- var/empower_targets
for(var/mob/living/mob in mobs_in_range)
if(empower_targets >= max_targets)
break
@@ -184,26 +192,24 @@
accumulative_health += main_empower_base_shield
+ ADD_TRAIT(xeno, TRAIT_ABILITY_EMPOWER, TRAIT_SOURCE_ABILITY("empower"))
xeno.add_xeno_shield(accumulative_health, XENO_SHIELD_SOURCE_RAVAGER)
xeno.overlay_shields()
- if(empower_targets >= behavior.super_empower_threshold) //you go in deep you reap the rewards
- super_empower(xeno, empower_targets, behavior)
+ if(empower_targets >= super_empower_threshold) //you go in deep you reap the rewards
+ super_empower(xeno, empower_targets)
-/datum/action/xeno_action/onclick/empower/proc/super_empower(mob/living/carbon/xenomorph/xeno, empower_targets, datum/behavior_delegate/ravager_base/behavior)
+/datum/action/xeno_action/onclick/empower/proc/super_empower(mob/living/carbon/xenomorph/xeno, empower_targets)
xeno.visible_message(SPAN_DANGER("[xeno] glows an eerie red as it empowers further with the strength of [empower_targets] hostiles!"), SPAN_XENOHIGHDANGER("We begin to glow an eerie red, empowered by the [empower_targets] enemies!"))
xeno.emote("roar")
-
- behavior.empower_targets = empower_targets
-
var/color = "#FF0000"
var/alpha = 70
color += num2text(alpha, 2, 16)
xeno.add_filter("empower_rage", 1, list("type" = "outline", "color" = color, "size" = 3))
- addtimer(CALLBACK(src, PROC_REF(weaken_superbuff), xeno, behavior), 5 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(weaken_superbuff), xeno), 5 SECONDS)
-/datum/action/xeno_action/onclick/empower/proc/weaken_superbuff(mob/living/carbon/xenomorph/xeno, datum/behavior_delegate/ravager_base/behavior)
+/datum/action/xeno_action/onclick/empower/proc/weaken_superbuff(mob/living/carbon/xenomorph/xeno)
xeno.remove_filter("empower_rage")
var/color = "#FF0000"
@@ -211,80 +217,63 @@
color += num2text(alpha, 2, 16)
xeno.add_filter("empower_rage", 1, list("type" = "outline", "color" = color, "size" = 3))
- addtimer(CALLBACK(src, PROC_REF(remove_superbuff), xeno, behavior), 1.5 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(remove_superbuff), xeno), 1.5 SECONDS)
-/datum/action/xeno_action/onclick/empower/proc/remove_superbuff(mob/living/carbon/xenomorph/xeno, datum/behavior_delegate/ravager_base/behavior)
- behavior.empower_targets = 0
+/datum/action/xeno_action/onclick/empower/proc/remove_superbuff(mob/living/carbon/xenomorph/xeno)
+ empower_targets = 0
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_EMPOWER, TRAIT_SOURCE_ABILITY("empower"))
xeno.visible_message(SPAN_DANGER("[xeno]'s glow slowly dims."), SPAN_XENOHIGHDANGER("Our glow fades away, the power leaving our form!"))
xeno.remove_filter("empower_rage")
/datum/action/xeno_action/onclick/empower/proc/get_initial_shield()
var/mob/living/carbon/xenomorph/xeno = owner
- if(!activated_once)
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_PRE_EMPOWER))
return
xeno.add_xeno_shield(initial_activation_shield, XENO_SHIELD_SOURCE_RAVAGER)
xeno.overlay_shields()
/datum/action/xeno_action/onclick/empower/proc/timeout()
- if(!activated_once)
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_PRE_EMPOWER))
return
- var/mob/living/carbon/xenomorph/xeno = owner
actual_empower(xeno)
-/datum/action/xeno_action/onclick/empower/action_cooldown_check()
- if (cooldown_timer_id == TIMER_ID_NULL)
- return TRUE
- else if (activated_once)
- return TRUE
- else
- return FALSE
-
// Supplemental behavior for our charge
/datum/action/xeno_action/activable/pounce/charge/additional_effects(mob/living/living)
-
var/mob/living/carbon/human/human = living
var/mob/living/carbon/xenomorph/xeno = owner
- var/datum/behavior_delegate/ravager_base/behavior = xeno.behavior_delegate
- if(behavior.empower_targets < behavior.super_empower_threshold)
+
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_EMPOWER))
return
- behavior.mid_charge = TRUE
+
+ ADD_TRAIT(xeno, TRAIT_ABILITY_POUNCE_CHARGE, TRAIT_SOURCE_ABILITY("pounce_charge"))
xeno.visible_message(SPAN_XENODANGER("[xeno] uses its shield to bash [human] as it charges at them!"), SPAN_XENODANGER("We use our shield to bash [human] as we charge at them!"))
- human.apply_effect(behavior.knockdown_amount, WEAKEN)
+ human.apply_effect(knockdown_amount, WEAKEN)
human.attack_alien(xeno, rand(xeno.melee_damage_lower, xeno.melee_damage_upper), unblockable=TRUE)
- behavior.mid_charge = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_POUNCE_CHARGE, TRAIT_SOURCE_ABILITY("pounce_charge"))
var/facing = get_dir(xeno, human)
- xeno.throw_carbon(human, facing, behavior.fling_distance, SPEED_VERY_FAST, shake_camera = FALSE, immobilize = TRUE)
+ xeno.throw_carbon(human, facing, fling_distance, SPEED_VERY_FAST, shake_camera = FALSE, immobilize = TRUE)
/datum/action/xeno_action/activable/scissor_cut/use_ability(atom/target_atom)
- var/mob/living/carbon/xenomorph/ravager_user = owner
-
- if (!action_cooldown_check())
- return
-
- if (!ravager_user.check_state())
- return
+ var/mob/living/carbon/xenomorph/xeno = owner
- // Determine whether or not we should daze here
- var/should_sslow = FALSE
- var/datum/behavior_delegate/ravager_base/ravager_delegate = ravager_user.behavior_delegate
- if(ravager_delegate.empower_targets >= ravager_delegate.super_empower_threshold)
- should_sslow = TRUE
+ XENO_ACTION_CHECK(xeno)
// Get line of turfs
var/list/turf/target_turfs = list()
- var/facing = Get_Compass_Dir(ravager_user, target_atom)
- var/turf/turf = ravager_user.loc
- var/turf/temp = ravager_user.loc
+ var/facing = Get_Compass_Dir(xeno, target_atom)
+ var/turf/turf = xeno.loc
+ var/turf/temp = xeno.loc
var/list/telegraph_atom_list = list()
- for (var/step in 0 to 3)
+ for(var/step in 0 to 3)
temp = get_step(turf, facing)
if(facing in GLOB.diagonals) // check if it goes through corners
var/reverse_face = GLOB.reverse_dir[facing]
@@ -319,31 +308,31 @@
telegraph_atom_list += new /obj/effect/xenomorph/xeno_telegraph/red(turf, 0.25 SECONDS)
// Extract our 'optimal' turf, if it exists
- if (length(target_turfs) >= 2)
- ravager_user.animation_attack_on(target_turfs[length(target_turfs)], 15)
+ if(length(target_turfs) >= 2)
+ xeno.animation_attack_on(target_turfs[length(target_turfs)], 15)
// Hmm today I will kill a marine while looking away from them
- ravager_user.face_atom(target_atom)
- ravager_user.emote("roar")
- ravager_user.visible_message(SPAN_XENODANGER("[ravager_user] sweeps its claws through the area in front of it!"), SPAN_XENODANGER("We sweep our claws through the area in front of us!"))
+ xeno.face_atom(target_atom)
+ xeno.emote("roar")
+ xeno.visible_message(SPAN_XENODANGER("[xeno] sweeps its claws through the area in front of it!"), SPAN_XENODANGER("We sweep our claws through the area in front of us!"))
// Loop through our turfs, finding any humans there and dealing damage to them
- for (var/turf/target_turf in target_turfs)
- for (var/mob/living/carbon/carbon_target in target_turf)
- if (carbon_target.stat == DEAD)
+ for(var/turf/target_turf in target_turfs)
+ for(var/mob/living/carbon/carbon_target in target_turf)
+ if(carbon_target.stat == DEAD)
continue
- if (HAS_TRAIT(carbon_target, TRAIT_NESTED))
+ if(HAS_TRAIT(carbon_target, TRAIT_NESTED))
continue
- if(ravager_user.can_not_harm(carbon_target))
+ if(xeno.can_not_harm(carbon_target))
continue
- ravager_user.flick_attack_overlay(carbon_target, "slash")
+ xeno.flick_attack_overlay(carbon_target, "slash")
carbon_target.apply_armoured_damage(damage, ARMOR_MELEE, BRUTE)
playsound(get_turf(carbon_target), "alien_claw_flesh", 30, TRUE)
- if(should_sslow)
- new /datum/effects/xeno_slow/superslow(carbon_target, ravager_user, ttl = superslow_duration)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_EMPOWER))
+ new /datum/effects/xeno_slow/superslow(carbon_target, xeno, ttl = superslow_duration)
apply_cooldown()
return ..()
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm
index 2a0e3db43890b..1beadcbdedf76 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm
@@ -110,6 +110,11 @@
if(hide)
hide.post_attack()
+/datum/action/xeno_action/activable/pounce/runner/start_airbone()
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ ADD_TRAIT(xeno, TRAIT_ABILITY_POUNCE, TRAIT_SOURCE_ABILITY("pounce"))
+
/datum/action/xeno_action/activable/runner_skillshot/use_ability(atom/affected_atom)
var/mob/living/carbon/xenomorph/xeno = owner
if(!istype(xeno))
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm b/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm
index 40613db49e62e..cae028674021d 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Sentinel.dm
@@ -77,37 +77,32 @@
var/increment_amount = 10
/datum/behavior_delegate/sentinel_base/melee_attack_modify_damage(original_damage, mob/living/carbon/carbon_target)
- if (!buffed_slashes)
+ if(!next_slash_buffed)
return original_damage
- if (!isxeno_human(carbon_target))
+ if(!isxeno_human(carbon_target))
return original_damage
if(skillcheck(carbon_target, SKILL_ENDURANCE, SKILL_ENDURANCE_MAX ))
carbon_target.visible_message(SPAN_DANGER("[carbon_target] withstands the neurotoxin!"))
return original_damage //endurance 5 makes you immune to weak neurotoxin
if(ishuman(carbon_target))
- var/mob/living/carbon/human/human = carbon_target
- if(human.chem_effect_flags & CHEM_EFFECT_RESIST_NEURO || human.species.flags & NO_NEURO)
- human.visible_message(SPAN_DANGER("[human] shrugs off the neurotoxin!"))
- return original_damage //species like zombies or synths are immune to neurotoxin
- if (buffed_slashes)
- to_chat(bound_xeno, SPAN_XENOHIGHDANGER("Our slash applied a large amount of neurotoxin!"))
- to_chat(carbon_target, SPAN_XENOHIGHDANGER("You feel your muscles, as [bound_xeno] slashes you with its neurotoxin coated claws!"))
- var/datum/effects/sentinel_neuro_stacks/sns = null
- for (var/datum/effects/sentinel_neuro_stacks/sentinel_neuro_stacks in human.effects_list)
- sns = sentinel_neuro_stacks
- break
-
- if (sns == null)
- sns = new /datum/effects/sentinel_neuro_stacks(human)
- sns.increment_stack_count(increment_amount)
-
- buffed_slashes --
- if(!buffed_slashes)
+ var/mob/living/carbon/human/target_human = carbon_target
+ if(target_human.chem_effect_flags & CHEM_EFFECT_RESIST_NEURO || target_human.species.flags & NO_NEURO)
+ target_human.visible_message(SPAN_DANGER("[target_human] shrugs off the neurotoxin!"))
+ next_slash_buffed = FALSE
+ return //species like zombies or synths are immune to neurotoxin
+ if(next_slash_buffed)
+ to_chat(bound_xeno, SPAN_XENOHIGHDANGER("We add neurotoxin into our attack, [carbon_target] is about to fall over paralyzed!"))
+ to_chat(carbon_target, SPAN_XENOHIGHDANGER("You feel like you're about to fall over, as [bound_xeno] slashes you with its neurotoxin coated claws!"))
+ carbon_target.sway_jitter(times = 3, steps = floor(NEURO_TOUCH_DELAY/3))
+ carbon_target.apply_effect(4, DAZE)
+ addtimer(CALLBACK(src, PROC_REF(paralyzing_slash), carbon_target), NEURO_TOUCH_DELAY)
+ next_slash_buffed = FALSE
+ if(!next_slash_buffed)
var/datum/action/xeno_action/onclick/paralyzing_slash/ability = get_action(bound_xeno, /datum/action/xeno_action/onclick/paralyzing_slash)
- if (ability && istype(ability))
- ability.button.icon_state = "template_xeno"
+ if(ability && istype(ability))
+ ability.button.icon_state = "template"
return original_damage
/datum/behavior_delegate/sentinel_base/override_intent(mob/living/carbon/target_carbon)
@@ -119,89 +114,84 @@
if(buffed_slashes)
return INTENT_HARM
+/datum/behavior_delegate/sentinel_base/proc/paralyzing_slash(mob/living/carbon/human/human_target)
+ human_target.KnockDown(2)
+ human_target.Stun(2)
+ to_chat(human_target, SPAN_XENOHIGHDANGER("You fall over, paralyzed by the toxin!"))
-/datum/action/xeno_action/activable/slowing_spit/use_ability(atom/target)
- var/mob/living/carbon/xenomorph/slowspit_user = owner
- if(!slowspit_user.check_state())
- return
+
+/datum/action/xeno_action/activable/slowing_spit/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
if(!action_cooldown_check())
to_chat(src, SPAN_WARNING("We must wait for our spit glands to refill."))
return
- var/turf/current_turf = get_turf(slowspit_user)
+ var/turf/current_turf = get_turf(xeno)
if(!current_turf)
return
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- slowspit_user.visible_message(SPAN_XENOWARNING("[slowspit_user] spits at [target]!"),
- SPAN_XENOWARNING("You spit at [target]!") )
+ xeno.visible_message(SPAN_XENOWARNING("[xeno] spits at [target_atom]!"),
+ SPAN_XENOWARNING("You spit at [target_atom]!") )
var/sound_to_play = pick(1, 2) == 1 ? 'sound/voice/alien_spitacid.ogg' : 'sound/voice/alien_spitacid2.ogg'
- playsound(slowspit_user.loc, sound_to_play, 25, 1)
+ playsound(xeno.loc, sound_to_play, 25, 1)
- slowspit_user.ammo = GLOB.ammo_list[/datum/ammo/xeno/toxin]
- var/obj/projectile/projectile = new /obj/projectile(current_turf, create_cause_data(initial(slowspit_user.caste_type), slowspit_user))
- projectile.generate_bullet(slowspit_user.ammo)
- projectile.permutated += slowspit_user
- projectile.def_zone = slowspit_user.get_limbzone_target()
- projectile.fire_at(target, slowspit_user, slowspit_user, slowspit_user.ammo.max_range, slowspit_user.ammo.shell_speed)
+ xeno.ammo = GLOB.ammo_list[/datum/ammo/xeno/toxin]
+ var/obj/projectile/projectile = new /obj/projectile(current_turf, create_cause_data(initial(xeno.caste_type), xeno))
+ projectile.generate_bullet(xeno.ammo)
+ projectile.permutated += xeno
+ projectile.def_zone = xeno.get_limbzone_target()
+ projectile.fire_at(target_atom, xeno, xeno, xeno.ammo.max_range, xeno.ammo.shell_speed)
apply_cooldown()
return ..()
-/datum/action/xeno_action/activable/scattered_spit/use_ability(atom/target)
- var/mob/living/carbon/xenomorph/scatterspit_user = owner
- if(!scatterspit_user.check_state())
- return
+/datum/action/xeno_action/activable/scattered_spit/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
if(!action_cooldown_check())
to_chat(src, SPAN_WARNING("We must wait for your spit glands to refill."))
return
- var/turf/current_turf = get_turf(scatterspit_user)
+ var/turf/current_turf = get_turf(xeno)
if(!current_turf)
return
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- scatterspit_user.visible_message(SPAN_XENOWARNING("[scatterspit_user] spits at [target]!"),
- SPAN_XENOWARNING("You spit at [target]!") )
+ xeno.visible_message(SPAN_XENOWARNING("[xeno] spits at [target_atom]!"),
+ SPAN_XENOWARNING("You spit at [target_atom]!") )
var/sound_to_play = pick(1, 2) == 1 ? 'sound/voice/alien_spitacid.ogg' : 'sound/voice/alien_spitacid2.ogg'
- playsound(scatterspit_user.loc, sound_to_play, 25, 1)
+ playsound(xeno.loc, sound_to_play, 25, 1)
- scatterspit_user.ammo = GLOB.ammo_list[/datum/ammo/xeno/toxin/shotgun]
- var/obj/projectile/projectile = new /obj/projectile(current_turf, create_cause_data(initial(scatterspit_user.caste_type), scatterspit_user))
- projectile.generate_bullet(scatterspit_user.ammo)
- projectile.permutated += scatterspit_user
- projectile.def_zone = scatterspit_user.get_limbzone_target()
- projectile.fire_at(target, scatterspit_user, scatterspit_user, scatterspit_user.ammo.max_range, scatterspit_user.ammo.shell_speed)
+ xeno.ammo = GLOB.ammo_list[/datum/ammo/xeno/toxin/shotgun]
+ var/obj/projectile/projectile = new /obj/projectile(current_turf, create_cause_data(initial(xeno.caste_type), xeno))
+ projectile.generate_bullet(xeno.ammo)
+ projectile.permutated += xeno
+ projectile.def_zone = xeno.get_limbzone_target()
+ projectile.fire_at(target_atom, xeno, xeno, xeno.ammo.max_range, xeno.ammo.shell_speed)
apply_cooldown()
return ..()
-/datum/action/xeno_action/onclick/paralyzing_slash/use_ability(atom/target)
- var/mob/living/carbon/xenomorph/paraslash_user = owner
-
- if (!istype(paraslash_user))
- return
+/datum/action/xeno_action/onclick/paralyzing_slash/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
- if (!action_cooldown_check())
+ if(!istype(xeno))
return
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- var/datum/behavior_delegate/sentinel_base/behavior = paraslash_user.behavior_delegate
- if (istype(behavior))
- behavior.buffed_slashes = behavior.max_buffed_slashes
+ var/datum/behavior_delegate/sentinel_base/behavior = xeno.behavior_delegate
+ if(istype(behavior))
+ behavior.next_slash_buffed = TRUE
- to_chat(paraslash_user, SPAN_XENOHIGHDANGER("Our next three slashes will apply neurotoxin!"))
+ to_chat(xeno, SPAN_XENOHIGHDANGER("Our next slash will apply neurotoxin!"))
button.icon_state = "template_active"
addtimer(CALLBACK(src, PROC_REF(unbuff_slash)), buff_duration)
@@ -210,17 +200,17 @@
return ..()
/datum/action/xeno_action/onclick/paralyzing_slash/proc/unbuff_slash()
- var/mob/living/carbon/xenomorph/unbuffslash_user = owner
- if (!istype(unbuffslash_user))
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!istype(xeno))
return
- var/datum/behavior_delegate/sentinel_base/behavior = unbuffslash_user.behavior_delegate
- if (istype(behavior))
+ var/datum/behavior_delegate/sentinel_base/behavior = xeno.behavior_delegate
+ if(istype(behavior))
// In case slash has already landed
- if (!behavior.buffed_slashes)
+ if(!behavior.next_slash_buffed)
return
behavior.buffed_slashes = 0
- to_chat(unbuffslash_user, SPAN_XENODANGER("We have waited too long, our slash will no longer apply neurotoxin!"))
+ to_chat(xeno, SPAN_XENODANGER("We have waited too long, our slash will no longer apply neurotoxin!"))
button.icon_state = "template_xeno"
/datum/action/xeno_action/activable/draining_bite/use_ability(atom/target)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Spitter.dm b/code/modules/mob/living/carbon/xenomorph/castes/Spitter.dm
index 4fe0425c410f0..21373622e1e70 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Spitter.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Spitter.dm
@@ -68,35 +68,32 @@
skull = /obj/item/skull/spitter
pelt = /obj/item/pelt/spitter
-/datum/action/xeno_action/onclick/charge_spit/use_ability(atom/A)
- var/mob/living/carbon/xenomorph/zenomorf = owner
+/datum/action/xeno_action/onclick/charge_spit/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
- if (!action_cooldown_check())
+ if(!istype(xeno))
return
- if (!istype(zenomorf) || !zenomorf.check_state())
+ if(buffs_active)
+ to_chat(xeno, SPAN_XENOHIGHDANGER("We cannot stack this!"))
return
- if (buffs_active)
- to_chat(zenomorf, SPAN_XENOHIGHDANGER("We cannot stack this!"))
- return
-
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- to_chat(zenomorf, SPAN_XENOHIGHDANGER("We accumulate acid in your glands. Our next spit will be stronger but shorter-ranged."))
- to_chat(zenomorf, SPAN_XENOWARNING("Additionally, we are slightly faster and more armored for a small amount of time."))
- zenomorf.create_custom_empower(icolor = "#93ec78", ialpha = 200, small_xeno = TRUE)
- zenomorf.balloon_alert(zenomorf, "our next spit will be stronger", text_color = "#93ec78")
+ to_chat(xeno, SPAN_XENOHIGHDANGER("We accumulate acid in your glands. Our next spit will be stronger but shorter-ranged."))
+ to_chat(xeno, SPAN_XENOWARNING("Additionally, we are slightly faster and more armored for a small amount of time."))
+ xeno.create_custom_empower(icolor = "#93ec78", ialpha = 200, small_xeno = TRUE)
+ xeno.balloon_alert(xeno, "our next spit will be stronger", text_color = "#93ec78")
buffs_active = TRUE
- zenomorf.ammo = GLOB.ammo_list[/datum/ammo/xeno/acid/spatter] // shitcode is my city
- zenomorf.speed_modifier -= speed_buff_amount
- zenomorf.armor_modifier += armor_buff_amount
- zenomorf.recalculate_speed()
- zenomorf.recalculate_armor()
+ xeno.ammo = GLOB.ammo_list[/datum/ammo/xeno/acid/spatter] // shitcode is my city
+ xeno.speed_modifier -= speed_buff_amount
+ xeno.armor_modifier += armor_buff_amount
+ xeno.recalculate_speed()
+ xeno.recalculate_armor()
+ start_duration_display(duration)
/// Though the ability's other buffs are supposed to last for its duration, it's only supposed to enhance one spit.
- RegisterSignal(zenomorf, COMSIG_XENO_POST_SPIT, PROC_REF(disable_spatter))
+ RegisterSignal(xeno, COMSIG_XENO_POST_SPIT, PROC_REF(disable_spatter))
addtimer(CALLBACK(src, PROC_REF(remove_effects)), duration)
@@ -105,28 +102,29 @@
/datum/action/xeno_action/onclick/charge_spit/proc/disable_spatter()
SIGNAL_HANDLER
- var/mob/living/carbon/xenomorph/zenomorf = owner
- if(zenomorf.ammo == GLOB.ammo_list[/datum/ammo/xeno/acid/spatter])
- to_chat(zenomorf, SPAN_XENOWARNING("Our acid glands empty out and return back to normal. We will once more fire long-ranged weak spits."))
- zenomorf.balloon_alert(zenomorf, "our spits are back to normal", text_color = "#93ec78")
- zenomorf.ammo = GLOB.ammo_list[/datum/ammo/xeno/acid] // el codigo de mierda es mi ciudad
- UnregisterSignal(zenomorf, COMSIG_XENO_POST_SPIT)
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(xeno.ammo == GLOB.ammo_list[/datum/ammo/xeno/acid/spatter])
+ to_chat(xeno, SPAN_XENOWARNING("Our acid glands empty out and return back to normal. We will once more fire long-ranged weak spits."))
+ xeno.balloon_alert(xeno, "our spits are back to normal", text_color = "#93ec78")
+ xeno.ammo = GLOB.ammo_list[/datum/ammo/xeno/acid] // el codigo de mierda es mi ciudad
+ UnregisterSignal(xeno, COMSIG_XENO_POST_SPIT)
+ end_duration_display()
/datum/action/xeno_action/onclick/charge_spit/proc/remove_effects()
- var/mob/living/carbon/xenomorph/zenomorf = owner
+ var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(zenomorf))
+ if(!istype(xeno))
return
- zenomorf.speed_modifier += speed_buff_amount
- zenomorf.armor_modifier -= armor_buff_amount
- zenomorf.recalculate_speed()
- zenomorf.recalculate_armor()
- to_chat(zenomorf, SPAN_XENOHIGHDANGER("We feel our movement speed slow down!"))
+ xeno.speed_modifier += speed_buff_amount
+ xeno.armor_modifier -= armor_buff_amount
+ xeno.recalculate_speed()
+ xeno.recalculate_armor()
+ to_chat(xeno, SPAN_XENOHIGHDANGER("We feel our movement speed slow down!"))
disable_spatter()
buffs_active = FALSE
-/datum/action/xeno_action/activable/tail_stab/spitter/use_ability(atom/A)
+/datum/action/xeno_action/activable/tail_stab/spitter/use_ability(atom/target_atom)
var/target = ..()
if(iscarbon(target))
var/mob/living/carbon/carbon_target = target
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm b/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm
index ec3729688f6f6..c8107481cf44c 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm
@@ -78,7 +78,6 @@
var/lifesteal_lock_duration = 20 // This will remove the glow effect on warrior after 2 seconds
var/color = "#6c6f24"
var/emote_cooldown = 0
- var/lunging = FALSE // whether or not the warrior is currently lunging (holding) a target
/mob/living/carbon/xenomorph/warrior/handle_special_state()
return HAS_TRAIT(src, TRAIT_ABILITY_ENCLOSED_PLATES)
@@ -87,20 +86,19 @@
if(HAS_TRAIT(src, TRAIT_ABILITY_ENCLOSED_PLATES))
return "Warrior_plates_[severity]"
-/mob/living/carbon/xenomorph/warrior/throw_item(atom/target)
+/mob/living/carbon/xenomorph/warrior/throw_item(atom/target_atom)
toggle_throw_mode(THROW_MODE_OFF)
/mob/living/carbon/xenomorph/warrior/stop_pulling()
var/datum/behavior_delegate/warrior_base/warrior_delegate = behavior_delegate
- if(isliving(pulling) && istype(warrior_delegate) && warrior_delegate.lunging)
- warrior_delegate.lunging = FALSE // To avoid extreme cases of stopping a lunge then quickly pulling and stopping to pull someone else
+ if(isliving(pulling) && istype(warrior_delegate) && HAS_TRAIT(src, TRAIT_ABILITY_LUNGE))
+ REMOVE_TRAIT(src, TRAIT_ABILITY_LUNGE, TRAIT_SOURCE_ABILITY("lunge"))
var/mob/living/lunged = pulling
lunged.set_effect(0, STUN)
lunged.set_effect(0, WEAKEN)
return ..()
/mob/living/carbon/xenomorph/warrior/start_pulling(atom/movable/movable_atom, lunge)
- var/datum/behavior_delegate/warrior_base/warrior_delegate = behavior_delegate
if(!check_state())
return FALSE
@@ -117,8 +115,8 @@
if(.) //successful pull
if(isxeno(living_mob))
- var/mob/living/carbon/xenomorph/xeno = living_mob
- if(xeno.tier >= 2) // Tier 2 castes or higher immune to warrior grab stuns
+ var/mob/living/carbon/xenomorph/target_xeno = living_mob
+ if(target_xeno.tier >= 2) // Tier 2 castes or higher immune to warrior grab stuns
return
if(should_neckgrab && living_mob.mob_size < MOB_SIZE_BIG)
@@ -130,12 +128,11 @@
return // Grab was broken, probably as Stun side effect (eg. target getting knocked away from a manned M56D)
visible_message(SPAN_XENOWARNING("[src] grabs [living_mob] by the throat!"),
SPAN_XENOWARNING("We grab [living_mob] by the throat!"))
- warrior_delegate.lunging = TRUE
+ ADD_TRAIT(src, TRAIT_ABILITY_LUNGE, TRAIT_SOURCE_ABILITY("lunge"))
addtimer(CALLBACK(src, PROC_REF(stop_lunging)), get_xeno_stun_duration(living_mob, 2) SECONDS + 1 SECONDS)
/mob/living/carbon/xenomorph/warrior/proc/stop_lunging(world_time)
- var/datum/behavior_delegate/warrior_base/warrior_delegate = behavior_delegate
- warrior_delegate.lunging = FALSE
+ REMOVE_TRAIT(src, TRAIT_ABILITY_LUNGE, TRAIT_SOURCE_ABILITY("lunge"))
/mob/living/carbon/xenomorph/warrior/hitby(atom/movable/movable_atom)
if(ishuman(movable_atom))
@@ -143,7 +140,7 @@
..()
-/datum/behavior_delegate/warrior_base/melee_attack_additional_effects_target(mob/living/carbon/carbon)
+/datum/behavior_delegate/warrior_base/melee_attack_additional_effects_target(mob/living/carbon/target_carbon)
..()
if(SEND_SIGNAL(bound_xeno, COMSIG_XENO_PRE_HEAL) & COMPONENT_CANCEL_XENO_HEAL)
@@ -152,14 +149,14 @@
var/final_lifesteal = lifesteal_percent
var/list/mobs_in_range = oviewers(lifesteal_range, bound_xeno)
- for(var/mob/mob as anything in mobs_in_range)
+ for(var/mob/target_mob as anything in mobs_in_range)
if(final_lifesteal >= max_lifesteal)
break
- if(mob.stat == DEAD || HAS_TRAIT(mob, TRAIT_NESTED))
+ if(target_mob.stat == DEAD || HAS_TRAIT(target_mob, TRAIT_NESTED))
continue
- if(bound_xeno.can_not_harm(mob))
+ if(bound_xeno.can_not_harm(target_mob))
continue
final_lifesteal++
@@ -182,8 +179,7 @@
if(!isxeno_human(target_carbon))
return
-
- if(lunging && target_carbon)
+ if(HAS_TRAIT(bound_xeno, TRAIT_ABILITY_LUNGE) && target_carbon)
return INTENT_HARM
@@ -192,101 +188,92 @@
/datum/action/xeno_action/activable/lunge/use_ability(atom/affected_atom)
- var/mob/living/carbon/xenomorph/lunge_user = owner
+ var/mob/living/carbon/xenomorph/xeno = owner
if(!action_cooldown_check())
- if(twitch_message_cooldown < world.time )
- lunge_user.visible_message(SPAN_XENOWARNING("[lunge_user]'s claws twitch."), SPAN_XENOWARNING("Our claws twitch as we try to lunge but lack the strength. Wait a moment to try again."))
+ if(twitch_message_cooldown < world.time)
+ xeno.visible_message(SPAN_XENOWARNING("[xeno]'s claws twitch."), SPAN_XENOWARNING("Our claws twitch as we try to lunge but lack the strength. Wait a moment to try again."))
twitch_message_cooldown = world.time + 5 SECONDS
return //this gives a little feedback on why your lunge didn't hit other than the lunge button going grey. Plus, it might spook marines that almost got lunged if they know why the message appeared, and extra spookiness is always good.
if(!affected_atom)
return
- if(!isturf(lunge_user.loc))
- to_chat(lunge_user, SPAN_XENOWARNING("We can't lunge from here!"))
- return
-
- if(!lunge_user.check_state())
+ if(!isturf(xeno.loc))
+ to_chat(xeno, SPAN_XENOWARNING("We can't lunge from here!"))
return
- if(lunge_user.can_not_harm(affected_atom) || !ismob(affected_atom))
+ if(xeno.can_not_harm(affected_atom) || !ismob(affected_atom))
apply_cooldown_override(click_miss_cooldown)
return
- var/mob/living/carbon/carbon = affected_atom
- if(carbon.stat == DEAD)
+ var/mob/living/carbon/target_carbon = affected_atom
+ if(target_carbon.stat == DEAD)
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
apply_cooldown()
..()
- lunge_user.visible_message(SPAN_XENOWARNING("[lunge_user] lunges towards [carbon]!"), SPAN_XENOWARNING("We lunge at [carbon]!"))
+ xeno.visible_message(SPAN_XENOWARNING("[xeno] lunges towards [target_carbon]!"), SPAN_XENOWARNING("We lunge at [target_carbon]!"))
- lunge_user.throw_atom(get_step_towards(affected_atom, lunge_user), grab_range, SPEED_FAST, lunge_user, tracking=TRUE)
+ xeno.throw_atom(get_step_towards(affected_atom, xeno), grab_range, SPEED_FAST, xeno, tracking=TRUE)
- if(lunge_user.Adjacent(carbon))
- lunge_user.start_pulling(carbon,1)
- if(ishuman(carbon))
- INVOKE_ASYNC(carbon, TYPE_PROC_REF(/mob, emote), "scream")
+ if(xeno.Adjacent(target_carbon))
+ xeno.start_pulling(target_carbon,1)
+ if(ishuman(target_carbon))
+ INVOKE_ASYNC(target_carbon, TYPE_PROC_REF(/mob, emote), "scream")
else
- lunge_user.visible_message(SPAN_XENOWARNING("[lunge_user]'s claws twitch."), SPAN_XENOWARNING("Our claws twitch as we lunge but are unable to grab onto our target. Wait a moment to try again."))
+ xeno.visible_message(SPAN_XENOWARNING("[xeno]'s claws twitch."), SPAN_XENOWARNING("Our claws twitch as we lunge but are unable to grab onto our target. Wait a moment to try again."))
return TRUE
/datum/action/xeno_action/activable/fling/use_ability(atom/affected_atom)
- var/mob/living/carbon/xenomorph/fling_user = owner
+ var/mob/living/carbon/xenomorph/xeno = owner
- if(!action_cooldown_check())
+ if(!isxeno_human(affected_atom) || xeno.can_not_harm(affected_atom))
return
- if(!isxeno_human(affected_atom) || fling_user.can_not_harm(affected_atom))
- return
+ XENO_ACTION_CHECK(xeno)
- if(!fling_user.check_state())
+ if(!xeno.Adjacent(affected_atom))
return
- if(!fling_user.Adjacent(affected_atom))
+ var/mob/living/carbon/target_carbon = affected_atom
+ if(target_carbon.stat == DEAD)
return
- var/mob/living/carbon/carbon = affected_atom
- if(carbon.stat == DEAD)
+ if(HAS_TRAIT(target_carbon, TRAIT_NESTED))
return
- if(HAS_TRAIT(carbon, TRAIT_NESTED))
- return
+ if(target_carbon == xeno.pulling)
+ xeno.stop_pulling()
- if(carbon == fling_user.pulling)
- fling_user.stop_pulling()
-
- if(carbon.mob_size >= MOB_SIZE_BIG)
- to_chat(fling_user, SPAN_XENOWARNING("[carbon] is too big for us to fling!"))
+ if(target_carbon.mob_size >= MOB_SIZE_BIG)
+ to_chat(xeno, SPAN_XENOWARNING("[target_carbon] is too big for us to fling!"))
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- fling_user.visible_message(SPAN_XENOWARNING("[fling_user] effortlessly flings [carbon] to the side!"), SPAN_XENOWARNING("We effortlessly fling [carbon] to the side!"))
- playsound(carbon,'sound/weapons/alien_claw_block.ogg', 75, 1)
+ xeno.visible_message(SPAN_XENOWARNING("[xeno] effortlessly flings [target_carbon] to the side!"), SPAN_XENOWARNING("We effortlessly fling [target_carbon] to the side!"))
+ playsound(target_carbon,'sound/weapons/alien_claw_block.ogg', 75, 1)
if(stun_power)
- carbon.Stun(get_xeno_stun_duration(carbon, stun_power))
+ target_carbon.Stun(get_xeno_stun_duration(target_carbon, stun_power))
if(weaken_power)
- carbon.KnockDown(get_xeno_stun_duration(carbon, weaken_power))
+ target_carbon.KnockDown(get_xeno_stun_duration(target_carbon, weaken_power))
if(slowdown)
- if(carbon.slowed < slowdown)
- carbon.apply_effect(slowdown, SLOW)
- carbon.last_damage_data = create_cause_data(initial(fling_user.caste_type), fling_user)
+ if(target_carbon.slowed < slowdown)
+ target_carbon.apply_effect(slowdown, SLOW)
+ target_carbon.last_damage_data = create_cause_data(initial(xeno.caste_type), xeno)
- var/facing = get_dir(fling_user, carbon)
+ var/facing = get_dir(xeno, target_carbon)
// Hmm today I will kill a marine while looking away from them
- fling_user.face_atom(carbon)
- fling_user.animation_attack_on(carbon)
- fling_user.flick_attack_overlay(carbon, "disarm")
- fling_user.throw_carbon(carbon, facing, fling_distance, SPEED_VERY_FAST, shake_camera = TRUE, immobilize = TRUE)
+ xeno.face_atom(target_carbon)
+ xeno.animation_attack_on(target_carbon)
+ xeno.flick_attack_overlay(target_carbon, "disarm")
+ xeno.throw_carbon(target_carbon, facing, fling_distance, SPEED_VERY_FAST, shake_camera = TRUE, immobilize = TRUE)
apply_cooldown()
return ..()
@@ -294,73 +281,68 @@
/datum/action/xeno_action/activable/warrior_punch/use_ability(atom/affected_atom)
var/mob/living/carbon/xenomorph/punch_user = owner
- if(!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(punch_user)
if(!isxeno_human(affected_atom) || punch_user.can_not_harm(affected_atom))
return
- if(!punch_user.check_state())
- return
-
var/distance = get_dist(punch_user, affected_atom)
if(distance > 2)
return
- var/mob/living/carbon/carbon = affected_atom
+ var/mob/living/carbon/target_carbon = affected_atom
- if(!punch_user.Adjacent(carbon))
+ if(!punch_user.Adjacent(target_carbon))
return
- if(carbon.stat == DEAD)
+ if(target_carbon.stat == DEAD)
return
- if(HAS_TRAIT(carbon, TRAIT_NESTED))
+ if(HAS_TRAIT(target_carbon, TRAIT_NESTED))
return
- var/obj/limb/target_limb = carbon.get_limb(check_zone(punch_user.zone_selected))
+ var/obj/limb/target_limb = target_carbon.get_limb(check_zone(punch_user.zone_selected))
- if(ishuman(carbon) && (!target_limb || (target_limb.status & LIMB_DESTROYED)))
- target_limb = carbon.get_limb("chest")
+ if(ishuman(target_carbon) && (!target_limb || (target_limb.status & LIMB_DESTROYED)))
+ target_limb = target_carbon.get_limb("chest")
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(punch_user)
- carbon.last_damage_data = create_cause_data(initial(punch_user.caste_type), punch_user)
+ target_carbon.last_damage_data = create_cause_data(initial(punch_user.caste_type), punch_user)
- punch_user.visible_message(SPAN_XENOWARNING("[punch_user] hits [carbon] in the [target_limb ? target_limb.display_name : "chest"] with a devastatingly powerful punch!"),
- SPAN_XENOWARNING("We hit [carbon] in the [target_limb ? target_limb.display_name : "chest"] with a devastatingly powerful punch!"))
+ punch_user.visible_message(SPAN_XENOWARNING("[punch_user] hits [target_carbon] in the [target_limb ? target_limb.display_name : "chest"] with a devastatingly powerful punch!"),
+ SPAN_XENOWARNING("We hit [target_carbon] in the [target_limb ? target_limb.display_name : "chest"] with a devastatingly powerful punch!"))
var/sound = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg',)
- playsound(carbon, sound, 50, 1)
- do_base_warrior_punch(carbon, target_limb)
+ playsound(target_carbon, sound, 50, 1)
+ do_base_warrior_punch(target_carbon, target_limb)
apply_cooldown()
return ..()
-/datum/action/xeno_action/activable/warrior_punch/proc/do_base_warrior_punch(mob/living/carbon/carbon, obj/limb/target_limb)
- var/mob/living/carbon/xenomorph/warrior = owner
+/datum/action/xeno_action/activable/warrior_punch/proc/do_base_warrior_punch(mob/living/carbon/target_carbon, obj/limb/target_limb)
+ var/mob/living/carbon/xenomorph/punch_user = owner
var/damage = rand(base_damage, base_damage + damage_variance)
- if(ishuman(carbon))
+ if(ishuman(target_carbon))
if((target_limb.status & LIMB_SPLINTED) && !(target_limb.status & LIMB_SPLINTED_INDESTRUCTIBLE)) //If they have it splinted, the splint won't hold.
target_limb.status &= ~LIMB_SPLINTED
- playsound(get_turf(carbon), 'sound/items/splintbreaks.ogg', 20)
- to_chat(carbon, SPAN_DANGER("The splint on your [target_limb.display_name] comes apart!"))
- carbon.pain.apply_pain(PAIN_BONE_BREAK_SPLINTED)
+ playsound(get_turf(target_carbon), 'sound/items/splintbreaks.ogg', 20)
+ to_chat(target_carbon, SPAN_DANGER("The splint on your [target_limb.display_name] comes apart!"))
+ target_carbon.pain.apply_pain(PAIN_BONE_BREAK_SPLINTED)
- if(ishuman_strict(carbon))
- carbon.apply_effect(3, SLOW)
+ if(ishuman_strict(target_carbon))
+ target_carbon.apply_effect(3, SLOW)
- if(isyautja(carbon))
+ if(isyautja(target_carbon))
damage = rand(base_punch_damage_pred, base_punch_damage_pred + damage_variance)
else if(target_limb.status & (LIMB_ROBOT|LIMB_SYNTHSKIN))
damage = rand(base_punch_damage_synth, base_punch_damage_synth + damage_variance)
- carbon.apply_armoured_damage(get_xeno_damage_slash(carbon, damage), ARMOR_MELEE, BRUTE, target_limb ? target_limb.name : "chest")
+ target_carbon.apply_armoured_damage(get_xeno_damage_slash(target_carbon, damage), ARMOR_MELEE, BRUTE, target_limb ? target_limb.name : "chest")
// Hmm today I will kill a marine while looking away from them
- warrior.face_atom(carbon)
- warrior.animation_attack_on(carbon)
- warrior.flick_attack_overlay(carbon, "punch")
- shake_camera(carbon, 2, 1)
- step_away(carbon, warrior, 2)
+ punch_user.face_atom(target_carbon)
+ punch_user.animation_attack_on(target_carbon)
+ punch_user.flick_attack_overlay(target_carbon, "punch")
+ shake_camera(target_carbon, 2, 1)
+ step_away(target_carbon, punch_user, 2)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/caste_datum.dm b/code/modules/mob/living/carbon/xenomorph/castes/caste_datum.dm
index f3bcd560ed8b7..b9a4facaaa362 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/caste_datum.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/caste_datum.dm
@@ -103,8 +103,6 @@
/// if fire_immunity is set to be vulnerable, how much will fire damage be multiplied. Defines in xeno.dm
var/fire_vulnerability_mult = 0
- var/burrow_cooldown = 5 SECONDS
- var/tunnel_cooldown = 10 SECONDS
///whether the xeno heals even outside weeds.
var/innate_healing = FALSE
diff --git a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm
index 97c25f0430a4f..39ce178ee55b8 100644
--- a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm
+++ b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm
@@ -1,4 +1,6 @@
/mob/living/carbon/xenomorph/attackby(obj/item/item, mob/user)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
+ return
if(user.a_intent != INTENT_HELP)
return ..()
if(HAS_TRAIT(item, TRAIT_TOOL_MULTITOOL) && ishuman(user))
@@ -45,6 +47,8 @@
return ..()
/mob/living/carbon/xenomorph/ex_act(severity, direction, datum/cause_data/cause_data, pierce=0, enviro=FALSE)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
+ return
if(body_position == LYING_DOWN && direction > 0)
severity *= EXPLOSION_PRONE_MULTIPLIER
@@ -327,4 +331,8 @@
fire.set_on_fire(src) //Deals an extra proc of fire when you're crossing it. 30 damage per tile crossed, plus 15 per Process().
next_move_slowdown = next_move_slowdown + (SLOWDOWN_AMT_GREENFIRE * resist_modifier)
if(resist_modifier > 0)
- to_chat(src, SPAN_DANGER("We feel pieces of our exoskeleton fusing with the viscous fluid below and tearing off as we struggle to move through the flames!"))
+ if(!HAS_TRAIT(src, TRAIT_ABILITY_POUNCE))
+ to_chat(src, SPAN_DANGER("We feel pieces of our exoskeleton fusing with the viscous fluid below and tearing off as we struggle to move through the flames!"))
+ else
+ if(!prob(75))
+ to_chat(src, SPAN_DANGER("We feel searing heat full of chemicals from below us, melting our exoskeleton as we pass above the flames!"))
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm
index 26d36331587b2..cf4194182e71b 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm
@@ -56,31 +56,31 @@
. += "Insight Amount: [trap_ability.empowering_charge_counter]/[trap_ability.empower_charge_max]"
/datum/behavior_delegate/boiler_trapper/on_hitby_projectile(ammo)
- if (temp_movespeed_usable)
+ if(temp_movespeed_usable)
temp_movespeed_time_used = world.time
temp_movespeed_usable = FALSE
- if (isxeno(bound_xeno))
+ if(isxeno(bound_xeno))
var/mob/living/carbon/xenomorph/xeno = bound_xeno
xeno.speed_modifier -= temp_movespeed_amount
xeno.recalculate_speed()
addtimer(CALLBACK(src, PROC_REF(remove_speed_buff)), temp_movespeed_duration)
/datum/behavior_delegate/boiler_trapper/ranged_attack_additional_effects_target(atom/target_atom)
- if (!ishuman(target_atom))
+ if(!ishuman(target_atom))
return
- if (!istype(bound_xeno))
+ if(!istype(bound_xeno))
return
var/mob/living/carbon/human/target_human = target_atom
var/datum/effects/boiler_trap/found = null
- for (var/datum/effects/boiler_trap/trap in target_human.effects_list)
- if (trap.cause_data?.resolve_mob() == bound_xeno)
+ for(var/datum/effects/boiler_trap/trap in target_human.effects_list)
+ if(trap.cause_data?.resolve_mob() == bound_xeno)
found = trap
break
var/datum/action/xeno_action/activable/boiler_trap/trap_ability = get_action(bound_xeno, /datum/action/xeno_action/activable/boiler_trap)
- if (found)
+ if(found)
target_human.apply_armoured_damage(bonus_damage_shotgun_trapped, ARMOR_BIO, BURN)
trap_ability.empowering_charge_counter = trap_ability.empower_charge_max
else
@@ -96,15 +96,15 @@
trap_ability.empowering_charge_counter = trap_ability.empower_charge_max
/datum/behavior_delegate/boiler_trapper/on_life()
- if ((temp_movespeed_time_used + temp_movespeed_cooldown) < world.time)
- if (!temp_movespeed_messaged)
+ if((temp_movespeed_time_used + temp_movespeed_cooldown) < world.time)
+ if(!temp_movespeed_messaged)
to_chat(bound_xeno, SPAN_XENODANGER("You feel your adrenaline glands refill! Your speedboost will activate again."))
temp_movespeed_messaged = TRUE
temp_movespeed_usable = TRUE
return
/datum/behavior_delegate/boiler_trapper/proc/remove_speed_buff()
- if (isxeno(bound_xeno))
+ if(isxeno(bound_xeno))
var/mob/living/carbon/xenomorph/xeno = bound_xeno
xeno.speed_modifier += temp_movespeed_amount
xeno.recalculate_speed()
@@ -113,21 +113,14 @@
/datum/action/xeno_action/activable/boiler_trap/use_ability(atom/affected_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
+ if(!istype(xeno))
return
- if (!action_cooldown_check())
- return
-
- if (!xeno.check_state())
- return
-
- if (!can_see(xeno, affected_atom, TRAPPER_VIEWRANGE))
+ if(!can_see(xeno, affected_atom, TRAPPER_VIEWRANGE))
to_chat(xeno, SPAN_XENODANGER("We cannot see that location!"))
return
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
// 5-long line of turfs orthogonal to the line between us and our target as precisely as we can figure it
var/dir_between = Get_Compass_Dir(xeno, affected_atom)
@@ -141,16 +134,16 @@
target_turfs += get_step(left_turf, turn(dir_between, -90))
target_turfs += get_step(right_turf, turn(dir_between, 90))
- for (var/turf/turf in target_turfs)
- if (!istype(turf) || turf.density)
+ for(var/turf/turf in target_turfs)
+ if(!istype(turf) || turf.density)
continue
var/trap_found = FALSE
- for (var/obj/effect/alien/resin/boilertrap/boiler_trap in turf)
+ for(var/obj/effect/alien/resin/boilertrap/boiler_trap in turf)
trap_found = TRUE
break
- if (trap_found)
+ if(trap_found)
continue
var/obj/effect/alien/resin/boilertrap/boiler_trap
@@ -176,13 +169,7 @@
/datum/action/xeno_action/activable/acid_mine/use_ability(atom/affected_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
- return
-
- if (!xeno.check_state())
- return
-
- if (!action_cooldown_check())
+ if(!istype(xeno))
return
if(!affected_atom || affected_atom.layer >= FLY_LAYER || !isturf(xeno.loc))
@@ -192,8 +179,7 @@
to_chat(xeno, SPAN_XENOWARNING("Something is in the way!"))
return
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
var/turf/turf = get_turf(affected_atom)
var/acid_bolt_message = "a bolt of acid"
@@ -203,7 +189,7 @@
xeno.visible_message(SPAN_XENODANGER("[xeno] fires " + acid_bolt_message + " at [affected_atom]!"), SPAN_XENODANGER("We fire " + acid_bolt_message + " at [affected_atom]!"))
new /obj/effect/xenomorph/acid_damage_delay/boiler_landmine(turf, damage, delay, empowered, "You are blasted with " + acid_bolt_message + "!", xeno)
- for (var/turf/target_turf in orange(1, turf))
+ for(var/turf/target_turf in orange(1, turf))
new /obj/effect/xenomorph/acid_damage_delay/boiler_landmine(target_turf, damage, delay, empowered, "You are blasted with a " + acid_bolt_message + "!", xeno)
if(empowered)
@@ -215,13 +201,12 @@
/datum/action/xeno_action/activable/acid_shotgun/use_ability(atom/affected_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(xeno))
+ if(!istype(xeno))
return
- if (!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(xeno)
- if(!affected_atom || affected_atom.layer >= FLY_LAYER || !isturf(xeno.loc) || !xeno.check_state())
+ if(!affected_atom || affected_atom.layer >= FLY_LAYER || !isturf(xeno.loc))
return
xeno.visible_message(SPAN_XENOWARNING("[xeno] fires a blast of acid at [affected_atom]!"), SPAN_XENOWARNING("We fire a blast of acid at [affected_atom]!"))
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/crusher/charger.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/crusher/charger.dm
index 67567161b1da4..b75b9286a62d8 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/crusher/charger.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/crusher/charger.dm
@@ -50,7 +50,7 @@
/datum/behavior_delegate/crusher_charger/add_to_xeno()
RegisterSignal(bound_xeno, COMSIG_MOB_SET_FACE_DIR, PROC_REF(cancel_dir_lock))
- RegisterSignal(bound_xeno, COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE, PROC_REF(apply_directional_armor))
+ RegisterSignal(bound_xeno, COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE, PROC_REF(apply_directional_projectile_armor))
my_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/charger_charge)
if(my_action == null)
@@ -63,7 +63,7 @@
SIGNAL_HANDLER
return COMPONENT_CANCEL_SET_FACE_DIR
-/datum/behavior_delegate/crusher_charger/proc/apply_directional_armor(mob/living/carbon/xenomorph/xeno, list/damagedata)
+/datum/behavior_delegate/crusher_charger/proc/apply_directional_projectile_armor(mob/living/carbon/xenomorph/xeno, list/damagedata)
SIGNAL_HANDLER
var/projectile_direction = damagedata["direction"]
if(xeno.dir & REVERSE_DIR(projectile_direction))
@@ -118,6 +118,136 @@
return ..()
+/datum/action/xeno_action/onclick/charger_charge/proc/handle_position_change(mob/living/carbon/xenomorph/xeno, body_position)
+ SIGNAL_HANDLER
+ if(body_position == LYING_DOWN)
+ handle_movement(xeno)
+
+/datum/action/xeno_action/onclick/charger_charge/proc/handle_movement(mob/living/carbon/xenomorph/xeno, atom/oldloc, dir, forced)
+ SIGNAL_HANDLER
+ if(xeno.pulling)
+ if(!momentum)
+ steps_taken = 0
+ return
+ else
+ xeno.stop_pulling()
+
+ if(xeno.is_mob_incapacitated())
+ if(!momentum)
+ return
+ var/distance_to_throw = get_ranged_target_turf(xeno, charge_dir, momentum/2)
+ INVOKE_ASYNC(xeno, TYPE_PROC_REF(/atom/movable, throw_atom), distance_to_throw, momentum/2, SPEED_FAST, null, TRUE)
+ stop_momentum()
+ return
+ if(!isturf(xeno.loc))
+ stop_momentum()
+ return
+ // Don't build up charge if you move via getting propelled by something
+ if(xeno.throwing)
+ stop_momentum()
+ return
+
+ var/do_stop_momentum = FALSE
+
+ // Need to be constantly moving in order to maintain charge
+ if(world.time > last_charge_move + 0.5 SECONDS)
+ do_stop_momentum = TRUE
+ if(dir != charge_dir)
+ charge_dir = dir
+ do_stop_momentum = TRUE
+
+ if(do_stop_momentum)
+ stop_momentum()
+ if(xeno.plasma_stored <= plasma_per_step)
+ stop_momentum()
+ return
+ last_charge_move = world.time
+ steps_taken++
+ if(steps_taken < steps_to_charge)
+ return
+ if(momentum < max_momentum)
+ momentum++
+ ADD_TRAIT(xeno, TRAIT_CHARGING, TRAIT_SOURCE_XENO_ACTION_CHARGE)
+ xeno.update_icons()
+ if(momentum == max_momentum)
+ xeno.emote("roar")
+ //X.use_plasma(plasma_per_step) // take if you are in toggle charge mode
+ if(momentum > 0)
+ xeno.use_plasma(plasma_per_step) // take plasma when you have momentum
+
+ noise_timer = noise_timer ? --noise_timer : 3
+ if(noise_timer == 3)
+ playsound(xeno, 'sound/effects/alien_footstep_charge1.ogg', 50)
+
+ for(var/mob/living/carbon/human/Mob in xeno.loc)
+ if(Mob.body_position == LYING_DOWN && Mob.stat != DEAD)
+ xeno.visible_message(SPAN_DANGER("[xeno] runs [Mob] over!"),
+ SPAN_DANGER("We run [Mob] over!")
+ )
+ var/ram_dir = pick(get_perpen_dir(xeno.dir))
+ var/dist = 1
+ if(momentum == max_momentum)
+ dist = momentum * 0.25
+ step(Mob, ram_dir, dist)
+ Mob.take_overall_armored_damage(momentum * 6)
+ INVOKE_ASYNC(Mob, TYPE_PROC_REF(/mob/living/carbon/human, emote),"pain")
+ shake_camera(Mob, 7,3)
+ animation_flash_color(Mob)
+
+ xeno.recalculate_speed()
+
+/datum/action/xeno_action/onclick/charger_charge/proc/handle_dir_change(datum/source, old_dir, new_dir)
+ SIGNAL_HANDLER
+ if(new_dir != charge_dir)
+ charge_dir = new_dir
+ if(momentum)
+ stop_momentum()
+
+/datum/action/xeno_action/onclick/charger_charge/proc/handle_river(datum/source, covered)
+ SIGNAL_HANDLER
+ if(!covered)
+ stop_momentum()
+
+/datum/action/xeno_action/onclick/charger_charge/proc/update_speed(mob/living/carbon/xenomorph/xeno)
+ SIGNAL_HANDLER
+ xeno.speed += momentum * speed_per_momentum
+
+/datum/action/xeno_action/onclick/charger_charge/proc/stop_momentum(datum/source)
+ SIGNAL_HANDLER
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(momentum == max_momentum)
+ xeno.visible_message(SPAN_DANGER("[xeno] skids to a halt!"))
+
+ REMOVE_TRAIT(xeno, TRAIT_CHARGING, TRAIT_SOURCE_XENO_ACTION_CHARGE)
+ steps_taken = 0
+ momentum = 0
+ xeno.recalculate_speed()
+ xeno.update_icons()
+
+/datum/action/xeno_action/onclick/charger_charge/proc/lose_momentum(amount)
+ if(amount >= momentum)
+ stop_momentum()
+ else
+ momentum -= amount
+ var/mob/living/carbon/xenomorph/xeno = owner
+ xeno.recalculate_speed()
+
+/datum/action/xeno_action/onclick/charger_charge/proc/handle_collision(mob/living/carbon/xenomorph/xeno, atom/tar)
+ SIGNAL_HANDLER
+ if(!momentum)
+ stop_momentum()
+ return
+
+ var/result = tar.handle_charge_collision(xeno, src)
+ switch(result)
+ if(XENO_CHARGE_TRY_MOVE)
+ if(step(xeno, charge_dir))
+ return COMPONENT_LIVING_COLLIDE_HANDLED
+
+/datum/action/xeno_action/onclick/charger_charge/proc/start_charging(datum/source)
+ SIGNAL_HANDLER
+ steps_taken = steps_to_charge
+
/datum/action/xeno_action/activable/tumble/use_ability(atom/Target)
if(!action_cooldown_check())
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/defender/steel_crest.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/defender/steel_crest.dm
index 50957326b920d..5aa96e538c864 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/defender/steel_crest.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/defender/steel_crest.dm
@@ -17,12 +17,11 @@
/datum/xeno_strain/steel_crest/apply_strain(mob/living/carbon/xenomorph/defender/defender)
defender.damage_modifier -= XENO_DAMAGE_MOD_VERY_SMALL
- if(defender.fortify)
+ if(HAS_TRAIT(defender, TRAIT_ABILITY_FORTIFY))
defender.ability_speed_modifier += 2.5
defender.recalculate_stats()
-
// Steel crest override
/datum/action/xeno_action/activable/fortify/steel_crest/apply_modifiers(mob/living/carbon/xenomorph/xeno, fortify_state)
if(fortify_state)
@@ -36,27 +35,36 @@
xeno.ability_speed_modifier -= 3
xeno.damage_modifier += XENO_DAMAGE_MOD_SMALL
+/datum/action/xeno_action/activable/fortify/proc/check_directional_projectile_armor(mob/living/carbon/xenomorph/defendy, list/damagedata)
+ SIGNAL_HANDLER
+ var/projectile_direction = damagedata["direction"]
+ // If the defender is facing the projectile.
+ if(defendy.dir & REVERSE_DIR(projectile_direction))
+ damagedata["armor"] += frontal_armor
-/datum/action/xeno_action/onclick/soak/use_ability(atom/A)
- var/mob/living/carbon/xenomorph/steelcrest = owner
+/datum/action/xeno_action/activable/fortify/proc/unconscious_check()
+ SIGNAL_HANDLER
- if (!action_cooldown_check())
+ if(QDELETED(owner))
return
- if (!steelcrest.check_state())
- return
+ UnregisterSignal(owner, COMSIG_XENO_ENTER_CRIT)
+ UnregisterSignal(owner, COMSIG_MOB_DEATH)
- if(!check_and_use_plasma_owner())
- return
+/datum/action/xeno_action/onclick/soak/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- RegisterSignal(steelcrest, COMSIG_MOB_TAKE_DAMAGE, PROC_REF(damage_accumulate))
+ RegisterSignal(xeno, COMSIG_MOB_TAKE_DAMAGE, PROC_REF(damage_accumulate))
addtimer(CALLBACK(src, PROC_REF(stop_accumulating)), 6 SECONDS)
+ start_duration_display(6 SECONDS)
- steelcrest.balloon_alert(steelcrest, "begins to tank incoming damage!")
+ xeno.balloon_alert(xeno, "begins to tank incoming damage!")
- to_chat(steelcrest, SPAN_XENONOTICE("We begin to tank incoming damage!"))
+ to_chat(xeno, SPAN_XENONOTICE("We begin to tank incoming damage!"))
- steelcrest.add_filter("steelcrest_enraging", 1, list("type" = "outline", "color" = "#421313", "size" = 1))
+ xeno.add_filter("steelcrest_enraging", 1, list("type" = "outline", "color" = "#421313", "size" = 1))
apply_cooldown()
return ..()
@@ -74,23 +82,26 @@
/datum/action/xeno_action/onclick/soak/proc/stop_accumulating()
UnregisterSignal(owner, COMSIG_MOB_TAKE_DAMAGE)
+ end_duration_display()
damage_accumulated = 0
to_chat(owner, SPAN_XENONOTICE("We stop taking incoming damage."))
owner.remove_filter("steelcrest_enraging")
/datum/action/xeno_action/onclick/soak/proc/enraged()
+ end_duration_display()
owner.remove_filter("steelcrest_enraging")
owner.add_filter("steelcrest_enraged", 1, list("type" = "outline", "color" = "#ad1313", "size" = 1))
- owner.visible_message(SPAN_XENOWARNING("[owner] gets enraged after being damaged enough!"), SPAN_XENOWARNING("We feel enraged after taking in oncoming damage! Our tail slam's cooldown is reset and we heal!"))
+ owner.visible_message(SPAN_XENOWARNING("[owner] gets enraged and their carapace start to rapidly mend!"), SPAN_XENOWARNING("We feel enraged after taking in oncoming damage! Our tail slam's cooldown is reset and our carapace start to rapidly mend!"))
+ owner.flick_heal_overlay(3 SECONDS, "#00B800")
- var/mob/living/carbon/xenomorph/enraged_mob = owner
- enraged_mob.gain_health(75) // pretty reasonable amount of health recovered
+ var/mob/living/carbon/xenomorph/xeno = owner
+ new /datum/effects/heal_over_time(xeno, healing_time = 3, heal_amount = 75) // pretty reasonable amount of health recovered over time.
// Check actions list for tail slam and reset it's cooldown if it's there
var/datum/action/xeno_action/activable/tail_stab/slam/slam_action = locate() in owner.actions
- if (slam_action && !slam_action.action_cooldown_check())
+ if(slam_action && !slam_action.action_cooldown_check())
slam_action.end_cooldown()
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/lurker/vampire.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/lurker/vampire.dm
index 1d5c0931116eb..ad2d8b5e94e69 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/lurker/vampire.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/lurker/vampire.dm
@@ -31,6 +31,13 @@
lurker.recalculate_everything()
+
+/datum/action/xeno_action/activable/pounce/rush/start_airbone()
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ ADD_TRAIT(xeno, TRAIT_ABILITY_POUNCE, TRAIT_SOURCE_ABILITY("pounce"))
+
+
/datum/action/xeno_action/activable/pounce/rush/additional_effects(mob/living/living_target) //pounce effects
var/mob/living/carbon/target = living_target
var/mob/living/carbon/xenomorph/xeno = owner
@@ -47,10 +54,8 @@
if(!istype(xeno))
return
- if(!xeno.check_state())
- return
- if(!action_cooldown_check())
- return
+
+ XENO_ACTION_CHECK(xeno)
xeno.visible_message(SPAN_DANGER("[xeno] drags its claws in a wide area in front of it!"),
SPAN_XENOWARNING("We unleash a barrage of slashes!"))
@@ -106,23 +111,18 @@
playsound(get_turf(target), 'sound/weapons/alien_claw_flesh4.ogg', 30, TRUE)
if(!xeno.on_fire)
xeno.flick_heal_overlay(1 SECONDS, "#00B800")
- xeno.gain_health(30)
+ new /datum/effects/heal_over_time(xeno, healing_time = 2, heal_amount = 30)
xeno.animation_attack_on(target)
xeno.emote("roar")
return ..()
/datum/action/xeno_action/activable/tail_jab/use_ability(atom/targeted_atom)
-
var/mob/living/carbon/xenomorph/xeno = owner
var/mob/living/carbon/hit_target = targeted_atom
var/distance = get_dist(xeno, hit_target)
- if(!action_cooldown_check())
- return
-
- if(!xeno.check_state())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
if(distance > 2)
return
@@ -220,6 +220,10 @@
if(xeno.can_not_harm(target_carbon))
return
+ if(target_carbon.stat == DEAD)
+ to_chat(xeno, SPAN_XENODANGER("They are already dead!"))
+ return
+
if(!(HAS_TRAIT(target_carbon, TRAIT_KNOCKEDOUT) || target_carbon.stat == UNCONSCIOUS)) //called knocked out because for some reason .stat seems to have a delay .
to_chat(xeno, SPAN_XENOHIGHDANGER("We can only headbite an unconscious, adjacent target!"))
return
@@ -228,10 +232,7 @@
to_chat(xeno, SPAN_XENOHIGHDANGER("We can only headbite an unconscious, adjacent target!"))
return
- if(xeno.stat == UNCONSCIOUS)
- return
-
- if(xeno.stat == DEAD)
+ if(xeno.stat == UNCONSCIOUS || xeno.stat == DEAD)
return
if(xeno.action_busy)
@@ -243,6 +244,8 @@
to_chat(xeno, SPAN_WARNING("We should not harm this host! It has a sister inside."))
return
+ XENO_ACTION_CHECK(xeno)
+
xeno.visible_message(SPAN_DANGER("[xeno] grabs [target_carbon]’s head aggressively."),
SPAN_XENOWARNING("We grab [target_carbon]’s head aggressively."))
@@ -266,7 +269,7 @@
target_carbon.apply_armoured_damage(60, ARMOR_MELEE, BRUTE, "head", 5) //DIE
target_carbon.death(create_cause_data("headbite execution", xeno), FALSE)
if(!xeno.on_fire)
- xeno.gain_health(150)
+ new /datum/effects/heal_over_time(xeno, healing_time = 3, heal_amount = 150)
xeno.xeno_jitter(1 SECONDS)
xeno.flick_heal_overlay(3 SECONDS, "#00B800")
xeno.emote("roar")
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/dancer.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/dancer.dm
index 616418396fadc..46e5455ac9c5f 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/dancer.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/dancer.dm
@@ -45,28 +45,6 @@
/// How much time is left on timer. (used for status)
var/time_left = null
- /// Check for slashed target that had yellow tag
- var/spread_slash_triggered = FALSE
-
- /// How many targets got yellow tag.
- var/spread_count = 0
-
- /// How much damage Harpoon Tail on DISARM mode do. (pierces armor)
- var/blunt_damage = 8
- /// Harpoon Tail mode, used only to display in status.
- var/tail_mode = null
-
- /// Is Dodge ability active?
- var/dodge_activated = FALSE
- /// Used to countdown DANCER_DODGE_TIME.
- var/dodge_start_time = -1
- /// How much refund we want to get back? 1.0 is 1s used to 1s cooldown, 2.0 is 1s used 2s cooldown.
- var/refund_multiplier = 2.0
- /// Used in calculation, finalized number will be displayed as cooldown.
- var/recharge_time = null
- /// Cooldown after activation to prevent accidental double click.
- var/safe_click_cooldown = 0
-
/// Timer to prevent dancer from spreading yellow tags.
var/last_dancer_spread_time = 0
@@ -74,23 +52,27 @@
. = list()
. += "Guaranteed Dodge every [bound_xeno.dodge_threshold] bullet\s."
. += "Yellow Tag Spread Delay: 5 seconds."
- intent_detection()
- . += "Tail Lance Intent: [tail_mode]"
- if(tail_mode == "Blunt")
- . += "Damage: [blunt_damage] AP"
+
+ var/datum/action/xeno_action/activable/tail_stab/harpoon_tail/harpoon_action = get_action(bound_xeno, /datum/action/xeno_action/activable/tail_stab/harpoon_tail)
+ harpoon_action.intent_detection()
+ . += "Tail Lance Intent: [harpoon_action.tail_mode]"
+ if(harpoon_action.tail_mode == "Blunt")
+ . += "Damage: [harpoon_action.blunt_damage] AP"
. += "Cooldown: 3 seconds."
- if(dodge_start_time != -1)
- time_left = (DANCER_DODGE_TIME - (world.time - dodge_start_time)) / 10
+
+ var/datum/action/xeno_action/onclick/prae_dodge/dodge_action = get_action(bound_xeno, /datum/action/xeno_action/onclick/prae_dodge)
+ if(dodge_action.dodge_start_time != -1)
+ time_left = (DANCER_DODGE_TIME - (world.time - dodge_action.dodge_start_time)) / 10
. += "Dodge Remaining: [time_left] second\s."
return
/datum/behavior_delegate/praetorian_dancer/melee_attack_additional_effects_self()
..()
- if(!spread_slash_triggered)
+ if(!HAS_TRAIT(bound_xeno, TRAIT_ABILITY_YELLOW_TAG))
return
- spread_slash_triggered = FALSE
+ REMOVE_TRAIT(bound_xeno, TRAIT_ABILITY_YELLOW_TAG, TRAIT_SOURCE_ABILITY("yellow_tag"))
var/datum/action/xeno_action/activable/prae_impale/impale_action = get_action(bound_xeno, /datum/action/xeno_action/activable/prae_impale)
if(!impale_action.action_cooldown_check())
@@ -121,30 +103,30 @@
break
if(consumed_spread)
- spread_slash_triggered = TRUE
+ ADD_TRAIT(bound_xeno, TRAIT_ABILITY_YELLOW_TAG, TRAIT_SOURCE_ABILITY("yellow_tag"))
if(target_carbon.health <= 0)
try_spread_tags_from(target_carbon)
-/datum/behavior_delegate/praetorian_dancer/proc/try_spread_tags_from(mob/living/carbon/human/source)
- if(!ishuman(source))
+/datum/behavior_delegate/praetorian_dancer/proc/try_spread_tags_from(mob/living/carbon/human/target_human)
+ if(!ishuman(target_human))
return
- var/turf/origin = get_turf(source)
+ var/turf/origin = get_turf(target_human)
if(!origin)
return
if(world.time < last_dancer_spread_time + DANCER_YELLOW_TAG_SPREAD_DURATION)
return
- if(world.time < source.last_target_spread_time + DANCER_YELLOW_TAG_SPREAD_CD)
+ if(world.time < target_human.last_target_spread_time + DANCER_YELLOW_TAG_SPREAD_CD)
return
- source.last_target_spread_time = world.time
+ target_human.last_target_spread_time = world.time
var/spread_count = 0
for(var/mob/living/carbon/human/human_target in view(DANCER_YELLOW_TAG_SPREAD_DIST))
- if(human_target == source)
+ if(human_target == target_human)
continue
if(human_target.stat == DEAD || human_target.stat == UNCONSCIOUS)
continue
@@ -164,95 +146,92 @@
if(spread_count >= 0)
to_chat(bound_xeno, SPAN_XENOHIGHDANGER("Fear spreads among the prey, their weakness fuels your instincts to strike them down!"))
-/datum/behavior_delegate/praetorian_dancer/proc/intent_detection()
- if(bound_xeno && bound_xeno.a_intent == INTENT_DISARM)
- tail_mode = "Blunt"
- else
- tail_mode = "Normal"
-/datum/action/xeno_action/activable/tail_stab/harpoon_tail/ability_act(mob/living/carbon/xenomorph/xeno, mob/living/carbon/target, obj/limb/limb)
- if(!istype(xeno) || !istype(target))
- return
- var/datum/behavior_delegate/praetorian_dancer/behavior = xeno.behavior_delegate
- if(!istype(behavior))
+/datum/action/xeno_action/activable/tail_stab/harpoon_tail/ability_act(mob/living/carbon/xenomorph/xeno, mob/living/carbon/target_carbon, obj/limb/limb)
+ if(!istype(xeno) || !istype(target_carbon))
return
if(xeno.a_intent == INTENT_DISARM)
- target.last_damage_data = create_cause_data(initial(xeno.caste_type), xeno)
+ target_carbon.last_damage_data = create_cause_data(initial(xeno.caste_type), xeno)
xeno.visible_message(
- SPAN_XENOWARNING("[xeno] smash [target] with flat side of its tail!"),
- SPAN_XENOWARNING("We smash [target] with flat side of our tail!")
+ SPAN_XENOWARNING("[xeno] smash [target_carbon] with flat side of its tail!"),
+ SPAN_XENOWARNING("We smash [target_carbon] with flat side of our tail!")
)
- xeno.animation_attack_on(target)
- xeno.flick_attack_overlay(target, "slam")
+ xeno.animation_attack_on(target_carbon)
+ xeno.flick_attack_overlay(target_carbon, "slam")
if(xeno.behavior_delegate)
- xeno.behavior_delegate.melee_attack_additional_effects_target(target)
+ xeno.behavior_delegate.melee_attack_additional_effects_target(target_carbon)
- playsound(target, "punch", 25, TRUE)
- target.apply_damage(behavior.blunt_damage, BRUTE, "chest")
+ playsound(target_carbon, "punch", 25, TRUE)
+ target_carbon.apply_damage(blunt_damage, BRUTE, "chest")
apply_cooldown(cooldown_modifier = 0.3)
update_button_icon()
- return target
+ return target_carbon
return ..()
-/datum/action/xeno_action/activable/prae_impale/use_ability(atom/target_atom)
- var/mob/living/carbon/xenomorph/dancer_user = owner
+/datum/action/xeno_action/activable/tail_stab/harpoon_tail/proc/intent_detection()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(xeno && xeno.a_intent == INTENT_DISARM)
+ tail_mode = "Blunt"
+ else
+ tail_mode = "Normal"
- if(!action_cooldown_check())
- return
- if(!dancer_user.check_state())
- return
+
+
+/datum/action/xeno_action/activable/prae_impale/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ XENO_ACTION_CHECK(xeno)
if(!ismob(target_atom))
apply_cooldown_override(impale_click_miss_cooldown)
update_button_icon()
return
- if(!isxeno_human(target_atom) || dancer_user.can_not_harm(target_atom))
- to_chat(dancer_user, SPAN_XENODANGER("We must target a hostile!"))
+ if(!isxeno_human(target_atom) || xeno.can_not_harm(target_atom))
+ to_chat(xeno, SPAN_XENODANGER("We must target a hostile!"))
return
var/mob/living/carbon/target_carbon = target_atom
if(target_carbon.stat == DEAD)
- to_chat(dancer_user, SPAN_XENOWARNING("[target_atom] is dead, why would we want to attack it?"))
+ to_chat(xeno, SPAN_XENOWARNING("[target_atom] is dead, why would we want to attack it?"))
return
- var/dist = get_dist(dancer_user, target_carbon)
+ var/dist = get_dist(xeno, target_carbon)
if(dist > range)
- to_chat(dancer_user, SPAN_WARNING("[target_carbon] is too far away!"))
+ to_chat(xeno, SPAN_WARNING("[target_carbon] is too far away!"))
return
if(dist > 1)
- var/turf/target_turf = get_step(dancer_user, get_dir(dancer_user, target_carbon))
+ var/turf/target_turf = get_step(xeno, get_dir(xeno, target_carbon))
if(target_turf.density)
- to_chat(dancer_user, SPAN_WARNING("We can't attack through [target_turf]!"))
+ to_chat(xeno, SPAN_WARNING("We can't attack through [target_turf]!"))
return
else
for(var/atom/atom_in_turf in target_turf)
if(atom_in_turf.density && !atom_in_turf.throwpass && !istype(atom_in_turf, /obj/structure/barricade) && !istype(atom_in_turf, /mob/living))
- to_chat(dancer_user, SPAN_WARNING("We can't attack through [atom_in_turf]!"))
+ to_chat(xeno, SPAN_WARNING("We can't attack through [atom_in_turf]!"))
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
apply_cooldown()
- var/buffed = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_RED_TAG, TRAIT_SOURCE_ABILITY("red_tag"))
for(var/datum/effects/dancer_tag/spread/tag_spread in target_carbon.effects_list)
- buffed = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_RED_TAG, TRAIT_SOURCE_ABILITY("red_tag"))
qdel(tag_spread)
apply_cooldown_override()
break
for(var/datum/effects/dancer_tag/normal/dancer_tag_effect in target_carbon.effects_list)
- buffed = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_RED_TAG, TRAIT_SOURCE_ABILITY("red_tag"))
qdel(dancer_tag_effect)
break
@@ -260,72 +239,64 @@
var/mob/living/carbon/human/human_target = target_carbon
human_target.update_xeno_hostile_hud()
- // Hmm today visible_message(SPAN_DANGER("\The [dancer_user] violently slices [target_atom] with its tail[buffed?" twice":""]!"),
- dancer_user.face_atom(target_atom)
-
- var/damage = get_xeno_damage_slash(target_carbon, rand(dancer_user.melee_damage_lower, dancer_user.melee_damage_upper))
+ // Hmm today visible_message(SPAN_DANGER("\The [xeno] violently slices [target_atom] with its tail[buffed?" twice":""]!"),
+ xeno.face_atom(target_atom)
- dancer_user.visible_message(SPAN_DANGER("\The [dancer_user] violently slices [target_atom] with its tail[buffed?" twice":""]!"),
+ var/damage = get_xeno_damage_slash(target_carbon, rand(xeno.melee_damage_lower, xeno.melee_damage_upper))
+ var/buffed = HAS_TRAIT(xeno, TRAIT_ABILITY_RED_TAG)
+ xeno.visible_message(SPAN_DANGER("\The [xeno] violently slices [target_atom] with its tail[buffed?" twice":""]!"),
SPAN_DANGER("We slice [target_atom] with our tail[buffed?" twice":""]!"))
- var/list/attack_data = list(
- "attacker" = dancer_user,
- "target" = target_carbon,
- "damage" = damage
- )
- impale_strike(attack_data)
+ impale_strike(xeno, target_carbon, damage)
if(buffed)
- dancer_user.emote("roar") // Feedback for the player that we got the magic double impale
- addtimer(CALLBACK(src, PROC_REF(impale_strike), attack_data), 4 DECISECONDS)
+ xeno.emote("roar") // Feedback for the player that we got the magic double impale
+ addtimer(CALLBACK(src, PROC_REF(impale_strike), xeno, target_carbon, damage), 4 DECISECONDS)
return ..()
-/datum/action/xeno_action/activable/prae_impale/proc/impale_strike(list/attack_data)
- var/mob/living/carbon/xenomorph/attacker = attack_data["attacker"]
- var/mob/living/carbon/target = attack_data["target"]
- var/damage = attack_data["damage"]
- if(!attacker || !target || target.stat == DEAD || QDELETED(attacker) || QDELETED(target))
+
+/datum/action/xeno_action/activable/prae_impale/proc/impale_strike(mob/living/carbon/xenomorph/xeno, mob/living/carbon/target_carbon, damage)
+ if(!xeno || !target_carbon || target_carbon.stat == DEAD || QDELETED(xeno) || QDELETED(target_carbon))
return
- attacker.animation_attack_on(target)
- attacker.flick_attack_overlay(target, "tail")
+ xeno.animation_attack_on(target_carbon)
+ xeno.flick_attack_overlay(target_carbon, "tail")
- target.last_damage_data = create_cause_data(initial(attacker.caste_type), attacker)
- target.apply_armoured_damage(damage, ARMOR_MELEE, BRUTE, "chest", 10)
- playsound(target, 'sound/weapons/alien_tail_attack.ogg', 30, TRUE)
+ target_carbon.last_damage_data = create_cause_data(initial(xeno.caste_type), xeno)
+ target_carbon.apply_armoured_damage(damage, ARMOR_MELEE, BRUTE, "chest", 10)
+ playsound(target_carbon, 'sound/weapons/alien_tail_attack.ogg', 30, TRUE)
-/datum/action/xeno_action/onclick/prae_dodge/use_ability(atom/target)
- var/mob/living/carbon/xenomorph/dodge_user = owner
- if(!istype(dodge_user) || !dodge_user.check_state())
- return
- var/datum/behavior_delegate/praetorian_dancer/behavior = dodge_user.behavior_delegate
- if(!istype(behavior))
+
+/datum/action/xeno_action/onclick/prae_dodge/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!istype(xeno))
return
- if(behavior.dodge_activated)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_DODGE))
remove_effects()
return
- if(!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(xeno)
if(!check_and_use_plasma_owner(200))
return
- behavior.dodge_activated = TRUE
- behavior.dodge_start_time = world.time
- behavior.safe_click_cooldown = world.time + 1 SECONDS
+ ADD_TRAIT(xeno, TRAIT_ABILITY_DODGE, TRAIT_SOURCE_ABILITY("dodge"))
+ dodge_start_time = world.time
+ safe_click_cooldown = world.time + 1 SECONDS
button.icon_state = "template_active"
- dodge_user.speed_modifier -= speed_buff_amount
- dodge_user.dodge_threshold -= 3
- dodge_user.add_temp_pass_flags(PASS_MOB_THRU)
- dodge_user.recalculate_speed()
- dodge_user.balloon_alert(dodge_user, "we start our evasive stance!", text_color = "#7d32bb", delay = 1 SECONDS)
+ xeno.speed_modifier -= speed_buff_amount
+ xeno.dodge_threshold -= 3
+ xeno.add_temp_pass_flags(PASS_MOB_THRU)
+ xeno.recalculate_speed()
+ xeno.balloon_alert(xeno, "we start our evasive stance!", text_color = "#7d32bb", delay = 1 SECONDS)
+
+ start_duration_display(duration)
- INVOKE_ASYNC(src, PROC_REF(create_afterimage_sequence), dodge_user, duration)
+ INVOKE_ASYNC(src, PROC_REF(create_afterimage_sequence), xeno, duration)
if(dodge_timer != TIMER_ID_NULL)
deltimer(dodge_timer)
@@ -335,51 +306,49 @@
return ..()
/datum/action/xeno_action/onclick/prae_dodge/proc/remove_effects()
- var/mob/living/carbon/xenomorph/dodge_remove = owner
- if(!istype(dodge_remove))
- return
-
- var/datum/behavior_delegate/praetorian_dancer/behavior = dodge_remove.behavior_delegate
- if(!istype(behavior))
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!istype(xeno))
return
- if(!behavior.dodge_activated)
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_DODGE))
return
- if(world.time < behavior.safe_click_cooldown)
- to_chat(dodge_remove, SPAN_XENOWARNING("We need a moment before breaking our evasive stance!"))
+ if(world.time < safe_click_cooldown)
+ to_chat(xeno, SPAN_XENOWARNING("We need a moment before breaking our evasive stance!"))
return
- behavior.dodge_activated = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_DODGE, TRAIT_SOURCE_ABILITY("dodge"))
button.icon_state = "template_xeno"
- dodge_remove.speed_modifier += speed_buff_amount
- dodge_remove.dodge_threshold += 3
- dodge_remove.remove_temp_pass_flags(PASS_MOB_THRU)
- dodge_remove.recalculate_speed()
- dodge_remove.reset_position_to_initial()
- dodge_remove.balloon_alert(dodge_remove, "our evasive stance fades", text_color = "#bb5d32", delay = 1 SECONDS)
+ xeno.speed_modifier += speed_buff_amount
+ xeno.dodge_threshold += 3
+ xeno.remove_temp_pass_flags(PASS_MOB_THRU)
+ xeno.recalculate_speed()
+ xeno.reset_position_to_initial()
+ xeno.balloon_alert(xeno, "our evasive stance fades", text_color = "#bb5d32", delay = 1 SECONDS)
+
+ end_duration_display()
if(dodge_timer != TIMER_ID_NULL)
deltimer(dodge_timer)
dodge_timer = TIMER_ID_NULL
- if(behavior.dodge_start_time > 0)
- var/used_ratio = round((world.time - behavior.dodge_start_time) / duration, 0.1)
- behavior.recharge_time = max(DANCER_DODGE_TIME * used_ratio * behavior.refund_multiplier, 5 SECONDS)
+ if(dodge_start_time > 0)
+ var/used_ratio = round((world.time - dodge_start_time) / duration, 0.1)
+ recharge_time = max(DANCER_DODGE_TIME * used_ratio * refund_multiplier, 5 SECONDS)
- behavior.dodge_start_time = -1
- apply_cooldown_override(behavior.recharge_time)
+ dodge_start_time = -1
+ apply_cooldown_override(recharge_time)
-/datum/action/xeno_action/onclick/prae_dodge/proc/create_afterimage_sequence(mob/living/carbon/xenomorph/dodge_user, duration)
- if(!dodge_user || !dodge_user.loc)
+/datum/action/xeno_action/onclick/prae_dodge/proc/create_afterimage_sequence(mob/living/carbon/xenomorph/xeno, duration)
+ if(!xeno || !xeno.loc)
return
var/afterimage_count = round(duration / afterimage_interval)
var/datum/afterimage_state/state = new
- state.owner = dodge_user
+ state.owner = xeno
state.remaining = afterimage_count
- state.last_turf = get_turf(dodge_user.loc)
+ state.last_turf = get_turf(xeno.loc)
addtimer(CALLBACK(src, PROC_REF(process_afterimage_tick), state), afterimage_interval)
@@ -387,20 +356,19 @@
if(!state || !state.owner || !state.owner.loc)
return
- var/mob/living/carbon/xenomorph/dodge_user = state.owner
- var/datum/behavior_delegate/praetorian_dancer/behavior = dodge_user.behavior_delegate
- if(!istype(behavior) || !behavior.dodge_activated)
+ var/mob/living/carbon/xenomorph/xeno = state.owner
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_DODGE))
return
- var/turf/current_position = get_turf(dodge_user.loc)
+ var/turf/current_position = get_turf(xeno.loc)
if(current_position && current_position != state.last_turf)
var/random_offset_x = rand(-4, 4)
var/random_offset_y = rand(-4, 4)
- dodge_user.reset_position_to_initial()
- dodge_user.apply_offset(random_offset_x, random_offset_y)
+ xeno.reset_position_to_initial()
+ xeno.apply_offset(random_offset_x, random_offset_y)
- create_afterimage(dodge_user, random_offset_x, random_offset_y)
+ create_afterimage(xeno, random_offset_x, random_offset_y)
state.last_turf = current_position
state.remaining--
@@ -408,20 +376,20 @@
if(state.remaining > 0)
addtimer(CALLBACK(src, PROC_REF(process_afterimage_tick), state), afterimage_interval)
else
- addtimer(CALLBACK(dodge_user, TYPE_PROC_REF(/atom/movable, reset_position_to_initial)), 2 DECISECONDS)
+ addtimer(CALLBACK(xeno, TYPE_PROC_REF(/atom/movable, reset_position_to_initial)), 2 DECISECONDS)
-/datum/action/xeno_action/onclick/prae_dodge/proc/create_afterimage(mob/living/carbon/xenomorph/dodge_user, random_offset_x, random_offset_y)
- if(!dodge_user || !dodge_user.loc)
+/datum/action/xeno_action/onclick/prae_dodge/proc/create_afterimage(mob/living/carbon/xenomorph/xeno, random_offset_x, random_offset_y)
+ if(!xeno || !xeno.loc)
return
- var/turf/afterimage_location = get_turf(dodge_user.loc)
+ var/turf/afterimage_location = get_turf(xeno.loc)
if(!afterimage_location)
return
var/directional_offset_x = 0
var/directional_offset_y = 0
- switch(dodge_user.dir)
+ switch(xeno.dir)
if(NORTH)
directional_offset_y = -16
if(SOUTH)
@@ -432,18 +400,20 @@
directional_offset_x = 16
var/obj/effect/overlay/afterimage = new /obj/effect/overlay/afterimage(afterimage_location)
- afterimage.icon = dodge_user.icon
- afterimage.icon_state = dodge_user.icon_state
- afterimage.color = dodge_user.color
- afterimage.layer = dodge_user.layer
- afterimage.dir = dodge_user.dir
+ afterimage.icon = xeno.icon
+ afterimage.icon_state = xeno.icon_state
+ afterimage.color = xeno.color
+ afterimage.layer = xeno.layer
+ afterimage.dir = xeno.dir
afterimage.alpha = 200
afterimage.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- afterimage.pixel_x = dodge_user.pixel_x + directional_offset_x
- afterimage.pixel_y = dodge_user.pixel_y + directional_offset_y
+ afterimage.pixel_x = xeno.pixel_x + directional_offset_x
+ afterimage.pixel_y = xeno.pixel_y + directional_offset_y
addtimer(CALLBACK(afterimage, TYPE_PROC_REF(/obj/effect/overlay/afterimage, fade_out_afterimage)))
+
+
/obj/effect/overlay/afterimage/proc/fade_out_afterimage()
if(!src)
return
@@ -484,80 +454,79 @@
var/fade_max_steps = 3
var/fade_delay = 1 DECISECONDS
+
+
/datum/action/xeno_action/activable/prae_tail_trip/use_ability(atom/target_atom)
- var/mob/living/carbon/xenomorph/dancer_user = owner
+ var/mob/living/carbon/xenomorph/xeno = owner
- if(!action_cooldown_check())
+ if(!istype(xeno))
return
- if(!istype(dancer_user) || !dancer_user.check_state())
- return
+ XENO_ACTION_CHECK(xeno)
if(!ismob(target_atom))
apply_cooldown_override(tail_click_miss_cooldown)
update_button_icon()
return
- if(!isxeno_human(target_atom) || dancer_user.can_not_harm(target_atom))
- to_chat(dancer_user, SPAN_XENODANGER("We must target a hostile!"))
+ if(!isxeno_human(target_atom) || xeno.can_not_harm(target_atom))
+ to_chat(xeno, SPAN_XENODANGER("We must target a hostile!"))
return
var/mob/living/carbon/target_carbon = target_atom
if(target_carbon.stat == DEAD)
- to_chat(dancer_user, SPAN_XENOWARNING("[target_atom] is dead, why would we want to attack it?"))
- return
-
- if(!check_and_use_plasma_owner())
+ to_chat(xeno, SPAN_XENOWARNING("[target_atom] is dead, why would we want to attack it?"))
return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
if(ishuman(target_carbon))
var/mob/living/carbon/human/target_human = target_carbon
target_human.update_xeno_hostile_hud()
- var/dist = get_dist(dancer_user, target_carbon)
+ var/dist = get_dist(xeno, target_carbon)
if(dist > range)
- to_chat(dancer_user, SPAN_WARNING("[target_carbon] is too far away!"))
+ to_chat(xeno, SPAN_WARNING("[target_carbon] is too far away!"))
return
if(dist > 1)
- var/turf/target_turf = get_step(dancer_user, get_dir(dancer_user, target_carbon))
+ var/turf/target_turf = get_step(xeno, get_dir(xeno, target_carbon))
if(target_turf.density)
- to_chat(dancer_user, SPAN_WARNING("We can't attack through [target_turf]!"))
+ to_chat(xeno, SPAN_WARNING("We can't attack through [target_turf]!"))
return
else
for(var/atom/atom_in_turf in target_turf)
if(atom_in_turf.density && !atom_in_turf.throwpass && !istype(atom_in_turf, /obj/structure/barricade) && !istype(atom_in_turf, /mob/living))
- to_chat(dancer_user, SPAN_WARNING("We can't attack through [atom_in_turf]!"))
+ to_chat(xeno, SPAN_WARNING("We can't attack through [atom_in_turf]!"))
return
// Hmm today I will kill a marine while looking away from them
- dancer_user.face_atom(target_carbon)
- dancer_user.flick_attack_overlay(target_carbon, "disarm")
+ xeno.face_atom(target_carbon)
+ xeno.flick_attack_overlay(target_carbon, "disarm")
- var/buffed = FALSE
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_RED_TAG, TRAIT_SOURCE_ABILITY("red_tag"))
var/datum/effects/dancer_tag/normal/dancer_tag_effect = locate() in target_carbon.effects_list
var/datum/effects/dancer_tag/spread/tag_spread = locate() in target_carbon.effects_list
if(tag_spread)
- buffed = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_RED_TAG, TRAIT_SOURCE_ABILITY("red_tag"))
qdel(tag_spread)
apply_cooldown_override()
if(dancer_tag_effect)
- buffed = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_RED_TAG, TRAIT_SOURCE_ABILITY("red_tag"))
qdel(dancer_tag_effect)
- if(!buffed)
- new /datum/effects/xeno_slow(target_carbon, dancer_user, null, null, get_xeno_stun_duration(target_carbon, slow_duration))
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_RED_TAG))
+ new /datum/effects/xeno_slow(target_carbon, xeno, null, null, get_xeno_stun_duration(target_carbon, slow_duration))
var/stun_duration = stun_duration_default
var/daze_duration = 0
- if(buffed)
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_RED_TAG))
stun_duration = stun_duration_buffed
daze_duration = daze_duration_buffed
@@ -568,20 +537,20 @@
if(Xeno.mob_size >= MOB_SIZE_BIG)
xeno_smashed = TRUE
shake_camera(Xeno, 10, 1)
- dancer_user.visible_message(SPAN_XENODANGER("[dancer_user] smashes [Xeno] with it's tail!"), SPAN_XENODANGER("We smash [Xeno] with your tail!"))
- to_chat(Xeno, SPAN_XENOHIGHDANGER("You feel dizzy as [dancer_user] smashes you with their tail!"))
- dancer_user.animation_attack_on(Xeno)
+ xeno.visible_message(SPAN_XENODANGER("[xeno] smashes [Xeno] with it's tail!"), SPAN_XENODANGER("We smash [Xeno] with your tail!"))
+ to_chat(Xeno, SPAN_XENOHIGHDANGER("You feel dizzy as [xeno] smashes you with their tail!"))
+ xeno.animation_attack_on(Xeno)
if(!xeno_smashed)
- if (stun_duration > 0)
+ if(stun_duration > 0)
target_carbon.apply_effect(stun_duration, WEAKEN)
- dancer_user.visible_message(SPAN_XENODANGER("[dancer_user] trips [target_atom] with it's tail!"), SPAN_XENODANGER("We trip [target_atom] with our tail!"))
- dancer_user.spin_circle()
- dancer_user.emote("tail")
- to_chat(target_carbon, SPAN_XENOHIGHDANGER("You are swept off your feet by [dancer_user]!"))
+ xeno.visible_message(SPAN_XENODANGER("[xeno] trips [target_atom] with it's tail!"), SPAN_XENODANGER("We trip [target_atom] with our tail!"))
+ xeno.spin_circle()
+ xeno.emote("tail")
+ to_chat(target_carbon, SPAN_XENOHIGHDANGER("You are swept off your feet by [xeno]!"))
if(daze_duration > 0)
target_carbon.apply_effect(daze_duration, DAZE)
- playsound(dancer_user, 'sound/effects/hit_kick.ogg', 75, 1)
+ playsound(xeno, 'sound/effects/hit_kick.ogg', 75, 1)
apply_cooldown()
return ..()
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/oppressor.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/oppressor.dm
index d3843ebbef424..08b55a5c902f3 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/oppressor.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/oppressor.dm
@@ -51,17 +51,10 @@
/datum/action/xeno_action/activable/tail_stab/tail_seize/use_ability(atom/targetted_atom)
var/mob/living/carbon/xenomorph/stabbing_xeno = owner
- if(!action_cooldown_check())
+ if(world.time <= stabbing_xeno.next_move)
return FALSE
- if(!stabbing_xeno.check_state())
- return FALSE
-
- if (world.time <= stabbing_xeno.next_move)
- return FALSE
-
- if(!check_and_use_plasma_owner())
- return FALSE
+ XENO_ACTION_CHECK_USE_PLASMA(stabbing_xeno)
stabbing_xeno.visible_message(SPAN_XENODANGER("\The [stabbing_xeno] uncoils and wildly throws out its tail!"), SPAN_XENODANGER("We uncoil our tail wildly in front of us!"))
@@ -79,27 +72,23 @@
xeno_attack_delay(stabbing_xeno)
return ..()
-/datum/action/xeno_action/activable/prae_abduct/use_ability(atom/atom)
- var/mob/living/carbon/xenomorph/abduct_user = owner
+/datum/action/xeno_action/activable/prae_abduct/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
- if(!atom || atom.layer >= FLY_LAYER || !isturf(abduct_user.loc))
+ if(!target_atom || target_atom.layer >= FLY_LAYER || !isturf(xeno.loc))
return
- if(!action_cooldown_check() || abduct_user.action_busy)
+ if(xeno.action_busy)
return
- if(!abduct_user.check_state())
- return
-
- if(!check_plasma_owner())
- return
+ XENO_ACTION_CHECK(xeno)
// Build our turflist
var/list/turf/turflist = list()
var/list/telegraph_atom_list = list()
- var/facing = get_dir(abduct_user, atom)
- var/turf/turf = abduct_user.loc
- var/turf/temp = abduct_user.loc
+ var/facing = get_dir(xeno, target_atom)
+ var/turf/turf = xeno.loc
+ var/turf/temp = xeno.loc
for(var/distance in 0 to max_distance)
temp = get_step(turf, facing)
if(facing in GLOB.diagonals) // check if it goes through corners
@@ -158,65 +147,72 @@
break
turflist += turf
- facing = get_dir(turf, atom)
+ facing = get_dir(turf, target_atom)
telegraph_atom_list += new /obj/effect/xenomorph/xeno_telegraph/abduct_hook(turf, windup)
if(allow_one_more_step)
break
if(!length(turflist))
- to_chat(abduct_user, SPAN_XENOWARNING("We don't have any room to do our abduction!"))
+ to_chat(xeno, SPAN_XENOWARNING("We don't have any room to do our abduction!"))
return
- abduct_user.visible_message(SPAN_XENODANGER("\The [abduct_user]'s segmented tail starts coiling..."), SPAN_XENODANGER("We begin coiling our tail, aiming towards \the [atom]..."))
- abduct_user.emote("roar")
+ xeno.visible_message(SPAN_XENODANGER("\The [xeno]'s segmented tail starts coiling..."), SPAN_XENODANGER("We begin coiling our tail, aiming towards \the [target_atom]..."))
+ xeno.emote("roar")
- var/throw_target_turf = get_step(abduct_user, facing)
+ var/throw_target_turf = get_step(xeno, facing)
- ADD_TRAIT(abduct_user, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Abduct"))
- if(!do_after(abduct_user, windup, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE, numticks = 1))
- to_chat(abduct_user, SPAN_XENOWARNING("You relax your tail."))
+ ADD_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Abduct"))
+ start_duration_display(windup)
+ if(!do_after(xeno, windup, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE, numticks = 1))
+ end_duration_display(windup)
+ to_chat(xeno, SPAN_XENOWARNING("You relax your tail."))
apply_cooldown()
- for (var/obj/effect/xenomorph/xeno_telegraph/xenotelegraph in telegraph_atom_list)
+ for(var/obj/effect/xenomorph/xeno_telegraph/xenotelegraph in telegraph_atom_list)
telegraph_atom_list -= xenotelegraph
qdel(xenotelegraph)
- REMOVE_TRAIT(abduct_user, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Abduct"))
+ REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Abduct"))
return
- if(!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- REMOVE_TRAIT(abduct_user, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Abduct"))
+ REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Abduct"))
- playsound(get_turf(abduct_user), 'sound/effects/bang.ogg', 25, 0)
- abduct_user.visible_message(SPAN_XENODANGER("\The [abduct_user] suddenly uncoils its tail, firing it towards [atom]!"), SPAN_XENODANGER("We uncoil our tail, sending it out towards \the [atom]!"))
+ playsound(get_turf(xeno), 'sound/effects/bang.ogg', 25, 0)
+ xeno.visible_message(SPAN_XENODANGER("\The [xeno] suddenly uncoils its tail, firing it towards [target_atom]!"), SPAN_XENODANGER("We uncoil our tail, sending it out towards \the [target_atom]!"))
var/list/targets = list()
for(var/turf/target_turf in turflist)
for(var/mob/living/carbon/target in target_turf)
- if(!isxeno_human(target) || abduct_user.can_not_harm(target) || target.is_dead() || target.is_mob_incapacitated(TRUE) || target.mob_size >= MOB_SIZE_BIG)
+ if(!isxeno_human(target) || xeno.can_not_harm(target) || target.is_dead() || target.is_mob_incapacitated(TRUE) || target.mob_size >= MOB_SIZE_BIG)
continue
-
targets += target
- if(LAZYLEN(targets) == 1)
- abduct_user.balloon_alert(abduct_user, "slowed one target", text_color = "#51a16c")
- else if(LAZYLEN(targets) == 2)
- abduct_user.balloon_alert(abduct_user, "rooted two targets", text_color = "#51a16c")
- else if(LAZYLEN(targets) >= 3)
- abduct_user.balloon_alert(abduct_user, "stunned [LAZYLEN(targets)] targets", text_color = "#51a16c")
+
+ var/target_count = LAZYLEN(targets)
+ var/captured_message
+
+ if(target_count == 1)
+ captured_message = "slowed one target"
+ else if(target_count == 2)
+ captured_message = "rooted two targets"
+ else if(target_count >= 3)
+ captured_message = "stunned [target_count] targets"
+
+ if(captured_message)
+ xeno.balloon_alert(xeno, captured_message, text_color = "#51a16c")
apply_cooldown()
for(var/mob/living/carbon/target in targets)
- abduct_user.visible_message(SPAN_XENODANGER("\The [abduct_user]'s hooked tail coils itself around [target]!"), SPAN_XENODANGER("Our hooked tail coils itself around [target]!"))
+ xeno.visible_message(SPAN_XENODANGER("\The [xeno]'s hooked tail coils itself around [target]!"), SPAN_XENODANGER("Our hooked tail coils itself around [target]!"))
target.apply_effect(0.2, WEAKEN)
if(LAZYLEN(targets) == 1)
- new /datum/effects/xeno_slow(target, abduct_user, null, null, 2.5 SECONDS)
+ new /datum/effects/xeno_slow(target, xeno, null, null, 2.5 SECONDS)
target.apply_effect(1, SLOW)
else if(LAZYLEN(targets) == 2)
ADD_TRAIT(target, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Abduct"))
@@ -224,17 +220,16 @@
var/mob/living/carbon/human/target_human = target
target_human.update_xeno_hostile_hud()
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(unroot_human), target, TRAIT_SOURCE_ABILITY("Abduct")), get_xeno_stun_duration(target, 2.5 SECONDS))
- to_chat(target, SPAN_XENOHIGHDANGER("[abduct_user] has pinned you to the ground! You cannot move!"))
+ to_chat(target, SPAN_XENOHIGHDANGER("[xeno] has pinned you to the ground! You cannot move!"))
target.set_effect(2, DAZE)
else if(LAZYLEN(targets) >= 3)
target.apply_effect(get_xeno_stun_duration(target, 1.3), WEAKEN)
- to_chat(target, SPAN_XENOHIGHDANGER("You are slammed into the other victims of [abduct_user]!"))
-
+ to_chat(target, SPAN_XENOHIGHDANGER("You are slammed into the other victims of [xeno]!"))
shake_camera(target, 10, 1)
- var/obj/effect/beam/tail_beam = abduct_user.beam(target, "oppressor_tail", 'icons/effects/beam.dmi', 0.5 SECONDS, 8)
+ var/obj/effect/beam/tail_beam = xeno.beam(target, "oppressor_tail", 'icons/effects/beam.dmi', 0.5 SECONDS, 8)
var/image/tail_image = image('icons/effects/status_effects.dmi', "hooked")
target.overlays += tail_image
@@ -249,62 +244,55 @@
overlayed_human.overlays -= tail_image
/datum/action/xeno_action/activable/oppressor_punch/use_ability(atom/target_atom)
- var/mob/living/carbon/xenomorph/oppressor_user = owner
-
- if (!action_cooldown_check())
- return
+ var/mob/living/carbon/xenomorph/xeno = owner
- if (!isxeno_human(target_atom) || oppressor_user.can_not_harm(target_atom))
- return
-
- if (!oppressor_user.check_state())
+ if(!isxeno_human(target_atom) || xeno.can_not_harm(target_atom))
return
var/mob/living/carbon/target_carbon = target_atom
- if (!oppressor_user.Adjacent(target_carbon))
+ if(!xeno.Adjacent(target_carbon))
return
if(target_carbon.stat == DEAD)
return
- var/obj/limb/target_limb = target_carbon.get_limb(check_zone(oppressor_user.zone_selected))
+ var/obj/limb/target_limb = target_carbon.get_limb(check_zone(xeno.zone_selected))
- if (ishuman(target_carbon) && (!target_limb || (target_limb.status & LIMB_DESTROYED)))
+ if(ishuman(target_carbon) && (!target_limb || (target_limb.status & LIMB_DESTROYED)))
target_limb = target_carbon.get_limb("chest")
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- target_carbon.last_damage_data = create_cause_data(oppressor_user.caste_type, oppressor_user)
+ target_carbon.last_damage_data = create_cause_data(xeno.caste_type, xeno)
- oppressor_user.visible_message(SPAN_XENOWARNING("\The [oppressor_user] hits [target_carbon] in the [target_limb? target_limb.display_name : "chest"] with a devastatingly powerful punch!"),
+ xeno.visible_message(SPAN_XENOWARNING("\The [xeno] hits [target_carbon] in the [target_limb? target_limb.display_name : "chest"] with a devastatingly powerful punch!"),
SPAN_XENOWARNING("We hit [target_carbon] in the [target_limb ? target_limb.display_name : "chest"] with a devastatingly powerful punch!"))
var/hitsound = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg')
playsound(target_carbon,hitsound, 50, 1)
- oppressor_user.face_atom(target_carbon)
- oppressor_user.animation_attack_on(target_carbon)
- oppressor_user.flick_attack_overlay(target_carbon, "punch")
+ xeno.face_atom(target_carbon)
+ xeno.animation_attack_on(target_carbon)
+ xeno.flick_attack_overlay(target_carbon, "punch")
- if (!(target_carbon.mobility_flags & MOBILITY_MOVE) || !(target_carbon.mobility_flags & MOBILITY_STAND) || target_carbon.slowed)
+ if(!(target_carbon.mobility_flags & MOBILITY_MOVE) || !(target_carbon.mobility_flags & MOBILITY_STAND) || target_carbon.slowed)
target_carbon.apply_damage(get_xeno_damage_slash(target_carbon, damage), BRUTE, target_limb? target_limb.name : "chest")
ADD_TRAIT(target_carbon, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Oppressor Punch"))
- if (ishuman(target_carbon))
+ if(ishuman(target_carbon))
var/mob/living/carbon/human/human_to_update = target_carbon
human_to_update.update_xeno_hostile_hud()
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(unroot_human), target_carbon, TRAIT_SOURCE_ABILITY("Oppressor Punch")), get_xeno_stun_duration(target_carbon, 1.2 SECONDS))
- to_chat(target_carbon, SPAN_XENOHIGHDANGER("[oppressor_user] has pinned you to the ground! You cannot move!"))
+ to_chat(target_carbon, SPAN_XENOHIGHDANGER("[xeno] has pinned you to the ground! You cannot move!"))
else
target_carbon.apply_armoured_damage(get_xeno_damage_slash(target_carbon, damage), ARMOR_MELEE, BRUTE, target_limb? target_limb.name : "chest")
- step_away(target_carbon, oppressor_user, 2)
+ step_away(target_carbon, xeno, 2)
shake_camera(target_carbon, 2, 1)
- var/datum/action/xeno_action/activable/prae_abduct/abduct_action = get_action(oppressor_user, /datum/action/xeno_action/activable/prae_abduct)
- var/datum/action/xeno_action/activable/tail_lash/tail_lash_action = get_action(oppressor_user, /datum/action/xeno_action/activable/tail_lash)
+ var/datum/action/xeno_action/activable/prae_abduct/abduct_action = get_action(xeno, /datum/action/xeno_action/activable/prae_abduct)
+ var/datum/action/xeno_action/activable/tail_lash/tail_lash_action = get_action(xeno, /datum/action/xeno_action/activable/tail_lash)
if(abduct_action && !abduct_action.action_cooldown_check())
abduct_action.reduce_cooldown(5 SECONDS)
if(tail_lash_action && !tail_lash_action.action_cooldown_check())
@@ -313,17 +301,16 @@
apply_cooldown()
return ..()
-/datum/action/xeno_action/activable/tail_lash/use_ability(atom/atoms)
- var/mob/living/carbon/xenomorph/lash_user = owner
+/datum/action/xeno_action/activable/tail_lash/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
- if (!istype(lash_user) || !lash_user.check_state() || !action_cooldown_check())
+ if(!istype(xeno) || !target_atom)
return
- if(!atoms || atoms.layer >= FLY_LAYER || !isturf(lash_user.loc))
+ if(target_atom.layer >= FLY_LAYER || !isturf(xeno.loc))
return
- if (!check_plasma_owner())
- return
+ XENO_ACTION_CHECK(xeno)
// Transient turf list
var/list/target_turfs = list()
@@ -331,8 +318,8 @@
var/list/telegraph_atom_list = list()
// Code to get a 2x3 area of turfs
- var/turf/root = get_turf(lash_user)
- var/facing = Get_Compass_Dir(lash_user, atoms)
+ var/turf/root = get_turf(xeno)
+ var/facing = Get_Compass_Dir(xeno, target_atom)
var/turf/infront = get_step(root, facing)
var/turf/left = get_step(root, turn(facing, 90))
var/turf/right = get_step(root, turn(facing, -90))
@@ -345,57 +332,56 @@
temp_turfs += infront_right
for(var/turf/turfs_to_check in temp_turfs)
- if (!istype(turfs_to_check))
+ if(!istype(turfs_to_check))
continue
- if (turfs_to_check.density)
+ if(turfs_to_check.density)
continue
target_turfs += turfs_to_check
telegraph_atom_list += new /obj/effect/xenomorph/xeno_telegraph/lash(turfs_to_check, windup)
var/turf/next_turf = get_step(turfs_to_check, facing)
- if (!istype(next_turf) || next_turf.density)
+ if(!istype(next_turf) || next_turf.density)
continue
target_turfs += next_turf
telegraph_atom_list += new /obj/effect/xenomorph/xeno_telegraph/lash(next_turf, windup)
if(!length(target_turfs))
- to_chat(lash_user, SPAN_XENOWARNING("We don't have any room to do our tail lash!"))
+ to_chat(xeno, SPAN_XENOWARNING("We don't have any room to do our tail lash!"))
return
- if(!do_after(lash_user, windup, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
- to_chat(lash_user, SPAN_XENOWARNING("We cancel our tail lash."))
+ if(!do_after(xeno, windup, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
+ to_chat(xeno, SPAN_XENOWARNING("We cancel our tail lash."))
for(var/obj/effect/xenomorph/xeno_telegraph/tail_telegraph in telegraph_atom_list)
telegraph_atom_list -= tail_telegraph
qdel(tail_telegraph)
return
- if(!action_cooldown_check() || !check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
apply_cooldown()
- lash_user.visible_message(SPAN_XENODANGER("[lash_user] lashes its tail furiously, hitting everything in front of it!"), SPAN_XENODANGER("We lash our tail furiously, hitting everything in front of us!"))
- lash_user.spin_circle()
- lash_user.emote("tail")
+ xeno.visible_message(SPAN_XENODANGER("[xeno] lashes its tail furiously, hitting everything in front of it!"), SPAN_XENODANGER("We lash our tail furiously, hitting everything in front of us!"))
+ xeno.spin_circle()
+ xeno.emote("tail")
- for (var/turf/targets_in_turf in target_turfs)
- for (var/mob/living/carbon/possible_targets in targets_in_turf)
- if (possible_targets.stat == DEAD)
+ for(var/turf/targets_in_turf in target_turfs)
+ for(var/mob/living/carbon/possible_targets in targets_in_turf)
+ if(possible_targets.stat == DEAD)
continue
- if(!isxeno_human(possible_targets) || lash_user.can_not_harm(possible_targets))
+ if(!isxeno_human(possible_targets) || xeno.can_not_harm(possible_targets))
continue
if(possible_targets.mob_size >= MOB_SIZE_BIG)
continue
- lash_user.throw_carbon(possible_targets, facing, fling_dist)
+ xeno.throw_carbon(possible_targets, facing, fling_dist)
possible_targets.apply_effect(get_xeno_stun_duration(possible_targets, 0.5), WEAKEN)
- new /datum/effects/xeno_slow(possible_targets, lash_user, ttl = get_xeno_stun_duration(possible_targets, 2.5 SECONDS))
+ new /datum/effects/xeno_slow(possible_targets, xeno, ttl = get_xeno_stun_duration(possible_targets, 2.5 SECONDS))
return ..()
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm
index a30a02a97c649..93f0b1f5fb918 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm
@@ -1,6 +1,6 @@
/datum/xeno_strain/vanguard
name = PRAETORIAN_VANGUARD
- description = "You forfeit all of your acid-based abilities and some health for some extra speed and a rechargable shield that can block one attack. Use your Pierce from up to three paces away to stab through talls, while stabbing through two or more will completely recharge your shield. Use your charge to plow through enemies and use it again to unleash a powerful AoE slash that reaches up to three paces. You also have a Cleave ability, amplified by your shield, which you can toggle to either immobilize or fling a target away."
+ description = "You forfeit all of your acid-based abilities and some health for some extra speed and a rechargeable shield that begins rapidly decaying after taking a hit. Use your Pierce from up to three paces away to stab through talls, while stabbing through two or more will completely recharge your shield. Use your charge to plow through enemies and use it again to unleash a powerful AoE slash that reaches up to three paces. You also have a Cleave ability, amplified by your shield, which you can toggle to either immobilize or fling a target away."
flavor_description = "Fearless you are born, fearless you serve, fearless you die. This one will become my Vanguard"
icon_state_prefix = "Vanguard"
@@ -40,7 +40,7 @@
var/last_shield_regen_time = 0
/datum/behavior_delegate/praetorian_vanguard/on_life()
- if (last_shield_regen_time <= last_combat_time && last_combat_time + shield_recharge_time <= world.time)
+ if(last_shield_regen_time <= last_combat_time && last_combat_time + shield_recharge_time <= world.time)
regen_shield()
@@ -54,46 +54,39 @@
last_combat_time = world.time
/datum/behavior_delegate/praetorian_vanguard/proc/regen_shield()
- var/mob/living/carbon/xenomorph/praetorian = bound_xeno
var/datum/xeno_shield/vanguard/found_shield = null
- last_shield_regen_time = world.time
- for (var/datum/xeno_shield/vanguard/vanguard_shield in praetorian.xeno_shields)
- if (vanguard_shield.shield_source == XENO_SHIELD_SOURCE_VANGUARD_PRAE)
+ for(var/datum/xeno_shield/vanguard/vanguard_shield in bound_xeno.xeno_shields)
+ if(vanguard_shield.shield_source == XENO_SHIELD_SOURCE_VANGUARD_PRAE)
found_shield = vanguard_shield
break
+ if(bound_xeno.stat == UNCONSCIOUS || (HAS_TRAIT(bound_xeno, TRAIT_INCAPACITATED) && HAS_TRAIT(bound_xeno, TRAIT_FLOORED)))
+ return
+
+ last_shield_regen_time = world.time
+
if(found_shield)
- praetorian.add_xeno_shield(800, XENO_SHIELD_SOURCE_VANGUARD_PRAE, /datum/xeno_shield/vanguard)
+ bound_xeno.add_xeno_shield(800, XENO_SHIELD_SOURCE_VANGUARD_PRAE, /datum/xeno_shield/vanguard)
else
- var/datum/xeno_shield/vanguard/new_shield = praetorian.add_xeno_shield(800, XENO_SHIELD_SOURCE_VANGUARD_PRAE, /datum/xeno_shield/vanguard)
- bound_xeno.explosivearmor_modifier += 1.5*XENO_EXPOSIVEARMOR_MOD_VERY_LARGE
+ var/datum/xeno_shield/vanguard/new_shield = bound_xeno.add_xeno_shield(800, XENO_SHIELD_SOURCE_VANGUARD_PRAE, /datum/xeno_shield/vanguard)
+ bound_xeno.explosivearmor_modifier += 1.5 * XENO_EXPOSIVEARMOR_MOD_VERY_LARGE
bound_xeno.recalculate_armor()
- new_shield.explosive_armor_amount = 1.5*XENO_EXPOSIVEARMOR_MOD_VERY_LARGE
- to_chat(praetorian, SPAN_XENOHIGHDANGER("We feel our defensive shell regenerate! It will block one hit!"))
+ new_shield.explosive_armor_amount = 1.5 * XENO_EXPOSIVEARMOR_MOD_VERY_LARGE
+ to_chat(bound_xeno, SPAN_XENOHIGHDANGER("We feel our defensive shell regenerate! It will block one hit!"))
+ ADD_TRAIT(bound_xeno, TRAIT_ABILITY_CLEAVE_BUFFED, TRAIT_SOURCE_ABILITY("cleave_buffed"))
- var/datum/action/xeno_action/activable/cleave/caction = get_action(bound_xeno, /datum/action/xeno_action/activable/cleave)
- if(istype(caction))
- caction.buffed = TRUE
/datum/action/xeno_action/activable/pierce/use_ability(atom/targetted_atom)
- var/mob/living/carbon/xenomorph/pierce_user = owner
+ var/mob/living/carbon/xenomorph/xeno = owner
var/pierce_sounds = pick('sound/effects/pierce1.ogg', 'sound/effects/pierce2.ogg', 'sound/effects/pierce3.ogg')
- if (!action_cooldown_check())
+ if(!targetted_atom || targetted_atom.layer >= FLY_LAYER || !isturf(xeno.loc))
return
- if (!pierce_user.check_state())
- return
-
- if(!targetted_atom || targetted_atom.layer >= FLY_LAYER || !isturf(pierce_user.loc))
- return
-
- if (!check_and_use_plasma_owner())
- return
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- //X = xeno user, A = target atom
- var/list/turf/target_turfs = get_line(pierce_user, targetted_atom, include_start_atom = FALSE)
+ var/list/turf/target_turfs = get_line(xeno, targetted_atom, include_start_atom = FALSE)
var/length_of_line = LAZYLEN(target_turfs)
if(length_of_line > 3)
target_turfs = target_turfs.Copy(1, 4)
@@ -126,158 +119,190 @@
//Check for mobs and add them to our target list for damage
if(iscarbon(path_content))
var/mob/living/carbon/mob_to_act = path_content
- if(!isxeno_human(mob_to_act) || pierce_user.can_not_harm(mob_to_act))
+ if(!isxeno_human(mob_to_act) || xeno.can_not_harm(mob_to_act))
continue
if(!(mob_to_act in target_mobs))
target_mobs += mob_to_act
- pierce_user.visible_message(SPAN_XENODANGER("[pierce_user] slashes its claws through the area in front of it!"), SPAN_XENODANGER("We slash our claws through the area in front of us!"))
- pierce_user.animation_attack_on(targetted_atom, 15)
+ xeno.visible_message(SPAN_XENODANGER("[xeno] slashes its claws through the area in front of it!"), SPAN_XENODANGER("We slash our claws through the area in front of us!"))
+ xeno.animation_attack_on(targetted_atom, 15)
- pierce_user.emote("roar")
+ xeno.emote("roar")
// Loop through our mob list, finding any humans there and dealing damage to them
- for (var/mob/living/carbon/current_mob in target_mobs)
- if (!isxeno_human(current_mob) || pierce_user.can_not_harm(current_mob))
+ for(var/mob/living/carbon/current_mob in target_mobs)
+ if(!isxeno_human(current_mob) || xeno.can_not_harm(current_mob))
continue
- if (current_mob.stat == DEAD)
+ if(current_mob.stat == DEAD)
continue
- if (HAS_TRAIT(current_mob, TRAIT_NESTED))
+ if(HAS_TRAIT(current_mob, TRAIT_NESTED))
continue
current_mob.flick_attack_overlay(current_mob, "slash")
current_mob.apply_armoured_damage(get_xeno_damage_slash(current_mob, damage), ARMOR_MELEE, BRUTE, null, 20)
playsound(current_mob, pierce_sounds, 30, 1)
- if (length(target_mobs) >= shield_regen_threshold)
- var/datum/behavior_delegate/praetorian_vanguard/behavior = pierce_user.behavior_delegate
- if (istype(behavior))
+ if(length(target_mobs) >= shield_regen_threshold)
+ var/datum/behavior_delegate/praetorian_vanguard/behavior = xeno.behavior_delegate
+ if(istype(behavior))
behavior.regen_shield()
apply_cooldown()
return ..()
-/datum/action/xeno_action/activable/pounce/prae_dash/use_ability(atom/A)
- if(!activated_once && !action_cooldown_check() || owner.throwing)
+
+
+/datum/action/xeno_action/activable/pounce/prae_dash/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_PRE_DASH) && !action_cooldown_check() || owner.throwing)
return
- if(!activated_once)
+ if(!HAS_TRAIT(xeno, TRAIT_ABILITY_PRE_DASH))
. = ..()
if(.)
- activated_once = TRUE
+ ADD_TRAIT(xeno, TRAIT_ABILITY_PRE_DASH, TRAIT_SOURCE_ABILITY("pre_dash"))
button.icon_state = "template_active"
addtimer(CALLBACK(src, PROC_REF(timeout)), time_until_timeout)
else
damage_nearby_targets()
return TRUE
-/datum/action/xeno_action/activable/pounce/prae_dash/proc/timeout()
- if (activated_once)
- activated_once = FALSE
- damage_nearby_targets()
-
/datum/action/xeno_action/activable/pounce/prae_dash/ability_cooldown_over()
update_button_icon()
return
+/datum/action/xeno_action/activable/pounce/prae_dash/proc/timeout()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_PRE_DASH))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_PRE_DASH, TRAIT_SOURCE_ABILITY("pre_dash"))
+ damage_nearby_targets()
+
/datum/action/xeno_action/activable/pounce/prae_dash/proc/damage_nearby_targets()
- var/mob/living/carbon/xenomorph/dash_user = owner
+ var/mob/living/carbon/xenomorph/xeno = owner
- if (QDELETED(dash_user) || !dash_user.check_state())
+ if(QDELETED(xeno) || !xeno.check_state())
return
- activated_once = FALSE
- button.icon_state = dash_user.selected_ability == src ? "template_on" : "template_xeno"
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_PRE_DASH, TRAIT_SOURCE_ABILITY("pre_dash"))
+ button.icon_state = xeno.selected_ability == src ? "template_on" : "template_xeno"
var/list/target_mobs = list()
- var/list/list_of_targets = orange(1, dash_user)
- for (var/mob/living/carbon/targets_in_range in list_of_targets)
- if (!isxeno_human(targets_in_range) || dash_user.can_not_harm(targets_in_range))
+ var/list/list_of_targets = orange(1, xeno)
+ for(var/mob/living/carbon/targets_in_range in list_of_targets)
+ if(!isxeno_human(targets_in_range) || xeno.can_not_harm(targets_in_range))
continue
- if (!(targets_in_range in target_mobs))
+ if(!(targets_in_range in target_mobs))
target_mobs += targets_in_range
- if (targets_in_range.stat)
+ if(targets_in_range.stat)
continue
- if (HAS_TRAIT(targets_in_range, TRAIT_NESTED))
+ if(HAS_TRAIT(targets_in_range, TRAIT_NESTED))
continue
- if (!isxeno_human(targets_in_range) || dash_user.can_not_harm(targets_in_range))
+ if(!isxeno_human(targets_in_range) || xeno.can_not_harm(targets_in_range))
continue
- dash_user.flick_attack_overlay(targets_in_range, "slash")
+ xeno.flick_attack_overlay(targets_in_range, "slash")
targets_in_range.apply_armoured_damage(get_xeno_damage_slash(targets_in_range, damage), ARMOR_MELEE, BRUTE)
playsound(get_turf(targets_in_range), "alien_claw_flesh", 30, 1)
- dash_user.visible_message(SPAN_XENODANGER("[dash_user] slashes its claws through the area around it!"), SPAN_XENODANGER("We slash our claws through the area around us!"))
- dash_user.spin_circle()
+ xeno.visible_message(SPAN_XENODANGER("[xeno] slashes its claws through the area around it!"), SPAN_XENODANGER("We slash our claws through the area around us!"))
+ xeno.spin_circle()
- if (length(target_mobs) >= shield_regen_threshold)
- var/datum/behavior_delegate/praetorian_vanguard/behavior = dash_user.behavior_delegate
- if (istype(behavior))
+ if(length(target_mobs) >= shield_regen_threshold)
+ var/datum/behavior_delegate/praetorian_vanguard/behavior = xeno.behavior_delegate
+ if(istype(behavior))
behavior.regen_shield()
-/datum/action/xeno_action/activable/cleave/use_ability(atom/target_atom)
- var/mob/living/carbon/xenomorph/cleave_user = owner
- if (!action_cooldown_check())
- return
- if (!cleave_user.check_state())
- return
- if (!check_and_use_plasma_owner())
- return
+/datum/action/xeno_action/activable/cleave/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+
+ XENO_ACTION_CHECK_USE_PLASMA(xeno)
- if (!isxeno_human(target_atom) || cleave_user.can_not_harm(target_atom))
- to_chat(cleave_user, SPAN_XENODANGER("We must target a hostile!"))
+ if(!isxeno_human(target_atom) || xeno.can_not_harm(target_atom))
+ to_chat(xeno, SPAN_XENODANGER("We must target a hostile!"))
return
var/mob/living/carbon/target_carbon = target_atom
- if (!cleave_user.Adjacent(target_carbon))
- to_chat(cleave_user, SPAN_XENOWARNING("We must be adjacent to our target!"))
+ if(!xeno.Adjacent(target_carbon))
+ to_chat(xeno, SPAN_XENOWARNING("We must be adjacent to our target!"))
return
- if (target_carbon.stat == DEAD)
- to_chat(cleave_user, SPAN_XENODANGER("[target_carbon] is dead, why would we want to touch it?"))
+ if(target_carbon.stat == DEAD)
+ to_chat(xeno, SPAN_XENODANGER("[target_carbon] is dead, why would we want to touch it?"))
return
// Flick overlay and play sound
- cleave_user.face_atom(target_carbon)
- cleave_user.animation_attack_on(target_atom, 10)
+ xeno.face_atom(target_carbon)
+ xeno.animation_attack_on(target_atom, 10)
var/hitsound = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg')
playsound(target_carbon, hitsound, 75, 1)
- if (root_toggle)
+ var/buffed = HAS_TRAIT(xeno, TRAIT_ABILITY_CLEAVE_ROOT)
+
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CLEAVE_ROOT))
var/root_duration = buffed ? root_duration_buffed : root_duration_unbuffed
- cleave_user.visible_message(SPAN_XENODANGER("[cleave_user] slams [target_atom] into the ground!"), SPAN_XENOHIGHDANGER("We slam [target_atom] into the ground!"))
+ xeno.visible_message(SPAN_XENODANGER("[xeno] slams [target_atom] into the ground!"), SPAN_XENOHIGHDANGER("We slam [target_atom] into the ground!"))
ADD_TRAIT(target_carbon, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Cleave"))
- if (ishuman(target_carbon))
- var/mob/living/carbon/human/Hu = target_carbon
- Hu.update_xeno_hostile_hud()
+ if(ishuman(target_carbon))
+ var/mob/living/carbon/human/target_human = target_carbon
+ target_human.update_xeno_hostile_hud()
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(unroot_human), target_carbon, TRAIT_SOURCE_ABILITY("Cleave")), get_xeno_stun_duration(target_carbon, root_duration))
- to_chat(target_carbon, SPAN_XENOHIGHDANGER("[cleave_user] has pinned you to the ground! You cannot move!"))
- cleave_user.flick_attack_overlay(target_carbon, "punch")
+ to_chat(target_carbon, SPAN_XENOHIGHDANGER("[xeno] has pinned you to the ground! You cannot move!"))
+ xeno.flick_attack_overlay(target_carbon, "punch")
else
var/fling_distance = buffed ? fling_dist_buffed : fling_dist_unbuffed
if(target_carbon.mob_size >= MOB_SIZE_BIG)
fling_distance *= 0.1
- cleave_user.visible_message(SPAN_XENODANGER("[cleave_user] deals [target_atom] a massive blow, sending them flying!"), SPAN_XENOHIGHDANGER("We deal [target_atom] a massive blow, sending them flying!"))
- cleave_user.flick_attack_overlay(target_carbon, "slam")
- cleave_user.throw_carbon(target_atom, null, fling_distance)
+ xeno.visible_message(SPAN_XENODANGER("[xeno] deals [target_atom] a massive blow, sending them flying!"), SPAN_XENOHIGHDANGER("We deal [target_atom] a massive blow, sending them flying!"))
+ xeno.flick_attack_overlay(target_carbon, "slam")
+ xeno.throw_carbon(target_atom, null, fling_distance)
apply_cooldown()
return ..()
/datum/action/xeno_action/activable/cleave/proc/remove_buff()
- buffed = FALSE
+ var/mob/living/carbon/xenomorph/xeno = owner
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_CLEAVE_BUFFED, TRAIT_SOURCE_ABILITY("cleave_buffed"))
+
+
+
+/datum/action/xeno_action/onclick/toggle_cleave/can_use_action()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(xeno && !xeno.buckled && !xeno.is_mob_incapacitated())
+ return TRUE
+
+/datum/action/xeno_action/onclick/toggle_cleave/use_ability(atom/target_atom)
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!istype(xeno))
+ return
+
+ if(!xeno.check_state(TRUE))
+ return
+
+ var/action_icon_result
+ if(HAS_TRAIT(xeno, TRAIT_ABILITY_CLEAVE_ROOT))
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_CLEAVE_ROOT, TRAIT_SOURCE_ABILITY("cleave_root"))
+ action_icon_result = "prae_cleave_root"
+ to_chat(xeno, SPAN_WARNING("We will now root marines with our cleave."))
+ else
+ ADD_TRAIT(xeno, TRAIT_ABILITY_CLEAVE_ROOT, TRAIT_SOURCE_ABILITY("cleave_root"))
+ action_icon_result = "prae_cleave_fling" // TODO: update
+ to_chat(xeno, SPAN_WARNING("We will now throw marines with our cleave."))
+
+ button.overlays.Cut()
+ button.overlays += image('icons/mob/hud/actions_xeno.dmi', button, action_icon_result)
+ return ..()
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/hedgehog.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/hedgehog.dm
index 8632830e2172e..bbc653b739b0c 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/hedgehog.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/hedgehog.dm
@@ -34,12 +34,9 @@
var/shards_per_projectile = 10
var/shards_per_slash = 15
var/armor_buff_per_fifty_shards = 2.50
- var/shard_lock_duration = 150
- var/shard_lock_speed_mod = 0.45
// Shard state
var/shards = 0
- var/shards_locked = FALSE //are we locked at 0 shards?
// Armor buff state
var/times_armor_buffed = 0
@@ -49,46 +46,21 @@
. += "Bone Shards: [shards]/[max_shards]"
. += "Shards Armor Bonus: [times_armor_buffed*armor_buff_per_fifty_shards]"
-/datum/behavior_delegate/ravager_hedgehog/proc/lock_shards()
-
- if (!bound_xeno)
- return
-
- to_chat(bound_xeno, SPAN_XENODANGER("You have shed your spikes and cannot gain any more for [shard_lock_duration/10] seconds!"))
-
- bound_xeno.speed_modifier -= shard_lock_speed_mod
- bound_xeno.recalculate_speed()
-
- shards = 0
- shards_locked = TRUE
- addtimer(CALLBACK(src, PROC_REF(unlock_shards)), shard_lock_duration)
-
-/datum/behavior_delegate/ravager_hedgehog/proc/unlock_shards()
-
- if (!bound_xeno)
- return
-
- to_chat(bound_xeno, SPAN_XENODANGER("You feel your ability to gather shards return!"))
-
- bound_xeno.speed_modifier += shard_lock_speed_mod
- bound_xeno.recalculate_speed()
- shards_locked = FALSE
-
// Return true if we have enough shards, false otherwise
/datum/behavior_delegate/ravager_hedgehog/proc/check_shards(amount)
- if (!amount)
+ if(!amount)
return FALSE
else
return (shards >= amount)
/datum/behavior_delegate/ravager_hedgehog/proc/use_shards(amount)
- if (!amount)
+ if(!amount)
return
shards = max(0, shards - amount)
/datum/behavior_delegate/ravager_hedgehog/on_life()
- if (!shards_locked)
+ if(!HAS_TRAIT(bound_xeno, TRAIT_ABILITY_SHED_SPIKES))
shards = min(max_shards, shards + shard_gain_onlife)
var/armor_buff_count = shards/50 //0-6
@@ -110,7 +82,6 @@
bound_xeno.small_explosives_stun = TRUE
bound_xeno.remove_filter("hedge_unstunnable", 1, list("type" = "outline", "color" = "#421313", "size" = 1))
-
return
@@ -119,27 +90,23 @@
holder.overlays.Cut()
/datum/behavior_delegate/ravager_hedgehog/on_hitby_projectile()
- if (!shards_locked)
+ if(!HAS_TRAIT(bound_xeno, TRAIT_ABILITY_SHED_SPIKES))
shards = min(max_shards, shards + shards_per_projectile)
return
/datum/behavior_delegate/ravager_hedgehog/melee_attack_additional_effects_self()
- if (!shards_locked)
+ if(!HAS_TRAIT(bound_xeno, TRAIT_ABILITY_SHED_SPIKES))
shards = min(max_shards, shards + shards_per_slash)
return
-/datum/action/xeno_action/onclick/spike_shield/use_ability(atom/target)
+/datum/action/xeno_action/onclick/spike_shield/use_ability(atom/target_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!action_cooldown_check())
- return
-
- if (!xeno.check_state())
- return
+ XENO_ACTION_CHECK(xeno)
var/datum/behavior_delegate/ravager_hedgehog/behavior = xeno.behavior_delegate
- if (!behavior.check_shards(shard_cost))
+ if(!behavior.check_shards(shard_cost))
to_chat(xeno, SPAN_DANGER("Not enough shards! We need [shard_cost - behavior.shards] more!"))
return
behavior.use_shards(shard_cost)
@@ -148,7 +115,7 @@
// Add our shield
var/datum/xeno_shield/hedgehog_shield/shield = xeno.add_xeno_shield(shield_amount, XENO_SHIELD_SOURCE_HEDGE_RAV, /datum/xeno_shield/hedgehog_shield)
- if (shield)
+ if(shield)
shield.owner = xeno
shield.shrapnel_amount = shield_shrapnel_amount
xeno.overlay_shields()
@@ -162,7 +129,7 @@
return ..()
/datum/action/xeno_action/onclick/spike_shield/action_cooldown_check()
- if (shield_active) // If active shield, return FALSE so that this action does not get carried out
+ if(shield_active) // If active shield, return FALSE so that this action does not get carried out
return FALSE
else if (cooldown_timer_id == TIMER_ID_NULL)
var/mob/living/carbon/xenomorph/xeno = owner
@@ -173,14 +140,14 @@
/datum/action/xeno_action/onclick/spike_shield/proc/remove_shield()
var/mob/living/carbon/xenomorph/xeno = owner
- if (!shield_active)
+ if(!shield_active)
return
shield_active = FALSE
button.icon_state = "template_xeno"
- for (var/datum/xeno_shield/shield in xeno.xeno_shields)
- if (shield.shield_source == XENO_SHIELD_SOURCE_HEDGE_RAV)
+ for(var/datum/xeno_shield/shield in xeno.xeno_shields)
+ if(shield.shield_source == XENO_SHIELD_SOURCE_HEDGE_RAV)
shield.on_removal()
qdel(shield)
break
@@ -192,28 +159,27 @@
/datum/action/xeno_action/activable/rav_spikes/use_ability(atom/affected_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!action_cooldown_check())
+ if(!affected_atom || affected_atom.layer >= FLY_LAYER || !isturf(xeno.loc))
return
- if(!affected_atom || affected_atom.layer >= FLY_LAYER || !isturf(xeno.loc) || !xeno.check_state())
- return
+ XENO_ACTION_CHECK(xeno)
var/datum/behavior_delegate/ravager_hedgehog/behavior = xeno.behavior_delegate
- if (!behavior.check_shards(shard_cost))
+ if(!behavior.check_shards(shard_cost))
to_chat(xeno, SPAN_DANGER("Not enough shards! We need [shard_cost - behavior.shards] more!"))
return
behavior.use_shards(shard_cost)
xeno.visible_message(SPAN_XENOWARNING("[xeno] fires their spikes at [affected_atom]!"), SPAN_XENOWARNING("We fire our spikes at [affected_atom]!"))
- var/turf/target = locate(affected_atom.x, affected_atom.y, affected_atom.z)
+ var/turf/target_turf = locate(affected_atom.x, affected_atom.y, affected_atom.z)
var/obj/projectile/projectile = new /obj/projectile(xeno.loc, create_cause_data(initial(xeno.caste_type), xeno))
var/datum/ammo/ammo_datum = GLOB.ammo_list[ammo_type]
projectile.generate_bullet(ammo_datum)
- projectile.fire_at(target, xeno, xeno, ammo_datum.max_range, ammo_datum.shell_speed)
+ projectile.fire_at(target_turf, xeno, xeno, ammo_datum.max_range, ammo_datum.shell_speed)
playsound(xeno, 'sound/effects/spike_spray.ogg', 25, 1)
apply_cooldown()
@@ -222,7 +188,7 @@
/datum/action/xeno_action/activable/rav_spikes/action_cooldown_check()
if(!owner)
return FALSE
- if (cooldown_timer_id == TIMER_ID_NULL)
+ if(cooldown_timer_id == TIMER_ID_NULL)
var/mob/living/carbon/xenomorph/xeno = owner
if(!istype(xeno))
return FALSE
@@ -234,18 +200,14 @@
/datum/action/xeno_action/onclick/spike_shed/use_ability(atom/affected_atom)
var/mob/living/carbon/xenomorph/xeno = owner
- if (!action_cooldown_check())
- return
-
- if (!xeno.check_state())
- return
+ XENO_ACTION_CHECK(xeno)
var/datum/behavior_delegate/ravager_hedgehog/behavior = xeno.behavior_delegate
- if (!behavior.check_shards(shard_cost))
+ if(!behavior.check_shards(shard_cost))
to_chat(xeno, SPAN_DANGER("Not enough shards! We need [shard_cost - behavior.shards] more!"))
return
behavior.use_shards(shard_cost)
- behavior.lock_shards()
+ lock_shards()
xeno.visible_message(SPAN_XENOWARNING("[xeno] sheds their spikes, firing them in all directions!"), SPAN_XENOWARNING("We shed our spikes, firing them in all directions!!"))
xeno.spin_circle()
@@ -256,9 +218,36 @@
return ..()
/datum/action/xeno_action/onclick/spike_shed/action_cooldown_check()
- if (cooldown_timer_id == TIMER_ID_NULL)
+ if(cooldown_timer_id == TIMER_ID_NULL)
var/mob/living/carbon/xenomorph/xeno = owner
var/datum/behavior_delegate/ravager_hedgehog/behavior = xeno.behavior_delegate
return behavior.check_shards(shard_cost)
else
return FALSE
+
+/datum/action/xeno_action/onclick/spike_shed/proc/lock_shards()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!xeno)
+ return
+
+ to_chat(xeno, SPAN_XENODANGER("You have shed your spikes and cannot gain any more for [shard_lock_duration/10] seconds!"))
+
+ xeno.speed_modifier -= shard_lock_speed_mod
+ xeno.recalculate_speed()
+
+ var/datum/behavior_delegate/ravager_hedgehog/behavior = xeno.behavior_delegate
+ behavior.shards = 0
+ start_duration_display(shard_lock_duration)
+ ADD_TRAIT(xeno, TRAIT_ABILITY_SHED_SPIKES, TRAIT_SOURCE_ABILITY("shed_spikes"))
+ addtimer(CALLBACK(src, PROC_REF(unlock_shards)), shard_lock_duration)
+
+/datum/action/xeno_action/onclick/spike_shed/proc/unlock_shards()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!xeno)
+ return
+
+ to_chat(xeno, SPAN_XENODANGER("You feel your ability to gather shards return!"))
+
+ xeno.speed_modifier += shard_lock_speed_mod
+ xeno.recalculate_speed()
+ REMOVE_TRAIT(xeno, TRAIT_ABILITY_SHED_SPIKES, TRAIT_SOURCE_ABILITY("shed_spikes"))
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/runner/acider.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/runner/acider.dm
index 448b5f426e2f0..9778691181a9f 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/castes/runner/acider.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/runner/acider.dm
@@ -26,12 +26,7 @@
/datum/behavior_delegate/runner_acider
var/acid_amount = 0
- var/caboom_left = 20
- var/caboom_trigger
- var/caboom_last_proc
-
var/max_acid = 1000
- var/caboom_timer = 20
var/acid_slash_regen_lying = 8
var/acid_slash_regen_standing = 14
var/acid_passive_regen = 1
@@ -50,14 +45,6 @@
/// How much acid is required to fill a trap
var/fill_acid_cost = 75
- var/list/caboom_sound = list('sound/effects/runner_charging_1.ogg','sound/effects/runner_charging_2.ogg')
- var/caboom_loop = 1
-
- var/caboom_acid_ratio = 200
- var/caboom_burn_damage_ratio = 5
- var/caboom_burn_range_ratio = 100
- var/caboom_struct_acid_type = /obj/effect/xenomorph/acid
-
var/drool_overlay_active = FALSE
var/mutable_appearance/drool_applied_icon
var/mutable_appearance/acid_overlays_icon
@@ -81,8 +68,6 @@
if(acid_amount >= acid_gen_cap)
. += "Passive acid generation cap ([acid_gen_cap]) reached"
. += "Battle acid generation: [combat_gen_active ? "Active" : "Inactive"]"
- if(caboom_trigger)
- . += "FOR THE HIVE!: in [caboom_left] seconds"
/datum/behavior_delegate/runner_acider/melee_attack_additional_effects_target(mob/living/carbon/target_mob)
if(ishuman(target_mob)) //Will acid be applied to the mob
@@ -112,6 +97,7 @@
drool_overlay_active = TRUE //turns the overlay on
/datum/behavior_delegate/runner_acider/on_life()
+ var/datum/action/xeno_action/activable/acider_for_the_hive/acider_fth = get_action(bound_xeno, /datum/action/xeno_action/activable/acider_for_the_hive)
if(acid_amount < acid_gen_cap)
modify_acid(acid_passive_regen)
if(combat_gen_active)
@@ -120,19 +106,19 @@
return
if(bound_xeno.stat == DEAD)
return
- if(caboom_trigger)
- var/wt = world.time
- if(caboom_last_proc)
- caboom_left -= (wt - caboom_last_proc)/10
- caboom_last_proc = wt
- var/amplitude = 50 + 50 * (caboom_timer - caboom_left) / caboom_timer
- playsound(bound_xeno, caboom_sound[caboom_loop], amplitude, FALSE, 10)
- caboom_loop++
- if(caboom_loop > length(caboom_sound))
- caboom_loop = 1
- if(caboom_left <= 0)
- caboom_trigger = FALSE
- do_caboom()
+ if(acider_fth.caboom_trigger)
+ var/world_time = world.time
+ if(acider_fth.caboom_last_proc)
+ acider_fth.caboom_left -= (world_time - acider_fth.caboom_last_proc)/10
+ acider_fth.caboom_last_proc = world_time
+ var/amplitude = 50 + 50 * (acider_fth.caboom_timer - acider_fth.caboom_left) / acider_fth.caboom_timer
+ playsound(bound_xeno, acider_fth.caboom_sound[acider_fth.caboom_loop], amplitude, FALSE, 10)
+ acider_fth.caboom_loop++
+ if(acider_fth.caboom_loop > length(acider_fth.caboom_sound))
+ acider_fth.caboom_loop = 1
+ if(acider_fth.caboom_left <= 0)
+ acider_fth.caboom_trigger = FALSE
+ acider_fth.do_caboom()
return
var/image/holder = bound_xeno.hud_list[SPECIAL_HUD]
@@ -144,70 +130,11 @@
if(acid_amount >= acid_gen_cap)
holder.overlays += image('icons/mob/hud/hud.dmi', "cap[percentage_acid_cap]")
-/datum/behavior_delegate/runner_acider/handle_death(mob/M)
+/datum/behavior_delegate/runner_acider/handle_death()
var/image/holder = bound_xeno.hud_list[SPECIAL_HUD]
holder.overlays.Cut()
STOP_PROCESSING(SSfasteffects, src)
-/datum/behavior_delegate/runner_acider/proc/do_caboom()
- if(!bound_xeno)
- return
- var/acid_range = acid_amount / caboom_acid_ratio
- var/max_burn_damage = acid_amount / caboom_burn_damage_ratio
- var/burn_range = acid_amount / caboom_burn_range_ratio
-
- for(var/barricades in dview(acid_range, bound_xeno))
- if(istype(barricades, /obj/structure/barricade))
- new caboom_struct_acid_type(get_turf(barricades), barricades)
- continue
- if(istype(barricades, /mob))
- new /datum/effects/acid(barricades, bound_xeno, initial(bound_xeno.caste_type))
- continue
- var/x = bound_xeno.x
- var/y = bound_xeno.y
- FOR_DVIEW(var/mob/living/target_living, burn_range, bound_xeno, HIDE_INVISIBLE_OBSERVER)
- if (!isxeno_human(target_living) || bound_xeno.can_not_harm(target_living))
- continue
- var/dist = 0
- // such cheap, much fast
- var/dx = abs(target_living.x - x)
- var/dy = abs(target_living.y - y)
- if(dx>=dy)
- dist = (0.934*dx) + (0.427*dy)
- else
- dist = (0.427*dx) + (0.934*dy)
- var/damage = floor((burn_range - dist) * max_burn_damage / burn_range)
- if(isxeno(target_living))
- damage *= XVX_ACID_DAMAGEMULT
-
- target_living.apply_damage(damage, BURN)
- FOR_DVIEW_END
- FOR_DVIEW(var/turf/T, acid_range, bound_xeno, HIDE_INVISIBLE_OBSERVER)
- new /obj/effect/particle_effect/smoke/acid_runner_harmless(T)
- FOR_DVIEW_END
- playsound(bound_xeno, 'sound/effects/blobattack.ogg', 75)
- if(bound_xeno.client && bound_xeno.hive)
- var/datum/hive_status/hive_status = bound_xeno.hive
- var/turf/spawning_turf = get_turf(bound_xeno)
- if(!hive_status.hive_location)
- addtimer(CALLBACK(bound_xeno.hive, TYPE_PROC_REF(/datum/hive_status, respawn_on_turf), bound_xeno.client, spawning_turf), 0.5 SECONDS)
- else
- addtimer(CALLBACK(bound_xeno.hive, TYPE_PROC_REF(/datum/hive_status, free_respawn), bound_xeno.client), 5 SECONDS)
- bound_xeno.gib(create_cause_data("internal acid rupture", src))
-
-/mob/living/carbon/xenomorph/runner/ventcrawl_carry()
- var/datum/behavior_delegate/runner_acider/behavior_delegates = behavior_delegate
- if(istype(behavior_delegates) && behavior_delegates.caboom_trigger)
- to_chat(src, SPAN_XENOWARNING("You cannot ventcrawl when you are about to explode!"))
- return FALSE
- return ..()
-
-/mob/living/carbon/xenomorph/runner/get_examine_text(mob/user)
- . = ..()
- var/datum/behavior_delegate/runner_acider/behavior = behavior_delegate
- if(istype(behavior) && isxeno(user))
- . += "it has [SPAN_GREEN(behavior.acid_amount)] acid!"
-
/datum/behavior_delegate/runner_acider/proc/combat_gen_end() //This proc is triggerd once the combat acid timer runs out.
combat_gen_active = FALSE //turns combat acid off
drool_overlay_active = FALSE
@@ -252,9 +179,9 @@
var/perc_index = 0
if(acid_amount > max_acid * 0.8)
perc_index = 3
- else if (acid_amount > max_acid * 0.5)
+ else if(acid_amount > max_acid * 0.5)
perc_index = 2
- else if (acid_amount > max_acid * 0.2)
+ else if(acid_amount > max_acid * 0.2)
perc_index = 1
if(perc_index && bound_runner.stat != DEAD)
@@ -276,7 +203,7 @@
to_chat(xeno, SPAN_XENOHIGHDANGER("Can only melt barricades and items!"))
return
var/datum/behavior_delegate/runner_acider/behavior_delegate = xeno.behavior_delegate
- if (!istype(behavior_delegate))
+ if(!istype(behavior_delegate))
return
if(behavior_delegate.acid_amount < acid_cost)
to_chat(xeno, SPAN_XENOHIGHDANGER("Not enough acid stored!"))
@@ -288,7 +215,7 @@
return ..()
-/datum/action/xeno_action/activable/acider_for_the_hive/use_ability(atom/affected_atom)
+/datum/action/xeno_action/activable/acider_for_the_hive/use_ability()
var/mob/living/carbon/xenomorph/xeno = owner
if(!istype(xeno))
@@ -303,17 +230,13 @@
to_chat(xeno, SPAN_XENOWARNING("We can't activate this here!"))
return
- if(!xeno.check_state())
- return
-
- if(!action_cooldown_check())
- return
+ XENO_ACTION_CHECK(xeno)
var/datum/behavior_delegate/runner_acider/behavior_delegate = xeno.behavior_delegate
if(!istype(behavior_delegate))
return
- if(behavior_delegate.caboom_trigger)
+ if(caboom_trigger)
cancel_ability()
return
@@ -328,12 +251,12 @@
xeno.set_light_color("#22FF22")
xeno.set_light_range(3)
- behavior_delegate.caboom_trigger = TRUE
- behavior_delegate.caboom_left = behavior_delegate.caboom_timer
- behavior_delegate.caboom_last_proc = 0
- xeno.set_effect(behavior_delegate.caboom_timer*2, SUPERSLOW)
+ caboom_trigger = TRUE
+ caboom_left = caboom_timer
+ caboom_last_proc = 0
+ xeno.set_effect(caboom_timer*2, SUPERSLOW)
- START_PROCESSING(SSfasteffects, src)
+ start_duration_display(caboom_left_display)
xeno.say(";FOR THE HIVE!!!")
return ..()
@@ -346,35 +269,85 @@
if(!istype(behavior_delegate))
return
- behavior_delegate.caboom_trigger = FALSE
+ caboom_trigger = FALSE
xeno.color = null
xeno.set_light_range(0)
behavior_delegate.modify_acid(-behavior_delegate.max_acid / 4)
// Done this way rather than setting to 0 in case something else slowed us
// -Original amount set - (time exploding + timer inaccuracy) * how much gets removed per tick / 2
- xeno.adjust_effect(behavior_delegate.caboom_timer * -2 - (behavior_delegate.caboom_timer - behavior_delegate.caboom_left + 2) * xeno.life_slow_reduction * 0.5, SUPERSLOW)
+ xeno.adjust_effect(caboom_timer * -2 - (caboom_timer - caboom_left + 2) * xeno.life_slow_reduction * 0.5, SUPERSLOW)
+ end_duration_display()
to_chat(xeno, SPAN_XENOWARNING("We remove all our explosive acid before it combusted."))
- STOP_PROCESSING(SSfasteffects, src)
- button.set_maptext()
+/datum/action/xeno_action/activable/acider_for_the_hive/proc/do_caboom()
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if(!istype(xeno))
+ return
-/datum/action/xeno_action/activable/acider_for_the_hive/process(delta_time)
- return update_caboom_maptext()
+ var/datum/behavior_delegate/runner_acider/behavior_delegate = xeno.behavior_delegate
+ if(!istype(behavior_delegate))
+ return
-/datum/action/xeno_action/activable/acider_for_the_hive/proc/update_caboom_maptext()
- var/mob/living/carbon/xenomorph/xeno = owner
- var/datum/behavior_delegate/runner_acider/delegate = xeno.behavior_delegate
- if(!istype(delegate) || !delegate.caboom_trigger || delegate.caboom_left <= 0)
- button.set_maptext()
- return PROCESS_KILL
+ var/acid_range = behavior_delegate.acid_amount / caboom_acid_ratio
+ var/max_burn_damage = behavior_delegate.acid_amount / caboom_burn_damage_ratio
+ var/burn_range = behavior_delegate.acid_amount / caboom_burn_range_ratio
- button.set_maptext(SMALL_FONTS_COLOR(7, delegate.caboom_left, "#e69d00"), 19, 2)
- return
+ for(var/barricades in dview(acid_range, xeno))
+ if(istype(barricades, /obj/structure/barricade))
+ new caboom_struct_acid_type(get_turf(barricades), barricades)
+ continue
+ if(istype(barricades, /mob))
+ new /datum/effects/acid(barricades, xeno, initial(xeno.caste_type))
+ continue
+ var/x = xeno.x
+ var/y = xeno.y
+ FOR_DVIEW(var/mob/living/target_living, burn_range, xeno, HIDE_INVISIBLE_OBSERVER)
+ if (!isxeno_human(target_living) || xeno.can_not_harm(target_living))
+ continue
+ var/dist = 0
+ // such cheap, much fast
+ var/dx = abs(target_living.x - x)
+ var/dy = abs(target_living.y - y)
+ if(dx>=dy)
+ dist = (0.934*dx) + (0.427*dy)
+ else
+ dist = (0.427*dx) + (0.934*dy)
+ var/damage = floor((burn_range - dist) * max_burn_damage / burn_range)
+ if(isxeno(target_living))
+ damage *= XVX_ACID_DAMAGEMULT
+
+ target_living.apply_damage(damage, BURN)
+ FOR_DVIEW_END
+ FOR_DVIEW(var/turf/target_turf, acid_range, xeno, HIDE_INVISIBLE_OBSERVER)
+ new /obj/effect/particle_effect/smoke/acid_runner_harmless(target_turf)
+ FOR_DVIEW_END
+ playsound(xeno, 'sound/effects/blobattack.ogg', 75)
+ if(xeno.client && xeno.hive)
+ var/datum/hive_status/hive_status = xeno.hive
+ var/turf/spawning_turf = get_turf(xeno)
+ if(!hive_status.hive_location)
+ addtimer(CALLBACK(xeno.hive, TYPE_PROC_REF(/datum/hive_status, respawn_on_turf), xeno.client, spawning_turf), 0.5 SECONDS)
+ else
+ addtimer(CALLBACK(xeno.hive, TYPE_PROC_REF(/datum/hive_status, free_respawn), xeno.client), 5 SECONDS)
+ xeno.gib(create_cause_data("internal acid rupture", src))
+/mob/living/carbon/xenomorph/runner/get_examine_text(mob/user)
+ . = ..()
+ var/datum/behavior_delegate/runner_acider/behavior = behavior_delegate
+ if(istype(behavior) && isxeno(user))
+ . += "it has [SPAN_GREEN(behavior.acid_amount)] acid!"
+
+/mob/living/carbon/xenomorph/runner/ventcrawl_carry()
+ var/datum/action/xeno_action/activable/acider_for_the_hive/acider_fth = get_action(src, /datum/action/xeno_action/activable/acider_for_the_hive)
+ if(acider_fth.caboom_trigger)
+ to_chat(src, SPAN_XENOWARNING("You cannot ventcrawl when you are about to explode!"))
+ return FALSE
+ return ..()
+
/mob/living/carbon/xenomorph/runner/corrosive_acid(atom/affected_atom, acid_type, plasma_cost)
if(!istype(strain, /datum/xeno_strain/acider))
return ..()
diff --git a/code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm b/code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm
index 8b73f42710425..5970fe150d8f5 100644
--- a/code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm
+++ b/code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm
@@ -171,7 +171,7 @@
to_chat(src, SPAN_WARNING("We must be at full health to take a strain."))
return FALSE
- if(fortify || crest_defense || stealth || HAS_TRAIT(src, TRAIT_ABILITY_ENCLOSED_PLATES) || HAS_TRAIT(src, TRAIT_ABILITY_REFLECTIVE_PLATES))
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY) || HAS_TRAIT(src, TRAIT_ABILITY_CREST) || HAS_TRAIT(src, TRAIT_ABILITY_INVIS) || HAS_TRAIT(src, TRAIT_ABILITY_ENCLOSED_PLATES) || HAS_TRAIT(src, TRAIT_ABILITY_REFLECTIVE_PLATES))
to_chat(src, SPAN_WARNING("We cannot take a strain while in this stance."))
return FALSE
diff --git a/code/modules/projectiles/guns/flamer/flamer.dm b/code/modules/projectiles/guns/flamer/flamer.dm
index bc55c7300c256..708e507a91cb6 100644
--- a/code/modules/projectiles/guns/flamer/flamer.dm
+++ b/code/modules/projectiles/guns/flamer/flamer.dm
@@ -727,7 +727,7 @@ GLOBAL_LIST_EMPTY(flamer_particles)
var/sig_result = SEND_SIGNAL(ignited_morb, COMSIG_LIVING_FLAMER_FLAMED, tied_reagent)
- if(!(sig_result & COMPONENT_NO_IGNITE))
+ if(!(sig_result & COMPONENT_NO_IGNITE) && !HAS_TRAIT(ignited_morb, TRAIT_ABILITY_POUNCE))
switch(fire_variant)
if(FIRE_VARIANT_TYPE_B) //Armor Shredding Greenfire, super easy to pat out. 50 duration -> 10 stacks (1 pat/resist)
ignited_morb.TryIgniteMob(floor(tied_reagent.durationfire / 5), tied_reagent)
@@ -815,7 +815,7 @@ GLOBAL_LIST_EMPTY(flamer_particles)
xeno_target.emote("roar")
xeno_target.plasma_stored = xeno_target.plasma_max
- if(!(sig_result & COMPONENT_NO_IGNITE) && burn_damage)
+ if(!(sig_result & COMPONENT_NO_IGNITE) && !HAS_TRAIT(target, TRAIT_ABILITY_POUNCE) && burn_damage)
switch(fire_variant)
if(FIRE_VARIANT_TYPE_B) //Armor Shredding Greenfire, super easy to pat out. 50 duration -> 10 stacks (1 pat/resist)
target.TryIgniteMob(floor(tied_reagent.durationfire / 5), tied_reagent)
@@ -841,8 +841,13 @@ GLOBAL_LIST_EMPTY(flamer_particles)
if(FIRE_VARIANT_TYPE_B)
if(isxeno(target))
var/mob/living/carbon/xenomorph/xeno_target = target
- xeno_target.armor_deflection?(variant_burn_msg=" We feel the flames weakening our exoskeleton!"):(variant_burn_msg=" You feel the flaming chemicals eating into your body!")
- to_chat(target, SPAN_DANGER("You are burned![variant_burn_msg?"[variant_burn_msg]":""]"))
+ if(!HAS_TRAIT(target, TRAIT_ABILITY_POUNCE))
+ xeno_target.armor_deflection?(variant_burn_msg=" We feel the flames weakening our exoskeleton!"):(variant_burn_msg=" You feel the flaming chemicals eating into your body!")
+ if(!HAS_TRAIT(target, TRAIT_ABILITY_POUNCE))
+ to_chat(target, SPAN_DANGER("You are burned![variant_burn_msg?"[variant_burn_msg]":""]"))
+ else
+ if(!prob(75)) // It spam like crazy, it even can lag client.
+ to_chat(target, SPAN_DANGER("We got burned from flames below!"))
target.updatehealth()
/obj/flamer_fire/proc/update_flame()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index c7b0c94feba55..4efda2b34057e 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -989,6 +989,8 @@
if(evasion > 0)
. -= evasion
+ if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED))
+ return 0
/obj/projectile/proc/play_hit_effect(mob/hit_mob)
if(ammo.sound_hit)
@@ -1476,3 +1478,4 @@
#undef DEBUG_HIT_CHANCE
#undef DEBUG_HUMAN_DEFENSE
#undef DEBUG_XENO_DEFENSE
+
diff --git a/code/modules/vehicles/multitile/multitile_bump.dm b/code/modules/vehicles/multitile/multitile_bump.dm
index e81097de0f75e..ae8f21ac23713 100644
--- a/code/modules/vehicles/multitile/multitile_bump.dm
+++ b/code/modules/vehicles/multitile/multitile_bump.dm
@@ -773,7 +773,7 @@
//DEFENDER
/mob/living/carbon/xenomorph/defender/handle_vehicle_bump(obj/vehicle/multitile/V)
- if(fortify)
+ if(HAS_TRAIT(src, TRAIT_ABILITY_FORTIFY))
if(V.vehicle_flags & VEHICLE_CLASS_WEAK) //defenders being able to completely block armored vehicles by crawling into a boulder is ridiculous
visible_message(SPAN_DANGER("[src] digs its claws into the ground, anchoring itself in place and halting [V] in its tracks!"),
SPAN_DANGER("You dig your claws into the ground, stopping [V] in its tracks!"))
diff --git a/sound/effects/pred_force_decloak.ogg b/sound/effects/pred_force_decloak.ogg
new file mode 100644
index 0000000000000..672a5314a3b2f
Binary files /dev/null and b/sound/effects/pred_force_decloak.ogg differ