Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/__DEFINES/keybinding.dm
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@
#define COMSIG_KB_XENO_PURCHASE_STRAIN "keybinding_purchase_strain"
#define COMSIG_KB_XENO_RESET_STRAIN "keybinding_reset_strain"
#define COMSIG_KB_XENO_BECOME_SEETHROUGH "keybinding_become_seethrough"
#define COMSIG_KB_XENO_RIP_LIMB "keybinding_rip_limb"

// Yautja

Expand Down
14 changes: 14 additions & 0 deletions code/datums/keybinding/xenomorph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,17 @@
current_xeno.toggle_seethrough()
return TRUE

/datum/keybinding/xenomorph/rip_limb
hotkey_keys = list("Unbound")
classic_keys = list("Unbound")
name = "rip_limb"
full_name = "Rip Limb"
keybind_signal = COMSIG_KB_XENO_RIP_LIMB

/datum/keybinding/xenomorph/rip_limb/down(client/user)
. = ..()
if(.)
return

var/mob/living/carbon/xenomorph/current_xeno = user?.mob
current_xeno.rip_limb()
36 changes: 35 additions & 1 deletion code/modules/mob/living/carbon/xenomorph/XenoProcs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,41 @@

/// Called when pulling something and attacking yourself wth the pull (Z hotkey) override for caste specific behaviour
/mob/living/carbon/xenomorph/proc/pull_power(mob/mob)
return
var/mob/living/carbon/pulled = src.pulling
if(!istype(pulled))
return
if(isxeno(pulled) || issynth(pulled))
to_chat(src, SPAN_WARNING("That wouldn't serve a purpose."))
return
if(pulled.buckled)
to_chat(src, SPAN_WARNING("[pulled] is buckled to something."))
return
if(pulled.stat == DEAD && !pulled.chestburst)
to_chat(src, SPAN_WARNING("Ew, [pulled] is already starting to rot."))
return
if(src.hauled_mob?.resolve()) // We can't carry more than one mob
to_chat(src, SPAN_WARNING("You already are carrying something, there's no way that will work."))
return
if(HAS_TRAIT(pulled, TRAIT_HAULED))
to_chat(src, SPAN_WARNING("They are already being hauled by someone else."))
return
if(src.action_busy)
to_chat(src, SPAN_WARNING("We are already busy with something."))
return
SEND_SIGNAL(src, COMSIG_MOB_EFFECT_CLOAK_CANCEL)
src.visible_message(SPAN_DANGER("[src] starts to restrain [pulled]!"),
SPAN_DANGER("We start restraining [pulled]!"), null, 5)
if(HAS_TRAIT(src, TRAIT_CLOAKED)) //cloaked don't show the visible message, so we gotta work around
to_chat(pulled, FONT_SIZE_HUGE(SPAN_DANGER("[src] is trying to restrain you!")))
if(do_after(src, 50, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE))
if((isxeno(pulled.loc) && !src.hauled_mob) || HAS_TRAIT(pulled, TRAIT_HAULED))
to_chat(src, SPAN_WARNING("Someone already took \the [pulled]."))
return
if(src.pulling == pulled && !pulled.buckled && (pulled.stat != DEAD || pulled.chestburst) && !src.hauled_mob?.resolve()) //make sure you've still got them in your claws, and alive
if(SEND_SIGNAL(pulled, COMSIG_MOB_HAULED, src) & COMPONENT_CANCEL_HAUL)
return FALSE
src.haul(pulled)
src.stop_pulling()

// Vent Crawl
/mob/living/carbon/xenomorph/proc/vent_crawl()
Expand Down
1 change: 0 additions & 1 deletion code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@
var/crest_defense = FALSE
/// 0/FALSE - upright, 1/TRUE - all fours
var/agility = FALSE
var/ripping_limb = FALSE
/// For drones/hivelords. Extends the maximum build range they have
var/extra_build_dist = 0
/// tiles from self you can plant eggs.
Expand Down
84 changes: 0 additions & 84 deletions code/modules/mob/living/carbon/xenomorph/castes/Warrior.dm
Original file line number Diff line number Diff line change
Expand Up @@ -181,90 +181,6 @@
bound_xeno.remove_filter("empower_rage")


/// Warrior specific behaviour for increasing pull power, limb rip.
/mob/living/carbon/xenomorph/warrior/pull_power(mob/mob)
if(!ripping_limb && mob.stat != DEAD)
if(mob.status_flags & XENO_HOST)
to_chat(src, SPAN_XENOWARNING("This would harm the embryo!"))
return
ripping_limb = TRUE
if(rip_limb(mob))
stop_pulling()
ripping_limb = FALSE


/// Warrior Rip Limb - called by pull_power()
/mob/living/carbon/xenomorph/warrior/proc/rip_limb(mob/mob)
if(!istype(mob, /mob/living/carbon/human))
return FALSE

