diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index f224d8cfb2e..e4ce9162048 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1232,6 +1232,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Makes a character be better/worse at defending against tackling depending on their tail's status #define TRAIT_TACKLING_TAILED_DEFENDER "tackling_tailed_defender" +/// Makes a character better at tackling if they have a tail +#define TRAIT_TACKLING_TAILED_POUNCE "tackling_tailed_pounce" + /// Is runechat for this atom/movable currently disabled, regardless of prefs or anything? #define TRAIT_RUNECHAT_HIDDEN "runechat_hidden" diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 2250bc23740..d878633fed4 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -539,6 +539,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SURGICALLY_ANALYZED" = TRAIT_SURGICALLY_ANALYZED, "TRAIT_TACKLING_FRAIL_ATTACKER" = TRAIT_TACKLING_FRAIL_ATTACKER, "TRAIT_TACKLING_TAILED_DEFENDER" = TRAIT_TACKLING_TAILED_DEFENDER, + "TRAIT_TACKLING_TAILED_POUNCE" = TRAIT_TACKLING_TAILED_POUNCE, "TRAIT_TACKLING_WINGED_ATTACKER" = TRAIT_TACKLING_WINGED_ATTACKER, "TRAIT_TACTICALLY_CAMOUFLAGED" = TRAIT_TACTICALLY_CAMOUFLAGED, "TRAIT_TAGGER" = TRAIT_TAGGER, diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 889d7ff01c6..442b70456b4 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -291,6 +291,9 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_SUPERMATTER_SOOTHER" = TRAIT_SUPERMATTER_SOOTHER, "TRAIT_SURGEON" = TRAIT_SURGEON, "TRAIT_SURGICALLY_ANALYZED" = TRAIT_SURGICALLY_ANALYZED, + "TRAIT_TACKLING_FRAIL_ATTACKER" = TRAIT_TACKLING_FRAIL_ATTACKER, + "TRAIT_TACKLING_TAILED_DEFENDER" = TRAIT_TACKLING_TAILED_DEFENDER, + "TRAIT_TACKLING_TAILED_POUNCE" = TRAIT_TACKLING_TAILED_POUNCE, "TRAIT_TAGGER" = TRAIT_TAGGER, "TRAIT_TENTACLE_IMMUNE" = TRAIT_TENTACLE_IMMUNE, "TRAIT_TESLA_SHOCKIMMUNE" = TRAIT_TESLA_SHOCKIMMUNE, diff --git a/code/controllers/subsystem/sprite_accessories.dm b/code/controllers/subsystem/sprite_accessories.dm index 127cd038222..57a7aa1d041 100644 --- a/code/controllers/subsystem/sprite_accessories.dm +++ b/code/controllers/subsystem/sprite_accessories.dm @@ -53,6 +53,7 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity var/list/tails_list_felinid var/list/tails_list_lizard var/list/tails_list_monkey + var/list/tails_list_xeno var/list/tails_list_fish var/list/ears_list var/list/wings_list @@ -129,6 +130,7 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity tails_list_lizard = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard)[DEFAULT_SPRITE_LIST] */ tails_list_monkey = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey)[DEFAULT_SPRITE_LIST] + tails_list_xeno = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/xeno)[DEFAULT_SPRITE_LIST] //tails fo fish organ infusions, not for prefs. tails_list_fish = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/fish)[DEFAULT_SPRITE_LIST] /* diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index d2d91f22920..2ff78f8fa15 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -26,6 +26,9 @@ /datum/bodypart_overlay/mutant/proc/on_mob_insert(obj/item/organ/parent, mob/living/carbon/receiver) SIGNAL_HANDLER + if (isalien(receiver)) + return // Xenomorphs have no dna or other features required to support this, maybe one day + if(!should_visual_organ_apply_to(parent.type, receiver)) stack_trace("adding a [parent.type] to a [receiver.type] when it shouldn't be!") diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index 3ae92c331f0..b2c19f8c6a0 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -106,7 +106,7 @@ RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(checkObstacle)) playsound(user, 'sound/items/weapons/thudswoosh.ogg', 40, TRUE, -1) - var/leap_word = isfeline(user) ? "pounce" : "leap" //If cat, "pounce" instead of "leap". // SKYRAT EDIT - FELINE TRAITS. Was: isfelinid(user) + var/leap_word = isfeline(user) || HAS_TRAIT(user, TRAIT_TACKLING_TAILED_POUNCE) ? "pounce" : "leap" //If cat, "pounce" instead of "leap". // SKYRAT EDIT - FELINE TRAITS. Was: isfelinid(user) if(can_see(user, clicked_atom, 7)) user.visible_message(span_warning("[user] [leap_word]s at [clicked_atom]!"), span_danger("You [leap_word] at [clicked_atom]!")) else @@ -434,6 +434,10 @@ if(HAS_TRAIT(sacker, TRAIT_NOGUNS)) //Those dedicated to martial combat are particularly skilled tacklers attack_mod += 2 + if(HAS_TRAIT(sacker, TRAIT_TACKLING_TAILED_POUNCE)) + var/obj/item/organ/tail/lizard/sacker_tail = sacker.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + attack_mod += sacker_tail ? 2 : -2 + if(HAS_TRAIT(sacker, TRAIT_TACKLING_WINGED_ATTACKER)) var/obj/item/organ/wings/moth/sacker_moth_wing = sacker.get_organ_slot(ORGAN_SLOT_EXTERNAL_WINGS) if(!sacker_moth_wing || sacker_moth_wing.burnt) diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index 980025f94b0..09fd1eff915 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -1825,6 +1825,21 @@ icon_state = "default" color_src = FALSE +/datum/sprite_accessory/tails/xeno + icon_state = "default" + color_src = FALSE + center = TRUE + +/datum/sprite_accessory/tails/xeno/default + name = "Xeno" + icon = 'icons/mob/human/species/alien/tail_xenomorph.dmi' + dimension_x = 40 + +/datum/sprite_accessory/tails/xeno/queen + name = "Xeno Queen" + icon = 'icons/mob/human/species/alien/tail_xenomorph_queen.dmi' + dimension_x = 64 + /datum/sprite_accessory/pod_hair icon = 'icons/mob/human/species/podperson_hair.dmi' em_block = TRUE diff --git a/code/modules/mob/living/carbon/alien/adult/caste/drone.dm b/code/modules/mob/living/carbon/alien/adult/caste/drone.dm index 1664fd77946..8a37e36ab00 100644 --- a/code/modules/mob/living/carbon/alien/adult/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/adult/caste/drone.dm @@ -16,6 +16,7 @@ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/large, ORGAN_SLOT_XENO_RESINSPINNER = /obj/item/organ/alien/resinspinner, ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid, + ORGAN_SLOT_EXTERNAL_TAIL = /obj/item/organ/tail/xeno, ) /mob/living/carbon/alien/adult/drone/Initialize(mapload) diff --git a/code/modules/mob/living/carbon/alien/adult/caste/hunter.dm b/code/modules/mob/living/carbon/alien/adult/caste/hunter.dm index 514cc23caab..c056f663849 100644 --- a/code/modules/mob/living/carbon/alien/adult/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/adult/caste/hunter.dm @@ -15,6 +15,7 @@ ORGAN_SLOT_EARS = /obj/item/organ/ears, ORGAN_SLOT_STOMACH = /obj/item/organ/stomach/alien, ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel/small, + ORGAN_SLOT_EXTERNAL_TAIL = /obj/item/organ/tail/xeno, ) var/atom/movable/screen/leap_icon = null diff --git a/code/modules/mob/living/carbon/alien/adult/caste/praetorian.dm b/code/modules/mob/living/carbon/alien/adult/caste/praetorian.dm index ad46f8d3d7e..7b8cfbf5128 100644 --- a/code/modules/mob/living/carbon/alien/adult/caste/praetorian.dm +++ b/code/modules/mob/living/carbon/alien/adult/caste/praetorian.dm @@ -18,6 +18,7 @@ ORGAN_SLOT_XENO_RESINSPINNER = /obj/item/organ/alien/resinspinner, ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid, ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin, + ORGAN_SLOT_EXTERNAL_TAIL = /obj/item/organ/tail/xeno, ) /mob/living/carbon/alien/adult/royal/praetorian/Initialize(mapload) diff --git a/code/modules/mob/living/carbon/alien/adult/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/adult/caste/sentinel.dm index 0d30f652211..1e8f3b13e78 100644 --- a/code/modules/mob/living/carbon/alien/adult/caste/sentinel.dm +++ b/code/modules/mob/living/carbon/alien/adult/caste/sentinel.dm @@ -17,6 +17,7 @@ ORGAN_SLOT_XENO_PLASMAVESSEL = /obj/item/organ/alien/plasmavessel, ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid, ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin, + ORGAN_SLOT_EXTERNAL_TAIL = /obj/item/organ/tail/xeno, ) /mob/living/carbon/alien/adult/sentinel/Initialize(mapload) diff --git a/code/modules/mob/living/carbon/alien/adult/queen.dm b/code/modules/mob/living/carbon/alien/adult/queen.dm index 8f91674e5c9..4356261fb7e 100644 --- a/code/modules/mob/living/carbon/alien/adult/queen.dm +++ b/code/modules/mob/living/carbon/alien/adult/queen.dm @@ -20,6 +20,8 @@ REMOVE_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) // that'd be a too cheeky shield bashing strat ADD_TRAIT(src, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED, INNATE_TRAIT) + // Lets you spin without falling over + ADD_TRAIT(src, TRAIT_STRENGTH, INNATE_TRAIT) AddComponent(/datum/component/seethrough_mob) /mob/living/carbon/alien/adult/royal/on_lying_down(new_lying_angle) @@ -56,12 +58,12 @@ ORGAN_SLOT_XENO_ACIDGLAND = /obj/item/organ/alien/acid, ORGAN_SLOT_XENO_NEUROTOXINGLAND = /obj/item/organ/alien/neurotoxin, ORGAN_SLOT_XENO_EGGSAC = /obj/item/organ/alien/eggsac, + ORGAN_SLOT_EXTERNAL_TAIL = /obj/item/organ/tail/xeno_queen, ) /mob/living/carbon/alien/adult/royal/queen/Initialize(mapload) var/static/list/innate_actions = list( /datum/action/cooldown/alien/promote, - /datum/action/cooldown/spell/aoe/repulse/xeno, ) grant_actions_by_list(innate_actions) diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm index 55ee105d56c..caa8e4a2043 100644 --- a/code/modules/movespeed/modifiers/mobs.dm +++ b/code/modules/movespeed/modifiers/mobs.dm @@ -180,3 +180,6 @@ /datum/movespeed_modifier/fish_on_water blacklisted_movetypes = MOVETYPES_NOT_TOUCHING_GROUND multiplicative_slowdown = - /turf/open/water::slowdown + +/datum/movespeed_modifier/tail_dragger + multiplicative_slowdown = 4 diff --git a/code/modules/spells/spell_types/aoe_spell/repulse.dm b/code/modules/spells/spell_types/aoe_spell/repulse.dm index c56ffd1180b..453b9475b6c 100644 --- a/code/modules/spells/spell_types/aoe_spell/repulse.dm +++ b/code/modules/spells/spell_types/aoe_spell/repulse.dm @@ -107,6 +107,22 @@ if(iscarbon(cast_on)) var/mob/living/carbon/carbon_caster = cast_on playsound(get_turf(carbon_caster), 'sound/mobs/non-humanoids/hiss/hiss5.ogg', 80, TRUE, TRUE) - carbon_caster.spin(6, 1) + carbon_caster.spin(0.6 SECONDS, 1) + if(isliving(cast_on) && !is_strongman(cast_on)) + addtimer(CALLBACK(src, PROC_REF(after_spin)), 0.6 SECONDS, TIMER_DELETE_ME) return ..() + +/// Returns true if you're strong enough +/datum/action/cooldown/spell/aoe/repulse/xeno/proc/is_strongman(mob/living/owner) + if (HAS_TRAIT(owner, TRAIT_STRENGTH)) + return TRUE + var/strength_level = owner.mind?.get_skill_level(/datum/skill/athletics) + return strength_level >= SKILL_LEVEL_MASTER + +/// You're not strong enough :( +/datum/action/cooldown/spell/aoe/repulse/xeno/proc/after_spin() + if(QDELETED(owner) || is_strongman(owner)) + return + var/mob/living/living_owner = owner + living_owner.Knockdown(5 SECONDS) diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 9e3e592d74a..ddf6a172830 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -91,7 +91,7 @@ /datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, - /datum/surgery_step/manipulate_organs/internal, + /datum/surgery_step/manipulate_organs/any, /datum/surgery_step/close, ) @@ -317,6 +317,13 @@ /datum/surgery_step/manipulate_organs/proc/can_use_organ(obj/item/organ/organ) return FALSE +/datum/surgery_step/manipulate_organs/any + time = 6.4 SECONDS + name = "manipulate organs (hemostat/organ)" + +/datum/surgery_step/manipulate_organs/any/can_use_organ(obj/item/organ/organ) + return TRUE + ///Surgery step for internal organs, like hearts and brains /datum/surgery_step/manipulate_organs/internal time = 6.4 SECONDS diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index de6da43404c..ed0da79ef2e 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -88,7 +88,7 @@ organ_owner.clear_mood_event("tail_regained") - if(type in organ_owner.dna.species.mutant_organs) + if(type in organ_owner.dna?.species.mutant_organs) organ_owner.add_mood_event("tail_lost", /datum/mood_event/tail_lost) organ_owner.add_mood_event("tail_balance_lost", /datum/mood_event/tail_balance_lost) @@ -187,10 +187,9 @@ /obj/item/organ/tail/monkey name = "monkey tail" preference = "feature_monkey_tail" - - bodypart_overlay = /datum/bodypart_overlay/mutant/tail/monkey - + icon_state = "severedmonkeytail" dna_block = null + bodypart_overlay = /datum/bodypart_overlay/mutant/tail/monkey ///Monkey tail bodypart overlay /datum/bodypart_overlay/mutant/tail/monkey @@ -200,6 +199,62 @@ /datum/bodypart_overlay/mutant/tail/monkey/get_global_feature_list() return SSaccessories.tails_list_monkey +/obj/item/organ/tail/xeno + name = "alien tail" + desc = "A long and flexible tail slightly resembling a spine, used by its original owner as both weapon and balance aid." + icon_state = "severedxenotail" + dna_block = null + bodypart_overlay = /datum/bodypart_overlay/mutant/tail/xeno + organ_traits = list(TRAIT_TACKLING_TAILED_POUNCE, TRAIT_FREERUNNING) + +/obj/item/organ/tail/xeno_queen + name = "alien queen's tail" + desc = "An enormous serrated tail, used to deadly effect by its original owner but perhaps too heavy for a human spine." + icon = 'icons/mob/human/species/alien/tail_xenomorph_queen.dmi' + icon_state = "severedqueentail" + w_class = WEIGHT_CLASS_BULKY + slowdown = 2 + item_flags = SLOWS_WHILE_IN_HAND + dna_block = null + bodypart_overlay = /datum/bodypart_overlay/mutant/tail/xeno/queen + /// Our tail whip action + var/datum/action/cooldown/spell/aoe/repulse/xeno/tail_whip + +/obj/item/organ/tail/xeno_queen/Initialize(mapload) + . = ..() + tail_whip = new(src) + +/obj/item/organ/tail/xeno_queen/on_mob_insert(mob/living/carbon/receiver, special, movement_flags) + . = ..() + tail_whip.Grant(receiver) + receiver.add_movespeed_modifier(/datum/movespeed_modifier/tail_dragger) + +/obj/item/organ/tail/xeno_queen/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags) + . = ..() + tail_whip.Remove(organ_owner) + organ_owner.remove_movespeed_modifier(/datum/movespeed_modifier/tail_dragger) + +///Alien tail bodypart overlay +/datum/bodypart_overlay/mutant/tail/xeno + color_source = NONE + feature_key = "tail_xeno" + imprint_on_next_insertion = FALSE + /// We don't want to bother writing this in DNA, just use this appearance + var/default_appearance = "Xeno" + +/datum/bodypart_overlay/mutant/tail/xeno/New() + . = ..() + set_appearance_from_name(default_appearance) + +/datum/bodypart_overlay/mutant/tail/xeno/get_global_feature_list() + return SSaccessories.tails_list_xeno + +/datum/bodypart_overlay/mutant/tail/xeno/randomize_appearance() + set_appearance_from_name(default_appearance) + +/datum/bodypart_overlay/mutant/tail/xeno/queen + default_appearance = "Xeno Queen" + /obj/item/organ/tail/lizard name = "lizard tail" desc = "A severed lizard tail. Somewhere, no doubt, a lizard hater is very pleased with themselves." diff --git a/icons/mob/human/species/alien/bodyparts.dmi b/icons/mob/human/species/alien/bodyparts.dmi index 6fc37963310..34103e2257b 100644 Binary files a/icons/mob/human/species/alien/bodyparts.dmi and b/icons/mob/human/species/alien/bodyparts.dmi differ diff --git a/icons/mob/human/species/alien/tail_xenomorph.dmi b/icons/mob/human/species/alien/tail_xenomorph.dmi new file mode 100644 index 00000000000..545f286e371 Binary files /dev/null and b/icons/mob/human/species/alien/tail_xenomorph.dmi differ diff --git a/icons/mob/human/species/alien/tail_xenomorph_queen.dmi b/icons/mob/human/species/alien/tail_xenomorph_queen.dmi new file mode 100644 index 00000000000..2761c3de057 Binary files /dev/null and b/icons/mob/human/species/alien/tail_xenomorph_queen.dmi differ diff --git a/icons/mob/nonhuman-player/alien.dmi b/icons/mob/nonhuman-player/alien.dmi index db04cdf8674..b9bc395c5e9 100644 Binary files a/icons/mob/nonhuman-player/alien.dmi and b/icons/mob/nonhuman-player/alien.dmi differ