diff --git a/code/__DEFINES/~darkpack/splats.dm b/code/__DEFINES/~darkpack/splats.dm index 81d9e7fa4d1c..fc8893c3c2f4 100644 --- a/code/__DEFINES/~darkpack/splats.dm +++ b/code/__DEFINES/~darkpack/splats.dm @@ -11,11 +11,15 @@ #define SPLAT_CORAX "splat_corax" #define SPLAT_SHIFTERS list(SPLAT_GAROU, SPLAT_CORAX) +#define SPLAT_FOMORI "splat_fomori" + #define SPLAT_PRIO_HALFSPLAT 100 #define SPLAT_PRIO_SPLAT 200 #define SPLAT_PRIO_KINFOLK 40 + SPLAT_PRIO_HALFSPLAT #define SPLAT_PRIO_GHOUL 70 + SPLAT_PRIO_HALFSPLAT +#define SPLAT_PRIO_FOMORI 20 + SPLAT_PRIO_SPLAT #define SPLAT_PRIO_SHIFTER 40 + SPLAT_PRIO_SPLAT #define SPLAT_PRIO_KINDRED 60 + SPLAT_PRIO_SPLAT + diff --git a/code/__DEFINES/~darkpack/traits/declarations.dm b/code/__DEFINES/~darkpack/traits/declarations.dm index 45a6aadb0b27..ed4e19b798c0 100644 --- a/code/__DEFINES/~darkpack/traits/declarations.dm +++ b/code/__DEFINES/~darkpack/traits/declarations.dm @@ -28,6 +28,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_BLOODY_SUCKER "bloody_sucker" #define TRAIT_NON_INT "non_intellectual" #define TRAIT_COFFIN_THERAPY "coffin_therapy" +// If we use combat_bite instead of vamp_bite +#define TRAIT_COMBAT_BITE "combat_bite" #define TRAIT_RUBICON "rubicon" #define TRAIT_HUNGRY "hungry" #define TRAIT_STAKE_RESISTANT "stake_resistant" @@ -159,6 +161,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Mob has had atleast one tooth yanked out while having no method of regenerating it. #define TRAIT_TOOTH_PULLED "tooth_pulled" +// Fomori Traits +#define TRAIT_FOMORI_REGEN "fomor_regen" + /// Sixth sense restricted to view range #define TRAIT_LOCAL_SIXTHSENSE "local_sixth_sense" /// If the mob can't have surgery done on it. See: Blood form Tzimisce @@ -188,6 +193,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_MERIT_UNTAMABLE "merit_untamable" #define TRAIT_FAIR_GLABRO "fair_glabro" #define TRAIT_EAT_FOOD "eat_food" +#define TRAIT_FOMORI_STIGMATA "fomori_stigmata" +#define TRAIT_FOMORI_HIDDEN_POWER "fomori_hidden_power" #define TRAIT_CALM_HEART "calm_heart" #define TRAIT_ACUTE_HEARING "acute_hearing" #define TRAIT_DISFIGURED_APPEARANCE "disfigured_appearance" diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 8da96263b42a..172dc32be054 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -688,6 +688,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_CAN_ENTER_TORPOR" = TRAIT_CAN_ENTER_TORPOR, // DARKPACK EDIT ADD "TRAIT_CHARMER" = TRAIT_CHARMER, // DARKPACK EDIT ADD "TRAIT_COFFIN_THERAPY" = TRAIT_COFFIN_THERAPY, // DARKPACK EDIT ADD + "TRAIT_COMBAT_BITE" = TRAIT_COMBAT_BITE, // DARKPACK EDIT ADD "TRAIT_CONSENSUAL_FEEDING_ONLY" = TRAIT_CONSENSUAL_FEEDING_ONLY, // DARKPACK EDIT ADD "TRAIT_DECEPTIVE_AURA" = TRAIT_DECEPTIVE_AURA, // DARKPACK EDIT ADD "TRAIT_DEFICIENT_VITAE" = TRAIT_DEFICIENT_VITAE, // DARKPACK EDIT ADD @@ -706,6 +707,9 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_FERA_FORMS" = TRAIT_FERA_FORMS, // DARKPACK EDIT ADD - WEREWOLF "TRAIT_FERA_FUR" = TRAIT_FERA_FUR, // DARKPACK EDIT ADD - WEREWOLF "TRAIT_FERA_RENOWN" = TRAIT_FERA_RENOWN, // DARKPACK EDIT ADD - WEREWOLF + "TRAIT_FOMORI_HIDDEN_POWER" = TRAIT_FOMORI_HIDDEN_POWER, // DARKPACK EDIT ADD - FOMORI + "TRAIT_FOMORI_REGEN" = TRAIT_FOMORI_REGEN, // DARKPACK EDIT ADD - FOMORI + "TRAIT_FOMORI_STIGMATA" = TRAIT_FOMORI_STIGMATA, // DARKPACK EDIT ADD - FOMORI "TRAIT_FORCED_EMOTION" = TRAIT_FORCED_EMOTION, // DARKPACK EDIT ADD - Melpominee "TRAIT_FRENETIC_AURA" = TRAIT_FRENETIC_AURA, // DARKPACK EDIT ADD "TRAIT_GHOST_VISION" = TRAIT_GHOST_VISION, // DARKPACK EDIT ADD - POWERS - (Necromancy) diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index a1afca476db3..eb8e7c272ae5 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -374,6 +374,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_CAN_ENTER_TORPOR" = TRAIT_CAN_ENTER_TORPOR, // DARKPACK EDIT ADD "TRAIT_CHARMER" = TRAIT_CHARMER, // DARKPACK EDIT ADD "TRAIT_COFFIN_THERAPY" = TRAIT_COFFIN_THERAPY, // DARKPACK EDIT ADD + "TRAIT_COMBAT_BITE" = TRAIT_COMBAT_BITE, // DARKPACK EDIT ADD "TRAIT_CONSENSUAL_FEEDING_ONLY" = TRAIT_CONSENSUAL_FEEDING_ONLY, // DARKPACK EDIT ADD "TRAIT_DECEPTIVE_AURA" = TRAIT_DECEPTIVE_AURA, // DARKPACK EDIT ADD "TRAIT_DEFICIENT_VITAE" = TRAIT_DEFICIENT_VITAE, // DARKPACK EDIT ADD @@ -389,6 +390,9 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_FEEDING_RESTRICTION" = TRAIT_FEEDING_RESTRICTION, // DARKPACK EDIT ADD "TRAIT_FERA_FUR" = TRAIT_FERA_FUR, // DARKPACK EDIT ADD - WEREWOLF "TRAIT_FERA_RENOWN" = TRAIT_FERA_RENOWN, // DARKPACK EDIT ADD - WEREWOLF + "TRAIT_FOMORI_HIDDEN_POWER" = TRAIT_FOMORI_HIDDEN_POWER, // DARKPACK EDIT ADD - FOMORI + "TRAIT_FOMORI_REGEN" = TRAIT_FOMORI_REGEN, // DARKPACK EDIT ADD - FOMORI + "TRAIT_FOMORI_STIGMATA" = TRAIT_FOMORI_STIGMATA, // DARKPACK EDIT ADD - FOMORI "TRAIT_FRENETIC_AURA" = TRAIT_FRENETIC_AURA, // DARKPACK EDIT ADD "TRAIT_GHOST_VISION" = TRAIT_GHOST_VISION, // DARKPACK EDIT ADD - POWERS - (Necromancy) "TRAIT_GLOWING_EYES" = TRAIT_GLOWING_EYES, // DARKPACK EDIT ADD - MERITS_FLAWS - PHYSICAL FLAWS diff --git a/config/darkpack_config.txt b/config/darkpack_config.txt index 5ba00c7d9d0b..2a839a040a38 100644 --- a/config/darkpack_config.txt +++ b/config/darkpack_config.txt @@ -43,6 +43,7 @@ ROUNDSTART_SPLATS splat_kindred ROUNDSTART_SPLATS splat_ghoul ROUNDSTART_SPLATS splat_kinfolk ROUNDSTART_SPLATS splat_garou +ROUNDSTART_SPLATS splat_fomori ROUNDSTART_SPLATS splat_corax ## If dead people and ghosts can LOOC to people who are alive. diff --git a/modular_darkpack/master_files/code/modules/mob/living/carbon/carbon_defines.dm b/modular_darkpack/master_files/code/modules/mob/living/carbon/carbon_defines.dm index 1c3c3d17781d..254e564d5cc2 100644 --- a/modular_darkpack/master_files/code/modules/mob/living/carbon/carbon_defines.dm +++ b/modular_darkpack/master_files/code/modules/mob/living/carbon/carbon_defines.dm @@ -9,3 +9,7 @@ var/fakediablerist = FALSE var/can_be_embraced = TRUE + //stats for combat bites // used for lupus, crinos, hispo, fomori, etc. + var/list/combat_bite_damages = list(BRUTE = 1 LETHAL_TTRPG_DAMAGE, BURN = 0, TOX = 0, OXY = 0, AGGRAVATED = 0) + var/list/combat_bite_stats = list(STAT_DEXTERITY, STAT_BRAWL) + var/list/combat_bite_difficulty = 5 diff --git a/modular_darkpack/master_files/code/modules/mob/living/carbon/examine.dm b/modular_darkpack/master_files/code/modules/mob/living/carbon/examine.dm index 93619c911c34..b80c61126c54 100644 --- a/modular_darkpack/master_files/code/modules/mob/living/carbon/examine.dm +++ b/modular_darkpack/master_files/code/modules/mob/living/carbon/examine.dm @@ -57,6 +57,16 @@ if(HAS_TRAIT(src, TRAIT_ANIMAL_MUSK)) . += span_warning("[p_they(TRUE)] smell[p_s()] weirdly animal like...
") + if(HAS_TRAIT(src, TRAIT_FOMORI_STIGMATA)) + var/datum/splat/werewolf/dog = get_werewolf_splat(user) + var/datum/quirk/darkpack/stigmata_of_the_wyrm/stigmata = get_quirk(/datum/quirk/darkpack/stigmata_of_the_wyrm) + var/stigmata_descriptor = stigmata.examine_print + + if(dog.tribe?.name == TRIBE_BLACK_SPIRAL_DANCERS || get_fomori_splat(user)) + . += span_warning("[p_They()] bear[p_s()] the Stigmata of the Wyrm, manifesting as [stigmata_descriptor].
") + else + . += span_warning("[p_They()] [p_have()] [stigmata_descriptor].
") + if(HAS_TRAIT(src, TRAIT_GRAVE_SMELL)) . += span_warning("[p_They()] smell[p_s()] like petrichor and freshly turned soil.
") diff --git a/modular_darkpack/modules/blood_drinking/code/bite_keybinding.dm b/modular_darkpack/modules/blood_drinking/code/bite_keybinding.dm index 39fcf252ca67..9c12cfa95be8 100644 --- a/modular_darkpack/modules/blood_drinking/code/bite_keybinding.dm +++ b/modular_darkpack/modules/blood_drinking/code/bite_keybinding.dm @@ -12,6 +12,9 @@ if(ishuman(user.mob)) var/mob/living/carbon/human/human_user = user.mob - human_user.vamp_bite() + if(HAS_TRAIT(human_user, TRAIT_COMBAT_BITE)) + human_user.combat_bite() + else + human_user.vamp_bite() return TRUE diff --git a/modular_darkpack/modules/blood_drinking/code/combat_bite.dm b/modular_darkpack/modules/blood_drinking/code/combat_bite.dm new file mode 100644 index 000000000000..8b6cc4fb605a --- /dev/null +++ b/modular_darkpack/modules/blood_drinking/code/combat_bite.dm @@ -0,0 +1,71 @@ +// Thanks to @hex37 for most of this +/** + * Biting for purposes other than drinking blood + * + * Arguments: + * * pulling - The mob we're biting + * * damage_type - What kind of damage we're doing as a list. If blank, grabs from vars. (ex. list(BRUTE = 0, BURN = 0, TOX = 0, OXY = 0, AGGRAVATED = 0)) + */ +/mob/living/carbon/proc/combat_bite(list/damage_types) + if(!COOLDOWN_FINISHED(src, drinkblood_use_cd) || !COOLDOWN_FINISHED(src, drinkblood_click_cd)) + return + COOLDOWN_START(src, drinkblood_click_cd, 1 SECONDS) + if(!damage_types) + damage_types = combat_bite_damages + + var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE)) + if(skipface) + to_chat(src, span_warning("Take your mask off first!")) + return + + if(grab_state > GRAB_PASSIVE) + if(isliving(pulling)) + var/mob/living/bit_living = pulling + visible_message(span_warning("[src] starts biting [bit_living] with [p_their()] sharp teeth!"), span_warning("You start biting [bit_living] with your sharp teeth!"), span_warning("You hear the sound of flesh tearing!")) + bit_living.emote("scream") + if(ishuman(bit_living)) + var/mob/living/carbon/human/bit_human = bit_living + bit_human.add_bite_animation() + + do_combat_bite(bit_living, damage_types, TRUE) + +/mob/living/carbon/proc/do_combat_bite(mob/living/chewed_on, list/damage_types, first_bite = FALSE) + + COOLDOWN_START(src, drinkblood_use_cd, 3 SECONDS) + + if(isnpc(chewed_on)) + var/mob/living/carbon/human/npc/NPC = chewed_on + NPC.danger_source = null + chewed_on.Stun(10) // NPCs can't resist right away + + if(chewed_on.health < (values_sum(damage_types)*1.5)) + to_chat(src, span_userdanger("Your victim is near death.")) + + if(!do_after(src, 2 SECONDS, target = chewed_on, timed_action_flags = NONE, progress = FALSE)) + stop_chewing(chewed_on) + return + + if(iscarbon(chewed_on)) + var/mob/living/carbon/chewtoy = chewed_on + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/damage/bite + roll_datum.difficulty = combat_bite_difficulty + var/roll_result = roll_datum.st_roll(src, chewtoy)+1 + if(roll_result) + for(var/damage_type, damage_amount in damage_types) + if(roll_result > 0) + chewtoy.apply_damage((damage_amount*roll_result), damage_type, sharpness = SHARP_POINTY) + playsound(get_turf(src), 'sound/items/weapons/bite.ogg', 50, TRUE) + + if(chewtoy.reagents) // We might ingest some blood on accident + if(length(chewtoy.reagents.reagent_list)) + if(prob(15)) // We might ingest some blood on accident + chewtoy.reagents.trans_to(src, min(10, chewtoy.reagents.total_volume), transferred_by = chewed_on, methods = INGEST) + + if(grab_state > GRAB_PASSIVE) + stop_sound_channel(CHANNEL_BLOOD) + do_combat_bite(chewed_on, damage_types) + +/mob/living/carbon/proc/stop_chewing() + stop_sound_channel(CHANNEL_BLOOD) + COOLDOWN_RESET(src, drinkblood_use_cd) + return diff --git a/modular_darkpack/modules/blood_drinking/code/movable_screens/drinkblood_hud.dm b/modular_darkpack/modules/blood_drinking/code/movable_screens/drinkblood_hud.dm index 594c1e6205b8..78ce63ff6242 100644 --- a/modular_darkpack/modules/blood_drinking/code/movable_screens/drinkblood_hud.dm +++ b/modular_darkpack/modules/blood_drinking/code/movable_screens/drinkblood_hud.dm @@ -10,4 +10,7 @@ /atom/movable/screen/drinkblood/proc/bite() if(ishuman(usr)) var/mob/living/carbon/human/human_user = usr - human_user.vamp_bite() + if(HAS_TRAIT(human_user, TRAIT_COMBAT_BITE)) + human_user.combat_bite() + else + human_user.vamp_bite() diff --git a/modular_darkpack/modules/fomori/README.md b/modular_darkpack/modules/fomori/README.md new file mode 100644 index 000000000000..2dac2a5c9c9c --- /dev/null +++ b/modular_darkpack/modules/fomori/README.md @@ -0,0 +1,25 @@ +https://github.com/DarkPack13/SecondCity/pull/953 + +## \ + +Module ID: FOMORI + +### Description: + +This module handles everything related to Fomori and their Powers, Taints, and Merits/Flaws. Dependent on BLOOD_DRINKING for the Combat Bite code. + +### TG Proc/File Changes: + +### Modular Overrides: + +### Defines: + +- N/A + +### Included files that are not contained in this module: + +- modular_darkpack/modules/blood_drinking/code/combat_bite.dm + +### Credits: + +dwinters99 (code), Major00 (sprites), Minzeyes (sprites) ((BLOCK PR IF THIS WARNING IS STILL HERE)), FalloutFallcon (troubleshooting), Chazzyjazzy (for gargoyle wings), hex37 (for blood-drinking code) diff --git a/modular_darkpack/modules/fomori/code/positive_quirks/hidden_power.dm b/modular_darkpack/modules/fomori/code/positive_quirks/hidden_power.dm new file mode 100644 index 000000000000..9e516315931a --- /dev/null +++ b/modular_darkpack/modules/fomori/code/positive_quirks/hidden_power.dm @@ -0,0 +1,15 @@ +/datum/quirk/darkpack/hidden_power // Freak Legion pg.22 + name = "Hidden Power" + desc = {"None of your powers or taints are physically obvious, and can be retracted or otherwise hidden."} + value = 4 + mob_trait = TRAIT_FOMORI_HIDDEN_POWER + gain_text = span_notice("You feel your corruption being hidden.") + lose_text = span_notice("You feel your corruption rise to the forefront.") + icon = FA_ICON_GHOST + allowed_splats = list(SPLAT_FOMORI) + failure_message = "Your corruption is too strong to hide your powers." + +/datum/quirk/darkpack/hidden_power/add() + for(var/datum/action/cooldown/power/fomori_power/power in quirk_holder.actions) + if(power.fomor_part) + power.remove_feature() diff --git a/modular_darkpack/modules/fomori/code/positive_quirks/stigmata_of_the_wyrm.dm b/modular_darkpack/modules/fomori/code/positive_quirks/stigmata_of_the_wyrm.dm new file mode 100644 index 000000000000..3f2a2b9e8ae9 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/positive_quirks/stigmata_of_the_wyrm.dm @@ -0,0 +1,56 @@ +/datum/quirk/darkpack/stigmata_of_the_wyrm // Freak Legion pg.32 + name = "Stigmata of the Wyrm" + desc = {"You have undergone some immense test or trial after total and complete devotion to the Wyrm, + leaving you with some kind of bodily mark that is known to other servants of the Wyrm."} + value = 4 + mob_trait = TRAIT_FOMORI_STIGMATA + gain_text = span_notice("You feel respected by servants of the Wyrm.") + lose_text = span_notice("You feel forsaken by servants of the Wyrm.") + icon = FA_ICON_STRIKETHROUGH + allowed_splats = list(SPLAT_FOMORI) + failure_message = "You feel forsaken by servants of the Wyrm." + var/stigmata // String which effects examine text + var/examine_print + +/datum/quirk/darkpack/stigmata_of_the_wyrm/add(client/client_source) + // add runs before add_unique so we rely on it to decide + if(!stigmata) + stigmata = client_source?.prefs.read_preference(/datum/preference/choiced/stigmata_of_the_wyrm) + +/datum/quirk/darkpack/stigmata_of_the_wyrm/add_unique(client/client_source) + switch(stigmata) + if("scars on palms") + examine_print = "scars on the center of [p_their()] palms" + if("forked tongue") + examine_print = "a forked tongue" + if("hypnotic tattoos") + examine_print = "tattoos that make your head spin" + if("always-open eyes") + examine_print = "eyes that haven't blinked since you've been looking" + if("brand burns") + examine_print = "burns like that of a cattle brand" + +/datum/quirk_constant_data/stigmata_of_the_wyrm_choice + associated_typepath = /datum/quirk/darkpack/stigmata_of_the_wyrm + customization_options = list(/datum/preference/choiced/stigmata_of_the_wyrm) + +/datum/preference/choiced/stigmata_of_the_wyrm + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "stigmata_of_the_wyrm" + savefile_identifier = PREFERENCE_CHARACTER + +/datum/preference/choiced/stigmata_of_the_wyrm/init_possible_values() + return list("scars on palms", "forked tongue", "hypnotic tattoos", "always-open eyes", "brand burns") + +/datum/preference/choiced/stigmata_of_the_wyrm/create_default_value() + return "scars on palms" + +/datum/preference/choiced/stigmata_of_the_wyrm/is_accessible(datum/preferences/preferences) + . = ..() + if (!.) + return FALSE + + return /datum/quirk/darkpack/stigmata_of_the_wyrm::name in preferences.all_quirks + +/datum/preference/choiced/stigmata_of_the_wyrm/apply_to_human(mob/living/carbon/human/target, value) + return diff --git a/modular_darkpack/modules/fomori/code/powers/_fomori_power.dm b/modular_darkpack/modules/fomori/code/powers/_fomori_power.dm new file mode 100644 index 000000000000..b53047534114 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/_fomori_power.dm @@ -0,0 +1,81 @@ +// Presently a dummy placeholder, might want to do stuff like flavor the ui, change the dice roll, make fomori_powers private by default or the like +/datum/storyteller_roll/fomori_power + +/datum/action/cooldown/power/fomori_power + background_icon = 'modular_darkpack/modules/fomori/icons/fomori_abilities.dmi' + background_icon_state = "bg_fomori_power" + button_icon = 'modular_darkpack/modules/fomori/icons/fomori_abilities.dmi' + //button_icon_state = "" + overlay_icon = 'modular_darkpack/modules/fomori/icons/fomori_abilities.dmi' + + check_flags = AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS + + // Snowflake toggle behavior + var/deployed = FALSE + + // Body feature for horns, fangs, etc. + var/datum/bodypart_overlay/simple/fomor_part + // What bodypart are we putting our feature on? + var/feature_bodypart = BODY_ZONE_HEAD + + // What organ are we adding? + var/obj/item/organ/fomor_organ + // Where are we inserting it? + var/fomor_organ_slot + // Do we violate the veil if seen? Only used for the overlays + var/masq_violating_overlay = TRUE + +/atom/movable/screen/alert/status_effect/fomori_power + icon = 'modular_darkpack/modules/fomori/icons/fomori_abilities.dmi' + icon_state = "bg_fomori_power" + overlay_icon = 'modular_darkpack/modules/fomori/icons/fomori_abilities.dmi' + +/datum/action/cooldown/power/fomori_power/Grant(mob/granted_to) + . = ..() + if(!istype(granted_to, /mob/living/carbon/human/dummy) && !isnull(fomor_part)) + add_feature() + +///checks if we lose a limb a feature is attached to +/datum/action/cooldown/power/fomori_power/proc/on_removed_limb(datum/source, obj/item/bodypart/removed_limb, special, dismembered) + SIGNAL_HANDLER + + var/mob/living/carbon/human/carbon_owner = astype(owner, /mob/living/carbon) + var/obj/item/bodypart/bodypart = carbon_owner.get_bodypart(feature_bodypart) + + if(fomor_part && istype(removed_limb, bodypart.type)) + remove_feature() + +///for adding fomor features i.e. fangs, horns +/datum/action/cooldown/power/fomori_power/proc/add_feature() + var/mob/living/carbon/human/fomor = owner + var/obj/item/bodypart/bodypart = fomor?.get_bodypart(feature_bodypart) + + if(isnull(bodypart)) + return + + if(isnull(fomor_part)) + return + + fomor_part = new fomor_part() //creates our overlay + bodypart.add_bodypart_overlay(fomor_part) + if(masq_violating_overlay) + SEND_SIGNAL(owner, COMSIG_MASQUERADE_VIOLATION) + +///removes the fomor feature +/datum/action/cooldown/power/fomori_power/proc/remove_feature() + var/mob/living/carbon/human/fomor = owner + var/obj/item/bodypart/bodypart = fomor?.get_bodypart(feature_bodypart) + bodypart?.remove_bodypart_overlay(fomor_part) + QDEL_NULL(fomor_part) + fomor_part = initial(fomor_part) + +///toggles the feature, TRUE for remove and FALSE for add +/datum/action/cooldown/power/fomori_power/proc/toggle_feature(current_state) + if(current_state) + if(!HAS_TRAIT(owner, TRAIT_FOMORI_HIDDEN_POWER)) + return FALSE + remove_feature() + else + add_feature() + + return TRUE diff --git a/modular_darkpack/modules/fomori/code/powers/_fomori_power_weapon.dm b/modular_darkpack/modules/fomori/code/powers/_fomori_power_weapon.dm new file mode 100644 index 000000000000..b193e46fbb47 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/_fomori_power_weapon.dm @@ -0,0 +1,53 @@ +/datum/action/cooldown/power/fomori_power/weapon + name = "fomor weapon power" + desc = "Report on github if you see this!" + cooldown_time = 1 TURNS // Can't sheathe/unsheathe for at least 5 seconds after use + + shared_cooldown = MOB_SHARED_COOLDOWN_2 + + feature_bodypart = null // Makes the overlay code skip us unless we define on subtype + + fomor_part = "none" // So code that checks for fomor_part catches us + + var/sheathe_text = "Your skub melts back into your skin." + + var/weapon_type = /obj/item/skub + var/unsheathe_sound = 'sound/effects/blob/blobattack.ogg' + var/sheathe_sound = 'sound/effects/meatslap.ogg' + + var/obj/item/weapon // The item we spawned of type weapon_type + var/obj/item/weapon_offhand // The item we spawned in our offhand of type weapon_type + +/datum/action/cooldown/power/fomori_power/weapon/Activate(atom/target) + var/obj/item/held = owner.get_active_held_item() + var/obj/item/off_held = owner.get_inactive_held_item() + if(held && off_held && deployed) + qdel(held) + qdel(off_held) + to_chat(owner, span_warning(sheathe_text)) + playsound(get_turf(owner), sheathe_sound, 50) + deployed = FALSE + return + + if(held && !owner.dropItemToGround(held)) + owner.balloon_alert(owner, "hand occupied!") + return FALSE + else if(off_held && !owner.dropItemToGround(off_held)) + owner.balloon_alert(owner, "off-hand occupied!") + return FALSE + + . = ..() + + weapon = new weapon_type(owner) + weapon_offhand = new weapon_type(owner) + + deployed = TRUE + + playsound(get_turf(owner), unsheathe_sound, 50) + owner.put_in_l_hand(weapon) + owner.put_in_r_hand(weapon_offhand) + + + + + diff --git a/modular_darkpack/modules/fomori/code/powers/mental/berserker.dm b/modular_darkpack/modules/fomori/code/powers/mental/berserker.dm new file mode 100644 index 000000000000..8d3cef34c1cd --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/mental/berserker.dm @@ -0,0 +1 @@ +// Freak Legion pg.30 // This file is here to hold a place! A placeholder! Need to wait for pointbuy to be implemented for this to exist. diff --git a/modular_darkpack/modules/fomori/code/powers/mental/corrupted_visions.dm b/modular_darkpack/modules/fomori/code/powers/mental/corrupted_visions.dm new file mode 100644 index 000000000000..350cb208d555 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/mental/corrupted_visions.dm @@ -0,0 +1,45 @@ +/datum/storyteller_roll/corrupted_visions // Freak Legion pg.31-32 + bumper_text = "corrupted visions" + difficulty = 8 + applicable_stats = list(STAT_MANIPULATION, STAT_SUBTERFUGE) + numerical = TRUE + roll_output_type = ROLL_PRIVATE + +/datum/action/cooldown/power/fomori_power/corrupted_visions + name = "Corrupted Visions" + desc = "Spend a willpower point to induce hallucinations in your prey." + button_icon_state = "corrupted_visions" + rank = 1 // of 1 + click_to_activate = TRUE + willpower_cost = 1 + +/datum/action/cooldown/power/fomori_power/corrupted_visions/Activate(atom/target) + if(!isliving(target)) + return FALSE + + var/mob/living/victim = target + + . = ..() + + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/corrupted_visions + var/roll_result = roll_datum.st_roll(owner) + + to_chat(owner, span_purple("You attempt to induce visions in [target]...")) + + SEND_SOUND(owner, 'modular_darkpack/modules/deprecated/sounds/insanity.ogg') + SEND_SOUND(victim, 'modular_darkpack/modules/deprecated/sounds/insanity.ogg') + + + if(roll_result > 0) + if(!victim.has_quirk(/datum/quirk/darkpack/derangement)) + victim.add_quirk(/datum/quirk/darkpack/derangement) + addtimer(CALLBACK(src, PROC_REF(end_visions), victim), roll_result TURNS) + else + to_chat(owner, span_warning("[victim] doesn't seem bothered by their visions...")) + to_chat(victim, span_hypnophrase("The FREAK attempts to disturb the disturbed...")) + + StartCooldown() + return TRUE + +/datum/action/cooldown/power/fomori_power/corrupted_visions/proc/end_visions(mob/living/victim) + victim.remove_quirk(/datum/quirk/darkpack/derangement) diff --git a/modular_darkpack/modules/fomori/code/powers/mental/deception.dm b/modular_darkpack/modules/fomori/code/powers/mental/deception.dm new file mode 100644 index 000000000000..d8ab1e0223eb --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/mental/deception.dm @@ -0,0 +1,31 @@ +/datum/storyteller_roll/deception // Freak Legion pg.32 + bumper_text = "deception" + difficulty = 8 + applicable_stats = list(STAT_WITS, STAT_SUBTERFUGE) + numerical = TRUE + roll_output_type = ROLL_PRIVATE + +/datum/action/cooldown/power/fomori_power/deception + name = "Deception" + desc = "Spend a willpower point to disguise your taint from those capable of percieving it." + button_icon_state = "deception" + rank = 1 // of 1 + click_to_activate = TRUE + willpower_cost = 1 + +/datum/action/cooldown/power/fomori_power/deception/Activate(atom/target) + if(!isliving(target)) + return FALSE + if(!(target in range(1, owner))) + return FALSE + + var/mob/living/victim = target + + . = ..() + + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/deception + var/roll_result = roll_datum.st_roll(owner) + + StartCooldown() + return TRUE +#warn DECEPTION UNFINISHED diff --git a/modular_darkpack/modules/fomori/code/powers/mental/eyes_of_the_wyrm.dm b/modular_darkpack/modules/fomori/code/powers/mental/eyes_of_the_wyrm.dm new file mode 100644 index 000000000000..025766c73d1f --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/mental/eyes_of_the_wyrm.dm @@ -0,0 +1,33 @@ +/datum/storyteller_roll/eyes_of_the_wyrm // For defending // Freak Legion pg.32-33 + bumper_text = "eyes_of_the_wyrm" + difficulty = 8 + applicable_stats = list(STAT_TEMPORARY_WILLPOWER) + roll_output_type = ROLL_PRIVATE + +/datum/action/cooldown/power/fomori_power/eyes_of_the_wyrm + name = "Eyes of the Wyrm" + desc = "(UNFINISHED) Shock your prey into immobility with the Wyrm's Damnation." + button_icon_state = "eyes_of_the_wyrm" + rank = 1 // of 1 + click_to_activate = TRUE + willpower_cost = 1 + +/datum/action/cooldown/power/fomori_power/eyes_of_the_wyrm/Activate(atom/target) + if(!isliving(target)) + return FALSE + if(!(target in range(1, owner))) + return FALSE + + var/mob/living/victim = target + + . = ..() + + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/eyes_of_the_wyrm + var/roll_result = roll_datum.st_roll(victim) + + if(roll_result != ROLL_SUCCESS) + + StartCooldown() + return TRUE + +#warn EYES OF THE WYRM UNFINISHED diff --git a/modular_darkpack/modules/fomori/code/powers/mental/mind_blast.dm b/modular_darkpack/modules/fomori/code/powers/mental/mind_blast.dm new file mode 100644 index 000000000000..24c3b82842fd --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/mental/mind_blast.dm @@ -0,0 +1,57 @@ +/obj/item/ammo_casing/magic/fomor_mind_blast + projectile_type = /obj/projectile/mind_blast + icon_state = "" + +/obj/projectile/mind_blast + name = "mind blast" + icon_state = "scatterdisabler" // Could prob get a better icon for this + damage = 0 + alpha = 128 + +/datum/storyteller_roll/mind_blast + bumper_text = "mind blast" + difficulty = 6 + applicable_stats = list(STAT_WITS, STAT_INTIMIDATION) + numerical = TRUE + roll_output_type = ROLL_PRIVATE + +/datum/storyteller_roll/mind_blast/defender + bumper_text = "willpower" + applicable_stats = list(STAT_TEMPORARY_WILLPOWER) + numerical = TRUE + +/datum/action/cooldown/power/fomori_power/mind_blast + name = "Mind Blast" + desc = "Spend a willpower point to shock the mind of a victim." + button_icon_state = "mind_blast" + rank = 1 // of 1 + click_to_activate = TRUE + willpower_cost = 1 + +/datum/action/cooldown/power/fomori_power/mind_blast/Activate(atom/target) + if(!isliving(target)) + return FALSE + + var/mob/living/victim = target + + . = ..() + + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/mind_blast + var/ourpower = roll_datum.st_roll(owner) + + var/datum/storyteller_roll/defender_datum = new /datum/storyteller_roll/mind_blast/defender + var/theirpower = defender_datum.st_roll(target) + + + if(ourpower > theirpower) + var/obj/item/ammo_casing/magic/fomor_mind_blast/casing = new (owner.loc) + casing.fire_casing(victim, owner, null, null, null, ran_zone(), 0, owner) + if(ishuman(victim)) + victim.emote("groan") + + victim.Stun((ourpower TURNS)) // TODO: Make this an actual skillshot + + StartCooldown() + return TRUE + + diff --git a/modular_darkpack/modules/fomori/code/powers/mental/mind_reave.dm b/modular_darkpack/modules/fomori/code/powers/mental/mind_reave.dm new file mode 100644 index 000000000000..6b4767b25a20 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/mental/mind_reave.dm @@ -0,0 +1,80 @@ +/datum/storyteller_roll/mind_reave + bumper_text = "mind reave" + difficulty = 6 + applicable_stats = list(STAT_INTELLIGENCE, STAT_INTIMIDATION) + numerical = TRUE + roll_output_type = ROLL_PRIVATE + +/datum/storyteller_roll/mind_reave/defender + bumper_text = "willpower" + applicable_stats = list(STAT_TEMPORARY_WILLPOWER) + numerical = FALSE + roll_output_type = ROLL_NONE + +/datum/action/cooldown/power/fomori_power/mind_reave + name = "Mind Reave" + desc = "Spend a willpower point to rest thoughts and memories from a victim's mind." + button_icon_state = "mind_reave" + rank = 1 // of 1 + click_to_activate = TRUE + willpower_cost = 1 + +/datum/action/cooldown/power/fomori_power/mind_reave/Activate(atom/target) + if(!isliving(target)) + return FALSE + + var/mob/living/victim = target + + . = ..() + + to_chat(owner, span_warning("You begin to probe into the mind of [victim]...")) + + if(!do_after(owner, 1 TURNS, victim)) + to_chat(owner, span_userdanger("...but you stop short of getting anything out of it.")) + + StartCooldown() + return TRUE + + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/mind_reave + var/ourpower = roll_datum.st_roll(owner) + + var/datum/storyteller_roll/defender_datum = new /datum/storyteller_roll/mind_reave/defender + var/theirpower = defender_datum.st_roll(owner) + + + if(ourpower > theirpower) + to_chat(victim, span_userdanger("You feel your mind being ravaged by malignant energy!")) + SEND_SOUND(victim, sound('sound/effects/magic/clockwork/invoke_general.ogg', volume = 50)) + + var/successes = ourpower - theirpower + var/demand_text + + switch(successes) + if(1) + demand_text = "surface level thoughts such as emotions or current thoughts" + if(2) + demand_text = "deep thoughts like recent memories or strong opinions" + if(3 to INFINITY) + demand_text = "your deepest and most instinctual thoughts, feelings, or secrets" + + var/composed_message = "The malignant energy probing your mind reaches for [demand_text]. What does it learn?" + + var/input_text = tgui_input_text(victim, composed_message, "Mind Reave", CHAT_MESSAGE_MAX_LENGTH, multiline = TRUE, timeout = 30 SECONDS) + victim.Stun(30 SECONDS, TRUE) + + message_admins("[ADMIN_LOOKUPFLW(owner)] used [src] on [ADMIN_LOOKUPFLW(victim)] with [successes] successes.") + + if(input_text) + message_admins("[ADMIN_LOOKUPFLW(victim)] responded to [ADMIN_LOOKUPFLW(owner)]'s Mind Reave: \"[input_text]\".") + to_chat(owner, span_bolddanger("Your power wrests the following information from [victim]: \"[input_text]\"")) + to_chat(owner, span_bolddanger("Your feel your mind surrender the following information to [owner]: \"[input_text]\"")) + victim.SetStun(1 TURNS) + else + message_admins("[ADMIN_LOOKUPFLW(victim)] failed or declined to respond to [ADMIN_LOOKUPFLW(owner)]'s Mind Reave.") + to_chat(owner, span_userdanger("[victim]'s mind buckles under the pressure of your mental energy!")) + to_chat(victim, span_userdanger("Your mind buckles under the pressure of [owner]'s mental energy!")) + victim.Sleeping(30 SECONDS) + + StartCooldown() + return TRUE +#warn MIND REAVE NEEDS 2 CLIENT TESTING diff --git a/modular_darkpack/modules/fomori/code/powers/mental/numbing.dm b/modular_darkpack/modules/fomori/code/powers/mental/numbing.dm new file mode 100644 index 000000000000..a0b6fa9cc67e --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/mental/numbing.dm @@ -0,0 +1,46 @@ +/datum/storyteller_roll/numbing + bumper_text = "numbing" + applicable_stats = list(STAT_STAMINA, STAT_MEDICINE) + +/datum/action/cooldown/power/fomori_power/numbing + name = "Numbing" + desc = "Spend a willpower point to temporarily feel no pain." + button_icon_state = "numbing" + rank = 1 // of 1 + willpower_cost = 1 + cooldown_time = 1 SCENES + var/beforehealth + var/afterhealth + +/datum/action/cooldown/power/fomori_power/numbing/Activate() + . = ..() + var/mob/living/caster = owner + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/numbing + var/roll_result = roll_datum.st_roll(owner) + + if(roll_result == ROLL_SUCCESS) + if(!caster.has_quirk(/datum/quirk/numb)) + caster.apply_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy, type) + caster.add_traits(list(TRAIT_ANALGESIA, TRAIT_NO_DAMAGE_OVERLAY), "fomor_numbing") + addtimer(CALLBACK(src, PROC_REF(end_numbness)), 1 SCENES) + + beforehealth = caster.health + caster.heal_storyteller_health(3) + afterhealth = caster.health + var/obj/item/organ/tongue/our_tongue = owner.get_organ_slot(ORGAN_SLOT_TONGUE) + if(our_tongue) + our_tongue.on_begin_failure() + + StartCooldown() + return TRUE + +/datum/action/cooldown/power/fomori_power/numbing/proc/end_numbness() + var/mob/living/caster = owner + + caster.remove_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy, type) + caster.remove_traits(list(TRAIT_ANALGESIA, TRAIT_NO_DAMAGE_OVERLAY), "fomor_numbing") + caster.take_overall_damage(brute = abs(afterhealth-beforehealth)) + + var/obj/item/organ/tongue/our_tongue = owner.get_organ_slot(ORGAN_SLOT_TONGUE) + if(our_tongue) + our_tongue.on_failure_recovery() diff --git a/modular_darkpack/modules/fomori/code/powers/physical/body_barbs.dm b/modular_darkpack/modules/fomori/code/powers/physical/body_barbs.dm new file mode 100644 index 000000000000..13cf670869d3 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/body_barbs.dm @@ -0,0 +1,111 @@ +/obj/item/melee/body_barbs // Largely copied from changeling armblade // Freak Legion pg.30 + name = "body barb" + icon = 'modular_darkpack/modules/fomori/icons/fomori_items48x32.dmi' + icon_state = "body_barb" + inhand_icon_state = "body_barb" + lefthand_file = 'modular_darkpack/modules/fomori/icons/fomori_inhand_left.dmi' + righthand_file = 'modular_darkpack/modules/fomori/icons/fomori_inhand_right.dmi' + item_flags = ABSTRACT | DROPDEL + w_class = WEIGHT_CLASS_HUGE + force = 10 + damtype = AGGRAVATED + throwforce = 0 + throw_range = 0 + throw_speed = 0 + hitsound = 'sound/items/weapons/bladeslice.ogg' + wound_bonus = 10 + exposed_wound_bonus = 10 + armour_penetration = 35 + attack_verb_continuous = list("attacks", "slashes", "slices", "tears", "lacerates", "rips", "dices", "cuts") + attack_verb_simple = list("attack", "slash", "slice", "tear", "lacerate", "rip", "dice", "cut") + sharpness = SHARP_EDGED + wound_bonus = 10 + exposed_wound_bonus = 10 + armour_penetration = 35 + var/list/alt_continuous = list("stabs", "pierces", "impales") + var/list/alt_simple = list("stab", "pierce", "impale") + + attack_difficulty = 7 + + abstract_type = /obj/item/melee/body_barbs + +/obj/item/melee/body_barbs/Initialize(mapload,silent) // Largely copied from changeling armblade + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, INNATE_TRAIT) + alt_continuous = string_list(alt_continuous) + alt_simple = string_list(alt_simple) + AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -5) + AddComponent(/datum/component/butchering, \ + speed = 6 SECONDS, \ + effectiveness = 80, \ + ) + +/datum/bodypart_overlay/simple/fomor_body_barbs + icon_state = "body_barb" + icon = 'modular_darkpack/modules/fomori/icons/fomori_inhand_right.dmi' + layers = MUTATIONS_LAYER + var/bodyzone = BODY_ZONE_R_ARM + var/obj/item/bodypart/assigned_bodyzone + +/datum/bodypart_overlay/simple/fomor_body_barbs/l_arm + icon_state = "body_barb" + icon = 'modular_darkpack/modules/fomori/icons/fomori_inhand_left.dmi' + bodyzone = BODY_ZONE_L_ARM + +/datum/action/cooldown/power/fomori_power/weapon/body_barbs + name = "Body Barbs" + desc = "Use the grotesque spikes on your body to amplify your brawling ability." + button_icon_state = "body_barbs" + rank = 1 // of 5 // Determines how many extra dice we get, 2 points and 1 dice/level + weapon_type = /obj/item/melee/body_barbs + sheathe_text = "Your body barbs retract into your arms." + + var/list/overlay_list = list() + var/r_arm_overlay = /datum/bodypart_overlay/simple/fomor_body_barbs + var/l_arm_overlay = /datum/bodypart_overlay/simple/fomor_body_barbs/l_arm + +/datum/action/cooldown/power/fomori_power/weapon/body_barbs/Activate(atom/target) + . = ..() + weapon.force = rank LETHAL_TTRPG_DAMAGE + weapon_offhand.force = rank LETHAL_TTRPG_DAMAGE + + if(deployed) + owner.visible_message(span_warning("A pair of grotesque barbs extend from [owner]\'s arms!"), \ + span_warning("Your body barbs extend from your arms."), \ + span_hear("You hear organic matter ripping and tearing!")) + SEND_SIGNAL(owner, COMSIG_MASQUERADE_VIOLATION) + +/datum/action/cooldown/power/fomori_power/weapon/body_barbs/two + rank = 2 + +/datum/action/cooldown/power/fomori_power/weapon/body_barbs/three + rank = 3 + +/datum/action/cooldown/power/fomori_power/weapon/body_barbs/four + rank = 4 +/datum/action/cooldown/power/fomori_power/weapon/body_barbs/five + rank = 5 + +/datum/action/cooldown/power/fomori_power/weapon/body_barbs/add_feature() + var/mob/living/carbon/human/fomor = owner + + overlay_list = list(new r_arm_overlay, new l_arm_overlay) + + for(var/datum/bodypart_overlay/simple/fomor_body_barbs/bp_overlay in overlay_list) + bp_overlay.assigned_bodyzone = fomor?.get_bodypart(bp_overlay.bodyzone) + if(isnull(bp_overlay.assigned_bodyzone)) + qdel(bp_overlay) + continue + bp_overlay.assigned_bodyzone.add_bodypart_overlay(bp_overlay) + +///removes the fomor feature +/datum/action/cooldown/power/fomori_power/weapon/body_barbs/remove_feature() + var/mob/living/carbon/human/fomor = owner + if(HAS_TRAIT(owner, TRAIT_FOMORI_HIDDEN_POWER)) + for(var/datum/bodypart_overlay/simple/fomor_body_barbs/bp_overlay in overlay_list) + bp_overlay.assigned_bodyzone = fomor?.get_bodypart(bp_overlay.bodyzone) + bp_overlay.assigned_bodyzone.remove_bodypart_overlay(bp_overlay) + qdel(bp_overlay) + overlay_list = list() + +#warn BODY BARBS UNFINISHED - Need to factor rank into damage diff --git a/modular_darkpack/modules/fomori/code/powers/physical/chameleon_coloration.dm b/modular_darkpack/modules/fomori/code/powers/physical/chameleon_coloration.dm new file mode 100644 index 000000000000..6e484fa3d57d --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/chameleon_coloration.dm @@ -0,0 +1,50 @@ +/datum/action/cooldown/power/fomori_power/chameleon_coloration // Freak Legion pg.31 + name = "Chameleon Coloration" + desc = "Blend into the background to strike unseen." + button_icon_state = "chameleon_coloration" + rank = 1 // of 1 + + var/activated = FALSE + +/datum/action/cooldown/power/fomori_power/chameleon_coloration/Activate(atom/target) + . = ..() + if(activated) + activated = FALSE + owner.alpha = 255 + UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_UNARMED_ATTACK)) + else + activated = TRUE + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + RegisterSignal(owner, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + var/mob/living/living_owner = astype(owner) + living_owner.apply_status_effect(/datum/status_effect/chameleon_coloration) + +/datum/action/cooldown/power/fomori_power/chameleon_coloration/proc/on_move(atom/movable/source, atom/old_loc, move_dir, forced, list/atom/old_locs) + SIGNAL_HANDLER + + owner.alpha = 200 + +/datum/action/cooldown/power/fomori_power/chameleon_coloration/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, list/modifiers) + SIGNAL_HANDLER + + if(!proximity) + return + owner.alpha = 200 + +/datum/status_effect/chameleon_coloration + id = "chameleon_coloration" + duration = INFINITY + + status_type = STATUS_EFFECT_UNIQUE + + alert_type = /atom/movable/screen/alert/status_effect/chameleon_coloration + +/datum/status_effect/chameleon_coloration/tick(seconds_per_tick) + . = ..() + owner.alpha = max(owner.alpha - 50, 0) // TODO: use animate magic to make this look better + +/atom/movable/screen/alert/status_effect/chameleon_coloration + name = "Chameleon Coloration" + desc = "You are blending in with your surroundings." + icon = 'modular_darkpack/modules/deprecated/icons/hud/screen_alert.dmi' + icon_state = "riddle" // TODO: get an icon for this diff --git a/modular_darkpack/modules/fomori/code/powers/physical/claws.dm b/modular_darkpack/modules/fomori/code/powers/physical/claws.dm new file mode 100644 index 000000000000..098de62d2f41 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/claws.dm @@ -0,0 +1,75 @@ +/obj/item/knife/fomor_claws // Just a normal knife, but part of our hands! // Freak Legion pg.31 + name = "claw" + icon = 'modular_darkpack/modules/fomori/icons/fomori_items48x32.dmi' + icon_state = "claw" + inhand_icon_state = "claw" + lefthand_file = 'modular_darkpack/modules/fomori/icons/fomori_inhand_left.dmi' + righthand_file = 'modular_darkpack/modules/fomori/icons/fomori_inhand_right.dmi' + icon_angle = 0 + item_flags = ABSTRACT | DROPDEL + w_class = WEIGHT_CLASS_HUGE + throwforce = 0 + throw_speed = 0 + throw_range = 0 + + abstract_type = /obj/item/knife/fomor_claws + +/obj/item/knife/fomor_claws/Initialize(mapload,silent) // Largely copied from changeling armblade + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, INNATE_TRAIT) + AddComponent(/datum/component/alternative_sharpness, SHARP_POINTY, alt_continuous, alt_simple, -5) + +/datum/bodypart_overlay/simple/fomor_claws + icon_state = "claw" + icon = 'modular_darkpack/modules/fomori/icons/fomori_inhand_right.dmi' + layers = MUTATIONS_LAYER + var/bodyzone = BODY_ZONE_R_ARM + var/obj/item/bodypart/assigned_bodyzone + +/datum/bodypart_overlay/simple/fomor_claws/l_arm + icon_state = "claw" + icon = 'modular_darkpack/modules/fomori/icons/fomori_inhand_left.dmi' + bodyzone = BODY_ZONE_L_ARM + + +/datum/action/cooldown/power/fomori_power/weapon/claws + name = "Claws" + desc = "Use the grotesque claws on your hands to slice and dice." + button_icon_state = "claws" + rank = 1 // of 1 + weapon_type = /obj/item/knife/fomor_claws + unsheathe_sound = 'sound/items/weapons/parry.ogg' + sheathe_text = "Your claws retract into your arms." + + var/list/overlay_list = list() + var/r_arm_overlay = /datum/bodypart_overlay/simple/fomor_claws + var/l_arm_overlay = /datum/bodypart_overlay/simple/fomor_claws/l_arm + +/datum/action/cooldown/power/fomori_power/weapon/claws/Activate(atom/target) + . = ..() + if(deployed) + owner.visible_message(span_warning("A pair of grotesque claws extend from [owner]\'s hands!"), \ + span_warning("Your claws extend from your hands."), \ + span_hear("You hear organic matter ripping and tearing!")) + +/datum/action/cooldown/power/fomori_power/weapon/claws/add_feature() + var/mob/living/carbon/human/fomor = owner + + overlay_list = list(new r_arm_overlay, new l_arm_overlay) + + for(var/datum/bodypart_overlay/simple/fomor_claws/bp_overlay in overlay_list) + bp_overlay.assigned_bodyzone = fomor?.get_bodypart(bp_overlay.bodyzone) + if(isnull(bp_overlay.assigned_bodyzone)) + qdel(bp_overlay) + continue + bp_overlay.assigned_bodyzone.add_bodypart_overlay(bp_overlay) + +/datum/action/cooldown/power/fomori_power/weapon/claws/remove_feature() + var/mob/living/carbon/human/fomor = owner + for(var/datum/bodypart_overlay/simple/fomor_claws/bp_overlay in overlay_list) + bp_overlay.assigned_bodyzone = fomor?.get_bodypart(bp_overlay.bodyzone) + bp_overlay.assigned_bodyzone.remove_bodypart_overlay(bp_overlay) + qdel(bp_overlay) + overlay_list = list() + +#warn CLAWS SOFT FINISHED - Needs melee damage stats diff --git a/modular_darkpack/modules/fomori/code/powers/physical/darksight.dm b/modular_darkpack/modules/fomori/code/powers/physical/darksight.dm new file mode 100644 index 000000000000..11cb4f6512bd --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/darksight.dm @@ -0,0 +1,34 @@ +/datum/action/cooldown/power/fomori_power/darksight // Freak Legion pg.32 // TODO: Make this work with more light sources + name = "Darksight" + desc = "See in the dark unbidden, but beware bright lights." + button_icon_state = "darksight" + rank = 1 // of 1 + + check_flags = AB_CHECK_CONSCIOUS + cooldown_time = 1 SECONDS // So we don't click too fast + + var/activated = FALSE + +/datum/action/cooldown/power/fomori_power/darksight/Activate(atom/target) + . = ..() + to_chat(owner, span_notice("You [activated ? "activate" : "deactivate"] Darksight.")) + if(activated) + activated = FALSE + REMOVE_TRAIT(owner, TRAIT_TRUE_NIGHT_VISION, "fomor_darksight") + owner.remove_client_colour("fomor_darksight") + UnregisterSignal(owner, COMSIG_MOB_FLASHED, PROC_REF(on_flashed)) + else + activated = TRUE + ADD_TRAIT(owner, TRAIT_TRUE_NIGHT_VISION, "fomor_darksight") + owner.add_client_colour(/datum/client_colour/monochrome, "fomor_darksight") + RegisterSignal(owner, COMSIG_MOB_FLASHED) + owner.update_sight() + +/datum/action/cooldown/power/fomori_power/darksight/proc/on_flashed() + SIGNAL_HANDLER + + var/mob/living/carbon/carbon_owner = owner + var/our_perception = carbon_owner.st_get_stat(STAT_PERCEPTION) + carbon_owner.Stun(our_perception TURNS) // Stunned 1 TURNS per dot in perception + if(our_perception > 1) + to_chat(owner, span_userdanger("Your enhanced vision causes you to be stunned for an extra [our_perception] turns!")) diff --git a/modular_darkpack/modules/fomori/code/powers/physical/ectoplasmic_extrusion.dm b/modular_darkpack/modules/fomori/code/powers/physical/ectoplasmic_extrusion.dm new file mode 100644 index 000000000000..c9389ec9cdcb --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/ectoplasmic_extrusion.dm @@ -0,0 +1,28 @@ +/datum/bodypart_overlay/simple/ectoplasmic_extrusion // Freak Legion pg.32 + icon_state = "ectoplasmic_extrusion" + icon = 'modular_darkpack/modules/fomori/icons/fomori_sprite_accessories.dmi' + layers = LOW_FACEMASK_LAYER + +/datum/action/cooldown/power/fomori_power/weapon/ectoplasmic_extrusion + name = "Ectoplasmic Extrusion" + desc = "(UNIMPLEMENTED) Sprout grotesque tendrils from your back to use as extra hands or as a weapon." + button_icon_state = "ectoplasmic_extrusion" + rank = 1 // of 1 + +// weapon_type = /obj/item/melee/ectoplasmic_extrusion + sheathe_text = "Your ectoplasmic tendrils retract into your body." + + fomor_part = /datum/bodypart_overlay/simple/ectoplasmic_extrusion + feature_bodypart = BODY_ZONE_CHEST + +/datum/action/cooldown/power/fomori_power/horns/Activate(atom/target) + . = ..() + toggle_feature(deployed) + + if(deployed) + deployed = FALSE + else + deployed = TRUE + SEND_SIGNAL(owner, COMSIG_MASQUERADE_VIOLATION) + +#warn ECTOPLASMIC EXTRUSION UNFINISHED diff --git a/modular_darkpack/modules/fomori/code/powers/physical/exoskeleton.dm b/modular_darkpack/modules/fomori/code/powers/physical/exoskeleton.dm new file mode 100644 index 000000000000..ed968502a24f --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/exoskeleton.dm @@ -0,0 +1,96 @@ +/datum/bodypart_overlay/simple/fomor_exoskeleton // Freak Legion pg.32 + icon_state = "exoskeleton" + icon = 'modular_darkpack/modules/fomori/icons/fomori_sprite_accessories.dmi' + layers = BENEATH_HAIR_LAYER + var/bodyzone = BODY_ZONE_CHEST + var/obj/item/bodypart/assigned_bodyzone + +/datum/bodypart_overlay/simple/fomor_exoskeleton/head + icon_state = "exoskeleton-head" + bodyzone = BODY_ZONE_HEAD + +/datum/bodypart_overlay/simple/fomor_exoskeleton/r_arm + icon_state = "exoskeleton-r_arm" + bodyzone = BODY_ZONE_R_ARM + layers = MUTATIONS_LAYER + +/datum/bodypart_overlay/simple/fomor_exoskeleton/l_arm + icon_state = "exoskeleton-l_arm" + bodyzone = BODY_ZONE_L_ARM + layers = HALO_LAYER + +/datum/bodypart_overlay/simple/fomor_exoskeleton/r_leg + icon_state = "exoskeleton-r_leg" + bodyzone = BODY_ZONE_R_LEG + +/datum/bodypart_overlay/simple/fomor_exoskeleton/l_leg + icon_state = "exoskeleton-l_leg" + bodyzone = BODY_ZONE_L_LEG + +/datum/bodypart_overlay/simple/fomor_fangs/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE) + return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEFACE) + +/datum/action/cooldown/power/fomori_power/exoskeleton + name = "Exoskeleton" + desc = "Form a thick carapace around your body, protecting you from harm and increasing your strength." + button_icon_state = "exoskeleton" + rank = 1 // of 1 + + fomor_part = "none" // So we get caught by code that checks if we have a fomor_part + //Snowflake code + var/list/overlay_list = list() + + var/chest_overlay = /datum/bodypart_overlay/simple/fomor_exoskeleton + var/head_overlay = /datum/bodypart_overlay/simple/fomor_exoskeleton/head + var/r_arm_overlay = /datum/bodypart_overlay/simple/fomor_exoskeleton/r_arm + var/l_arm_overlay = /datum/bodypart_overlay/simple/fomor_exoskeleton/l_arm + var/r_leg_overlay = /datum/bodypart_overlay/simple/fomor_exoskeleton/r_leg + var/l_leg_overlay = /datum/bodypart_overlay/simple/fomor_exoskeleton/l_leg + +/datum/action/cooldown/power/fomori_power/exoskeleton/Activate(atom/target) + . = ..() + var/mob/living/carbon/carbon_owner = astype(owner, /mob/living/carbon) + + toggle_feature(deployed) + + if(deployed) + deployed = FALSE + carbon_owner.st_remove_stat_mod(STAT_STAMINA, 1, "exoskeleton") + carbon_owner.st_remove_stat_mod(STAT_STRENGTH, 1, "exoskeleton") + playsound(owner, 'modular_darkpack/modules/powers/sounds/potence_deactivate.ogg', 50) + owner.visible_message(span_warning("[owner]'s skin sheds it's thick carapace, returning to a normal state!"), \ + span_warning("Your skin returns to normal."), \ + span_hear("You hear organic matter ripping and tearing!")) + else + deployed = TRUE + carbon_owner.st_add_stat_mod(STAT_STAMINA, 1, "exoskeleton") + carbon_owner.st_add_stat_mod(STAT_STRENGTH, 1, "exoskeleton") + playsound(owner, 'modular_darkpack/modules/powers/sounds/potence_activate.ogg', 50) + owner.visible_message(span_warning("[owner]'s skin becomes a thick carapace!"), \ + span_warning("Your skin forms a thick carapace."), \ + span_hear("You hear organic matter ripping and tearing!")) + SEND_SIGNAL(owner, COMSIG_MASQUERADE_VIOLATION) + +///for adding fomor features i.e. fangs, horns +/datum/action/cooldown/power/fomori_power/exoskeleton/add_feature() + var/mob/living/carbon/human/fomor = owner + + overlay_list = list( + new chest_overlay, new head_overlay, new r_arm_overlay, + new l_arm_overlay, new r_leg_overlay, new l_leg_overlay) + + for(var/datum/bodypart_overlay/simple/fomor_exoskeleton/bp_overlay in overlay_list) + bp_overlay.assigned_bodyzone = fomor?.get_bodypart(bp_overlay.bodyzone) + if(isnull(bp_overlay.assigned_bodyzone)) + qdel(bp_overlay) + continue + bp_overlay.assigned_bodyzone.add_bodypart_overlay(bp_overlay) + +///removes the fomor feature +/datum/action/cooldown/power/fomori_power/exoskeleton/remove_feature() + var/mob/living/carbon/human/fomor = owner + for(var/datum/bodypart_overlay/simple/fomor_exoskeleton/bp_overlay in overlay_list) + bp_overlay.assigned_bodyzone = fomor?.get_bodypart(bp_overlay.bodyzone) + bp_overlay.assigned_bodyzone.remove_bodypart_overlay(bp_overlay) + qdel(bp_overlay) + overlay_list = list() diff --git a/modular_darkpack/modules/fomori/code/powers/physical/fangs.dm b/modular_darkpack/modules/fomori/code/powers/physical/fangs.dm new file mode 100644 index 000000000000..f2d64b840c3b --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/fangs.dm @@ -0,0 +1,30 @@ +/datum/bodypart_overlay/simple/fomor_fangs // Freak Legion pg.31 + icon_state = "fangs" + icon = 'modular_darkpack/modules/fomori/icons/fomori_sprite_accessories.dmi' + layers = MUTATIONS_LAYER + +/datum/bodypart_overlay/simple/fomor_fangs/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner, mob/living/carbon/owner, is_husked = FALSE) + return ..() && !(bodypart_owner.owner?.obscured_slots & HIDEFACE) + +/datum/action/cooldown/power/fomori_power/fangs + name = "Fangs" + desc = "Use the grotesque fangs spilling from your mouth to bite your enemies." + button_icon_state = "fangs" + rank = 1 // of 1 + + fomor_part = /datum/bodypart_overlay/simple/fomor_fangs + +/datum/action/cooldown/power/fomori_power/fangs/Activate(atom/target) + . = ..() + var/mob/living/carbon/carbon_owner = astype(owner, /mob/living/carbon) + toggle_feature(deployed) + + if(deployed) + REMOVE_TRAITS_IN(owner, "fomor_fangs") + deployed = FALSE + carbon_owner.combat_bite_damages = carbon_owner::combat_bite_damages + else + ADD_TRAIT(owner, TRAIT_COMBAT_BITE, "fomor_fangs") + ADD_TRAIT(owner, TRAIT_MASQUERADE_VIOLATING_FACE, "fomor_fangs") + deployed = TRUE + carbon_owner.combat_bite_damages = list(BRUTE = 0, BURN = 0, TOX = 0, OXY = 0, AGGRAVATED = 1 TTRPG_DAMAGE) diff --git a/modular_darkpack/modules/fomori/code/powers/physical/hide_of_the_wyrm.dm b/modular_darkpack/modules/fomori/code/powers/physical/hide_of_the_wyrm.dm new file mode 100644 index 000000000000..184454c258b7 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/hide_of_the_wyrm.dm @@ -0,0 +1,48 @@ +/datum/bodypart_overlay/simple/hide_of_the_wyrm // Freak Legion pg.33 + icon_state = "hide_of_the_wyrm" + icon = 'modular_darkpack/modules/fomori/icons/fomori_sprite_accessories.dmi' + layers = EXTERNAL_FRONT + +/datum/action/cooldown/power/fomori_power/hide_of_the_wyrm + name = "Hide of the Wyrm" + desc = "Form a hard, leathery hide around your body, protecting you from harm." + button_icon_state = "hide_of_the_wyrm" + rank = 1 // of 5 + + fomor_part = /datum/bodypart_overlay/simple/hide_of_the_wyrm + feature_bodypart = BODY_ZONE_CHEST + + var/datum/status_effect/status_effect_type + +/datum/action/cooldown/power/fomori_power/hide_of_the_wyrm/Grant(mob/granted_to) + . = ..() + switch(rank) + if(1) + status_effect_type = /datum/status_effect/fortitude/one + if(2) + status_effect_type = /datum/status_effect/fortitude/two + if(3) + status_effect_type = /datum/status_effect/fortitude/three + if(4) + status_effect_type = /datum/status_effect/fortitude/four + if(5) + status_effect_type = /datum/status_effect/fortitude/one + +/datum/action/cooldown/power/fomori_power/hide_of_the_wyrm/Activate(atom/target) // TODO: replace fortitude with soak dice if/when we get it + . = ..() + var/mob/living/carbon/carbon_owner = astype(owner, /mob/living/carbon) + + toggle_feature(deployed) + + if(deployed) + deployed = FALSE + owner.visible_message(span_warning("[owner]'s skin is no longer hard and leathery."), \ + span_warning("Your skin is no longer hard and leathery.")) + carbon_owner.remove_status_effect(status_effect_type) + playsound(owner, 'modular_darkpack/modules/powers/sounds/potence_deactivate.ogg', 50) + else + deployed = TRUE + owner.visible_message(span_warning("[owner]'s skin becomes hard and leathery!"), \ + span_warning("Your skin becomes hard and leathery.")) + carbon_owner.apply_status_effect(status_effect_type) // ! if we ever plan on allowing vampiric fomor, give this it's own status effect ! + playsound(owner, 'modular_darkpack/modules/powers/sounds/potence_activate.ogg', 50) diff --git a/modular_darkpack/modules/fomori/code/powers/physical/horns.dm b/modular_darkpack/modules/fomori/code/powers/physical/horns.dm new file mode 100644 index 000000000000..40f1300d17e8 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/horns.dm @@ -0,0 +1,23 @@ +/datum/bodypart_overlay/simple/fomor_horns // Freak Legion pg.31 + icon_state = "horns" + icon = 'modular_darkpack/modules/fomori/icons/fomori_sprite_accessories.dmi' + layers = LOW_FACEMASK_LAYER + +/datum/action/cooldown/power/fomori_power/horns + name = "Horns" + desc = "(UNIMPLEMENTED) Use the grotesque horns atop your head to gore your enemies." + button_icon_state = "horns" + rank = 1 // of 1 + + fomor_part = /datum/bodypart_overlay/simple/fomor_horns + +/datum/action/cooldown/power/fomori_power/horns/Activate(atom/target) + . = ..() + toggle_feature(deployed) + + if(deployed) + deployed = FALSE + else + deployed = TRUE + +#warn HORNS UNFINISHED diff --git a/modular_darkpack/modules/fomori/code/powers/physical/infectious_touch.dm b/modular_darkpack/modules/fomori/code/powers/physical/infectious_touch.dm new file mode 100644 index 000000000000..67fce149679c --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/infectious_touch.dm @@ -0,0 +1,52 @@ +/datum/storyteller_roll/infectious_touch // Freak Legion pg.34 + bumper_text = "infectious touch" + difficulty = 7 + applicable_stats = list(STAT_STAMINA, STAT_MEDICINE) + numerical = TRUE + roll_output_type = ROLL_PRIVATE + +/datum/storyteller_roll/infectious_touch/defender + applicable_stats = list(STAT_STAMINA) + roll_output_type = ROLL_NONE + +/datum/action/cooldown/power/fomori_power/infectious_touch + name = "Infectious Touch" + desc = "Spend a willpower point to cause an unnatural sickness to set in to your target's body." + button_icon_state = "infectious_touch" + rank = 1 // of 1 + click_to_activate = TRUE + willpower_cost = 1 + +/datum/action/cooldown/power/fomori_power/infectious_touch/Activate(atom/target) + if(!isliving(target)) + return + if(!(target in range(1, owner))) + return + + . = ..() + var/mob/living/defender = target + + to_chat(owner, span_warning("You touch [defender], intending to infect them with a grotesque illness...")) + + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/infectious_touch + var/datum/storyteller_roll/roll_datum_defender = new /datum/storyteller_roll/infectious_touch/defender + var/our_power = roll_datum.st_roll(owner) + var/their_power = roll_datum_defender.st_roll(defender) + + playsound(get_turf(src), 'sound/items/weapons/thudswoosh.ogg', 25, TRUE, -15) // Only hearable in extreme proximity + + if(our_power > their_power) + var/net_power = our_power - their_power + if(get_vampire_splat(defender)) + return // Stops just before applying damage without feedback so it's not a splat detector + + addtimer(CALLBACK(src, PROC_REF(infect), target, net_power), 3 TURNS) + + StartCooldown() + return TRUE + +/datum/action/cooldown/power/fomori_power/infectious_touch/proc/infect(mob/living/target, net_power) + target.apply_damage(30*net_power, TOX) // Rules as written it's supposed to be aggravated, but this is better for flavor I think. + if(target.stat < DEAD) + to_chat(target, span_userdanger("You feel woozy.")) + SEND_SOUND(target, 'sound/effects/wounds/sizzle2.ogg') diff --git a/modular_darkpack/modules/fomori/code/powers/physical/regeneration.dm b/modular_darkpack/modules/fomori/code/powers/physical/regeneration.dm new file mode 100644 index 000000000000..d2df004b29d6 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/powers/physical/regeneration.dm @@ -0,0 +1,62 @@ +/datum/storyteller_roll/fomor_regeneration // Freak Legion pg.37 + bumper_text = "regeneration" + difficulty = 6 + applicable_stats = list(STAT_STAMINA) + numerical = FALSE + roll_output_type = ROLL_PRIVATE + +/datum/action/cooldown/power/fomori_power/regeneration + name = "Regeneration" + desc = "Recover from your wounds much the same as the bestial Garou do." + button_icon_state = "regeneration" + rank = 1 // of 1 + +/datum/action/cooldown/power/fomori_power/regeneration/Grant(mob/granted_to) + . = ..() + ADD_TRAIT(owner, TRAIT_FOMORI_REGEN, "regeneration") + +/datum/action/cooldown/power/fomori_power/regeneration/Activate(atom/target) + . = ..() + var/datum/storyteller_roll/roll_datum = new /datum/storyteller_roll/fomor_regeneration + var/roll_result = roll_datum.st_roll(owner) + + if(roll_result) + force_heal() + +/datum/action/cooldown/power/fomori_power/regeneration/proc/force_heal() + var/mob/living/carbon/carbon_owner = astype(owner, /mob/living/carbon) + + //normal bashing/lethal damage + carbon_owner.heal_ordered_damage(30, list(BRUTE, TOX, OXY, STAMINA)) + + if(length(carbon_owner.all_wounds)) + for (var/i in 1 to min(rank, length(carbon_owner.all_wounds))) + var/datum/wound/wound = carbon_owner.all_wounds[i] + wound.remove_wound() + + //brain damage and traumas healing + var/obj/item/organ/brain/brain = carbon_owner.get_organ_slot(ORGAN_SLOT_BRAIN) + if (brain) + brain.apply_organ_damage(-30) + + for (var/i in 1 to min(rank, length(brain.get_traumas_type()))) + var/datum/brain_trauma/healing_trauma = pick(brain.get_traumas_type()) + brain.cure_trauma_type(healing_trauma, resilience = TRAUMA_RESILIENCE_WOUND) + + //miscellaneous organ damage healing + var/obj/item/organ/eyes/eyes = carbon_owner.get_organ_slot(ORGAN_SLOT_EYES) + if (eyes) + eyes.apply_organ_damage(-30) + + carbon_owner.adjust_temp_blindness(-6) + carbon_owner.adjust_eye_blur(-6) + + carbon_owner.visible_message( + span_warning("[carbon_owner]'s wounds heal with unnatural speed!"), + span_warning("Your wounds visibly heal with unnatural speed!")) + + SEND_SIGNAL(carbon_owner, COMSIG_MASQUERADE_VIOLATION) + + //update UI + carbon_owner.update_damage_overlays() + carbon_owner.update_health_hud() diff --git a/modular_darkpack/modules/fomori/code/splats/fomori_splat.dm b/modular_darkpack/modules/fomori/code/splats/fomori_splat.dm new file mode 100644 index 000000000000..a7066c886433 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/splats/fomori_splat.dm @@ -0,0 +1,74 @@ +/datum/splat/werewolf/fomori + name = "Fomori" + desc = "Mortals who have lost themselves to the Wyrm's corruption. \ + A slow death of the self — most do not even realize what has happened to them before the bane takes over completely. \ + Tools of Dancers, and wretched things to mercifully be slain by Gaians. \ + You are but another pawn in a scheme older and grander than you could've ever imagined." + + id = SPLAT_FOMORI + + splat_priority = SPLAT_PRIO_FOMORI + + power_type = /datum/action/cooldown/power/fomori_power + + uses_veil = TRUE + COOLDOWN_DECLARE(passive_healing_cd) + +/datum/splat/werewolf/fomori/splat_life(seconds_per_tick) + if(HAS_TRAIT(owner, TRAIT_FOMORI_REGEN)) + if(COOLDOWN_FINISHED(src, passive_healing_cd)) + owner.heal_storyteller_health(1, heal_scars = TRUE, heal_blood = TRUE) + COOLDOWN_START(src, passive_healing_cd, 1 TURNS) + +/mob/living/carbon/human/splat/fomori + auto_splats = list(/datum/splat/werewolf/fomori) + +/datum/splat/werewolf/fomori/on_gain() // WIP: Will be pointbuy eventually. Don't merge with this code in-tact + // PHYSICAL POWERS + owner.give_st_power(/datum/action/cooldown/power/fomori_power/weapon/body_barbs, 1) // done, needs melee rework + owner.give_st_power(/datum/action/cooldown/power/fomori_power/weapon/claws, 1) // done, needs melee rework + owner.give_st_power(/datum/action/cooldown/power/fomori_power/horns, 1) // unfinished +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/fangs, 1) // done +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/chameleon_coloration, 1) // done +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/darksight, 1) // done +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/exoskeleton, 1) // done +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/regeneration, 1) // done +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/hide_of_the_wyrm, 1) // done +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/infectious_touch, 1) // done + // MENTAL POWERS +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/berserker, 1) // need pointbuy +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/corrupted_visions, 1) // done + owner.give_st_power(/datum/action/cooldown/power/fomori_power/deception, 1) + owner.give_st_power(/datum/action/cooldown/power/fomori_power/eyes_of_the_wyrm, 1) +// owner.give_st_power(/datum/action/cooldown/power/fomori_power/mind_blast, 1) // done + owner.give_st_power(/datum/action/cooldown/power/fomori_power/mind_reave, 1) // need 2 client testing + owner.give_st_power(/datum/action/cooldown/power/fomori_power/numbing, 1) // need testing + + + +/datum/splat/werewolf/fomori/get_power(power_type) + RETURN_TYPE(/datum/action/cooldown/power/fomori_power) + + for(var/datum/action/cooldown/power/fomori_power/found_action as anything in powers) + if(!istype(found_action, power_type)) + continue + + return found_action + +/datum/splat/werewolf/fomori/add_power(power_type, level) + // Prevent duplicates + if(get_power(power_type)) + return FALSE + var/datum/action/cooldown/power/fomori_power/adding_action = new power_type() + adding_action.Grant(owner) + LAZYADD(powers, adding_action) + return TRUE + +/datum/splat/werewolf/fomori/remove_power(power_type) + var/datum/action/cooldown/power/fomori_power/found_action = get_power(power_type) + if(!found_action) + return FALSE + + LAZYREMOVE(powers, found_action) + qdel(found_action) + return TRUE diff --git a/modular_darkpack/modules/fomori/code/splats/is_fomori_helpers.dm b/modular_darkpack/modules/fomori/code/splats/is_fomori_helpers.dm new file mode 100644 index 000000000000..3972705e0b44 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/splats/is_fomori_helpers.dm @@ -0,0 +1,4 @@ +/proc/get_fomori_splat(mob/character) + RETURN_TYPE(/datum/splat/werewolf/fomori) + + return character.get_splat(/datum/splat/werewolf/fomori) diff --git a/modular_darkpack/modules/fomori/code/splats/pref_lore.dm b/modular_darkpack/modules/fomori/code/splats/pref_lore.dm new file mode 100644 index 000000000000..a3310345f910 --- /dev/null +++ b/modular_darkpack/modules/fomori/code/splats/pref_lore.dm @@ -0,0 +1,45 @@ +/datum/splat/werewolf/fomori/prepare_human_for_preview(mob/living/carbon/human/human) + human.set_haircolor("#554435", update = FALSE) + human.set_hairstyle("Boddicker", update = TRUE) + human.set_facial_hairstyle("Beard (Seven o Clock Shadow)", update = TRUE) + human.set_eye_color("#8281ca") + human.undershirt = "Tank Top (White)" + human.update_body() + human.equipOutfit(/datum/outfit/civillian4, TRUE) + +/datum/splat/werewolf/fomori/get_splat_description() + return "Mortals who have lost themselves to the Wyrm's corruption. \ + A slow death of the self — most do not even realize what has happened to them before the bane takes over completely. \ + Tools of Dancers, and wretched things to mercifully be slain by Gaians. \ + You are but another pawn in a scheme older and grander than you could've ever imagined." + +/datum/splat/werewolf/fomori/get_splat_lore() + return list( + "The fomori are created when a Bane possesses a human or an animal via a spiritual \"hole\" left by some form of sin or spiritual corruption. The Bane will slowly gain more and more influence, until they are completely fused with the host and cannot be separated.", + ) + +/datum/splat/werewolf/fomori/create_pref_unique_perks() + var/list/to_add = list() + + to_add += list( + list( + SPECIES_PERK_TYPE = SPECIES_NEUTRAL_PERK, + SPECIES_PERK_ICON = FA_ICON_BOOK_DEAD, + SPECIES_PERK_NAME = "Bane Possession", + SPECIES_PERK_DESC = "Fomori are possessed by spirits called Banes, which imbues them with various powers and taints.", + ), + list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = FA_ICON_CROSSHAIRS, + SPECIES_PERK_NAME = "Hunted and Subservient", + SPECIES_PERK_DESC = "Fomori are hunted by Gaians and expected to serve the Wyrm.", + ), + list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = FA_ICON_GHOST, + SPECIES_PERK_NAME = "Grotesque", + SPECIES_PERK_DESC = "Without a special merit, many powers and taints cause the fomor to violate the veil just be being seen.", + ), + ) + + return to_add diff --git a/modular_darkpack/modules/fomori/icons/fomori_abilities.dmi b/modular_darkpack/modules/fomori/icons/fomori_abilities.dmi new file mode 100644 index 000000000000..49df90f25bc3 Binary files /dev/null and b/modular_darkpack/modules/fomori/icons/fomori_abilities.dmi differ diff --git a/modular_darkpack/modules/fomori/icons/fomori_inhand_left.dmi b/modular_darkpack/modules/fomori/icons/fomori_inhand_left.dmi new file mode 100644 index 000000000000..805605e6f620 Binary files /dev/null and b/modular_darkpack/modules/fomori/icons/fomori_inhand_left.dmi differ diff --git a/modular_darkpack/modules/fomori/icons/fomori_inhand_right.dmi b/modular_darkpack/modules/fomori/icons/fomori_inhand_right.dmi new file mode 100644 index 000000000000..71392944059f Binary files /dev/null and b/modular_darkpack/modules/fomori/icons/fomori_inhand_right.dmi differ diff --git a/modular_darkpack/modules/fomori/icons/fomori_items48x32.dmi b/modular_darkpack/modules/fomori/icons/fomori_items48x32.dmi new file mode 100644 index 000000000000..cfa738b7871e Binary files /dev/null and b/modular_darkpack/modules/fomori/icons/fomori_items48x32.dmi differ diff --git a/modular_darkpack/modules/fomori/icons/fomori_sprite_accessories.dmi b/modular_darkpack/modules/fomori/icons/fomori_sprite_accessories.dmi new file mode 100644 index 000000000000..addd7f20a7dc Binary files /dev/null and b/modular_darkpack/modules/fomori/icons/fomori_sprite_accessories.dmi differ diff --git a/modular_darkpack/modules/masquerade/code/components/violation_observer.dm b/modular_darkpack/modules/masquerade/code/components/violation_observer.dm index 8973784cd92b..ebb9a0025404 100644 --- a/modular_darkpack/modules/masquerade/code/components/violation_observer.dm +++ b/modular_darkpack/modules/masquerade/code/components/violation_observer.dm @@ -67,17 +67,27 @@ source.observe_masquerade_reinforce(player_breacher) breached_players -= player_breacher -/atom/proc/observe_masquerade_violation(player_breacher) +/atom/proc/observe_masquerade_violation(mob/living/player_breacher) do_alert_animation() - if(get_werewolf_splat(player_breacher)) + var/should_use_veil + for(var/datum/splat/breacher_splat in player_breacher.splats) + if(breacher_splat.uses_veil) + should_use_veil = TRUE + + if(should_use_veil) to_chat(player_breacher, span_userdanger(span_bold("VEIL VIOLATION"))) playsound(player_breacher, 'modular_darkpack/modules/masquerade/sound/veil_violation.ogg', 50, FALSE, -5) return playsound(player_breacher, 'modular_darkpack/modules/masquerade/sound/masquerade_violation.ogg', 50, FALSE, -5) to_chat(player_breacher, span_userdanger(span_bold("MASQUERADE VIOLATION"))) -/atom/proc/observe_masquerade_reinforce(player_breacher) - if(get_werewolf_splat(player_breacher)) +/atom/proc/observe_masquerade_reinforce(mob/living/player_breacher) + var/should_use_veil + for(var/datum/splat/breacher_splat in player_breacher.splats) + if(breacher_splat.uses_veil) + should_use_veil = TRUE + + if(should_use_veil) to_chat(player_breacher, span_big(span_boldnicegreen("VEIL REINFORCED"))) playsound(player_breacher, 'modular_darkpack/modules/masquerade/sound/humanity_gain.ogg', 50, FALSE, -5) return diff --git a/modular_darkpack/modules/splats/code/__splat.dm b/modular_darkpack/modules/splats/code/__splat.dm index 3d2a50dfb225..7df8a6609a17 100644 --- a/modular_darkpack/modules/splats/code/__splat.dm +++ b/modular_darkpack/modules/splats/code/__splat.dm @@ -35,6 +35,8 @@ var/splat_biotypes /// Base type of the powers that this splat has var/power_type + /// Whether or not we use the MASQUERADE or the VEIL + var/uses_veil /// If examining the pulled tooth of the splat can gain some indication of what it is. var/tooth_fingerprint = FALSE diff --git a/modular_darkpack/modules/werewolf_the_apocalypse/code/hud.dm b/modular_darkpack/modules/werewolf_the_apocalypse/code/hud.dm index f03b9f164040..8cb76b16c95e 100644 --- a/modular_darkpack/modules/werewolf_the_apocalypse/code/hud.dm +++ b/modular_darkpack/modules/werewolf_the_apocalypse/code/hud.dm @@ -15,8 +15,8 @@ /datum/splat/werewolf/add_relevent_huds(datum/hud/hud_used) - hud_used.add_werewolf_elements(src) - + if(uses_hud) + hud_used.add_werewolf_elements() /atom/movable/screen/auspice name = "auspice" 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 3983a23cef03..aac89e85c25f 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 @@ -4,6 +4,8 @@ power_type = /datum/action/cooldown/power/gift + uses_veil = TRUE + // Perm is for rolls // Non-perm/ or temp is for expenditure var/uses_rage = FALSE @@ -14,6 +16,8 @@ var/permanent_gnosis = 10 var/gnosis = 0 + var/uses_hud = FALSE + var/list/renown = list() var/renown_rank = RANK_CUB @@ -99,6 +103,8 @@ uses_rage = TRUE uses_gnosis = TRUE + uses_hud = TRUE + splat_priority = SPLAT_PRIO_SHIFTER var/list/transformation_list = list() 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..d733f3ff30da 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 @@ -25,4 +25,3 @@ RETURN_TYPE(/datum/splat/werewolf/kinfolk) return character.get_splat(/datum/splat/werewolf/kinfolk) - diff --git a/tgstation.dme b/tgstation.dme index b26fe80e5b32..46e528f74dfa 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7179,6 +7179,7 @@ #include "modular_darkpack\modules\bitcoinminer\code\bitcoinminer.dm" #include "modular_darkpack\modules\blood_drinking\code\bite_helper_procs.dm" #include "modular_darkpack\modules\blood_drinking\code\bite_keybinding.dm" +#include "modular_darkpack\modules\blood_drinking\code\combat_bite.dm" #include "modular_darkpack\modules\blood_drinking\code\drinksomeblood.dm" #include "modular_darkpack\modules\blood_drinking\code\vamp_bite.dm" #include "modular_darkpack\modules\blood_drinking\code\kiss_status_effect\status_effect_kiss.dm" @@ -7343,6 +7344,31 @@ #include "modular_darkpack\modules\flavor_text\code\preferences\masked_flavor_text_preference.dm" #include "modular_darkpack\modules\flavor_text\code\preferences\nsfw_content_preference.dm" #include "modular_darkpack\modules\flavor_text\code\preferences\record_preferences.dm" +#include "modular_darkpack\modules\fomori\code\positive_quirks\hidden_power.dm" +#include "modular_darkpack\modules\fomori\code\positive_quirks\stigmata_of_the_wyrm.dm" +#include "modular_darkpack\modules\fomori\code\powers\_fomori_power.dm" +#include "modular_darkpack\modules\fomori\code\powers\_fomori_power_weapon.dm" +#include "modular_darkpack\modules\fomori\code\powers\mental\berserker.dm" +#include "modular_darkpack\modules\fomori\code\powers\mental\corrupted_visions.dm" +#include "modular_darkpack\modules\fomori\code\powers\mental\deception.dm" +#include "modular_darkpack\modules\fomori\code\powers\mental\eyes_of_the_wyrm.dm" +#include "modular_darkpack\modules\fomori\code\powers\mental\mind_blast.dm" +#include "modular_darkpack\modules\fomori\code\powers\mental\mind_reave.dm" +#include "modular_darkpack\modules\fomori\code\powers\mental\numbing.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\body_barbs.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\chameleon_coloration.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\claws.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\darksight.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\ectoplasmic_extrusion.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\exoskeleton.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\fangs.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\hide_of_the_wyrm.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\horns.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\infectious_touch.dm" +#include "modular_darkpack\modules\fomori\code\powers\physical\regeneration.dm" +#include "modular_darkpack\modules\fomori\code\splats\fomori_splat.dm" +#include "modular_darkpack\modules\fomori\code\splats\is_fomori_helpers.dm" +#include "modular_darkpack\modules\fomori\code\splats\pref_lore.dm" #include "modular_darkpack\modules\font_adjustments\font_procs.dm" #include "modular_darkpack\modules\food\code\drinking_glass.dm" #include "modular_darkpack\modules\food\code\drinks.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/darkpack_merits_flaws_preferences.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/darkpack_merits_flaws_preferences.tsx index d9edd1466156..49e2453d153d 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/darkpack_merits_flaws_preferences.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/darkpack_merits_flaws_preferences.tsx @@ -19,6 +19,11 @@ export const missing_arm: FeatureChoiced = { component: FeatureDropdownInput, }; +export const stigmata_of_the_wyrm: FeatureChoiced = { + name: 'Stigmata of the Wyrm', + component: FeatureDropdownInput, +}; + export const lame_leg: FeatureChoiced = { name: 'Lame Leg', component: FeatureDropdownInput,