if(action_busy) //can't stack the attempts
return FALSE

var/mob/living/carbon/human/human = mob
var/obj/limb/limb = human.get_limb(check_zone(zone_selected))

if(can_not_harm(human))
to_chat(src, SPAN_XENOWARNING("We can't harm this host!"))
return

if(!limb || limb.body_part == BODY_FLAG_CHEST || limb.body_part == BODY_FLAG_GROIN || (limb.status & LIMB_DESTROYED)) //Only limbs and head.
to_chat(src, SPAN_XENOWARNING("We can't rip off that limb."))
return FALSE

var/limb_time = rand(40,60)
if(limb.body_part == BODY_FLAG_HEAD)
limb_time = rand(90,110)

visible_message(SPAN_XENOWARNING("[src] begins pulling on [mob]'s [limb.display_name] with incredible strength!"),
SPAN_XENOWARNING("We begin to pull on [mob]'s [limb.display_name] with incredible strength!"))

if(!do_after(src, limb_time, INTERRUPT_ALL|INTERRUPT_DIFF_SELECT_ZONE, BUSY_ICON_HOSTILE) || mob.stat == DEAD || mob.status_flags & XENO_HOST)
to_chat(src, SPAN_NOTICE("We stop ripping off the limb."))
return FALSE

if(mob.status_flags & XENO_HOST)
to_chat(src, SPAN_NOTICE("We detect an embryo inside [mob] which overwhelms our instinct to rip."))
return FALSE

if(limb.status & LIMB_DESTROYED)
return FALSE

if(limb.status & (LIMB_ROBOT|LIMB_SYNTHSKIN))
limb.take_damage(rand(30,40), 0, 0) // just do more damage
visible_message(SPAN_XENOWARNING("You hear [mob]'s [limb.display_name] being pulled beyond its load limits!"),
SPAN_XENOWARNING("[mob]'s [limb.display_name] begins to tear apart!"))
else
visible_message(SPAN_XENOWARNING("We hear the bones in [mob]'s [limb.display_name] snap with a sickening crunch!"),
SPAN_XENOWARNING("[mob]'s [limb.display_name] bones snap with a satisfying crunch!"))
limb.take_damage(rand(15,25), 0, 0)
limb.fracture(100)
mob.last_damage_data = create_cause_data(initial(caste_type), src)
src.attack_log += text("\[[time_stamp()]\] <font color='red'>ripped the [limb.display_name] off of [mob.name] ([mob.ckey]) 1/2 progress</font>")
mob.attack_log += text("\[[time_stamp()]\] <font color='orange'>had their [limb.display_name] ripped off by [src.name] ([src.ckey]) 1/2 progress</font>")
log_attack("[src.name] ([src.ckey]) ripped the [limb.display_name] off of [mob.name] ([mob.ckey]) 1/2 progress")

if(!do_after(src, limb_time, INTERRUPT_ALL|INTERRUPT_DIFF_SELECT_ZONE, BUSY_ICON_HOSTILE) || mob.stat == DEAD || iszombie(mob))
to_chat(src, SPAN_NOTICE("We stop ripping off the limb."))
return FALSE

if(mob.status_flags & XENO_HOST)
to_chat(src, SPAN_NOTICE("We detect an embryo inside [mob] which overwhelms our instinct to rip."))
return FALSE

if(limb.status & LIMB_DESTROYED)
return FALSE

visible_message(SPAN_XENOWARNING("[src] rips [mob]'s [limb.display_name] away from their body!"),
SPAN_XENOWARNING("[mob]'s [limb.display_name] rips away from their body!"))
src.attack_log += text("\[[time_stamp()]\] <font color='red'>ripped the [limb.display_name] off of [mob.name] ([mob.ckey]) 2/2 progress</font>")
mob.attack_log += text("\[[time_stamp()]\] <font color='orange'>had their [limb.display_name] ripped off by [src.name] ([src.ckey]) 2/2 progress</font>")
log_attack("[src.name] ([src.ckey]) ripped the [limb.display_name] off of [mob.name] ([mob.ckey]) 2/2 progress")

limb.droplimb(0, 0, initial(name))

return TRUE

/datum/action/xeno_action/activable/lunge/use_ability(atom/affected_atom)
var/mob/living/carbon/xenomorph/lunge_user = owner

Expand Down
85 changes: 85 additions & 0 deletions code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,88 @@

// var/datum/techtree/T = GET_TREE(TREE_XENO)
// T.enter_mob(src)

/mob/living/carbon/xenomorph/verb/rip_limb()
set name = "Rip Limb"
set desc = "Rip off a limb from living pray."
set category = "Alien"

if(caste_type != XENO_CASTE_WARRIOR)
to_chat(src, SPAN_WARNING("Only Warriors can do this!"))
return

