diff --git a/code/__DEFINES/~darkpack/fera/fera.dm b/code/__DEFINES/~darkpack/fera/fera.dm
index 21335a4fa333..c34d6dafc261 100644
--- a/code/__DEFINES/~darkpack/fera/fera.dm
+++ b/code/__DEFINES/~darkpack/fera/fera.dm
@@ -16,6 +16,9 @@
#define BREED_CORAX_HOMID "Corax Homid"
#define BREED_CORVID "Corvid"
+#define BREED_ANANASI_HOMID "Ananasi Homid"
+#define BREED_ARACHNID "Arachnid"
+
#define FEATURE_FERA_FUR_COLOR "fera_fur_color"
#define FEATURE_FERA_HAIR(splat_id) "fera_hair" + splat_id
#define FEATURE_FERA_BODY(splat_id) "fera_body" + splat_id
@@ -37,7 +40,15 @@ GLOBAL_ALIST_INIT(fera_fur_colors, alist(
"green" = "green",
"red" = "red",
"gray" = "gray",
- )
+ ),
+ SPLAT_ANANASI = list(
+ "black" = "black",
+ "blue" = "blue",
+ "red" = "red",
+ "white" = "white",
+ "ginger" = "ginger",
+ "brown" = "brown",
+ ),
))
#define STATUS_EFFECT_DELIRIUM /datum/status_effect/delirium
diff --git a/code/__DEFINES/~darkpack/fera/werewolf_tribe.dm b/code/__DEFINES/~darkpack/fera/werewolf_tribe.dm
index 1d2c927cce83..75b7ddf60ea3 100644
--- a/code/__DEFINES/~darkpack/fera/werewolf_tribe.dm
+++ b/code/__DEFINES/~darkpack/fera/werewolf_tribe.dm
@@ -16,8 +16,18 @@
#define TRIBE_STARGAZERS "Stargazers"
#define TRIBE_BLACK_SPIRAL_DANCERS "Black Spiral Dancers"
+#define TRIBE_SECEAN "Secean"
+#define TRIBE_PLICARE "Plicare"
+#define TRIBE_GADERIN "Gaderin"
+#define TRIBE_AGERE "Agere"
+#define TRIBE_ANOMIA "Anomia"
+#define TRIBE_MALUM "Malum"
+#define TRIBE_KAR "Kar"
+#define TRIBE_AMARI_ALIQUID "Amari Aliquid"
+#define TRIBE_CHYMOS "Chymos"
+
#define TRIBE_LIST_ALL list(TRIBE_RONIN, TRIBE_GALESTALKERS, TRIBE_CHILDREN_OF_GAIA, TRIBE_UKTENA, TRIBE_FIANNA, TRIBE_GET_OF_FENRIS, TRIBE_BLACK_FURIES, TRIBE_SILVER_FANGS, TRIBE_SILENT_STRIDERS, TRIBE_RED_TALONS, TRIBE_STARGAZERS, TRIBE_GLASS_WALKERS, TRIBE_BONE_GNAWERS, TRIBE_SHADOW_LORDS, TRIBE_BLACK_SPIRAL_DANCERS)
#define TRIBE_LIST_GAIA list(TRIBE_GALESTALKERS, TRIBE_CHILDREN_OF_GAIA, TRIBE_UKTENA, TRIBE_FIANNA, TRIBE_GET_OF_FENRIS, TRIBE_BLACK_FURIES, TRIBE_SILVER_FANGS, TRIBE_SILENT_STRIDERS, TRIBE_RED_TALONS, TRIBE_STARGAZERS, TRIBE_GLASS_WALKERS, TRIBE_BONE_GNAWERS, TRIBE_SHADOW_LORDS)
-#define TRIBE_LIST_WYLD list(TRIBE_GALESTALKERS, TRIBE_CHILDREN_OF_GAIA, TRIBE_UKTENA, TRIBE_FIANNA, TRIBE_GET_OF_FENRIS, TRIBE_BLACK_FURIES, TRIBE_SILVER_FANGS, TRIBE_SILENT_STRIDERS, TRIBE_RED_TALONS, TRIBE_STARGAZERS, TRIBE_SHADOW_LORDS)
-#define TRIBE_LIST_WEAVER list(TRIBE_GLASS_WALKERS, TRIBE_BONE_GNAWERS)
-#define TRIBE_LIST_WYRM list(TRIBE_BLACK_SPIRAL_DANCERS)
+#define TRIBE_LIST_WYLD list(TRIBE_GALESTALKERS, TRIBE_CHILDREN_OF_GAIA, TRIBE_UKTENA, TRIBE_FIANNA, TRIBE_GET_OF_FENRIS, TRIBE_BLACK_FURIES, TRIBE_SILVER_FANGS, TRIBE_SILENT_STRIDERS, TRIBE_RED_TALONS, TRIBE_STARGAZERS, TRIBE_SHADOW_LORDS, TRIBE_KAR, TRIBE_AMARI_ALIQUID, TRIBE_CHYMOS)
+#define TRIBE_LIST_WEAVER list(TRIBE_GLASS_WALKERS, TRIBE_BONE_GNAWERS, TRIBE_SECEAN, TRIBE_PLICARE, TRIBE_GADERIN)
+#define TRIBE_LIST_WYRM list(TRIBE_BLACK_SPIRAL_DANCERS, TRIBE_AGERE, TRIBE_ANOMIA, TRIBE_MALUM)
diff --git a/code/__DEFINES/~darkpack/signals_kindred.dm b/code/__DEFINES/~darkpack/signals_kindred.dm
index 2b4f66a68af1..220c5f0a35dd 100644
--- a/code/__DEFINES/~darkpack/signals_kindred.dm
+++ b/code/__DEFINES/~darkpack/signals_kindred.dm
@@ -1,10 +1,11 @@
// This is the new signals file for every signal vampire related in WOD13
// New signals related to vampires and things vampires do should be defined here
-///called in bloodsucking.dm at the end of /mob/living/carbon/human/proc/drinksomeblood
+// WAS called in bloodsucking.dm at the end of /mob/living/carbon/human/proc/drinksomeblood, now
+// handled by a trait check. this could still be useful for other things though so keeping this
#define COMSIG_MOB_VAMPIRE_SUCKED "mob_vampire_sucked"
///vampire suck resisted
- #define COMPONENT_RESIST_VAMPIRE_KISS (1<<0)
+ // #define COMPONENT_RESIST_VAMPIRE_KISS (1<<0)
///baali demons have touched the target, time to apply the effect from daimonion 4
#define COMSIG_BAALI_DEMON_REACHED_TARGET "baali_demon_reached_target"
diff --git a/code/__DEFINES/~darkpack/splats.dm b/code/__DEFINES/~darkpack/splats.dm
index ccdb0ba3296c..61ee0b2208e6 100644
--- a/code/__DEFINES/~darkpack/splats.dm
+++ b/code/__DEFINES/~darkpack/splats.dm
@@ -9,7 +9,8 @@
//#define SPLAT_FERA "splat_fera"
#define SPLAT_GAROU "splat_garou"
#define SPLAT_CORAX "splat_corax"
-#define SPLAT_SHIFTERS list(SPLAT_GAROU, SPLAT_CORAX)
+#define SPLAT_ANANASI "splat_ananasi"
+#define SPLAT_SHIFTERS list(SPLAT_GAROU, SPLAT_CORAX, SPLAT_ANANASI)
#define SPLAT_PRIO_HALFSPLAT 100
#define SPLAT_PRIO_SPLAT 200
diff --git a/code/__DEFINES/~darkpack/traits/declarations.dm b/code/__DEFINES/~darkpack/traits/declarations.dm
index 349c39035373..47e99460f18e 100644
--- a/code/__DEFINES/~darkpack/traits/declarations.dm
+++ b/code/__DEFINES/~darkpack/traits/declarations.dm
@@ -109,6 +109,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_SCARRING_RESISTANT "scarring_resistant"// Temporal scars wont save
/// Stepping on glass shards immunity. Currently used for a couple Garou forms but could be used elsewhere.
#define TRAIT_HARDENED_SOLES "hardened_soles"
+// Splats that resist the affects of The Kiss
+#define TRAIT_RESISTS_KISS "resists_kiss"
#define TRAIT_IN_FRENZY "in_frenzy"
@@ -165,6 +167,14 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_JAMMING_WEAPONS "jamming_weapons"
#define TRAIT_NATURAL "natural"
#define TRAIT_AURA_OF_CONFIDENCE "aura_of_confidence"
+// Fera with no passive healing
+#define TRAIT_NO_PASSIVE_HEALING "no_passive_healing"
+// Wyrmling Kinship gift, per Changing Breeds - Ananasi Gifts - Hatar
+#define TRAIT_WYRMLING_KINSHIP "wyrmling_kinship"
+// Prevents bloodying, made for Groom gift, per Changing Breeds - Ananasi Gifts - Tenere
+#define TRAIT_ALWAYS_CLEAN "always_clean"
+// Blood Of Pain gift, per Changing Breeds - Ananasi Gifts - Hatar
+#define TRAIT_BLOOD_OF_PAIN "blood_of_pain"
/// Mob has had atleast one tooth yanked out while having no method of regenerating it.
#define TRAIT_TOOTH_PULLED "tooth_pulled"
diff --git a/code/__DEFINES/~darkpack/traits/sources.dm b/code/__DEFINES/~darkpack/traits/sources.dm
index 80bfe711b295..e8e8e8ab87fb 100644
--- a/code/__DEFINES/~darkpack/traits/sources.dm
+++ b/code/__DEFINES/~darkpack/traits/sources.dm
@@ -5,6 +5,9 @@
#define GIFT_TRAIT "gift"
+/// Trait given by a fera's Tribe
+#define TRIBE_TRAIT "tribe"
+
#define STAKE_TRAIT "stake"
#define DAMAGE_TRAIT "damage"
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index 5ec60bca7f14..1262115b7acb 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -696,12 +696,14 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_BRAIN_TRAUMA_IMMUNITY" = TRAIT_BRAIN_TRAUMA_IMMUNITY,
"TRAIT_NECROPOLIS_WORSHIP" = TRAIT_NECROPOLIS_WORSHIP,
"TRAIT_ACUTE_HEARING" = TRAIT_ACUTE_HEARING, // DARKPACK EDIT ADD - MERITS_FLAWS - ACUTE SENSE
+ "TRAIT_ALWAYS_CLEAN" = TRAIT_ALWAYS_CLEAN, // DARKPACK EDIT ADD - ANANASI
"TRAIT_ANIMAL_MUSK" = TRAIT_ANIMAL_MUSK, // DARKPACK EDIT ADD - MERITS_FLAWS
"TRAIT_AURA_OF_CONFIDENCE" = TRAIT_AURA_OF_CONFIDENCE, // DARKPACK EDIT ADD - WEREWOLF
"TRAIT_BANNED_TRANSFORMATION" = TRAIT_BANNED_TRANSFORMATION, // DARKPACK EDIT ADD - MERITS_FLAWS
"TRAIT_BEACON_OF_THE_UNHOLY" = TRAIT_BEACON_OF_THE_UNHOLY, // DARKPACK EDIT ADD - MERITS_FLAWS
"TRAIT_BETRAYERS_MARK" = TRAIT_BETRAYERS_MARK, // DARKPACK EDIT ADD - MERITS_FLAWS - (Tremere)
"TRAIT_BLOODY_LOVER" = TRAIT_BLOODY_LOVER, // DARKPACK EDIT ADD
+ "TRAIT_BLOOD_OF_PAIN" = TRAIT_BLOOD_OF_PAIN, // DARKPACK EDIT ADD - ANANASI
"TRAIT_BLOODY_SUCKER" = TRAIT_BLOODY_SUCKER, // DARKPACK EDIT ADD
"TRAIT_BLUSH_OF_HEALTH" = TRAIT_BLUSH_OF_HEALTH, // DARKPACK EDIT ADD
"TRAIT_BOND_WITHIN_THE_MOUNTAIN" = TRAIT_BOND_WITHIN_THE_MOUNTAIN, // DARKPACK EDIT ADD - POWERS - (Visceratika)
@@ -765,6 +767,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_NO_CUFF" = TRAIT_NO_CUFF, // DARKPACK EDIT ADD
"TRAIT_NO_EYE_CONTACT" = TRAIT_NO_EYE_CONTACT, // DARKPACK EDIT ADD
"TRAIT_NO_LYING_ANGLE" = TRAIT_NO_LYING_ANGLE, // DARKPACK EDIT ADD - WEREWOLF
+ "TRAIT_NO_PASSIVE_HEALING" = TRAIT_NO_PASSIVE_HEALING, // DARKPACK EDIT ADD - WEREWOLF - (Ananasi)
"TRAIT_OBFUSCATED" = TRAIT_OBFUSCATED, // DARKPACK EDIT ADD
"TRAIT_OPENS_MOONGATES" = TRAIT_OPENS_MOONGATES, // DARKPACK EDIT ADD - WEREWOLF
"TRAIT_ORGANOVORE" = TRAIT_ORGANOVORE, // DARKPACK EDIT ADD - Nagaraja
@@ -779,6 +782,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_RAZOR_CLAWS" = TRAIT_RAZOR_CLAWS, // DARKPACK EDIT ADD - WEREWOLF
"TRAIT_REJECTED_BY_TECHNOLOGY" = TRAIT_REJECTED_BY_TECHNOLOGY, // DARKPACK EDIT ADD
"TRAIT_REPELLED_BY_HOLINESS" = TRAIT_REPELLED_BY_HOLINESS, // DARKPACK EDIT ADD
+ "TRAIT_RESISTS_KISS" = TRAIT_RESISTS_KISS, // DARKPACK EDIT ADD
"TRAIT_RUBICON" = TRAIT_RUBICON, // DARKPACK EDIT ADD
"TRAIT_SANGUINE_INCONGRUITY" = TRAIT_SANGUINE_INCONGRUITY, // DARKPACK EDIT ADD - Giovanni Quirk
"TRAIT_SCARRING_RESISTANT" = TRAIT_SCARRING_RESISTANT, // DARKPACK EDIT ADD
@@ -814,6 +818,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_WEAK_DELIRIUM" = TRAIT_WEAK_DELIRIUM, // DARKPACK EDIT ADD - WEREWOLF - (corax)
"TRAIT_WEAK_TO_DOMINATE" = TRAIT_WEAK_TO_DOMINATE, // DARKPACK EDIT ADD - POWERS - (Dominate)
"TRAIT_WEAK_WILLED" = TRAIT_WEAK_WILLED, // DARKPACK EDIT ADD - MERITS_FLAWS
+ "TRAIT_WYRMLING_KINSHIP" = TRAIT_WYRMLING_KINSHIP, // DARKPACK EDIT ADD - ANANASI
"TRAIT_WYRMTAINTED" = TRAIT_WYRMTAINTED, // DARKPACK EDIT ADD - WEREWOLF
"TRAIT_WYRMTAINTED_SPRITE" = TRAIT_WYRMTAINTED_SPRITE, // DARKPACK EDIT ADD - WEREWOLF
"TRAIT_ANTHROPIC_TASTE" = TRAIT_ANTHROPIC_TASTE, //DARKPACK EDIT ADD - MERITS_FLAWS
diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm
index 72ddcc7edcc1..123f35a96990 100644
--- a/code/_globalvars/traits/admin_tooling.dm
+++ b/code/_globalvars/traits/admin_tooling.dm
@@ -368,11 +368,13 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_RIGHT_EYE_SCAR" = TRAIT_RIGHT_EYE_SCAR,
"TRAIT_CARPOTOXIN_IMMUNE" = TRAIT_CARPOTOXIN_IMMUNE,
"TRAIT_ACUTE_HEARING" = TRAIT_ACUTE_HEARING, // DARKPACK EDIT ADD - MERITS_FLAWS - ACUTE SENSE
+ "TRAIT_ALWAYS_CLEAN" = TRAIT_ALWAYS_CLEAN, // DARKPACK EDIT ADD - ANANASI
"TRAIT_ANIMAL_MUSK" = TRAIT_ANIMAL_MUSK, // DARKPACK EDIT ADD - MERITS_FLAWS
"TRAIT_AURA_OF_CONFIDENCE" = TRAIT_AURA_OF_CONFIDENCE, // DARKPACK EDIT ADD - WEREWOLF
"TRAIT_BANNED_TRANSFORMATION" = TRAIT_BANNED_TRANSFORMATION, // DARKPACK EDIT ADD - MERITS_FLAWS
"TRAIT_BEACON_OF_THE_UNHOLY" = TRAIT_BEACON_OF_THE_UNHOLY, // DARKPACK EDIT ADD - MERITS_FLAWS
"TRAIT_BLOODY_LOVER" = TRAIT_BLOODY_LOVER, // DARKPACK EDIT ADD
+ "TRAIT_BLOOD_OF_PAIN" = TRAIT_BLOOD_OF_PAIN, // DARKPACK EDIT ADD - ANANASI
"TRAIT_BLOODY_SUCKER" = TRAIT_BLOODY_SUCKER, // DARKPACK EDIT ADD
"TRAIT_BLUSH_OF_HEALTH" = TRAIT_BLUSH_OF_HEALTH, // DARKPACK EDIT ADD
"TRAIT_CALM_HEART" = TRAIT_CALM_HEART, // DARKPACK EDIT ADD - MERITS_FLAWS
@@ -427,6 +429,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_NO_CUFF" = TRAIT_NO_CUFF, // DARKPACK EDIT ADD
"TRAIT_NO_EYE_CONTACT" = TRAIT_NO_EYE_CONTACT, // DARKPACK EDIT ADD
"TRAIT_NO_LYING_ANGLE" = TRAIT_NO_LYING_ANGLE, // DARKPACK EDIT ADD - WEREWOLF
+ "TRAIT_NO_PASSIVE_HEALING" = TRAIT_NO_PASSIVE_HEALING, // DARKPACK EDIT ADD - WEREWOLF - (Ananasi)
"TRAIT_OBFUSCATED" = TRAIT_OBFUSCATED, // DARKPACK EDIT ADD
"TRAIT_OPENS_MOONGATES" = TRAIT_OPENS_MOONGATES, // DARKPACK EDIT ADD - WEREWOLF
"TRAIT_PAINFUL_VAMPIRE_KISS" = TRAIT_PAINFUL_VAMPIRE_KISS, // DARKPACK EDIT ADD
@@ -466,6 +469,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_WEAK_DELIRIUM" = TRAIT_WEAK_DELIRIUM, // DARKPACK EDIT ADD - WEREWOLF - (corax)
"TRAIT_WEAK_TO_DOMINATE" = TRAIT_WEAK_TO_DOMINATE, // DARKPACK EDIT ADD - POWERS - (Dominate)
"TRAIT_WEAK_WILLED" = TRAIT_WEAK_WILLED, // DARKPACK EDIT ADD - MERITS_FLAWS
+ "TRAIT_WYRMLING_KINSHIP" = TRAIT_WYRMLING_KINSHIP, // DARKPACK EDIT ADD - ANANASI
"TRAIT_WYRMTAINTED" = TRAIT_WYRMTAINTED, // DARKPACK EDIT ADD - WEREWOLF
"TRAIT_WYRMTAINTED_SPRITE" = TRAIT_WYRMTAINTED_SPRITE, // DARKPACK EDIT ADD - WEREWOLF
),
diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm
index daa4bbd164a7..0c1172d85f68 100644
--- a/code/datums/components/bloodysoles.dm
+++ b/code/datums/components/bloodysoles.dm
@@ -239,7 +239,7 @@
return
/// The character is agile enough to not mess their clothing and hands just from one blood splatter at floor
- if(HAS_TRAIT(wielder, TRAIT_LIGHT_STEP))
+ if(HAS_TRAIT(wielder, TRAIT_LIGHT_STEP) || HAS_TRAIT(wielder, TRAIT_ALWAYS_CLEAN)) // APOC EDIT CHANGE - (#139 Ananasi)
return
// Don't share from other feetprints, not super realistic but I think it ruins the effect a bit
diff --git a/code/modules/forensics/forensics_helpers.dm b/code/modules/forensics/forensics_helpers.dm
index f72e0e75ab18..77d5d753ef48 100644
--- a/code/modules/forensics/forensics_helpers.dm
+++ b/code/modules/forensics/forensics_helpers.dm
@@ -190,6 +190,8 @@
)
if(QDELING(src))
return FALSE
+ if(HAS_TRAIT(src, TRAIT_ALWAYS_CLEAN)) // APOC EDIT CHANGE - (#139 Ananasi)
+ return FALSE
if(!length(blood_DNA_to_add))
return FALSE
@@ -237,6 +239,8 @@
/mob/living/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases)
if(QDELING(src))
return FALSE
+ if(HAS_TRAIT(src, TRAIT_ALWAYS_CLEAN)) // APOC EDIT CHANGE - (#139 Ananasi)
+ return FALSE
if(!length(blood_DNA_to_add))
return FALSE
if(isnull(forensics))
diff --git a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm
index 10db1405eeac..bccac6c0dbcd 100644
--- a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm
+++ b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spiders.dm
@@ -596,3 +596,9 @@
AddElement(/datum/element/pet_bonus, "chitter")
AddElement(/datum/element/ai_retaliate)
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+
+// Ananasi Subtype
+/mob/living/basic/spider/giant/arachnid
+ name = "spider"
+ desc = "Furry and black, it makes you shudder to look at it."
+ speak_emote = list("hiss")
diff --git a/config/darkpack_config.txt b/config/darkpack_config.txt
index 20ac46815817..7f29fc46884a 100644
--- a/config/darkpack_config.txt
+++ b/config/darkpack_config.txt
@@ -50,6 +50,18 @@ ROUNDSTART_SPLATS splat_ghoul
ROUNDSTART_SPLATS splat_kinfolk
ROUNDSTART_SPLATS splat_garou
ROUNDSTART_SPLATS splat_corax
+ROUNDSTART_SPLATS splat_ananasi
+
+#WHITELISTED_SPLATS splat_garou
+#WHITELISTED_SPLATS splat_corax
+
+#WHITELISTED_CLANS baali
+#WHITELISTED_CLANS healer_salubri
+#WHITELISTED_CLANS warrior_salubri
+#WHITELISTED_CLANS true_brujah
+#WHITELISTED_CLANS cappadocian
+#WHITELISTED_CLANS harbinger
+
#WHITELISTED_SPLATS splat_garou
#WHITELISTED_SPLATS splat_corax
diff --git a/modular_darkpack/master_files/code/modules/mob/living/carbon/human/species_types/zombies.dm b/modular_darkpack/master_files/code/modules/mob/living/carbon/human/species_types/zombies.dm
index 8544be718970..fd358863e301 100644
--- a/modular_darkpack/master_files/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/modular_darkpack/master_files/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -13,7 +13,8 @@
TRAIT_NOBREATH,
TRAIT_TOXIMMUNE,
TRAIT_NOCRITDAMAGE,
- TRAIT_FAKEDEATH
+ TRAIT_FAKEDEATH,
+ TRAIT_RESISTS_KISS
)
//mutantbrain = /obj/item/organ/brain/vampire //to prevent brain transplant surgery
//mutanteyes = /obj/item/organ/eyes/night_vision/zombie
@@ -34,18 +35,7 @@
C.maxHealth = 300 //tanky
C.health = 300
- //zombies resist vampire bites better than mortals
- RegisterSignal(C, COMSIG_MOB_VAMPIRE_SUCKED, PROC_REF(on_zombie_bitten))
ADD_TRAIT(C, TRAIT_MASQUERADE_VIOLATING_FACE, "zombie")
-/datum/species/zombie/proc/on_zombie_bitten(datum/source, mob/living/carbon/being_bitten)
- SIGNAL_HANDLER
-
- return COMPONENT_RESIST_VAMPIRE_KISS
-
-/datum/species/zombie/on_species_loss(mob/living/carbon/human/human, datum/species/new_species, pref_load)
- . = ..()
- UnregisterSignal(human, COMSIG_MOB_VAMPIRE_SUCKED)
*/
-
#undef REGENERATION_DELAY
diff --git a/modular_darkpack/modules/blood_drinking/code/drinksomeblood.dm b/modular_darkpack/modules/blood_drinking/code/drinksomeblood.dm
index 86e13b1e75f1..0f252e68c53a 100644
--- a/modular_darkpack/modules/blood_drinking/code/drinksomeblood.dm
+++ b/modular_darkpack/modules/blood_drinking/code/drinksomeblood.dm
@@ -43,7 +43,7 @@
if(!do_after(src, 3 SECONDS, target = drunk_from, timed_action_flags = NONE, show_progress = FALSE))
remove_drinking_overlay(drunk_from)
- if(!(SEND_SIGNAL(drunk_from, COMSIG_MOB_VAMPIRE_SUCKED, drunk_from) & COMPONENT_RESIST_VAMPIRE_KISS))
+ if(get_kindred_splat(src) && !HAS_TRAIT(src, TRAIT_PAINFUL_VAMPIRE_KISS) && !HAS_TRAIT(drunk_from, TRAIT_RESISTS_KISS))
drunk_from.apply_status_effect(/datum/status_effect/kissed)
return
@@ -74,6 +74,17 @@
remove_drinking_overlay(drunk_from)
return
+ if(get_ananasi_splat(drunk_from))
+ to_chat(src, span_userdanger("Something is WRONG with [drunk_from]'s blood!"))
+ visible_message(span_danger("[src] throws up!"), span_userdanger("You throw up!"))
+ playsound(get_turf(src), 'modular_darkpack/modules/deprecated/sounds/vomit.ogg', 75, TRUE)
+ if(isturf(loc))
+ add_splatter_floor(loc)
+ remove_drinking_overlay(drunk_from)
+ if(HAS_TRAIT(drunk_from, TRAIT_BLOOD_OF_PAIN))
+ apply_status_effect(/datum/status_effect/blood_of_pain)
+ return
+
if(get_kindred_splat(drunk_from))
to_chat(src, span_userdanger("[drunk_from]'s blood tastes HEAVENLY..."))
adjust_brute_loss(-25, TRUE)
diff --git a/modular_darkpack/modules/blood_drinking/code/vamp_bite.dm b/modular_darkpack/modules/blood_drinking/code/vamp_bite.dm
index eb42ed870a9b..202eb403f535 100644
--- a/modular_darkpack/modules/blood_drinking/code/vamp_bite.dm
+++ b/modular_darkpack/modules/blood_drinking/code/vamp_bite.dm
@@ -6,10 +6,15 @@
if(grab_state > GRAB_PASSIVE)
if(isliving(pulling))
var/mob/living/bit_living = pulling
- if(!get_vampire_splat(src))
+ if(!get_vampire_splat(src) && !get_ananasi_splat(src))
SEND_SOUND(src, sound('modular_darkpack/modules/blood_drinking/sounds/need_blood.ogg', volume = 75))
to_chat(src, span_warning("You're not desperate enough to try that."))
return
+ if(get_ananasi_splat(src))
+ if(get_kindred_splat(bit_living))
+ SEND_SOUND(src, sound('modular_darkpack/modules/blood_drinking/sounds/need_blood.ogg', volume = 75))
+ to_chat(src, span_warning("This BLOOD is toxic to you!"))
+ return
// Allow ghouls to steal viate?
if(get_ghoul_splat(src))
if(!get_kindred_splat(bit_living))
@@ -78,7 +83,9 @@
if(get_kindred_splat(src))
bit_living.emote("groan")
- else if(get_ghoul_splat(src))
+ if(get_ghoul_splat(src))
+ bit_living.emote("scream")
+ if(get_ananasi_splat(src))
bit_living.emote("scream")
if(ishuman(bit_living))
diff --git a/modular_darkpack/modules/jobs/code/anarchs/bruiser.dm b/modular_darkpack/modules/jobs/code/anarchs/bruiser.dm
index cb5f2d547614..9672138dd9d2 100644
--- a/modular_darkpack/modules/jobs/code/anarchs/bruiser.dm
+++ b/modular_darkpack/modules/jobs/code/anarchs/bruiser.dm
@@ -32,7 +32,8 @@
JOB_BRUISER
)
allowed_clans = list(VAMPIRE_CLAN_DAUGHTERS_OF_CACOPHONY, VAMPIRE_CLAN_TRUE_BRUJAH, VAMPIRE_CLAN_BRUJAH, VAMPIRE_CLAN_NOSFERATU, VAMPIRE_CLAN_GANGREL, VAMPIRE_CLAN_CITY_GANGREL, VAMPIRE_CLAN_TOREADOR, VAMPIRE_CLAN_TREMERE, VAMPIRE_CLAN_MALKAVIAN, VAMPIRE_CLAN_BANU_HAQIM, VAMPIRE_CLAN_TZIMISCE, VAMPIRE_CLAN_CAITIFF, VAMPIRE_CLAN_VENTRUE, VAMPIRE_CLAN_LASOMBRA, VAMPIRE_CLAN_GARGOYLE, VAMPIRE_CLAN_KIASYD, VAMPIRE_CLAN_CAPPADOCIAN, VAMPIRE_CLAN_SETITE, VAMPIRE_CLAN_HEALER_SALUBRI, VAMPIRE_CLAN_SAMEDI, VAMPIRE_CLAN_NAGARAJA)
- allowed_splats = list(SPLAT_KINDRED, SPLAT_GHOUL)
+ allowed_splats = list(SPLAT_KINDRED, SPLAT_GHOUL, SPLAT_ANANASI)
+ splat_slots = list(SPLAT_ANANASI = 1)
maximal_generation = 9
maximum_immortal_age = 200
description = "You are the enforcer of the Anarchs. The baron is always in need of muscle power. Enforce the Traditions - in the anarch way."
diff --git a/modular_darkpack/modules/jobs/code/anarchs/tapster.dm b/modular_darkpack/modules/jobs/code/anarchs/tapster.dm
index 3efc62832d99..0fb46823c061 100644
--- a/modular_darkpack/modules/jobs/code/anarchs/tapster.dm
+++ b/modular_darkpack/modules/jobs/code/anarchs/tapster.dm
@@ -32,8 +32,8 @@
JOB_SWEEPER,
JOB_TAPSTER
)
- allowed_splats = list(SPLAT_NONE, SPLAT_GHOUL)
- splat_slots = list(SPLAT_NONE = 2, SPLAT_GHOUL = 2)
+ allowed_splats = list(SPLAT_NONE, SPLAT_GHOUL, SPLAT_ANANASI)
+ splat_slots = list(SPLAT_NONE = 2, SPLAT_GHOUL = 2, SPLAT_ANANASI = 1)
description = "You are an employee of the local smoke shop. Serve the eclectic clients that pass through, and try not to ask too many questions." // APOC EDIT CHANGE - JOBS
minimum_masquerade = 0
diff --git a/modular_darkpack/modules/jobs/code/camarilla/hound.dm b/modular_darkpack/modules/jobs/code/camarilla/hound.dm
index 0ae7d3792e9a..4b20e39c3b28 100644
--- a/modular_darkpack/modules/jobs/code/camarilla/hound.dm
+++ b/modular_darkpack/modules/jobs/code/camarilla/hound.dm
@@ -19,8 +19,9 @@
maximal_generation = 9
maximum_immortal_age = 200
minimum_masquerade = 3
- allowed_splats = list(SPLAT_KINDRED, SPLAT_GHOUL)
+ allowed_splats = list(SPLAT_KINDRED, SPLAT_GHOUL, SPLAT_ANANASI)
allowed_clans = list(VAMPIRE_CLAN_TRUE_BRUJAH, VAMPIRE_CLAN_DAUGHTERS_OF_CACOPHONY, VAMPIRE_CLAN_BRUJAH, VAMPIRE_CLAN_TREMERE, VAMPIRE_CLAN_VENTRUE, VAMPIRE_CLAN_NOSFERATU, VAMPIRE_CLAN_GANGREL, VAMPIRE_CLAN_CITY_GANGREL, VAMPIRE_CLAN_TOREADOR, VAMPIRE_CLAN_MALKAVIAN, VAMPIRE_CLAN_DOMINATE_MALKAVIAN, VAMPIRE_CLAN_BANU_HAQIM, VAMPIRE_CLAN_BANU_HAQIM_VIZIER, VAMPIRE_CLAN_TLACIQUE, VAMPIRE_CLAN_LASOMBRA, VAMPIRE_CLAN_GARGOYLE, VAMPIRE_CLAN_KIASYD, VAMPIRE_CLAN_CAPPADOCIAN, VAMPIRE_CLAN_TZIMISCE, VAMPIRE_CLAN_SAMEDI, VAMPIRE_CLAN_NAGARAJA)
+ splat_slots = list(SPLAT_ANANASI = 1)
known_contacts = list(
JOB_PRINCE,
diff --git a/modular_darkpack/modules/jobs/code/camarilla/tower_employee.dm b/modular_darkpack/modules/jobs/code/camarilla/tower_employee.dm
index 7fde64e27b32..5325932603ef 100644
--- a/modular_darkpack/modules/jobs/code/camarilla/tower_employee.dm
+++ b/modular_darkpack/modules/jobs/code/camarilla/tower_employee.dm
@@ -30,8 +30,9 @@
JOB_HOUND,
JOB_TOWERWORK
)
- allowed_splats = list(SPLAT_NONE, SPLAT_GHOUL, SPLAT_KINDRED)
+ allowed_splats = list(SPLAT_NONE, SPLAT_GHOUL, SPLAT_KINDRED, SPLAT_ANANASI)
allowed_clans = list(VAMPIRE_CLAN_TRUE_BRUJAH, VAMPIRE_CLAN_DAUGHTERS_OF_CACOPHONY, VAMPIRE_CLAN_BRUJAH, VAMPIRE_CLAN_TREMERE, VAMPIRE_CLAN_VENTRUE, VAMPIRE_CLAN_NOSFERATU, VAMPIRE_CLAN_GANGREL, VAMPIRE_CLAN_CITY_GANGREL, VAMPIRE_CLAN_TOREADOR, VAMPIRE_CLAN_MALKAVIAN, VAMPIRE_CLAN_DOMINATE_MALKAVIAN, VAMPIRE_CLAN_BANU_HAQIM, VAMPIRE_CLAN_BANU_HAQIM_VIZIER, VAMPIRE_CLAN_SETITE, VAMPIRE_CLAN_TLACIQUE, VAMPIRE_CLAN_LASOMBRA, VAMPIRE_CLAN_GARGOYLE, VAMPIRE_CLAN_KIASYD, VAMPIRE_CLAN_CAPPADOCIAN, VAMPIRE_CLAN_TZIMISCE, VAMPIRE_CLAN_SAMEDI, VAMPIRE_CLAN_NAGARAJA)
+ splat_slots = list(SPLAT_ANANASI = 1)
description = "You work directly for the Millenium Tower and its administrative staff in a variety of ways, you may even be a personal retainer of one of the top three, to the point that any oddities that you may see over night or hear are either things you are already aware or you simply laugh them off and try not to think about it."
minimum_masquerade = 4
diff --git a/modular_darkpack/modules/jobs/code/clinic/doctor.dm b/modular_darkpack/modules/jobs/code/clinic/doctor.dm
index ed866624d632..795fdb8815aa 100644
--- a/modular_darkpack/modules/jobs/code/clinic/doctor.dm
+++ b/modular_darkpack/modules/jobs/code/clinic/doctor.dm
@@ -22,7 +22,6 @@
description = "Help your fellow kindred in all matters medicine related. Sell blood. Keep your human colleagues ignorant."
maximal_generation = 9
maximum_immortal_age = 200
- allowed_splats = list(SPLAT_KINDRED, SPLAT_GHOUL, SPLAT_KINFOLK, SPLAT_NONE)
allowed_clans = list(VAMPIRE_CLAN_DAUGHTERS_OF_CACOPHONY, VAMPIRE_CLAN_HEALER_SALUBRI, VAMPIRE_CLAN_BAALI, VAMPIRE_CLAN_BRUJAH, VAMPIRE_CLAN_TREMERE, VAMPIRE_CLAN_VENTRUE, VAMPIRE_CLAN_VENTRUE_ANTITRIBU, VAMPIRE_CLAN_NOSFERATU, VAMPIRE_CLAN_GANGREL, VAMPIRE_CLAN_CITY_GANGREL, VAMPIRE_CLAN_TOREADOR, VAMPIRE_CLAN_MALKAVIAN, VAMPIRE_CLAN_DOMINATE_MALKAVIAN, VAMPIRE_CLAN_BANU_HAQIM, VAMPIRE_CLAN_BANU_HAQIM_VIZIER, VAMPIRE_CLAN_GIOVANNI, VAMPIRE_CLAN_SETITE, VAMPIRE_CLAN_TLACIQUE, VAMPIRE_CLAN_TZIMISCE, VAMPIRE_CLAN_LASOMBRA, VAMPIRE_CLAN_CAITIFF, VAMPIRE_CLAN_KIASYD, VAMPIRE_CLAN_NAGARAJA)
known_contacts = list("Clinic Director")
diff --git a/modular_darkpack/modules/jobs/code/miscelllaneous/club_worker.dm b/modular_darkpack/modules/jobs/code/miscelllaneous/club_worker.dm
index cb42c6c94141..e35a7785a6c6 100644
--- a/modular_darkpack/modules/jobs/code/miscelllaneous/club_worker.dm
+++ b/modular_darkpack/modules/jobs/code/miscelllaneous/club_worker.dm
@@ -26,8 +26,6 @@
"Club Attendant"
)
- allowed_splats = list(SPLAT_KINDRED, SPLAT_GHOUL, SPLAT_KINFOLK, SPLAT_NONE)
-
maximal_generation = 9
maximum_immortal_age = 200
description = "Offer strip club services. Some of your clientele may be... Unusual, but you are either addicted to vampire bites, or bribed to listen little and say even less."
diff --git a/modular_darkpack/modules/jobs/code/supply/dealer.dm b/modular_darkpack/modules/jobs/code/supply/dealer.dm
index 146f53afdc14..4f9e47f1e359 100644
--- a/modular_darkpack/modules/jobs/code/supply/dealer.dm
+++ b/modular_darkpack/modules/jobs/code/supply/dealer.dm
@@ -25,7 +25,6 @@
JOB_HARPY,
JOB_EMISSARY
)
- allowed_splats = list(SPLAT_KINDRED, SPLAT_GHOUL, SPLAT_GAROU, SPLAT_NONE)
splat_slots = list(SPLAT_NONE = 1)
description = "You provide both legal and illegal supplies to those that get busy during the night. You are your own person yet you know people are out for you. Time to buckle in..."
minimum_masquerade = 0
diff --git a/modular_darkpack/modules/vampire_the_masquerade/code/splats/kindred_splat/kindred_splat.dm b/modular_darkpack/modules/vampire_the_masquerade/code/splats/kindred_splat/kindred_splat.dm
index d970cc1fcc0b..784ab18f878f 100644
--- a/modular_darkpack/modules/vampire_the_masquerade/code/splats/kindred_splat/kindred_splat.dm
+++ b/modular_darkpack/modules/vampire_the_masquerade/code/splats/kindred_splat/kindred_splat.dm
@@ -18,6 +18,7 @@
TRAIT_DRINKS_BLOOD,
TRAIT_PALE_AURA,
TRAIT_SCARRING_RESISTANT,
+ TRAIT_RESISTS_KISS,
)
splat_actions = list(
/datum/action/cooldown/mob_cooldown/give_vitae,
@@ -73,9 +74,6 @@
//vampires don't die while in crit, they just slip into torpor after 2 minutes of being critted
RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(handle_enter_critical_condition))
- //vampires resist vampire bites better than mortals
- RegisterSignal(owner, COMSIG_MOB_VAMPIRE_SUCKED, PROC_REF(on_vampire_bitten))
-
// Apply bashing damage resistance
RegisterSignal(owner, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(damage_resistance))
@@ -110,7 +108,6 @@
UnregisterSignal(owner, list(
COMSIG_CARBON_LOSE_ORGAN,
COMSIG_MOB_STATCHANGE,
- COMSIG_MOB_VAMPIRE_SUCKED,
COMSIG_MOB_APPLY_DAMAGE_MODIFIERS,
COMSIG_HUMAN_ON_HANDLE_BLOOD,
COMSIG_PATH_HIT,
@@ -207,13 +204,11 @@
/**
* On being bit by a vampire
*
- * This handles vampire bite sleep immunity and any future special interactions.
+ * This handles any future special interactions. Vampire bite immunity is now handled by TRAIT_RESISTS_KISS.
*/
/datum/splat/vampire/kindred/proc/on_vampire_bitten(datum/source, mob/living/carbon/being_bitten)
SIGNAL_HANDLER
- return COMPONENT_RESIST_VAMPIRE_KISS
-
/datum/splat/vampire/kindred/proc/kindred_blood(mob/living/carbon/human/kindred, seconds_per_tick, times_fired)
SIGNAL_HANDLER
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/auspices/philodox.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/auspices/philodox.dm
index a9344b5e2184..14bf25741e3e 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/auspices/philodox.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/auspices/philodox.dm
@@ -1,7 +1,7 @@
/datum/action/cooldown/power/gift/resist_pain
name = "Resist Pain"
- desc = "Through force of will, the Philodox is able to ignore the pain of his wounds and continue acting normally."
+ desc = "Through force of will, the Fera is able to ignore the pain of their wounds and continue acting normally."
button_icon_state = "resist_pain"
rank = 1
willpower_cost = 1
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/changing_breeds/ananasi.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/changing_breeds/ananasi.dm
new file mode 100644
index 000000000000..7b367315732d
--- /dev/null
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/changing_breeds/ananasi.dm
@@ -0,0 +1,488 @@
+#define ALTER_MOOD_ENHANCE "Enhance"
+#define ALTER_MOOD_DAMPEN "Dampen"
+#define ANANASI_COCOON_TRAIT "ananasi_cocoon"
+
+/datum/action/cooldown/power/gift/bloodheal
+ name = "Blood Heal"
+ desc = "The Ananasi can heal their wounds by drawing on their own blood."
+ button_icon_state = "bloodheal"
+ click_to_activate = FALSE
+ rank = 1
+ handles_spend_resources = FALSE
+
+/datum/action/cooldown/power/gift/bloodheal/can_afford(feedback)
+ var/mob/living/human_owner = astype(owner)
+ if(!human_owner)
+ return ..()
+ if(human_owner.bloodpool < 1)
+ if(feedback)
+ to_chat(owner, span_warning("You don't have enough blood to cast [src]!"))
+ return FALSE
+ return ..()
+
+/datum/action/cooldown/power/gift/bloodheal/spend_resources()
+ var/mob/living/human_owner = astype(owner)
+ . = ..()
+ if(human_owner)
+ human_owner.adjust_blood_pool(-1)
+
+/datum/action/cooldown/power/gift/bloodheal/Activate(atom/target)
+ var/mob/living/human_owner = astype(owner)
+ if(!human_owner)
+ return FALSE
+ if(!do_after(human_owner, 1 TURNS))
+ return FALSE
+
+ . = ..()
+
+ playsound(owner, 'modular_darkpack/modules/vampire_the_masquerade/sounds/bloodhealing.ogg', 50, FALSE)
+ human_owner.heal_ordered_damage(30, list(BRUTE, TOX, OXY, STAMINA))
+ human_owner.heal_ordered_damage(6, list(BURN, AGGRAVATED))
+ human_owner.update_damage_overlays()
+ human_owner.update_health_hud()
+ return TRUE
+
+/datum/action/cooldown/power/gift/spin_web
+ name = "Spin Web"
+ desc = "The Ananasi in Pithus form can break down stored blood and spin very strong, very durable webs."
+ button_icon_state = "spin_web"
+ click_to_activate = FALSE
+ rank = 1
+ handles_spend_resources = FALSE
+
+ // /tg/ giant spider web actions! minus reflector, spikes, and effigy bc they don't really fit
+ var/static/list/web_action_choices = list(
+ /datum/action/cooldown/mob_cooldown/lay_web,
+ /datum/action/cooldown/mob_cooldown/lay_web/solid_web,
+ /datum/action/cooldown/mob_cooldown/lay_web/web_passage,
+ /datum/action/cooldown/mob_cooldown/lay_web/sticky_web,
+ /datum/action/cooldown/mob_cooldown/wrap/ananasi_cocoon,
+ )
+
+/datum/action/cooldown/power/gift/spin_web/can_afford(feedback)
+ var/mob/living/human_owner = astype(owner)
+ if(!human_owner)
+ return ..()
+ if(human_owner.bloodpool < 1)
+ if(feedback)
+ to_chat(owner, span_warning("You don't have enough blood to cast [src]!"))
+ return FALSE
+ return ..()
+
+/datum/action/cooldown/power/gift/spin_web/spend_resources()
+ var/mob/living/human_owner = astype(owner)
+ . = ..()
+ if(human_owner)
+ human_owner.adjust_blood_pool(-1)
+
+// only pithus form can spin webs. crawlerling can too but not to any significant effect
+/datum/action/cooldown/power/gift/spin_web/proc/in_valid_form(mob/living/carbon/human/human_owner)
+ var/datum/species/human/shifter/shifter_species = human_owner.dna?.species
+ if(!istype(shifter_species))
+ return FALSE
+ return (shifter_species.id == SPECIES_FERA_DIRE)
+
+/datum/action/cooldown/power/gift/spin_web/Activate(atom/target)
+ var/mob/living/carbon/human/human_owner = astype(owner)
+ if(!human_owner)
+ return FALSE
+ if(!in_valid_form(human_owner))
+ to_chat(owner, span_warning("You must be in Pithus form to spin webs!"))
+ return FALSE
+
+ var/list/choices = list()
+ var/list/name_to_type = list()
+ for(var/datum/action/cooldown/mob_cooldown/web_action_type as anything in web_action_choices)
+ var/datum/radial_menu_choice/option = new
+ option.image = image(icon = initial(web_action_type.button_icon), icon_state = initial(web_action_type.button_icon_state))
+ option.info = span_boldnotice(initial(web_action_type.name))
+ name_to_type[initial(web_action_type.name)] = web_action_type
+ choices[initial(web_action_type.name)] = option
+
+ var/picked_name = show_radial_menu(human_owner, human_owner, choices, tooltips = TRUE)
+ var/chosen_type = name_to_type[picked_name]
+ if(!chosen_type)
+ return FALSE
+
+ . = ..()
+
+ var/datum/action/cooldown/mob_cooldown/action_instance = new chosen_type()
+ action_instance.owner_has_control = FALSE
+ action_instance.Grant(human_owner)
+ action_instance.Trigger(human_owner, NONE)
+ if(!action_instance.click_to_activate)
+ action_instance.Remove(human_owner)
+ qdel(action_instance)
+ return TRUE
+
+// the people demanded cocoon wrapping
+/datum/action/cooldown/mob_cooldown/wrap/ananasi_cocoon
+ name = "Cocoon"
+ desc = "Wrap a nearby target in a cocoon, restraining them until they can force their way free. While restrained, you may drain them of their blood."
+
+/datum/action/cooldown/mob_cooldown/wrap/ananasi_cocoon/wrap_target(mob/living/to_wrap)
+ var/mob/living/cocoon_owner = owner
+ var/obj/structure/spider/cocoon/ananasi/casing = new(to_wrap.loc)
+ to_wrap.forceMove(casing)
+ ADD_TRAIT(to_wrap, TRAIT_HANDS_BLOCKED, ANANASI_COCOON_TRAIT)
+ if(isliving(to_wrap) && (to_wrap.mob_biotypes & MOB_HUMANOID))
+ casing.icon_state = pick("cocoon_large1", "cocoon_large2", "cocoon_large3")
+ else
+ casing.icon_state = pick("cocoon1", "cocoon2", "cocoon3")
+ cocoon_owner?.visible_message(
+ span_notice("[cocoon_owner] wraps [to_wrap] tightly in silk!"),
+ span_notice("You finish wrapping [to_wrap] into a cocoon."),
+ )
+
+/datum/action/cooldown/mob_cooldown/wrap/ananasi_cocoon/cocoon(atom/movable/to_wrap)
+ var/mob/living/cocoon_owner = owner
+ . = ..()
+ Remove(cocoon_owner)
+ qdel(src)
+
+/obj/structure/spider/cocoon/ananasi
+ name = "silken cocoon"
+ desc = "A cocoon of dense spider silk. Something is bound within, struggling weakly."
+
+/obj/structure/spider/cocoon/ananasi/Destroy()
+ for(var/mob/living/trapped_mob in contents)
+ REMOVE_TRAIT(trapped_mob, TRAIT_HANDS_BLOCKED, ANANASI_COCOON_TRAIT)
+ return ..()
+
+// per ananasi breedbook, webs resist Strength rolls with an effective Strength of 9
+/obj/structure/spider/cocoon/ananasi/container_resist_act(mob/living/user)
+ user.changeNext_move(CLICK_CD_BREAKOUT)
+ user.last_special = world.time + CLICK_CD_BREAKOUT
+ user.visible_message(
+ span_warning("[user] strains against the webbing, trying to break free!"),
+ span_notice("You strain against the sticky bonds..."),
+ )
+ var/datum/storyteller_roll/escape_roll = new()
+ escape_roll.applicable_stats = list(STAT_STRENGTH)
+ escape_roll.difficulty = 9
+ escape_roll.roll_output_type = ROLL_PRIVATE
+
+ if(QDELETED(src) || user.loc != src)
+ return
+ if(escape_roll.st_roll(user, user) != ROLL_SUCCESS)
+ to_chat(user, span_warning("You fail to break free of the webbing!"))
+ user.Stun(6 SECONDS)
+ return
+
+ REMOVE_TRAIT(user, TRAIT_HANDS_BLOCKED, ANANASI_COCOON_TRAIT)
+ user.forceMove(get_turf(src))
+ qdel(src)
+
+/obj/structure/spider/cocoon/ananasi/attack_hand(mob/user, list/modifiers)
+ . = ..()
+ if(.)
+ return
+ var/mob/living/living_user = astype(user)
+ if(living_user?.combat_mode)
+ var/datum/storyteller_roll/tear_roll = new()
+ tear_roll.applicable_stats = list(STAT_STRENGTH)
+ tear_roll.difficulty = 9
+ tear_roll.roll_output_type = ROLL_PUBLIC
+ living_user.visible_message(
+ span_danger("[living_user] starts tearing [src] apart!"),
+ span_danger("You start tearing [src] apart!"),
+ )
+ if(!do_after(living_user, 3 SECONDS, target = src))
+ return
+ if(QDELETED(src))
+ return
+ if(tear_roll.st_roll(user, user) != ROLL_SUCCESS)
+ to_chat(user, span_warning("You fail to tear through the silk!"))
+ return
+ living_user.visible_message(
+ span_danger("[living_user] rips [src] to shreds!"),
+ span_danger("You rip [src] to shreds!"),
+ )
+ qdel(src)
+ return
+ var/mob/living/attacker = astype(user)
+ if(!attacker || !get_ananasi_splat(attacker))
+ return
+ var/mob/living/victim = locate(/mob/living) in contents
+ if(!victim)
+ return
+ if(get_kindred_splat(victim))
+ to_chat(attacker, span_warning("[victim]'s blood would be toxic to you!"))
+ return
+ if(victim.blood_volume <= 0)
+ to_chat(attacker, span_warning("[victim] has no more blood left to drain!"))
+ return
+ playsound(src, 'modular_darkpack/modules/blood_drinking/sounds/drinkblood1.ogg', 50, TRUE)
+ attacker.visible_message(
+ span_danger("[attacker] sinks its fangs into [victim] through the cocoon!"),
+ span_danger("You begin drinking the blood from [victim]!"),
+ )
+ if(!do_after(attacker, 6 SECONDS, target = src))
+ return
+ if(QDELETED(src) || QDELETED(victim) || (victim.loc != src))
+ return
+ attacker.adjust_blood_pool(2)
+ victim.adjust_blood_pool(-2)
+ victim.adjust_blood_volume(-112)
+ log_combat(attacker, victim, "drained the blood from")
+ to_chat(attacker, span_notice("You finish drinking [victim]'s blood."))
+
+/datum/action/cooldown/power/gift/stolen_moments
+ name = "Stolen Moments"
+ desc = "This Gift allows the Ananasi to literally steal away the last few minutes of memories from another being."
+ button_icon_state = "stolen_moments"
+ click_to_activate = TRUE
+ rank = 1
+
+ gnosis_cost = 1
+
+/datum/action/cooldown/power/gift/stolen_moments/Activate(atom/target)
+ var/mob/living/living_target = astype(target)
+ if(!living_target)
+ return FALSE
+ . = ..()
+
+ var/datum/splat/werewolf/shifter/shifter_splat = get_shifter_splat(owner)
+ var/datum/subsplat/werewolf/breed_form/breed = shifter_splat?.breed_form
+ var/datum/storyteller_roll/roll_datum = new()
+ roll_datum.difficulty = living_target.st_get_stat(STAT_TEMPORARY_WILLPOWER)
+ roll_datum.roll_output_type = ROLL_PRIVATE_AND_TARGET
+ var/roll_result = roll_datum.st_roll(owner, target, breed?.start_gnosis || 0)
+
+ if(roll_result != ROLL_SUCCESS)
+ return
+
+ SEND_SOUND(target, sound('modular_darkpack/modules/powers/sounds/dominate.ogg', volume = 50))
+ SEND_SIGNAL(target, COMSIG_ALL_MASQUERADE_REINFORCE)
+ to_chat(target, span_hypnophrase("At [owner]'s touch, the last fifteen minutes of your memory are stolen away. You feel a sense of confusion and disorientation as you struggle to recall what just happened."))
+ log_combat(owner, target, "used Stolen Moments on")
+
+ StartCooldown()
+ return TRUE
+
+/datum/action/cooldown/power/gift/breath_of_the_wyld/inspire
+ name = "Inspire"
+ desc = "The Ananasi instills a target with a rush of lucidity."
+
+/datum/action/cooldown/power/gift/breath_of_the_wyld/inspire/Activate(atom/target)
+ if(!isliving(target))
+ return
+ if(!(target in range(1, owner)))
+ return
+
+ . = ..()
+
+ var/mob/living/victim = target
+ var/mob/living/caster = owner
+ var/datum/splat/werewolf/casting_splat = get_werewolf_splat(caster)
+ var/roll_difficulty = get_werewolf_splat(target) ? 5 : 6
+ if(!roll_datum)
+ roll_datum = new()
+ roll_datum.difficulty = roll_difficulty
+ roll_datum.roll_output_type = ROLL_PRIVATE_AND_TARGET
+ var/roll_result = roll_datum.st_roll(caster, target, casting_splat.gnosis)
+
+ if(roll_result != ROLL_SUCCESS)
+ return
+
+ victim.apply_status_effect(/datum/status_effect/breath_of_the_wyld)
+
+ StartCooldown()
+ return TRUE
+
+/datum/status_effect/breath_of_the_wyld
+ id = "breath_of_the_wyld"
+ duration = 1 SCENES
+
+ status_type = STATUS_EFFECT_REPLACE
+
+ alert_type = /atom/movable/screen/alert/status_effect/breath_of_the_wyld
+
+/datum/status_effect/breath_of_the_wyld/on_apply()
+ owner.st_add_stat_mod(STAT_PERCEPTION, 1, type)
+ owner.st_add_stat_mod(STAT_INTELLIGENCE, 1, type)
+ owner.st_add_stat_mod(STAT_WITS, 1, type)
+ ADD_TRAIT(owner, TRAIT_DIFFICULT_RAGE, type)
+ to_chat(owner, span_notice("You feel a sense of heightened lucidity."))
+ return TRUE
+
+/datum/status_effect/breath_of_the_wyld/on_remove()
+ owner.st_remove_stat_mod(STAT_PERCEPTION, type)
+ owner.st_remove_stat_mod(STAT_INTELLIGENCE, type)
+ owner.st_remove_stat_mod(STAT_WITS, type)
+ REMOVE_TRAIT(owner, TRAIT_DIFFICULT_RAGE, type)
+ to_chat(owner, span_warning("Your mind settles, returning to it's normal state of lucidity."))
+
+/atom/movable/screen/alert/status_effect/breath_of_the_wyld/inspire
+ name = "Inspire"
+ desc = "Gain an additional die to all mental checks, but suffer a penalty to rage check difficulty."
+ icon = 'modular_darkpack/modules/deprecated/icons/hud/screen_alert.dmi'
+ icon_state = "riddle" // TODO: get an icon for this
+
+/datum/action/cooldown/power/gift/alter_mood
+ name = "Alter Mood"
+ desc = "The Wyrsta can enhance or dampen the mood of a single individual."
+ button_icon_state = "alter_mood"
+ click_to_activate = TRUE
+ rank = 1
+ gnosis_cost = 1
+ var/alter_types = list(ALTER_MOOD_ENHANCE, ALTER_MOOD_DAMPEN)
+
+/datum/action/cooldown/power/gift/alter_mood/Activate(atom/target)
+ var/mob/living/living_target = astype(target)
+ if(!living_target)
+ return FALSE
+
+ var/alter_type_selected = tgui_input_list(owner, "How do you want to alter the target's mood?", "Alter Mood Type Selection", alter_types, ALTER_MOOD_ENHANCE)
+ if(!alter_type_selected)
+ return FALSE
+
+ . = ..()
+
+ switch(alter_type_selected)
+ if(ALTER_MOOD_ENHANCE)
+ SEND_SOUND(target, sound('modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/altermood.ogg', volume = 50))
+ to_chat(living_target, span_boldnotice("An odd warmth spreads through your mind, heightening your emotional state. Any emotional highs or lows are suddenly more intense and extreme."))
+ log_combat(owner, target, "used Alter Mood (Enhance) on")
+ if(ALTER_MOOD_DAMPEN)
+ SEND_SOUND(target, sound('modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/altermood.ogg', volume = 50))
+ to_chat(living_target, span_boldwarning("An odd numbness sets over your mind, dulling your emotional state. Any extreme emotional highs or lows are suddenly muted to a more moderate, mundane level."))
+ log_combat(owner, target, "used Alter Mood (Dampen) on")
+
+ StartCooldown()
+ return TRUE
+
+/datum/action/cooldown/power/gift/blood_of_pain
+ name = "Blood of Pain"
+ desc = "The Hatar turns their blood into debilitating poison."
+ button_icon_state = "blood_of_pain"
+ rank = 1
+
+/datum/action/cooldown/power/gift/blood_of_pain/Grant(mob/granted_to)
+ . = ..()
+ ADD_TRAIT(granted_to, TRAIT_BLOOD_OF_PAIN, GIFT_TRAIT)
+
+/datum/action/cooldown/power/gift/blood_of_pain/Activate(atom/target)
+ . = ..()
+
+ if(HAS_TRAIT_FROM(owner, TRAIT_BLOOD_OF_PAIN, GIFT_TRAIT))
+ REMOVE_TRAIT(owner, TRAIT_BLOOD_OF_PAIN, GIFT_TRAIT)
+ to_chat(owner, span_notice("Your blood is no longer poisonous."))
+ else
+ ADD_TRAIT(owner, TRAIT_BLOOD_OF_PAIN, GIFT_TRAIT)
+ to_chat(owner, span_notice("Your blood is now poisonous."))
+
+/atom/movable/screen/alert/status_effect/blood_of_pain
+ name = "Blood of Pain"
+ desc = "The blood you have consumed is causing you horrible agony!"
+ icon = 'modular_darkpack/modules/deprecated/icons/hud/screen_alert.dmi'
+ icon_state = "default"
+
+/datum/status_effect/blood_of_pain
+ duration = 3 MINUTES
+ tick_interval = 5 SECONDS
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = /atom/movable/screen/alert/status_effect/blood_of_pain
+
+/datum/status_effect/blood_of_pain/tick(seconds_between_ticks)
+ var/datum/storyteller_roll/stamina_roll = new()
+ stamina_roll.applicable_stats = list(STAT_STAMINA)
+ stamina_roll.difficulty = 6
+ stamina_roll.roll_output_type = ROLL_PRIVATE
+ stamina_roll.spammy_roll = TRUE
+ if(stamina_roll.st_roll(owner, owner) != ROLL_SUCCESS)
+ to_chat(owner, span_danger("THE AGONY IS UNBEARABLE!"))
+ SEND_SOUND(owner, sound('modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/blood_of_pain.ogg', volume = 75))
+ owner.Stun(5 SECONDS)
+ else
+ SEND_SOUND(owner, sound('modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/blood_of_pain_pass.ogg', volume = 75))
+
+/datum/status_effect/blood_of_pain/on_apply()
+ to_chat(owner, span_danger("You feel horrible after drinking that blood..."))
+ return TRUE
+
+/datum/status_effect/blood_of_pain/on_remove()
+ to_chat(owner, span_danger("The agonizing pain subsides."))
+
+/datum/action/cooldown/power/gift/blood_of_pain/Remove(mob/removed_from)
+ . = ..()
+ REMOVE_TRAIT(removed_from, TRAIT_BLOOD_OF_PAIN, GIFT_TRAIT)
+
+/datum/action/cooldown/power/gift/beneath_notice
+ name = "Beneath Notice"
+ desc = "The Tenere can make an object blend into the surrounding area."
+ button_icon_state = "beneath_notice"
+ click_to_activate = TRUE
+ rank = 1
+ gnosis_cost = 1
+
+ var/hide_duration = 180 MINUTES
+ var/alpha_reduction = 220
+ var/list/hidden_targets = list()
+
+/datum/action/cooldown/power/gift/beneath_notice/Activate(atom/movable/target)
+ if(!isobj(target) && !isitem(target))
+ return FALSE
+ if(hidden_targets[target])
+ remove_beneath_notice(target)
+ to_chat(owner, span_warning("[target] is revealed!"))
+ StartCooldown()
+ return TRUE
+
+ . = ..()
+
+ target.alpha = max(target.alpha - alpha_reduction, 0)
+ ADD_TRAIT(target, TRAIT_EXAMINE_SKIP, GIFT_TRAIT)
+
+ if(isitem(target) && ismob(target.loc))
+ var/obj/item/worn_item = target
+ var/mob/wearer = target.loc
+ wearer.update_clothing(worn_item.slot_flags)
+
+ var/list/existing = list()
+ hidden_targets[target] = existing
+ RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_deleted))
+
+ existing["timer"] = addtimer(CALLBACK(src, PROC_REF(remove_beneath_notice), target), hide_duration, TIMER_STOPPABLE)
+
+ to_chat(owner, span_info("[target] is now hidden from sight."))
+ StartCooldown()
+ return TRUE
+
+/datum/action/cooldown/power/gift/beneath_notice/proc/remove_beneath_notice(atom/movable/target)
+ var/list/existing = hidden_targets[target]
+ if(!existing)
+ return
+ hidden_targets -= target
+ UnregisterSignal(target, COMSIG_QDELETING)
+
+ target.alpha = min(target.alpha + alpha_reduction, 255)
+ REMOVE_TRAIT(target, TRAIT_EXAMINE_SKIP, GIFT_TRAIT)
+
+ if(isitem(target) && ismob(target.loc))
+ var/obj/item/worn_item = target
+ var/mob/wearer = target.loc
+ wearer.update_clothing(worn_item.slot_flags)
+
+/datum/action/cooldown/power/gift/beneath_notice/proc/on_target_deleted(atom/movable/target)
+ SIGNAL_HANDLER
+ var/list/existing = hidden_targets[target]
+ if(!existing)
+ return
+
+ if(isitem(target) && ismob(target.loc))
+ var/obj/item/worn_item = target
+ var/mob/wearer = target.loc
+ wearer.update_clothing(worn_item.slot_flags)
+
+ hidden_targets -= target
+ deltimer(existing["timer"])
+ REMOVE_TRAIT(target, TRAIT_EXAMINE_SKIP, GIFT_TRAIT)
+
+
+
+#undef ALTER_MOOD_ENHANCE
+#undef ALTER_MOOD_DAMPEN
+#undef ANANASI_COCOON_TRAIT
+
+
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/innate/howling.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/innate/howling.dm
index 92136aa6ff92..411f88665099 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/innate/howling.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/gifts/innate/howling.dm
@@ -4,42 +4,35 @@
button_icon_state = "call_of_the_wyld"
rage_cost = 1
check_flags = null
- innate_ability = TRUE
+ innate_ability = FALSE
var/static/list/howls = list(
"attack" = list(
"menu" = "Attack",
SPLAT_GAROU = "A wolf howls a fierce call to attack",
- SPLAT_CORAX = "A raven hisses a fierce call to attack"
),
"retreat" = list(
"menu" = "Retreat",
SPLAT_GAROU = "A wolf howls a warning to retreat",
- SPLAT_CORAX = "A raven squawks a warning to retreat"
),
"help" = list(
"menu" = "Help",
SPLAT_GAROU = "A wolf howls a desperate plea for help",
- SPLAT_CORAX = "A raven shrieks a a desperate plea for help"
),
"gather" = list(
"menu" = "Gather",
SPLAT_GAROU = "A wolf howls to gather the pack",
- SPLAT_CORAX = "A raven beckons the conspiracy"
),
"victory" = list(
"menu" = "Victory",
SPLAT_GAROU = "A wolf howls in celebration of victory",
- SPLAT_CORAX = "A raven croaks in celebration of victory"
),
"dying" = list(
"menu" = "Dying",
SPLAT_GAROU = "A wolf howls in pain and despair",
- SPLAT_CORAX = "A raven shrieks in pain and despair"
),
"mourning" = list(
"menu" = "Mourning",
SPLAT_GAROU = "A wolf howls in deep mourning for the fallen",
- SPLAT_CORAX = "A raven mourns the loss of the fallen"
)
)
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/hud.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/hud.dm
index 0f4f8e558446..d9ca1e92a31c 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/hud.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/hud.dm
@@ -139,8 +139,9 @@
abstract_type = /atom/movable/screen/fera_transform
icon = 'modular_darkpack/modules/werewolf_the_apocalypse/icons/hud_transforms.dmi'
mouse_over_pointer = MOUSE_HAND_POINTER
- var/datum/species/left_click_transform
- var/datum/species/right_click_transform
+ /// Generic form slot (SPECIES_FERA_WAR, etc), resolved to the clicker's actual splat-specific species on use
+ var/left_click_form_id
+ var/right_click_form_id
/atom/movable/screen/fera_transform/Initialize(mapload, datum/hud/hud_owner)
. = ..()
@@ -157,9 +158,16 @@
return
var/datum/splat/werewolf/shifter/shifting = get_shifter_splat(clicker)
+ if(!istype(shifting))
+ return
+
var/list/modifiers = params2list(params)
// Right click for alt forms like glabro and hispo. Ctrl click to use rage to do it instantly (doesnt matter if its breed form tho)
- shifting.transform_fera(LAZYACCESS(modifiers, RIGHT_CLICK) ? right_click_transform : left_click_transform, LAZYACCESS(modifiers, CTRL_CLICK))
+ var/form_id = LAZYACCESS(modifiers, RIGHT_CLICK) ? right_click_form_id : left_click_form_id
+ var/datum/species/human/shifter/form_to_transform = shifting.get_form_by_id(form_id)
+ if(!form_to_transform)
+ return
+ shifting.transform_fera(form_to_transform, LAZYACCESS(modifiers, CTRL_CLICK))
/atom/movable/screen/fera_transform/update_icon(updates)
. = ..()
@@ -178,14 +186,19 @@
. = ..()
var/datum/splat/werewolf/shifter/shifting = get_shifter_splat(user)
+ if(!istype(shifting))
+ return
+
+ var/datum/species/human/shifter/left_form = shifting.get_form_by_id(left_click_form_id)
+ var/datum/species/human/shifter/right_form = shifting.get_form_by_id(right_click_form_id)
- if(left_click_transform && (left_click_transform in shifting.transformation_list))
- context[SCREENTIP_CONTEXT_LMB] = "Shift to [left_click_transform::name]"
- if(left_click_transform != shifting.get_breed_form_species())
+ if(left_form && (left_form in shifting.transformation_list))
+ context[SCREENTIP_CONTEXT_LMB] = "Shift to [initial(left_form.name)]"
+ if(left_form != shifting.get_breed_form_species())
context[SCREENTIP_CONTEXT_CTRL_LMB] = "Shift using rage"
- if(right_click_transform && (right_click_transform in shifting.transformation_list))
- context[SCREENTIP_CONTEXT_RMB] = "Shift to [right_click_transform::name]"
- if(right_click_transform != shifting.get_breed_form_species())
+ if(right_form && (right_form in shifting.transformation_list))
+ context[SCREENTIP_CONTEXT_RMB] = "Shift to [initial(right_form.name)]"
+ if(right_form != shifting.get_breed_form_species())
context[SCREENTIP_CONTEXT_CTRL_RMB] = "Shift using rage"
return CONTEXTUAL_SCREENTIP_SET
@@ -195,23 +208,23 @@
name = "homid form"
icon_state = "homid"
screen_loc = UI_LIVING_TRANSFORM_HOMID
- left_click_transform = /datum/species/human/shifter/homid
- right_click_transform = /datum/species/human/shifter/bestial
+ left_click_form_id = SPECIES_FERA_HOMID
+ right_click_form_id = SPECIES_FERA_BESTIAL
/atom/movable/screen/fera_transform/war
name = "war form"
icon_state = "war"
screen_loc = UI_LIVING_TRANSFORM_WAR
- left_click_transform = /datum/species/human/shifter/war
+ left_click_form_id = SPECIES_FERA_WAR
/atom/movable/screen/fera_transform/feral
name = "feral form"
icon_state = "feral"
screen_loc = UI_LIVING_TRANSFORM_FERAL
- left_click_transform = /datum/species/human/shifter/feral
- right_click_transform = /datum/species/human/shifter/dire
+ left_click_form_id = SPECIES_FERA_FERAL
+ right_click_form_id = SPECIES_FERA_DIRE
#undef UI_LIVING_TRANSFORM_HOMID
#undef UI_LIVING_TRANSFORM_WAR
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/breed.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/breed.dm
index 942eafa47e58..e184cb92b7db 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/breed.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/breed.dm
@@ -44,3 +44,7 @@
/datum/preference/choiced/subsplat/fera_breed/coeax
savefile_key = "corax_breed"
splat_id = SPLAT_CORAX
+
+/datum/preference/choiced/subsplat/fera_breed/ananasi
+ savefile_key = "ananasi_breed"
+ splat_id = SPLAT_ANANASI
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/customization/fur_color.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/customization/fur_color.dm
index 2c611855d712..a6d734d98804 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/customization/fur_color.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/customization/fur_color.dm
@@ -34,6 +34,9 @@
savefile_key = "corax_fur_color"
splat_id = SPLAT_CORAX
+/datum/preference/choiced/fera_fur_color/ananasi
+ savefile_key = "ananasi_fur_color"
+ splat_id = SPLAT_ANANASI
/datum/dna_block/feature/fera_fur_color
feature_key = FEATURE_FERA_FUR_COLOR
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/tribe.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/tribe.dm
index 287a19e4dd39..9b6a8c53571b 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/tribe.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/preferences/tribe.dm
@@ -42,3 +42,7 @@
splat_id = SPLAT_CORAX
savefile_key = "corax_tribe"
*/
+
+/datum/preference/choiced/subsplat/fera_tribe/ananasi
+ splat_id = SPLAT_ANANASI
+ savefile_key = "ananasi_tribe"
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/species/fera_species.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/species/fera_species.dm
index 095b2f1872a1..6a96022723f4 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/species/fera_species.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/species/fera_species.dm
@@ -337,10 +337,12 @@
fallback_icon = 'modular_darkpack/modules/werewolf_the_apocalypse/icons/garou_forms/hispo.dmi'
speed_mod = /datum/movespeed_modifier/shifter/dire
+/datum/species/human/shifter/dire/ananasi
+ form_causes_delirium = TRUE
+
/datum/species/human/shifter/dire/visible_gender_override(mob/living/carbon/human/holder)
return "beast"
-
/datum/species/human/shifter/feral
name = "feral form"
id = SPECIES_FERA_FERAL
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/species/transformation.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/species/transformation.dm
index b9c56ec83719..21f97851d0f4 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/species/transformation.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/species/transformation.dm
@@ -124,4 +124,14 @@
/datum/splat/werewolf/shifter/proc/get_breed_form_species()
return breed_form?.breed_species
+/// Resolves generic form slot (SPECIES_FERA_WAR, SPECIES_FERA_FERAL, etc) to whatever species
+/// type this splat uses for that slot, letting individual fera subtypes (garou/corax/ananasi/etc)
+/// swap in their own unique subtype species
+/datum/splat/werewolf/shifter/proc/get_form_by_id(form_id)
+ if(!form_id)
+ return
+ for(var/datum/species/human/shifter/form_type as anything in transformation_list)
+ if(initial(form_type.id) == form_id)
+ return form_type
+
#undef DOGGY_ANIMATION_TIME
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/examine_text.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/examine_text.dm
index e8bbbf0a44a9..a0d6b3749a33 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/examine_text.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/examine_text.dm
@@ -1,5 +1,6 @@
/datum/splat/werewolf/proc/examine_other_human(mob/living/carbon/examined)
- var/datum/splat/werewolf/wolp_splat = get_werewolf_splat(examined)
+ var/datum/splat/werewolf/shifter/garou/wolp_splat = get_garou_splat(examined)
+ var/datum/splat/werewolf/spiber_splat = get_ananasi_splat(examined)
if(wolp_splat)
var/list/honor_flavor = list("claim to good conduct", "claim to honor", "claim to chivalry")
var/list/wisdom_flavor = list("claim to insight", "claim to wisdom", "claim to sagacity")
@@ -46,3 +47,22 @@
. += "In the local Garou, you have heard of [examined.p_their(TRUE)] [glory_flavor[2]]."
if(10)
. += "In the local Garou, you have heard of [examined.p_their(TRUE)] [glory_flavor[3]]."
+
+ // Wyrmling Kinship gift for Hatar Ananasi
+ if(HAS_TRAIT(examined, TRAIT_WYRMLING_KINSHIP) && tribe?.name == TRIBE_BLACK_SPIRAL_DANCERS)
+ . += span_boldnicegreen("The Wyrm's presence clings to [examined.p_them()]. You recognize [examined.p_them()] as one of your own.")
+
+ // For now, only one pattern flavor on examine. When Renown is reworked, this will be expanded to describe more complex patterns based on rank.
+ if(spiber_splat && istype(src, /datum/splat/werewolf/shifter/ananasi))
+ var/list/tenere_flavor = list("structure and order", "immaculately weaved patterns")
+ var/list/hatar_flavor = list("death and decay", "indiscriminate destruction")
+ var/list/kumoti_flavor = list("growth and change", "chaos and life unbidden")
+
+ switch(spiber_splat.tribe?.name)
+ if(TRIBE_SECEAN, TRIBE_PLICARE, TRIBE_GADERIN)
+ . += "The patterns on [examined.p_their(TRUE)] skin depict [tenere_flavor[1]]."
+ if(TRIBE_AGERE, TRIBE_ANOMIA, TRIBE_MALUM)
+ . += "The patterns on [examined.p_their(TRUE)] skin depict [hatar_flavor[1]]."
+ if(TRIBE_KAR, TRIBE_AMARI_ALIQUID, TRIBE_CHYMOS)
+ . += "The patterns on [examined.p_their(TRUE)] skin depict [kumoti_flavor[1]]."
+
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/fera_splat.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/fera_splat.dm
index 9a90ffe4d63a..46652a55702d 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/fera_splat.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/fera_splat.dm
@@ -134,7 +134,6 @@
/datum/splat/werewolf/shifter/on_gain()
. = ..()
owner.set_species(/datum/species/human/shifter/homid)
- add_power(/datum/action/cooldown/power/gift/howling)
COOLDOWN_START(src, passive_regrowth_cd, 8 MINUTES)
RegisterSignal(owner, COMSIG_LIVING_DEATH, PROC_REF(revert_to_breed_form))
@@ -143,8 +142,6 @@
. = ..()
if(!QDELETED(owner))
owner.set_species(/datum/species/human)
-
- remove_power(/datum/action/cooldown/power/gift/howling)
UnregisterSignal(owner, COMSIG_LIVING_DEATH)
/datum/splat/werewolf/shifter/splat_life(seconds_per_tick)
@@ -153,7 +150,7 @@
// their fast healing is represented in day/days in breed-form so we just dont.
var/can_passively_heal = !(is_breed_form() && (get_breed_form_species() != /datum/species/human/shifter/war))
if(COOLDOWN_FINISHED(src, passive_healing_cd))
- if(can_passively_heal)
+ if(can_passively_heal && !HAS_TRAIT(owner, TRAIT_NO_PASSIVE_HEALING))
// 2 to represent lethal. Fera passive regen closes burn, but not aggravated damage.
owner.heal_storyteller_health(2, heal_aggravated = FALSE, heal_scars = TRUE, heal_blood = TRUE, heal_burn = TRUE)
// Keep organ healing ticking so internal damage recovers even between major regrowth pulses.
@@ -302,6 +299,50 @@
. = ..()
remove_power(/datum/action/cooldown/power/gift/eye_drink)
+/datum/splat/werewolf/shifter/ananasi
+ name = "Ananasi"
+ id = SPLAT_ANANASI
+ uses_rage = FALSE
+ splat_traits = list(
+ TRAIT_FERA_FORMS,
+ TRAIT_FERA_FUR,
+ TRAIT_FERA_RENOWN,
+ TRAIT_NO_PASSIVE_HEALING,
+ )
+ transformation_list = list(
+ /datum/species/human/shifter/homid,
+ /datum/species/human/shifter/war,
+ /datum/species/human/shifter/dire/ananasi,
+ /datum/species/human/shifter/feral
+ )
+ transformation_stats = list(
+ SPECIES_FERA_WAR = list(
+ STAT_STRENGTH = 3,
+ STAT_STAMINA = 2,
+ STAT_DEXTERITY = 3,
+ STAT_MANIPULATION = -1,
+ STAT_APPEARANCE = -1
+ ),
+ SPECIES_FERA_FERAL = list(
+ STAT_DEXTERITY = 6,
+ ),
+ SPECIES_FERA_DIRE = list(
+ STAT_STRENGTH = 4,
+ STAT_DEXTERITY = 2,
+ STAT_MANIPULATION = -3,
+ STAT_APPEARANCE = -2
+ )
+ )
+ transform_sound = 'modular_darkpack/modules/werewolf_the_apocalypse/sounds/ananasi_transform.ogg'
+ mob_icons = list(
+ SPECIES_FERA_WAR = 'modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/lilian.dmi',
+ SPECIES_FERA_DIRE = 'modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/pithus.dmi',
+ SPECIES_FERA_FERAL = 'modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/crawlerling.dmi'
+ )
+ transform_hud_icon = 'modular_darkpack/modules/werewolf_the_apocalypse/icons/hud_transforms.dmi'
+ mimmicing_animal = /mob/living/basic/spider/giant/arachnid
+
+ warcry_emote = "hiss"
/mob/living/carbon/human/splat/kinfolk
auto_splats = list(/datum/splat/werewolf/kinfolk)
@@ -311,3 +352,6 @@
/mob/living/carbon/human/splat/corax
auto_splats = list(/datum/splat/werewolf/shifter/corax)
+
+/mob/living/carbon/human/splat/ananasi
+ auto_splats = list(/datum/splat/werewolf/shifter/ananasi)
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/is_werewolf_helpers.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/is_werewolf_helpers.dm
index 1054fee7653b..82b47ad705e7 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/is_werewolf_helpers.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/is_werewolf_helpers.dm
@@ -21,6 +21,11 @@
return character.get_splat(/datum/splat/werewolf/shifter/corax)
+/proc/get_ananasi_splat(mob/character)
+ RETURN_TYPE(/datum/splat/werewolf/shifter/ananasi)
+
+ return character.get_splat(/datum/splat/werewolf/shifter/ananasi)
+
/proc/get_kinfolk_splat(mob/character)
RETURN_TYPE(/datum/splat/werewolf/kinfolk)
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/pref_lore.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/pref_lore.dm
index 0e12111cee0c..145af8a4ecb8 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/pref_lore.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/splats/pref_lore.dm
@@ -93,3 +93,39 @@
)
return to_add
+
+// START - ANANASI SPLAT
+/datum/splat/werewolf/shifter/ananasi/prepare_human_for_preview(mob/living/carbon/human/human)
+ human.set_haircolor("#50504f", update = FALSE)
+ human.set_hairstyle("Wisp", update = TRUE)
+ human.undershirt = "Shirt (Black)"
+ human.glasses = "Prescription Glasses"
+ human.update_body()
+
+/datum/splat/werewolf/shifter/ananasi/get_splat_description()
+ return "Lorem Ipsum"
+
+/datum/splat/werewolf/shifter/ananasi/get_splat_lore()
+ return list(
+ "Lorem Ipsum",
+ )
+
+/datum/splat/werewolf/shifter/ananasi/create_pref_unique_perks()
+ var/list/to_add = list()
+
+ to_add += list(
+ list(
+ SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK,
+ SPECIES_PERK_ICON = FA_ICON_SPIDER,
+ SPECIES_PERK_NAME = "Shapeshifting",
+ SPECIES_PERK_DESC = "Ananasi can shift between 4 different forms that grant them bonuses.",
+ ),
+ list(
+ SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK,
+ SPECIES_PERK_ICON = FA_ICON_BAND_AID,
+ SPECIES_PERK_NAME = "Blood healing",
+ SPECIES_PERK_DESC = "Ananasi can use blood they've consumed to heal their injuries.",
+ ),
+ )
+
+ return to_add
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/breeds/ananasi.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/breeds/ananasi.dm
new file mode 100644
index 000000000000..d61c994a068c
--- /dev/null
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/breeds/ananasi.dm
@@ -0,0 +1,30 @@
+/datum/subsplat/werewolf/breed_form/ananasi
+ abstract_type = /datum/subsplat/werewolf/breed_form/ananasi
+ fera_restriction = SPLAT_ANANASI
+
+/datum/subsplat/werewolf/breed_form/ananasi/homid
+ name = BREED_ANANASI_HOMID
+ start_gnosis = 4
+ breed_species = /datum/species/human/shifter/homid
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/bloodheal,
+ /datum/action/cooldown/power/gift/spin_web,
+ /datum/action/cooldown/power/gift/resist_pain,
+ /datum/action/cooldown/power/gift/stolen_moments
+ )
+
+/datum/subsplat/werewolf/breed_form/ananasi/arachnid
+ name = BREED_ARACHNID
+ start_gnosis = 4
+ breed_species = /datum/species/human/shifter/feral
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/bloodheal,
+ /datum/action/cooldown/power/gift/spin_web,
+ /datum/action/cooldown/power/gift/resist_pain,
+ /datum/action/cooldown/power/gift/stolen_moments
+ )
+
+/datum/subsplat/werewolf/breed_form/ananasi/arachnid/generation_pref_icon(datum/universal_icon/main_icon)
+ var/datum/universal_icon/breed_crinos = uni_icon('modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/lilian.dmi', "black")
+ breed_crinos.scale(32, 32)
+ main_icon.blend_icon(breed_crinos, ICON_OVERLAY)
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/breeds/garou.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/breeds/garou.dm
index 5c97ce104781..3d57e19a8920 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/breeds/garou.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/breeds/garou.dm
@@ -1,6 +1,9 @@
/datum/subsplat/werewolf/breed_form/garou
abstract_type = /datum/subsplat/werewolf/breed_form/garou
fera_restriction = SPLAT_GAROU
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/howling
+ )
/datum/subsplat/werewolf/breed_form/garou/homid
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/tribes/_tribe.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/tribes/_tribe.dm
index 51ba4e11911e..504e501b08a4 100644
--- a/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/tribes/_tribe.dm
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/tribes/_tribe.dm
@@ -1,7 +1,20 @@
/datum/subsplat/werewolf/tribe
abstract_type = /datum/subsplat/werewolf/tribe
- //var/tribe_trait
+ // Traits granted from a tribe
+ var/list/tribe_traits = list()
+
+/datum/subsplat/werewolf/tribe/on_gain(mob/living/carbon/human/gaining_mob, datum/splat/gaining_splat, joining_round)
+ . = ..()
+
+ for(var/trait in tribe_traits)
+ ADD_TRAIT(gaining_mob, trait, TRIBE_TRAIT)
+
+/datum/subsplat/werewolf/tribe/on_lose(mob/living/carbon/human/losing_mob)
+ . = ..()
+
+ for(var/trait in tribe_traits)
+ REMOVE_TRAIT(losing_mob, trait, TRIBE_TRAIT)
/**
* Gets the singleton of an tribe
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/tribes/ananasi.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/tribes/ananasi.dm
new file mode 100644
index 000000000000..814936306d8e
--- /dev/null
+++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/subsplats/tribes/ananasi.dm
@@ -0,0 +1,85 @@
+/datum/subsplat/werewolf/tribe/ananasi
+ abstract_type = /datum/subsplat/werewolf/tribe/ananasi
+ fera_restriction = SPLAT_ANANASI
+
+/datum/subsplat/werewolf/tribe/ananasi/secean
+ name = TRIBE_SECEAN
+ desc = "Tenere Myrmidon; Warriors of the Weaver, seeking to understand the nature of the universe to better serve the Mother-Queen. The Secean are explorers and seekers of knowledge unbidden.\nGifts: \n Open Seal - Open nearly any sort of closed or locked physical device. Roll Gnosis against the area's gauntlet rating to unlock a locked object. \n Beneath Notice - Make an object blend into the surrounding area. Spend 1 Gnosis to hide an object almost completely from sight. Cast on the object again to unhide. \n Groom - No matter the circumstances, the Tenere always looks their best. The character is permanently immune to being bloodied."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/open_seal,
+ /datum/action/cooldown/power/gift/beneath_notice,
+ )
+ tribe_traits = list(TRAIT_ALWAYS_CLEAN)
+
+/datum/subsplat/werewolf/tribe/ananasi/plicare
+ name = TRIBE_PLICARE
+ desc = "Tenere Viskr; Mystics of the Weaver, masters of precise order and control. The Plicare are staunch perfectionists, maintaining and leveraging order and structure to achieve their goals. \nGifts: \n Mindspeak - By invoking the power of waking dreams, place characters into silent communion. Transmit a message to any Ananasi belonging to the same cabal. \n Beneath Notice - Make an object blend into the surrounding area. Spend 1 Gnosis to hide an object almost completely from sight. Cast on the object again to unhide. \n Groom - No matter the circumstances, the Tenere always looks their best. The character is permanently immune to being bloodied."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/mindspeak,
+ /datum/action/cooldown/power/gift/beneath_notice,
+ )
+ tribe_traits = list(TRAIT_ALWAYS_CLEAN)
+
+/datum/subsplat/werewolf/tribe/ananasi/gaderin
+ name = TRIBE_GADERIN
+ desc = "Tenere Wyrsta; Questioners of the Weaver, challengers of strict order. The Gaderin are obsessive collectors, seeking to grow the Mother-Queen's understanding of the world from her prison in Malfeas. \nGifts: \n Alter Mood - The Wyrsta can enhance or dampen the mood of a single individual, making that person elated rather than just happy, or muting utter despair into simple sadness. Spend 1 Gnosis enhance or dampen the mood of a target. \n Beneath Notice - Make an object blend into the surrounding area. Spend 1 Gnosis to hide an object almost completely from sight. Cast on the object again to unhide. \n Groom - No matter the circumstances, the Tenere always looks their best. The character is permanently immune to being bloodied."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/alter_mood,
+ /datum/action/cooldown/power/gift/beneath_notice,
+ )
+ tribe_traits = list(TRAIT_ALWAYS_CLEAN)
+
+/datum/subsplat/werewolf/tribe/ananasi/agere
+ name = TRIBE_AGERE
+ desc = "Hatar Myrmidon; Warriors of the Wyrm, fickle forces of entropy and destruction. The Agere are swift and deadly, moving wherever Ananasa wills them to strike and delivering the Wyrm's own destruction to their enemies. \nGifts: \n Open Seal - Open nearly any sort of closed or locked physical device. Roll Gnosis against the area's gauntlet rating to unlock a locked object. \n Blood of Pain - The Hatar turns their blood into debilitating poison. Any who drink your blood will fall helplessly ill, necessitating a Stamina roll (difficulty 6) to act each turn for the rest of the scene. Starts activated. \n Wyrmling Kinship - The Hatar can convince Wyrm-creatures that they are an ally or someone of no importance. Black Spiral Dancers and Fomori will recognize you as an ally."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/open_seal,
+ /datum/action/cooldown/power/gift/blood_of_pain,
+ )
+ tribe_traits = list(TRAIT_WYRMLING_KINSHIP)
+
+/datum/subsplat/werewolf/tribe/ananasi/anomia
+ name = TRIBE_ANOMIA
+ desc = "Hatar Viskr; Mystics of the Wyrm, master manipulators of mortal will. The Anomia are cunning controllers of fate, pulling strings and leaving the death and destruction to those most skilled in delivering it: Humanity. \nGifts: \n Mindspeak - By invoking the power of waking dreams, place characters into silent communion. Transmit a message to any Ananasi belonging to the same cabal. \n Blood of Pain - The Hatar turns their blood into debilitating poison. Any who drink your blood will fall helplessly ill, necessitating a Stamina roll (difficulty 6) to act each turn for the rest of the scene. Starts activated. \n Wyrmling Kinship - The Hatar can convince Wyrm-creatures that they are an ally or someone of no importance. Black Spiral Dancers and Fomori will recognize you as an ally."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/mindspeak,
+ /datum/action/cooldown/power/gift/blood_of_pain,
+ )
+ tribe_traits = list(TRAIT_WYRMLING_KINSHIP)
+
+/datum/subsplat/werewolf/tribe/ananasi/malum
+ name = TRIBE_MALUM
+ desc = "Hatar Wyrsta; Questioners of the Wyrm, seeking to restore the Wyrm's true and original purpose. The Malum are self-serving and unpredictable, rejecting the Wyrm's new role as the Corruptor and serving instead as agents of the Wyrm's true face: the Destroyer. \nGifts: \n Alter Mood - The Wyrsta can enhance or dampen the mood of a single individual, making that person elated rather than just happy, or muting utter despair into simple sadness. Spend 1 Gnosis enhance or dampen the mood of a target. \n Blood of Pain - The Hatar turns their blood into debilitating poison. Any who drink your blood will fall helplessly ill, necessitating a Stamina roll (difficulty 6) to act each turn for the rest of the scene. Starts activated. \n Wyrmling Kinship - The Hatar can convince Wyrm-creatures that they are an ally or someone of no importance. Black Spiral Dancers and Fomori will recognize you as an ally."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/alter_mood,
+ /datum/action/cooldown/power/gift/blood_of_pain,
+ )
+ tribe_traits = list(TRAIT_WYRMLING_KINSHIP)
+
+/datum/subsplat/werewolf/tribe/ananasi/kar
+ name = TRIBE_KAR
+ desc = "Kumoti Myrmidon; Warriors of the Wyld, forces of change and creation. The Kar protect the Wyld through minor but otherwise direct acts of sabotage against the Weaver and the Wyrm, seeking to expand the Wyld's influence. \nGifts: \n Open Seal - Open nearly any sort of closed or locked physical device. Roll Gnosis against the area's gauntlet rating to unlock a locked object. \n Inspire - As Breath of the Wyld: Instill a feeling of vitality and life in a living being. Spend 1 Gnosis to increase a target's Perception, Intelligence, and Wits by 1; and increase the difficulty of any Rage rolls by 1. \n Mother's Touch - Heal the wounds of any living creature, aggravated or otherwise, simply by laying hands over the affected area. Roll Intelligence and Empathy (Difficulty 5) to determine the effectiveness of the healing."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/open_seal,
+ /datum/action/cooldown/power/gift/breath_of_the_wyld/inspire,
+ /datum/action/cooldown/power/gift/mothers_touch,
+ )
+
+/datum/subsplat/werewolf/tribe/ananasi/amarialiquid
+ name = TRIBE_AMARI_ALIQUID
+ desc = "Kumoti Viskr; Mystics of the Wyld, acting on whim and instinct. The Amari Aliquid are gentle and persistent, making change through constant motion for better or worse. \nGifts: \n Mindspeak - By invoking the power of waking dreams, place characters into silent communion. Transmit a message to any Ananasi belonging to the same cabal. \n Inspire - As Breath of the Wyld: Instill a feeling of vitality and life in a living being. Spend 1 Gnosis to increase a target's Perception, Intelligence, and Wits by 1; and increase the difficulty of any Rage rolls by 1. \n Mother's Touch - Heal the wounds of any living creature, aggravated or otherwise, simply by laying hands over the affected area. Roll Intelligence and Empathy (Difficulty 5) to determine the effectiveness of the healing."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/mindspeak,
+ /datum/action/cooldown/power/gift/breath_of_the_wyld/inspire,
+ /datum/action/cooldown/power/gift/mothers_touch,
+ )
+
+/datum/subsplat/werewolf/tribe/ananasi/chymos
+ name = TRIBE_CHYMOS
+ desc = "Kumoti Wyrsta; Questioners of the Wyld, careful observers of the world and the minions of each Triatic spirit. The Chymos are patient and calculating, seeking to manipulate and disrupt imbalance in the world to restore Symmetry. \nGifts: \n Alter Mood - The Wyrsta can enhance or dampen the mood of a single individual, making that person elated rather than just happy, or muting utter despair into simple sadness. Spend 1 Gnosis enhance or dampen the mood of a target. \n Inspire - As Breath of the Wyld: Instill a feeling of vitality and life in a living being. Spend 1 Gnosis to increase a target's Perception, Intelligence, and Wits by 1; and increase the difficulty of any Rage rolls by 1. \n Mother's Touch - Heal the wounds of any living creature, aggravated or otherwise, simply by laying hands over the affected area. Roll Intelligence and Empathy (Difficulty 5) to determine the effectiveness of the healing."
+ gifts_provided = list(
+ /datum/action/cooldown/power/gift/alter_mood,
+ /datum/action/cooldown/power/gift/breath_of_the_wyld/inspire,
+ /datum/action/cooldown/power/gift/mothers_touch,
+ )
+
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/crawlerling.dmi b/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/crawlerling.dmi
new file mode 100644
index 000000000000..92f4dc15154e
Binary files /dev/null and b/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/crawlerling.dmi differ
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/lilian.dmi b/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/lilian.dmi
new file mode 100644
index 000000000000..1d5931f51231
Binary files /dev/null and b/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/lilian.dmi differ
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/pithus.dmi b/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/pithus.dmi
new file mode 100644
index 000000000000..1d5931f51231
Binary files /dev/null and b/modular_darkpack/modules/werewolf_the_apocalypse/icons/ananasi_forms/pithus.dmi differ
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/icons/tribes.dmi b/modular_darkpack/modules/werewolf_the_apocalypse/icons/tribes.dmi
index 45e6712d55ce..ad28d00c667a 100644
Binary files a/modular_darkpack/modules/werewolf_the_apocalypse/icons/tribes.dmi and b/modular_darkpack/modules/werewolf_the_apocalypse/icons/tribes.dmi differ
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/icons/werewolf_abilities.dmi b/modular_darkpack/modules/werewolf_the_apocalypse/icons/werewolf_abilities.dmi
index c7d80d11f83f..92dc78b8c878 100644
Binary files a/modular_darkpack/modules/werewolf_the_apocalypse/icons/werewolf_abilities.dmi and b/modular_darkpack/modules/werewolf_the_apocalypse/icons/werewolf_abilities.dmi differ
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/sounds/ananasi_transform.ogg b/modular_darkpack/modules/werewolf_the_apocalypse/sounds/ananasi_transform.ogg
new file mode 100644
index 000000000000..60bc29226fc6
Binary files /dev/null and b/modular_darkpack/modules/werewolf_the_apocalypse/sounds/ananasi_transform.ogg differ
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/altermood.ogg b/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/altermood.ogg
new file mode 100644
index 000000000000..366680f069ca
Binary files /dev/null and b/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/altermood.ogg differ
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/blood_of_pain.ogg b/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/blood_of_pain.ogg
new file mode 100644
index 000000000000..cb7b1490f8d1
Binary files /dev/null and b/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/blood_of_pain.ogg differ
diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/blood_of_pain_pass.ogg b/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/blood_of_pain_pass.ogg
new file mode 100644
index 000000000000..d610b6f518ab
Binary files /dev/null and b/modular_darkpack/modules/werewolf_the_apocalypse/sounds/gifts/blood_of_pain_pass.ogg differ
diff --git a/modular_zapoc/modules/decor/code/agility_shortcut.dm b/modular_zapoc/modules/decor/code/agility_shortcut.dm
index 02e82783d4cc..8d21521db298 100644
--- a/modular_zapoc/modules/decor/code/agility_shortcut.dm
+++ b/modular_zapoc/modules/decor/code/agility_shortcut.dm
@@ -103,7 +103,7 @@ GLOBAL_LIST_EMPTY(unallocated_agility_shortcuts)
/obj/agility_shortcut/urban/spiral
name = "hole"
desc = "There are a bunch of bricks missing. Not enough for you to crawl in. Unless you were insane."
- allowed_tribes = TRIBE_LIST_WYRM
+ allowed_tribes = list(TRIBE_BLACK_SPIRAL_DANCERS)
/obj/agility_shortcut/anyone
desc = "You could probably fit in there. Want to find out?"
diff --git a/tgstation.dme b/tgstation.dme
index 9c90b7bb22da..5db5c26e56cf 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -8269,6 +8269,7 @@
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\gifts\auspices\ragabash.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\gifts\auspices\theurge.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\gifts\changing_breeds\corax.dm"
+#include "modular_darkpack\modules\werewolf_the_apocalypse\code\gifts\changing_breeds\ananasi.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\gifts\innate\eye_drink.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\gifts\innate\howling.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\gifts\tribes\black_furies.dm"
@@ -8313,9 +8314,11 @@
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\auspices\_auspice.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\auspices\garou.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\breeds\_breed.dm"
+#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\breeds\ananasi.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\breeds\corax.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\breeds\garou.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\tribes\_tribe.dm"
+#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\tribes\ananasi.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\subsplats\tribes\garou.dm"
#include "modular_darkpack\modules\werewolf_the_apocalypse\code\weapons\klaives.dm"
#include "modular_darkpack\modules\westfield_mall\code\mall_areas.dm"
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/darkpack_fera.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/darkpack_fera.tsx
index 78db68478435..2c12b3dc9823 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/darkpack_fera.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/darkpack_fera.tsx
@@ -11,6 +11,10 @@ export const corax_fur_color: FeatureChoiced = {
component: FeatureDropdownInput,
};
+export const ananasi_fur_color: FeatureChoiced = {
+ name: 'Ananasi Exoskeleton Color',
+ component: FeatureDropdownInput,
+};
export const garou_hair: FeatureChoiced = {
name: 'Garou Hair',