diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_werewolf.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_werewolf.png new file mode 100644 index 000000000000..f9860dab6a3f Binary files /dev/null and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_werewolf.png differ diff --git a/maplestation.dme b/maplestation.dme index 13709f2dc079..a0e0a301671e 100644 --- a/maplestation.dme +++ b/maplestation.dme @@ -6309,6 +6309,7 @@ #include "maplestation_modules\code\datums\greyscale\_greyscale_config.dm" #include "maplestation_modules\code\datums\id_trim\jobs.dm" #include "maplestation_modules\code\datums\keybinding\communication.dm" +#include "maplestation_modules\code\datums\mood_events\other_mood_events.dm" #include "maplestation_modules\code\datums\mood_events\quirk_mood_events.dm" #include "maplestation_modules\code\datums\mood_events\reagent_mood_events.dm" #include "maplestation_modules\code\datums\pain\pain.dm" @@ -6620,6 +6621,7 @@ #include "maplestation_modules\code\modules\magic\story_spells\ice_blast.dm" #include "maplestation_modules\code\modules\magic\story_spells\ice_knife.dm" #include "maplestation_modules\code\modules\magic\story_spells\illusion.dm" +#include "maplestation_modules\code\modules\magic\story_spells\lycanthropy.dm" #include "maplestation_modules\code\modules\magic\story_spells\mage_hand.dm" #include "maplestation_modules\code\modules\magic\story_spells\mana_charge.dm" #include "maplestation_modules\code\modules\magic\story_spells\mana_sense.dm" @@ -6676,6 +6678,7 @@ #include "maplestation_modules\code\modules\mob\living\carbon\human\species_types\skrell.dm" #include "maplestation_modules\code\modules\mob\living\carbon\human\species_types\species.dm" #include "maplestation_modules\code\modules\mob\living\carbon\human\species_types\vampire.dm" +#include "maplestation_modules\code\modules\mob\living\carbon\human\species_types\werewolf.dm" #include "maplestation_modules\code\modules\mob\living\carbon\human\species_types\synth\synth.dm" #include "maplestation_modules\code\modules\mob\living\carbon\human\species_types\synth\synth_ion.dm" #include "maplestation_modules\code\modules\mob\living\silicon\robot\robot_defines.dm" @@ -6721,12 +6724,16 @@ #include "maplestation_modules\code\modules\surgery\bodyparts\cyber_digi.dm" #include "maplestation_modules\code\modules\surgery\bodyparts\cyber_reskins.dm" #include "maplestation_modules\code\modules\surgery\bodyparts\cyber_tech.dm" +#include "maplestation_modules\code\modules\surgery\bodyparts\werewolf_parts.dm" #include "maplestation_modules\code\modules\surgery\organs\augments_arms.dm" #include "maplestation_modules\code\modules\surgery\organs\augments_chest.dm" #include "maplestation_modules\code\modules\surgery\organs\augments_eyes.dm" #include "maplestation_modules\code\modules\surgery\organs\augments_internal.dm" #include "maplestation_modules\code\modules\surgery\organs\autosurgeon.dm" #include "maplestation_modules\code\modules\surgery\organs\ears.dm" +#include "maplestation_modules\code\modules\surgery\organs\eyes.dm" +#include "maplestation_modules\code\modules\surgery\organs\heart.dm" +#include "maplestation_modules\code\modules\surgery\organs\liver.dm" #include "maplestation_modules\code\modules\surgery\organs\tails.dm" #include "maplestation_modules\code\modules\surgery\organs\tongue.dm" #include "maplestation_modules\code\modules\uplink\uplink_devices.dm" diff --git a/maplestation_modules/code/__DEFINES/DNA.dm b/maplestation_modules/code/__DEFINES/DNA.dm index c4249c288de3..8e4959f01702 100644 --- a/maplestation_modules/code/__DEFINES/DNA.dm +++ b/maplestation_modules/code/__DEFINES/DNA.dm @@ -5,3 +5,4 @@ #define SPECIES_REPLOID "reploid" #define SPECIES_SYNTH "synth" #define SPECIES_ORNITHID "ornithid" +#define SPECIES_WEREWOLF "werewolf" diff --git a/maplestation_modules/code/__DEFINES/traits.dm b/maplestation_modules/code/__DEFINES/traits.dm index 32514177eae2..ef8ad69e888e 100644 --- a/maplestation_modules/code/__DEFINES/traits.dm +++ b/maplestation_modules/code/__DEFINES/traits.dm @@ -4,3 +4,7 @@ #define TRAIT_FEATHERED "feathers" /// Gives positive mood on drinking anything caffeinated, kinda generic so people can like coffee, tea, energy drinks, whatever. #define TRAIT_CAFFEINE_LOVER "caffeine_lover" +// Used to indicate a mob is vulnerable to silver, most notably werewolves. +#define TRAIT_SILVER_VULNERABLE "silver_vulnerable" +// Used to indicate a mob is a werewolf, regardless of their state. +#define TRAIT_WEREWOLF "werewolf" diff --git a/maplestation_modules/code/datums/mood_events/other_mood_events.dm b/maplestation_modules/code/datums/mood_events/other_mood_events.dm new file mode 100644 index 000000000000..49768bb79b93 --- /dev/null +++ b/maplestation_modules/code/datums/mood_events/other_mood_events.dm @@ -0,0 +1,5 @@ +// inflicted by witnessing a werewolf activate rage +/datum/mood_event/werewolf_delirium + description = "NOPENOPENOPENOPENOPENOPENOPENOPENOPENOPE!" + mood_change = -5 + timeout = 4 MINUTES diff --git a/maplestation_modules/code/modules/magic/story_spells/lycanthropy.dm b/maplestation_modules/code/modules/magic/story_spells/lycanthropy.dm new file mode 100644 index 000000000000..d9d27c894fd3 --- /dev/null +++ b/maplestation_modules/code/modules/magic/story_spells/lycanthropy.dm @@ -0,0 +1,143 @@ +// the many spells that are used to turn into versions of a werewolf + +/datum/action/cooldown/spell/shapeshift/lycanthrope // use this for the simplemob forms, like standard wolves + name = "Wolf Form" + desc = "Channel the wolf within yourself and turn into one of your possible forms. \ + Be careful, for you can still die within this form." + invocation = "RAAAAAAAAWR!" + invocation_type = INVOCATION_SHOUT + spell_requirements = NONE + possible_shapes = list( + /mob/living/simple_animal/hostile/asteroid/wolf, // room to add other forms + ) + +/datum/action/cooldown/spell/werewolf_form + name = "Werewolf Change" + desc = "Change to and from your full werewolf form. \ + You will gain the full effects of this, both negative and positive." + + invocation = "Grrrh-" + invocation_type = INVOCATION_SHOUT + + spell_requirements = SPELL_REQUIRES_HUMAN + cooldown_time = 10 SECONDS // so it can't be spammed + + button_icon = 'maplestation_modules/icons/mob/actions/actions_advspells.dmi' + button_icon_state = "moon" + + var/datum/species/owner_base_species // what species we are other than a werewolf + var/list/base_features = list("mcolor" = "#FFFFFF") + // yes this might cause other implications, such as mass species change, or with synths (synthcode moment) but i'll look into it later down the line + +/datum/action/cooldown/spell/werewolf_form/Grant(mob/grant_to) + . = ..() + var/mob/living/carbon/human/lycanthrope = grant_to + owner_base_species = lycanthrope.dna.species + base_features = lycanthrope.dna.features.Copy() + ADD_TRAIT(owner, TRAIT_WEREWOLF, TRAIT_GENERIC) // todo: move this to a datum (eg, like antag/heretic) + + +/datum/action/cooldown/spell/werewolf_form/cast(atom/movable/cast_on) + . = ..() + var/mob/living/carbon/human/lycanthrope = owner + if(istype(lycanthrope.dna.species, /datum/species/werewolf)) + lycanthrope.balloon_alert(cast_on, "changing back") + lycanthrope.dna.features = base_features + lycanthrope.set_species(owner_base_species) + else + to_chat(lycanthrope, span_green("You call upon the wolf within yourself, preparing to change shape...")) + lycanthrope.set_jitter_if_lower(3 SECONDS) + if(!do_after(lycanthrope, 3 SECONDS)) + to_chat(lycanthrope, span_warning("Your focus is broken, and your body returns to its original state.")) + return + base_features = lycanthrope.dna.features.Copy() + owner_base_species = lycanthrope.dna.species + lycanthrope.set_species(/datum/species/werewolf) + lycanthrope.say("ARRRROOOOO!!", forced = "spell ([src])") + +/datum/action/cooldown/spell/werewolf_rage + name = "Lycanthropic Rage" + desc = "Enrage" + invocation = "GRRR-!!" // todo: this sucks + invocation_type = INVOCATION_SHOUT + spell_requirements = SPELL_REQUIRES_HUMAN + cooldown_time = 3 MINUTES + button_icon_state = "splattercasting" + /// The radius around us that we frighten people. + var/scare_radius = 6 + +/datum/action/cooldown/spell/werewolf_rage/before_cast(mob/living/user) + ..() + if(user.has_status_effect(/datum/status_effect/werewolf_rage)) + user.balloon_alert(user, "already raging!") + return SPELL_CANCEL_CAST + +/datum/action/cooldown/spell/werewolf_rage/cast(mob/living/user) + ..() + + to_chat(user, span_green("You begin to dredge up the supernatural fury that boils within your body...")) + if(is_species(user, /datum/species/werewolf)) + for(var/mob/living/carbon/human/nearby_human in view(scare_radius, user)) + if(HAS_TRAIT(nearby_human, TRAIT_WEREWOLF) || HAS_TRAIT(nearby_human, TRAIT_MINDSHIELD) || HAS_TRAIT(nearby_human, TRAIT_DEAF) || HAS_TRAIT(nearby_human, TRAIT_FEARLESS) || nearby_human == user) + continue + to_chat(nearby_human, span_warning("You feel an unknown, primal terror building up within you...")) + + if(!do_after(user, 2 SECONDS)) + to_chat(user, span_warning("Your focus is broken, and you settle back down.")) + return + + to_chat(user, span_notice("You release the supernatural wrath within you!")) + user.apply_status_effect(/datum/status_effect/werewolf_rage) + + if(is_species(user, /datum/species/werewolf)) + user.say("RRRRAGGGGHHHH!!", forced = "spell ([src])") + playsound(user.loc, 'sound/creatures/space_dragon_roar.ogg', 40, use_reverb = TRUE) + // hearing a werewolf violently howl- and enter its enraged state, forces unprotected normal humans to panic + for(var/mob/living/carbon/human/nearby_human in view(scare_radius, user)) + if(nearby_human == user) + continue + // if you are: mentally protected, fearless, deaf, or a werewolf yourself (or the person who used this) you aren't affected. + if(HAS_TRAIT(nearby_human, TRAIT_WEREWOLF) || HAS_TRAIT(nearby_human, TRAIT_MINDSHIELD) || HAS_TRAIT(nearby_human, TRAIT_DEAF) || HAS_TRAIT(nearby_human, TRAIT_FEARLESS)) + to_chat(nearby_human, span_warning("You feel something horrible pass over you.")) + continue + + to_chat(nearby_human, span_danger("Your mind recoils as it is filled with a primordial terror!")) + // if you aren't, you'll become dizzy and jittery, alongside get a -5 negative moodlet + nearby_human.set_jitter_if_lower(7 SECONDS) + nearby_human.set_dizzy_if_lower(3 SECONDS) + nearby_human.add_mood_event("werewolf_delirium", /datum/mood_event/werewolf_delirium) + // and a chance to involuntarily scream + if(prob(4)) + nearby_human.emote("scream") + else + user.say("REEEEEEEEE!!!!", forced = "spell([src])") + playsound(user.loc, 'sound/effects/reee.ogg', 40, use_reverb = TRUE) + +/datum/status_effect/werewolf_rage + id = "blooddrunk" + duration = 60 + tick_interval = -1 + alert_type = /atom/movable/screen/alert/status_effect/werewolf_rage + +/atom/movable/screen/alert/status_effect/werewolf_rage + name = "Lycanthropic Rage" + desc = "You are filled with a supernatural rage! Your pulse thunders in your ears!" + icon_state = "blooddrunk" + +/datum/status_effect/werewolf_rage/on_apply() + owner.add_movespeed_mod_immunities(id, /datum/movespeed_modifier/damage_slowdown) + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.brute_mod *= 0.8 + human_owner.physiology.burn_mod *= 0.8 + human_owner.physiology.tox_mod *= 0.8 + owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1, use_reverb = FALSE) + return TRUE + +/datum/status_effect/werewolf_rage/on_remove() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.brute_mod *= 1.25 + human_owner.physiology.burn_mod *= 1.25 + human_owner.physiology.tox_mod *= 1.25 + owner.remove_movespeed_mod_immunities(id, /datum/movespeed_modifier/damage_slowdown) diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/human.dm b/maplestation_modules/code/modules/mob/living/carbon/human/human.dm index bacc2e93e79b..45e085aa313d 100644 --- a/maplestation_modules/code/modules/mob/living/carbon/human/human.dm +++ b/maplestation_modules/code/modules/mob/living/carbon/human/human.dm @@ -52,3 +52,7 @@ outfit_copy.implants = list() for(var/obj/item/implant/I in implants) outfit_copy.implants |= I.type + +// species mobs +/mob/living/carbon/human/species/werewolf + race = /datum/species/werewolf diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/werewolf.dm b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/werewolf.dm new file mode 100644 index 000000000000..a598019866ae --- /dev/null +++ b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/werewolf.dm @@ -0,0 +1,79 @@ +/datum/species/werewolf + name = "werewolf" + id = SPECIES_WEREWOLF + inherent_traits = list( + TRAIT_USES_SKINTONES, + TRAIT_NO_UNDERWEAR, + TRAIT_NO_AUGMENTS, + TRAIT_PUSHIMMUNE, + TRAIT_STUNIMMUNE, + TRAIT_PRIMITIVE, + TRAIT_CAN_STRIP, + TRAIT_CHUNKYFINGERS + ) + mutanttongue = /obj/item/organ/tongue/werewolf + mutantears = /obj/item/organ/ears/cat/werewolf + mutanteyes = /obj/item/organ/eyes/werewolf + mutantbrain = /obj/item/organ/brain/werewolf + mutantliver = /obj/item/organ/liver/werewolf + mutantheart = /obj/item/organ/heart/werewolf + mutant_organs = list( + /obj/item/organ/tail/fox = "Fox", // todo: add custom wolf tail + ) + skinned_type = /obj/item/stack/sheet/animalhide/human + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT + no_equip_flags = ITEM_SLOT_MASK | ITEM_SLOT_OCLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_SUITSTORE + + bodypart_overrides = list( + BODY_ZONE_HEAD = /obj/item/bodypart/head/werewolf, + BODY_ZONE_CHEST = /obj/item/bodypart/chest/werewolf, + BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/werewolf, + BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/werewolf, + BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/werewolf, + BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/werewolf, + ) + +/obj/item/organ/brain/werewolf + name = "werewolf brain" + desc = "a strange mixture of a human and wolf brain" + organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE, TRAIT_PRIMITIVE, TRAIT_CAN_STRIP) // you may be a raging monster, but you still retain traits of your normal self + // i'll look into making this more interesting when rage is fully implemented + +/obj/item/organ/brain/werewolf/get_attacking_limb(mob/living/carbon/human/target) + if(target.body_position == LYING_DOWN) + return owner.get_bodypart(BODY_ZONE_HEAD) // performs a "maul" attack which does increased melee damage + return ..() + +/datum/species/werewolf/prepare_human_for_preview(mob/living/carbon/human/human) + human.set_haircolor("#bb9966", update = FALSE) // brown + human.set_hairstyle("Business Hair", update = TRUE) + +/* this shouldn't be a roundstart/base species players can choose, and is instead obtainable mid round +feel free to update this section if any of the three below can be accessed out of character set up. */ +/datum/species/werewolf/get_species_description() + return "N/A" + +/datum/species/human/get_species_lore() + return list( + "N/A", + ) + +/datum/species/werewolf/create_pref_unique_perks() + var/list/to_add = list() + + to_add += list( + list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = "paw", + SPECIES_PERK_NAME = "The Creature", + SPECIES_PERK_DESC = "Werewolves are monstrous humans, and can't do most things a human can do. Computers are impossible, \ + complex machines are right out, and most clothes don't fit your larger form.", + ), + list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = "assistive-listening-systems", + SPECIES_PERK_NAME = "Sensitive Hearing", + SPECIES_PERK_DESC = "Werewolves are more sensitive to loud sounds, such as flashbangs.", + )) + + return to_add diff --git a/maplestation_modules/code/modules/surgery/bodyparts/werewolf_parts.dm b/maplestation_modules/code/modules/surgery/bodyparts/werewolf_parts.dm new file mode 100644 index 000000000000..df8577e3da1f --- /dev/null +++ b/maplestation_modules/code/modules/surgery/bodyparts/werewolf_parts.dm @@ -0,0 +1,127 @@ +///WEREWOLF +/obj/item/bodypart/head/werewolf + limb_id = SPECIES_WEREWOLF + icon_greyscale = 'maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi' + is_dimorphic = FALSE + should_draw_greyscale = TRUE + burn_modifier = 0.9 + brute_modifier = 0.8 + unarmed_attack_verbs = list("bite") + grappled_attack_verb = "maul" + unarmed_attack_effect = ATTACK_EFFECT_BITE + unarmed_attack_sound = 'sound/weapons/bite.ogg' + unarmed_miss_sound = 'sound/weapons/bite.ogg' + unarmed_damage_low = 30 + unarmed_damage_high = 35 + unarmed_effectiveness = 30 + dmg_overlay_type = null + head_flags = HEAD_EYESPRITES|HEAD_EYECOLOR|HEAD_EYEHOLES|HEAD_DEBRAIN|HEAD_HAIR + +/obj/item/bodypart/head/werewolf/update_limb(dropping_limb, is_creating) + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/wolf = owner + species_color = wolf.hair_color + +/obj/item/bodypart/chest/werewolf + limb_id = SPECIES_WEREWOLF + icon_greyscale = 'maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi' + is_dimorphic = TRUE + should_draw_greyscale = TRUE + burn_modifier = 0.9 + brute_modifier = 0.8 + dmg_overlay_type = null + bodypart_traits = list(TRAIT_NO_JUMPSUIT, TRAIT_PUSHIMMUNE, TRAIT_STUNIMMUNE) + wing_types = NONE + +/obj/item/bodypart/chest/werewolf/update_limb(dropping_limb, is_creating) + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/wolf = owner + species_color = wolf.hair_color + + +/obj/item/bodypart/arm/left/werewolf + limb_id = SPECIES_WEREWOLF + icon_greyscale = 'maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi' + should_draw_greyscale = TRUE + unarmed_attack_verbs = list("slash") + grappled_attack_verb = "lacerate" + unarmed_attack_effect = ATTACK_EFFECT_CLAW + unarmed_attack_sound = 'sound/weapons/slice.ogg' + unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + unarmed_damage_low = 17 + unarmed_damage_high = 23 + unarmed_effectiveness = 15 + burn_modifier = 0.9 + brute_modifier = 0.8 + dmg_overlay_type = null + bodypart_traits = list(TRAIT_CHUNKYFINGERS) + + +/obj/item/bodypart/arm/left/werewolf/update_limb(dropping_limb, is_creating) + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/wolf = owner + species_color = wolf.hair_color + + +/obj/item/bodypart/arm/right/werewolf + limb_id = SPECIES_WEREWOLF + icon_greyscale = 'maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi' + should_draw_greyscale = TRUE + unarmed_attack_verbs = list("slash") + grappled_attack_verb = "lacerate" + unarmed_attack_effect = ATTACK_EFFECT_CLAW + unarmed_attack_sound = 'sound/weapons/slice.ogg' + unarmed_miss_sound = 'sound/weapons/slashmiss.ogg' + unarmed_damage_low = 17 + unarmed_damage_high = 23 + unarmed_effectiveness = 15 + burn_modifier = 0.9 + brute_modifier = 0.8 + dmg_overlay_type = null + bodypart_traits = list(TRAIT_CHUNKYFINGERS) + +/obj/item/bodypart/arm/right/werewolf/update_limb(dropping_limb, is_creating) + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/wolf = owner + species_color = wolf.hair_color + + +/obj/item/bodypart/leg/left/werewolf + limb_id = SPECIES_WEREWOLF + icon_greyscale = 'maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi' + should_draw_greyscale = TRUE + burn_modifier = 0.9 + brute_modifier = 0.8 + speed_modifier = -0.1 + dmg_overlay_type = null + bodytype = BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_DIGITIGRADE + footstep_type = FOOTSTEP_MOB_CLAW + +/obj/item/bodypart/leg/left/werewolf/update_limb(dropping_limb, is_creating) + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/wolf = owner + species_color = wolf.hair_color + +/obj/item/bodypart/leg/right/werewolf + limb_id = SPECIES_WEREWOLF + icon_greyscale = 'maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi' + should_draw_greyscale = TRUE + burn_modifier = 0.9 + brute_modifier = 0.8 + speed_modifier = -0.1 + dmg_overlay_type = null + bodytype = BODYTYPE_ORGANIC + bodyshape = BODYSHAPE_DIGITIGRADE + footstep_type = FOOTSTEP_MOB_CLAW + +/obj/item/bodypart/leg/right/werewolf/update_limb(dropping_limb, is_creating) + . = ..() + if(ishuman(owner)) + var/mob/living/carbon/human/wolf = owner + species_color = wolf.hair_color diff --git a/maplestation_modules/code/modules/surgery/organs/ears.dm b/maplestation_modules/code/modules/surgery/organs/ears.dm index 854439985e0e..a966f75d83d5 100644 --- a/maplestation_modules/code/modules/surgery/organs/ears.dm +++ b/maplestation_modules/code/modules/surgery/organs/ears.dm @@ -19,3 +19,28 @@ icon_state = "catcyber" icon = 'maplestation_modules/icons/mob/mutant_bodyparts.dmi' locked = TRUE + +/obj/item/organ/ears/cat/werewolf + name = "wolf ears" + icon = 'icons/obj/clothing/head/costume.dmi' + icon_state = "kitty" + desc = "Allows the user to more easily hear whispers. The user becomes extra vulnerable to loud noises, however" + // Same sensitivity as felinid ears + damage_multiplier = 2 + +/obj/item/organ/ears/cat/werewolf/on_mob_insert(mob/living/carbon/human/ear_owner) + . = ..() + if(istype(ear_owner)) + ADD_TRAIT(ear_owner, TRAIT_GOOD_HEARING, ORGAN_TRAIT) + +/obj/item/organ/ears/cat/werewolf/on_mob_remove(mob/living/carbon/human/ear_owner) + . = ..() + if(istype(ear_owner)) + REMOVE_TRAIT(ear_owner, TRAIT_GOOD_HEARING, ORGAN_TRAIT) + +/datum/sprite_accessory/ears/werewolf + name = "Werewolf" + icon_state = "werewolf" + icon = 'maplestation_modules/icons/mob/mutant_bodyparts.dmi' + locked = TRUE + color_src = HAIR_COLOR diff --git a/maplestation_modules/code/modules/surgery/organs/eyes.dm b/maplestation_modules/code/modules/surgery/organs/eyes.dm new file mode 100644 index 000000000000..e1d16188c798 --- /dev/null +++ b/maplestation_modules/code/modules/surgery/organs/eyes.dm @@ -0,0 +1,7 @@ +/obj/item/organ/eyes/werewolf + name = "wolf eyes" + desc = "Large and powerful eyes." + sight_flags = SEE_MOBS + color_cutoffs = list(25, 5, 42) + icon_state = "werewolf_eyes" + icon = 'maplestation_modules/icons/obj/surgery.dmi' diff --git a/maplestation_modules/code/modules/surgery/organs/heart.dm b/maplestation_modules/code/modules/surgery/organs/heart.dm new file mode 100644 index 000000000000..99ed28bd47c3 --- /dev/null +++ b/maplestation_modules/code/modules/surgery/organs/heart.dm @@ -0,0 +1,21 @@ +/obj/item/organ/heart/werewolf + name = "massive heart" + desc = "An absolutely monstrous heart." + icon_state = "heart-on" + base_icon_state = "heart" + maxHealth = 2 * STANDARD_ORGAN_THRESHOLD + +/obj/item/organ/heart/werewolf/Initialize(mapload) + . = ..() + transform = transform.Scale(1.5) + +/obj/item/organ/heart/werewolf/on_mob_insert(mob/living/carbon/heart_owner) + . = ..() + // Gives rage to the heart owner. + var/datum/action/cooldown/spell/werewolf_rage/rage = new(heart_owner) + rage.Grant(heart_owner) + +/obj/item/organ/heart/werewolf/on_mob_remove(mob/living/carbon/heart_owner, special = FALSE) + . = ..() + var/datum/action/cooldown/spell/werewolf_rage/rage = locate() in heart_owner.actions + qdel(rage) diff --git a/maplestation_modules/code/modules/surgery/organs/liver.dm b/maplestation_modules/code/modules/surgery/organs/liver.dm new file mode 100644 index 000000000000..b4a7988b84c4 --- /dev/null +++ b/maplestation_modules/code/modules/surgery/organs/liver.dm @@ -0,0 +1,27 @@ +// Liver stuff + +// werewolf liver, used for various funny traits, like handling their silver weakness chemically +/obj/item/organ/liver/werewolf + + name = "Beastly liver" + desc = "A large monstrous liver." + icon_state = "liver" + organ_flags = ORGAN_UNREMOVABLE + // this is a major stop gap: i do want down the line for this to be removable, but this is the easiest way to keep liver in even when untransformed, and prevent werewolves from removing it for 0 downsides + organ_traits = list(TRAIT_SILVER_VULNERABLE) + +/obj/item/organ/liver/werewolf/handle_chemical(mob/living/carbon/organ_owner, datum/reagent/chem, seconds_per_tick, times_fired) + . = ..() + // parent returned COMSIG_MOB_STOP_REAGENT_CHECK or we are failing + if((. & COMSIG_MOB_STOP_REAGENT_CHECK) || (organ_flags & ORGAN_FAILING)) + return + if(istype(chem, /datum/reagent/silver)) + organ_owner.adjustStaminaLoss(2 * REM * seconds_per_tick, updating_stamina = TRUE) + organ_owner.adjustFireLoss(2 * REM * seconds_per_tick, updating_health = TRUE) + organ_owner.cause_pain(BODY_ZONES_ALL, 1 * REM * seconds_per_tick) + +/datum/reagent/silver/on_mob_metabolize(mob/living/exposed) // putting it here just because its relevant- move it down the line + . = ..() + if(HAS_TRAIT(exposed, TRAIT_SILVER_VULNERABLE)) // this is just a notifier the mob is silver vulnerable, unless impossible, what the silver actually DOES to them is decided on the mob itself + exposed.visible_message(span_warning("[exposed] recoils in agony!"), span_notice("Your body shudders upon exposure to pure [LOWER_TEXT(name)]!")) + exposed.emote("scream") diff --git a/maplestation_modules/code/modules/surgery/organs/tongue.dm b/maplestation_modules/code/modules/surgery/organs/tongue.dm index 94222e18886d..8d611713bfc3 100644 --- a/maplestation_modules/code/modules/surgery/organs/tongue.dm +++ b/maplestation_modules/code/modules/surgery/organs/tongue.dm @@ -73,3 +73,38 @@ speech_sound_list = list('maplestation_modules/sound/voice/shad1.ogg' = 55, 'maplestation_modules/sound/voice/shad2.ogg' = 55) speech_sound_list_question = null // same as regular speech sounds speech_sound_list_exclamation = list('maplestation_modules/sound/voice/shad_exclaim.ogg' = 55) + +/obj/item/organ/tongue/werewolf + name = "wolf tongue" + desc = "A large tongue that looks like a mix of a human's and a wolf's." + icon_state = "werewolf_tongue" + icon = 'maplestation_modules/icons/obj/surgery.dmi' + say_mod = "growls" + modifies_speech = TRUE + taste_sensitivity = 5 + liked_foodtypes = GROSS | MEAT | RAW | GORE + disliked_foodtypes = SUGAR + +/obj/item/organ/tongue/werewolf/modify_speech(datum/source, list/speech_args) + var/message = speech_args[SPEECH_MESSAGE] + if(message[1] != "*") + + // all occurrences of characters "ei" (case-insensitive) are replaced with "r" + message = replacetext(message, regex(@"[ei]", "ig"), "r") + // all characters other than "zhrgbmnaou .!?-" (case-insensitive) are stripped + message = replacetext(message, regex(@"[^zhrgbmnaou.!?-\s]", "ig"), "") + // multiple spaces are replaced with a single (whitespace is trimmed) + message = replacetext(message, regex(@"(\s+)", "g"), " ") + + var/list/old_words = splittext(message, " ") + var/list/new_words = list() + for(var/word in old_words) + // lower-case "r" at the end of words replaced with "rh" + word = replacetext(word, regex(@"\lr\b"), "rh") + // an "a" or "A" by itself will be replaced with "hra" + word = replacetext(word, regex(@"\b[Aa]\b"), "hra") + new_words += word + + message = new_words.Join(" ") + message = capitalize(message) + speech_args[SPEECH_MESSAGE] = message diff --git a/maplestation_modules/icons/mob/actions/actions_advspells.dmi b/maplestation_modules/icons/mob/actions/actions_advspells.dmi new file mode 100644 index 000000000000..63b27d78771d Binary files /dev/null and b/maplestation_modules/icons/mob/actions/actions_advspells.dmi differ diff --git a/maplestation_modules/icons/mob/mutant_bodyparts.dmi b/maplestation_modules/icons/mob/mutant_bodyparts.dmi index eeeaedce4666..6bc5a6d44142 100644 Binary files a/maplestation_modules/icons/mob/mutant_bodyparts.dmi and b/maplestation_modules/icons/mob/mutant_bodyparts.dmi differ diff --git a/maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi b/maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi new file mode 100644 index 000000000000..6c388d7b1374 Binary files /dev/null and b/maplestation_modules/icons/mob/werewolf_parts_greyscale.dmi differ diff --git a/maplestation_modules/icons/obj/surgery.dmi b/maplestation_modules/icons/obj/surgery.dmi index 429cf7214e45..9d3782e8fbe2 100644 Binary files a/maplestation_modules/icons/obj/surgery.dmi and b/maplestation_modules/icons/obj/surgery.dmi differ