diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 034de38eeb..5365223c4d 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -46,6 +46,11 @@
#define COMSIG_CLIENT_KEY_DOWN "client_key_down"
#define COMSIG_CLIENT_KEY_UP "client_key_up"
+///from /datum/key_down(): (key, client/user)
+#define COMSIG_DATUM_KEY_DOWN "datum_key_down"
+///from /datum/key_up(): (key, client/user)
+#define COMSIG_DATUM_KEY_UP "datum_key_up"
+
///from /datum/controller/subsystem/radio/get_available_tcomm_zs(): (list/tcomms)
#define COMSIG_SSRADIO_GET_AVAILABLE_TCOMMS_ZS "ssradio_get_available_tcomms_zs"
@@ -298,6 +303,10 @@
#define COMSIG_MOVABLE_PRE_LAUNCH "movable_pre_launch"
#define COMPONENT_LAUNCH_CANCEL (1<<0)
+///from /atom/movable/launch_towards(): (datum/launch_metadata/LM)
+#define COMSIG_MOVABLE_POST_LAUNCH "movable_post_launch"
+ #define COMPONENT_ABORT_COLLISION_CALLBACKS (1<<0)
+
// Return non-zero value to override original behaviour
#define COMSIG_MOB_SCREECH_ACT "mob_screech_act"
#define COMPONENT_SCREECH_ACT_CANCEL (1<<0)
diff --git a/code/__DEFINES/keybinding.dm b/code/__DEFINES/keybinding.dm
index 982fa8b417..6fedca7f15 100644
--- a/code/__DEFINES/keybinding.dm
+++ b/code/__DEFINES/keybinding.dm
@@ -55,6 +55,7 @@
#define COMSIG_KB_HUMAN_WEAPON_UNLOAD "keybinding_human_weapon_unload"
#define COMSIG_KB_HUMAN_WEAPON_ATTACHMENT "keybinding_human_weapon_attachment"
#define COMSIG_KB_HUMAN_WEAPON_ATTACHMENT_RAIL "keybinding_human_weapon_attachment_rail"
+#define COMSIG_KB_HUMAN_PARRY "keybinding_human_parry"
//Living
#define COMSIG_KB_LIVING_RESIST_DOWN "keybinding_living_resist_down"
diff --git a/code/datums/keybinding/human_combat.dm b/code/datums/keybinding/human_combat.dm
index 8d3bad1bfb..9eff2ab017 100644
--- a/code/datums/keybinding/human_combat.dm
+++ b/code/datums/keybinding/human_combat.dm
@@ -1,13 +1,14 @@
/datum/keybinding/human/combat
category = CATEGORY_HUMAN_COMBAT
weight = WEIGHT_MOB
+ var/requires_gun = TRUE
/datum/keybinding/human/combat/can_use(client/user)
. = ..()
if(!.)
return
var/mob/M = user.mob
- return isgun(M.get_held_item())
+ return !requires_gun || isgun(M.get_held_item())
/datum/keybinding/human/combat/field_strip_weapon
hotkey_keys = list()
@@ -169,3 +170,11 @@
var/obj/item/weapon/gun/G = H.get_held_item()
G.activate_rail_attachment_verb()
return TRUE
+
+/datum/keybinding/human/combat/parry
+ hotkey_keys = list("Space")
+ classic_keys = list()
+ name = "human_parry"
+ full_name = "Parry"
+ keybind_signal = COMSIG_KB_HUMAN_PARRY
+ requires_gun = FALSE
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index d8f13f8778..8a96ddfb89 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -46,7 +46,7 @@
singular_name = "medical gauze"
desc = "Some sterile gauze to wrap around bloody stumps and lacerations."
icon_state = "brutepack"
-
+
stack_id = "bruise pack"
/obj/item/stack/medical/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
@@ -90,7 +90,7 @@
singular_name = "ointment"
icon_state = "ointment"
heal_burn = 1
-
+
stack_id = "ointment"
/obj/item/stack/medical/ointment/attack(mob/living/carbon/M as mob, mob/user as mob)
@@ -119,7 +119,7 @@
SPAN_HELPFUL("[user] salves the wounds on your [affecting.display_name]."),
SPAN_NOTICE("[user] salves the wounds [possessive_their] [affecting.display_name]."))
use(1)
- playsound(user, 'sound/handling/ointment_spreading.ogg', 25, 1, 2)
+ playsound(user, 'sound/handling/ointment_spreading.ogg', 25, 1, 2)
else
if (H.can_be_operated_on()) //Checks if mob is lying down on table for surgery
if (do_surgery(H,user,src))
@@ -128,57 +128,46 @@
to_chat(user, SPAN_NOTICE("The [affecting.display_name] is cut open, you'll need more than a bandage!"))
-/obj/item/stack/medical/advanced/bruise_pack
- name = "advanced trauma kit"
- singular_name = "advanced trauma kit"
- desc = "An advanced trauma kit for severe injuries."
- icon_state = "traumakit"
- heal_brute = 12
-
- stack_id = "advanced bruise pack"
+/obj/item/stack/medical/advanced/attack(mob/living/carbon/M, mob/user)
+ if(..())
+ return TRUE
+ if(M.action_busy)
+ return
+ if (!istype(M, /mob/living/carbon/human))
+ return
-/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M, mob/user)
- if(..())
- return 1
+ var/mob/living/carbon/human/H = M
+ if((H.getBruteLoss() <= 0 || !heal_brute) && (H.getFireLoss() <= 0 || !heal_burn))
+ to_chat(user, SPAN_WARNING("[M] is already at full health!"))
+ return
- if (istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
+ if(!do_after(user, 30, INTERRUPT_NO_NEEDHAND, BUSY_ICON_FRIENDLY, M, INTERRUPT_MOVED, BUSY_ICON_MEDICAL))
+ return
- var/heal_amt = heal_brute
- if(user.skills)
- if(!skillcheck(user, SKILL_MEDICAL, SKILL_MEDICAL_MEDIC)) //untrained marines have a hard time using it
- to_chat(user, SPAN_WARNING("You start fumbling with [src]."))
- if(!do_after(user, 30, INTERRUPT_NO_NEEDHAND, BUSY_ICON_FRIENDLY, M, INTERRUPT_MOVED, BUSY_ICON_MEDICAL))
- return
- heal_amt = 3 //non optimal application means less healing
+ for(var/i in H.limbs)
+ var/obj/limb/affecting = i
+ affecting.remove_all_bleeding(TRUE, TRUE)
- var/obj/limb/affecting = H.get_limb(user.zone_selected)
- if(affecting.surgery_open_stage == 0)
- var/bandaged = affecting.bandage()
+ var/possessive = "[user == M ? "your" : "[M]'s"]"
+ var/possessive_their = "[user == M ? "their" : "[M]'s"]"
+ user.affected_message(M,
+ SPAN_HELPFUL("You clean and seal the wounds on [possessive] limbs with bioglue."),
+ SPAN_HELPFUL("[user] cleans and seals the wounds on your limbs with bioglue."),
+ SPAN_NOTICE("[user] cleans and seals the wounds on [possessive_their] limbs with bioglue."))
+ H.heal_overall_damage(heal_brute, heal_burn, TRUE)
+ use(1)
- if(!bandaged)
- to_chat(user, SPAN_WARNING("The wounds on [M]'s [affecting.display_name] have already been treated."))
- return 1
- else
- var/possessive = "[user == M ? "your" : "[M]'s"]"
- var/possessive_their = "[user == M ? "their" : "[M]'s"]"
- user.affected_message(M,
- SPAN_HELPFUL("You clean and seal the wounds on [possessive] [affecting.display_name] with bioglue."),
- SPAN_HELPFUL("[user] cleans and seals the wounds on your [affecting.display_name] with bioglue."),
- SPAN_NOTICE("[user] cleans and seals the wounds on [possessive_their] [affecting.display_name] with bioglue."))
- if(bandaged)
- H.apply_damage(-heal_amt, BRUTE, affecting)
- use(1)
- else
- if(H.can_be_operated_on()) //Checks if mob is lying down on table for surgery
- if(do_surgery(H, user, src))
- return
- else
- to_chat(user, SPAN_NOTICE("The [affecting.display_name] is cut open, you'll need more than a bandage!"))
+/obj/item/stack/medical/advanced/bruise_pack
+ name = "advanced trauma kit"
+ singular_name = "advanced trauma kit"
+ desc = "An advanced trauma kit for severe injuries."
+ icon_state = "traumakit"
+ heal_brute = 12
+ stack_id = "advanced bruise pack"
/obj/item/stack/medical/advanced/bruise_pack/tajaran
name = "\improper S'rendarr's Hand leaf"
singular_name = "S'rendarr's Hand leaf"
@@ -203,47 +192,8 @@
desc = "An advanced treatment kit for severe burns."
icon_state = "burnkit"
heal_burn = 12
-
- stack_id = "advanced burn kit"
-
-/obj/item/stack/medical/advanced/ointment/attack(mob/living/carbon/M as mob, mob/user as mob)
- if(..())
- return 1
-
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
-
- var/heal_amt = heal_burn
- if(user.skills)
- if(!skillcheck(user, SKILL_MEDICAL, SKILL_MEDICAL_MEDIC)) //untrained marines have a hard time using it
- to_chat(user, SPAN_WARNING("You start fumbling with [src]."))
- if(!do_after(user, 30, INTERRUPT_NO_NEEDHAND, BUSY_ICON_FRIENDLY, M, INTERRUPT_MOVED, BUSY_ICON_MEDICAL))
- return
- heal_amt = 3 //non optimal application means less healing
-
- var/obj/limb/affecting = H.get_limb(user.zone_selected)
-
- if(affecting.surgery_open_stage == 0)
- if(!affecting.salve())
- to_chat(user, SPAN_WARNING("The wounds on [M]'s [affecting.display_name] have already been salved."))
- return 1
- else
- var/possessive = "[user == M ? "your" : "[M]'s"]"
- var/possessive_their = "[user == M ? "their" : "[M]'s"]"
- user.affected_message(M,
- SPAN_HELPFUL("You cover the wounds on [possessive] [affecting.display_name] with regenerative membrane."),
- SPAN_HELPFUL("[user] covers the wounds on your [affecting.display_name] with regenerative membrane."),
- SPAN_NOTICE("[user] covers the wounds on [possessive_their] [affecting.display_name] with regenerative membrane."))
-
- H.apply_damage(-heal_amt, BURN, affecting)
- use(1)
- else
- if(H.can_be_operated_on()) //Checks if mob is lying down on table for surgery
- if(do_surgery(H,user,src))
- return
- else
- to_chat(user, SPAN_NOTICE("The [affecting.display_name] is cut open, you'll need more than a bandage!"))
+ stack_id = "advanced burn kit"
/obj/item/stack/medical/splint
name = "medical splints"
singular_name = "medical splint"
@@ -300,4 +250,4 @@
if(affecting.apply_splints(src, user, M, indestructible_splints)) // Referenced in external organ helpers.
use(1)
- playsound(user, 'sound/handling/splint1.ogg', 25, 1, 2)
\ No newline at end of file
+ playsound(user, 'sound/handling/splint1.ogg', 25, 1, 2)
diff --git a/code/modules/keybindings/setup.dm b/code/modules/keybindings/setup.dm
index f36a3256e5..bed7e8c333 100644
--- a/code/modules/keybindings/setup.dm
+++ b/code/modules/keybindings/setup.dm
@@ -1,8 +1,10 @@
// Set a client's focus to an object and override these procs on that object to let it handle keypresses
/datum/proc/key_down(key, client/user) // Called when a key is pressed down initially
+ SEND_SIGNAL(src, COMSIG_DATUM_KEY_DOWN, key, user)
return
/datum/proc/key_up(key, client/user) // Called when a key is released
+ SEND_SIGNAL(src, COMSIG_DATUM_KEY_UP, key, user)
return
/datum/proc/keyLoop(client/user) // Called once every frame
set waitfor = FALSE
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 002136db0d..6f47216e8e 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm
@@ -161,9 +161,10 @@
var/freeze_time = 5 // 5 for runners, 15 for lurkers
var/freeze_timer_id = TIMER_ID_NULL // Timer to cancel the end freeze if it can be cancelled earlier
- var/windup = FALSE // Is there a do_after before we pounce?
- var/windup_duration = 20 // How long to wind up, if applicable
+ var/windup = TRUE // Is there a do_after before we pounce?
+ var/windup_duration = 0.5 SECONDS // How long to wind up, if applicable
var/windup_interruptable = TRUE // Can the windup be interrupted?
+ var/windup_interrupt_flags = INTERRUPT_INCAPACITATED
var/can_be_shield_blocked = FALSE // Some legacy stuff, self explanatory
var/should_destroy_objects = FALSE // Only used for ravager charge
@@ -174,6 +175,9 @@
var/list/pounce_callbacks = null // Specific callbacks to invoke when a pounce lands on an atom of a specific type
// (note that if a collided atom does not match any of the key types, defaults to the appropriate X_launch_collision proc)
+ var/successful_parry = FALSE
+ var/atom/current_pounce_target
+
/datum/action/xeno_action/activable/pounce/New()
. = ..()
initialize_pounce_pass_flags()
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 9c20aa8a0a..39cb11bb05 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm
@@ -283,13 +283,17 @@
apply_cooldown()
+ cleanup_pounce_target()
+ current_pounce_target = A
+ RegisterSignal(A, COMSIG_KB_HUMAN_PARRY, .proc/handle_parry)
+
if (windup)
if (!windup_interruptable)
X.frozen = TRUE
X.anchored = TRUE
X.update_canmove()
- if (!do_after(X, windup_duration, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
+ if (!do_after(X, windup_duration, windup_interrupt_flags, BUSY_ICON_HOSTILE))
to_chat(X, SPAN_XENODANGER("You cancel your [ability_name]!"))
if (!windup_interruptable)
X.frozen = 0
@@ -316,6 +320,9 @@
LM.spin = FALSE
LM.pass_flags = pounce_pass_flags
LM.collision_callbacks = pounce_callbacks
+ LM.ignore_collision_behaviour = successful_parry
+ RegisterSignal(A, COMSIG_PARENT_QDELETING, .proc/cleanup_pounce_target)
+ RegisterSignal(owner, COMSIG_MOVABLE_POST_LAUNCH, .proc/handle_finish_launch, TRUE)
X.launch_towards(LM) //Victim, distance, speed
@@ -324,6 +331,57 @@
return
+/datum/action/xeno_action/activable/pounce/proc/handle_finish_launch()
+ SIGNAL_HANDLER
+ var/parried = successful_parry
+ var/mob/living/carbon/human/H = current_pounce_target
+
+ cleanup_pounce_target()
+ if(!H || !parried)
+ return
+ if(H.get_active_hand() && H.Adjacent(owner))
+ INVOKE_ASYNC(H, /mob.proc/do_click, owner, list())
+ var/turf/valid_turf
+ var/direction_between = get_dir(owner, H)
+ for(var/dir in GLOB.cardinals)
+ if(dir & direction_between)
+ continue
+
+ var/turf/T = get_step(H, dir)
+ if(LinkBlocked(H, get_turf(H), T, list(H)))
+ continue
+
+ valid_turf = T
+ break
+
+ if(valid_turf)
+ var/turf/prev_turf = get_turf(H)
+ H.Move(valid_turf, get_dir(H, valid_turf))
+ owner.Move(prev_turf, get_dir(owner, prev_turf))
+ return COMPONENT_ABORT_COLLISION_CALLBACKS
+
+/datum/action/xeno_action/activable/pounce/proc/cleanup_pounce_target()
+ SIGNAL_HANDLER
+ if(!current_pounce_target)
+ return
+ successful_parry = FALSE
+ UnregisterSignal(current_pounce_target, list(
+ COMSIG_KB_HUMAN_PARRY,
+ COMSIG_PARENT_QDELETING
+ ))
+ current_pounce_target = null
+
+/datum/action/xeno_action/activable/pounce/proc/handle_parry(var/mob/living/carbon/human/H)
+ SIGNAL_HANDLER
+ if(!owner)
+ return
+
+ successful_parry = TRUE
+ if(owner.launch_metadata)
+ owner.launch_metadata.ignore_collision_behaviour = TRUE
+ UnregisterSignal(H, COMSIG_KB_HUMAN_PARRY)
+ return COMPONENT_KB_ACTIVATED
+
// Massive, customizable spray_acid
/datum/action/xeno_action/activable/spray_acid/use_ability(atom/A)
var/mob/living/carbon/Xenomorph/X = owner
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 8ebdcf55b0..b44eb742ba 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
@@ -32,6 +32,8 @@
plasma_cost = 25
// Pounce config
+
+ windup = FALSE
distance = 5
knockdown = FALSE // Should we knock down the target?
slash = FALSE // Do we slash upon reception?
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/warrior/warrior_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/warrior/warrior_abilities.dm
index 1238bf42c3..b54977b5de 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/warrior/warrior_abilities.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/warrior/warrior_abilities.dm
@@ -30,7 +30,7 @@
// Warrior Lunge
-/datum/action/xeno_action/activable/lunge
+/datum/action/xeno_action/activable/pounce/lunge
name = "Lunge"
action_icon_state = "lunge"
ability_name = "lunge"
@@ -38,9 +38,13 @@
action_type = XENO_ACTION_CLICK
ability_primacy = XENO_PRIMARY_ACTION_2
xeno_cooldown = 100
-
+ plasma_cost = 0
+
// Configurables
- var/grab_range = 6
+ distance = 6
+ knockdown = FALSE
+ freeze_self = FALSE
+
var/click_miss_cooldown = 15
var/twitch_message_cooldown = 0 //apparently this is necessary for a tiny code that makes the lunge message on cooldown not be spammable, doesn't need to be big so 5 will do.
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/warrior/warrior_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/warrior/warrior_powers.dm
index 8926e0bace..2f7a79884c 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/warrior/warrior_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/warrior/warrior_powers.dm
@@ -1,4 +1,4 @@
-/datum/action/xeno_action/activable/lunge/use_ability(atom/A)
+/datum/action/xeno_action/activable/pounce/lunge/use_ability(atom/A)
var/mob/living/carbon/Xenomorph/X = owner
if (!action_cooldown_check())
@@ -7,16 +7,10 @@
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 (!A)
- return
-
if (!isturf(X.loc))
to_chat(X, SPAN_XENOWARNING("You can't lunge from here!"))
return
- if (!X.check_state() || X.agility)
- return
-
if(X.can_not_harm(A) || !ismob(A))
apply_cooldown_override(click_miss_cooldown)
return
@@ -25,15 +19,7 @@
if(H.stat == DEAD)
return
- if (!check_and_use_plasma_owner())
- return
-
- apply_cooldown()
- ..()
-
- X.visible_message(SPAN_XENOWARNING("\The [X] lunges towards [H]!"), SPAN_XENOWARNING("You lunge at [H]!"))
-
- X.throw_atom(get_step_towards(A, X), grab_range, SPEED_FAST, X)
+ . = ..()
if (X.Adjacent(H))
X.start_pulling(H,1)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm
index d23fa913db..d0f28971e9 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm
@@ -188,7 +188,7 @@
if(clear)
var/datum/action/xeno_action/A = get_xeno_action_by_type(src, /datum/action/xeno_action/activable/pounce/lurker)
- A.use_ability_async(get_turf(current_target))
+ A.use_ability_async(current_target)
SSxeno_pathfinding.stop_calculating_path(src)
//stop_calculating_path()
current_path = null
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm
index b0c4d62138..faf67c5c43 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm
@@ -79,6 +79,7 @@
if(pulling && can_move_and_apply_move_delay())
Move(get_step(loc, pull_direction), pull_direction)
+ current_path = null
else
if(!(src in view(world.view, current_target)))
travelling_turf = get_turf(current_target)
@@ -104,7 +105,7 @@
if(clear)
var/datum/action/xeno_action/A = get_xeno_action_by_type(src, /datum/action/xeno_action/activable/pounce)
- A.use_ability_async(get_turf(current_target))
+ A.use_ability_async(current_target)
SSxeno_pathfinding.stop_calculating_path(src)
//stop_calculating_path()
current_path = null
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm b/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm
index a19abb6c8f..03d17b3fdd 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm
@@ -45,7 +45,7 @@
/datum/action/xeno_action/onclick/regurgitate,
/datum/action/xeno_action/watch_xeno,
/datum/action/xeno_action/activable/warrior_punch,
- /datum/action/xeno_action/activable/lunge,
+ /datum/action/xeno_action/activable/pounce/lunge,
/datum/action/xeno_action/activable/fling,
)
@@ -78,6 +78,7 @@ GLOBAL_LIST_INIT(warrior_target_limbs, list(
if(pulling && can_move_and_apply_move_delay())
Move(get_step(loc, turn(dir, 180)), turn(dir, 180))
+ current_path = null
else
var/turf/T = get_turf(current_target)
if(get_dist(src, current_target) <= 1)
@@ -107,7 +108,7 @@ GLOBAL_LIST_INIT(warrior_target_limbs, list(
remove_temp_pass_flags(PASS_OVER_THROW_MOB)
if(clear)
- var/datum/action/xeno_action/A = get_xeno_action_by_type(src, /datum/action/xeno_action/activable/lunge)
+ var/datum/action/xeno_action/A = get_xeno_action_by_type(src, /datum/action/xeno_action/activable/pounce/lunge)
A.use_ability_async(current_target)
SSxeno_pathfinding.stop_calculating_path(src)
//stop_calculating_path()
diff --git a/code/modules/mob/living/carbon/xenomorph/mutators/strains/warrior/boxer.dm b/code/modules/mob/living/carbon/xenomorph/mutators/strains/warrior/boxer.dm
index ee3e4b6b41..b59e531875 100644
--- a/code/modules/mob/living/carbon/xenomorph/mutators/strains/warrior/boxer.dm
+++ b/code/modules/mob/living/carbon/xenomorph/mutators/strains/warrior/boxer.dm
@@ -6,7 +6,7 @@
caste_whitelist = list(XENO_CASTE_WARRIOR)
mutator_actions_to_remove = list(
/datum/action/xeno_action/activable/fling,
- /datum/action/xeno_action/activable/lunge,
+ /datum/action/xeno_action/activable/pounce/lunge,
)
mutator_actions_to_add = list(
/datum/action/xeno_action/activable/jab,
diff --git a/code/modules/movement/launching/launching.dm b/code/modules/movement/launching/launching.dm
index ce8392b51a..644f7bfd67 100644
--- a/code/modules/movement/launching/launching.dm
+++ b/code/modules/movement/launching/launching.dm
@@ -2,6 +2,7 @@
// Parameters
var/pass_flags = NO_FLAGS // Pass flags to add temporarily
var/call_all = FALSE // Whether to perform all callback calls or none of them
+ var/ignore_collision_behaviour = FALSE
var/atom/target
var/range
@@ -53,6 +54,11 @@
if (isnull(launch_metadata))
CRASH("launch_impact called without any stored metadata")
+ if(launch_metadata.ignore_collision_behaviour)
+ throwing = FALSE
+ rebounding = FALSE
+ return
+
var/list/collision_callbacks = launch_metadata.get_collision_callbacks(hit_atom)
if (islist(collision_callbacks))
for(var/datum/callback/CB in collision_callbacks)
@@ -180,8 +186,10 @@
break
sleep(delay)
+ var/result = SEND_SIGNAL(src, COMSIG_MOVABLE_POST_LAUNCH, LM)
+
//done throwing, either because it hit something or it finished moving
- if ((isobj(src) || ismob(src)) && throwing && !early_exit)
+ if (!(result & COMPONENT_ABORT_COLLISION_CALLBACKS) && (isobj(src) || ismob(src)) && throwing && !early_exit)
var/turf/T = get_turf(src)
if(!istype(T))
return