if(action_busy) //can't stack the attempts
return

if(!pulling)
to_chat(src, SPAN_XENOWARNING("We need to grab a target first!"))
return

if(!istype(pulling, /mob/living/carbon/human))
to_chat(src, SPAN_XENOWARNING("We prefer to rip off limbs from humanoids!"))
return

var/mob/living/carbon/human/target_human = pulling
var/obj/limb/limb = target_human.get_limb(check_zone(zone_selected))

if(!istype(target_human, /mob/living/carbon/human))
return

if(can_not_harm(target_human))
to_chat(src, SPAN_XENOWARNING("We can't harm this host!"))
return

if(!limb || limb.body_part == BODY_FLAG_CHEST || limb.body_part == BODY_FLAG_GROIN || (limb.status & LIMB_DESTROYED)) //Only limbs and head.
to_chat(src, SPAN_XENOWARNING("We can't rip off that limb."))
return

var/limb_time = rand(40,60)
if(limb.body_part == BODY_FLAG_HEAD)
limb_time = rand(90,110)

visible_message(SPAN_XENOWARNING("[src] begins pulling on [target_human]'s [limb.display_name] with incredible strength!"),
SPAN_XENOWARNING("We begin to pull on [target_human]'s [limb.display_name] with incredible strength!"))

if(!do_after(src, limb_time, INTERRUPT_ALL|INTERRUPT_DIFF_SELECT_ZONE, BUSY_ICON_HOSTILE) || target_human.stat == DEAD || target_human.status_flags & XENO_HOST)
to_chat(src, SPAN_NOTICE("We stop ripping off the limb."))
return

if(target_human.status_flags & XENO_HOST)
to_chat(src, SPAN_NOTICE("We detect an embryo inside [target_human] which overwhelms our instinct to rip."))
return

if(limb.status & LIMB_DESTROYED)
return

if(limb.status & (LIMB_ROBOT|LIMB_SYNTHSKIN))
limb.take_damage(rand(30,40), 0, 0) // just do more damage
visible_message(SPAN_XENOWARNING("You hear [target_human]'s [limb.display_name] being pulled beyond its load limits!"),
SPAN_XENOWARNING("[target_human]'s [limb.display_name] begins to tear apart!"))
else
visible_message(SPAN_XENOWARNING("We hear the bones in [target_human]'s [limb.display_name] snap with a sickening crunch!"),
SPAN_XENOWARNING("[target_human]'s [limb.display_name] bones snap with a satisfying crunch!"))
limb.take_damage(rand(15,25), 0, 0)
limb.fracture(100)
target_human.last_damage_data = create_cause_data(initial(caste_type), src)
src.attack_log += text("\[[time_stamp()]\] <font color='red'>ripped the [limb.display_name] off of [target_human.name] ([target_human.ckey]) 1/2 progress</font>")
target_human.attack_log += text("\[[time_stamp()]\] <font color='orange'>had their [limb.display_name] ripped off by [src.name] ([src.ckey]) 1/2 progress</font>")
log_attack("[src.name] ([src.ckey]) ripped the [limb.display_name] off of [target_human.name] ([target_human.ckey]) 1/2 progress")

if(!do_after(src, limb_time, INTERRUPT_ALL|INTERRUPT_DIFF_SELECT_ZONE, BUSY_ICON_HOSTILE) || target_human.stat == DEAD || iszombie(target_human))
to_chat(src, SPAN_NOTICE("We stop ripping off the limb."))
return

if(target_human.status_flags & XENO_HOST)
to_chat(src, SPAN_NOTICE("We detect an embryo inside [target_human] which overwhelms our instinct to rip."))
return

if(limb.status & LIMB_DESTROYED)
return

visible_message(SPAN_XENOWARNING("[src] rips [target_human]'s [limb.display_name] away from their body!"),
SPAN_XENOWARNING("[target_human]'s [limb.display_name] rips away from their body!"))
src.attack_log += text("\[[time_stamp()]\] <font color='red'>ripped the [limb.display_name] off of [target_human.name] ([target_human.ckey]) 2/2 progress</font>")
target_human.attack_log += text("\[[time_stamp()]\] <font color='orange'>had their [limb.display_name] ripped off by [src.name] ([src.ckey]) 2/2 progress</font>")
log_attack("[src.name] ([src.ckey]) ripped the [limb.display_name] off of [target_human.name] ([target_human.ckey]) 2/2 progress")

limb.droplimb(0, 0, initial(name))
2 changes: 1 addition & 1 deletion code/modules/mob/mob_grab.dm
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
return

if(!ishuman(user)) //only humans can reinforce a grab.
if (isxeno(user))
if(isxeno(user))
var/mob/living/carbon/xenomorph/xeno = user
xeno.pull_power(grabbed_thing)
return
Expand Down
Loading