diff --git a/code/__DEFINES/role_bans.dm b/code/__DEFINES/role_bans.dm
index 465b55d2a81..fe553c6b50d 100644
--- a/code/__DEFINES/role_bans.dm
+++ b/code/__DEFINES/role_bans.dm
@@ -21,6 +21,7 @@
ROLE_SYNDICATE,\
ROLE_MANIAC,\
ROLE_WEREWOLF,\
+ ROLE_VURDALAK,\
ROLE_VAMPIRE,\
ROLE_NBEAST,\
ROLE_BANDIT,\
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index cf724cd41d1..168a90cc445 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -9,6 +9,7 @@
#define ROLE_MANIAC "Maniac"
#define ROLE_WEREWOLF "Werewolf"
#define ROLE_VAMPIRE "Vampire"
+#define ROLE_VURDALAK "Vurdalak"
#define ROLE_NBEAST "Vampire Lord"
#define ROLE_BANDIT "Bandit"
#define ROLE_DELF "Dark Elf"
@@ -64,6 +65,7 @@ GLOBAL_LIST_INIT(special_roles_rogue, list(
ROLE_BANDIT = /datum/antagonist/bandit,
ROLE_ASPIRANT = /datum/antagonist/aspirant,
ROLE_WEREWOLF = /datum/antagonist/werewolf,
+ ROLE_VURDALAK = /datum/antagonist/vurdalak,
ROLE_ZIZOIDCULTIST = /datum/antagonist/zizocultist,
ROLE_NBEAST = /datum/antagonist/vampirelord,
ROLE_LICH = /datum/antagonist/lich
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index edcd6c3e05e..61364c1859b 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -183,7 +183,8 @@ GLOBAL_LIST_INIT(roguetraits, list(
TRAIT_SHARPER_BLADES = span_info("My weapons lose their sharpness slower."), // REDMOON ADD
TRAIT_BLACKLEG = span_info("I can cheat by rigging coin and dice, and peek at cards."), // REDMOON ADD
TRAIT_INQUISITION = span_info("I am a member of the Inquisition. I can easily identify others of my cadre at a glance."), // REDMOON ADD
- TRAIT_BARDIC_TRAINING = "Xylixian inspiration grants my songs boons and ailments.",
+ TRAIT_BARDIC_TRAINING = "Xylixian inspiration grants my songs boons and ailments.", // REDMOON ADD
+ TRAIT_GROUNDSLEEPER = span_info("I can sleep on floor or even bare soil with ease."), // REDMOON ADD
TRAIT_STUDENT = span_info("The scholar has taught me new skills!"),
TRAIT_DARKLING = span_info("I am a creature of the dark and am sensitive to the light. The hateful sun is especially harsh on my eyes, and I prefer to sleep during the dae."),
TRAIT_BOG_TREKKING = "Expert in navigating these lands.",
diff --git a/code/__REDFINES/DNA.dm b/code/___REDFINES/DNA.dm
similarity index 100%
rename from code/__REDFINES/DNA.dm
rename to code/___REDFINES/DNA.dm
diff --git a/code/__REDFINES/colors.dm b/code/___REDFINES/colors.dm
similarity index 100%
rename from code/__REDFINES/colors.dm
rename to code/___REDFINES/colors.dm
diff --git a/code/__REDFINES/mobs.dm b/code/___REDFINES/mobs.dm
similarity index 100%
rename from code/__REDFINES/mobs.dm
rename to code/___REDFINES/mobs.dm
diff --git a/code/__REDFINES/prefereces.dm b/code/___REDFINES/prefereces.dm
similarity index 100%
rename from code/__REDFINES/prefereces.dm
rename to code/___REDFINES/prefereces.dm
diff --git a/code/__REDFINES/stats.dm b/code/___REDFINES/stats.dm
similarity index 100%
rename from code/__REDFINES/stats.dm
rename to code/___REDFINES/stats.dm
diff --git a/code/__REDFINES/stress.dm b/code/___REDFINES/stress.dm
similarity index 100%
rename from code/__REDFINES/stress.dm
rename to code/___REDFINES/stress.dm
diff --git a/code/__REDFINES/traits.dm b/code/___REDFINES/traits.dm
similarity index 85%
rename from code/__REDFINES/traits.dm
rename to code/___REDFINES/traits.dm
index 18a0a59c791..33d869033c9 100644
--- a/code/__REDFINES/traits.dm
+++ b/code/___REDFINES/traits.dm
@@ -1,5 +1,6 @@
#define TRAIT_INQUISITION "Member of the Inquisition"
#define TRAIT_BARDIC_TRAINING "Bardic Training"
+#define TRAIT_GROUNDSLEEPER "Ground Sleeper"
#define TRAIT_SOFTHEARTED "softhearted" //no bad mood from dismembering or seeing this
#define BODYTYPE_FEMALE_PLUMP "female_plump"
#define TRAIT_EORA "Eora"
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index c8f6e46a17a..ed899600a32 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -74,6 +74,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_SEEPRICES" = TRAIT_SEEPRICES,
"Bardic Training" = TRAIT_BARDIC_TRAINING, // REDMOON ADD
"Blackleg" = TRAIT_BLACKLEG, // REDMOON ADD
+ "TRAIT_GROUNDSLEEPER" = TRAIT_GROUNDSLEEPER, // REDMOON ADD
"TRAIT_STUDENT" = TRAIT_STUDENT,
"TRAIT_BOG_TREKKING" = TRAIT_BOG_TREKKING,
"TRAIT_DEATHBYSNUSNU" = TRAIT_DEATHBYSNUSNU,
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 386266b9bfd..73a3396e7b7 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -755,7 +755,7 @@
var/mob/living/carbon/human/H = hud.mymob
if(H.mind && H.mind.antag_datums)
for(var/datum/antagonist/D in H.mind.antag_datums)
- if(istype(D, /datum/antagonist/vampirelord) || istype(D, /datum/antagonist/vampire) || istype(D, /datum/antagonist/bandit) || istype(D, /datum/antagonist/lich))
+ if(istype(D, /datum/antagonist/vampirelord) || istype(D, /datum/antagonist/vampire) || istype(D, /datum/antagonist/bandit) || istype(D, /datum/antagonist/lich) || istype(D, /datum/antagonist/vurdalak))
qdel(src)
return
if(H.advsetup)
diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm
index f8fa4a0b063..f47c892d762 100644
--- a/code/_onclick/other_mobs.dm
+++ b/code/_onclick/other_mobs.dm
@@ -253,6 +253,11 @@
caused_wound?.werewolf_infect_attempt()
if(prob(60))
user.werewolf_feed(src)
+ if(user.mind.has_antag_datum(/datum/antagonist/vurdalak))
+ if(prob(20))
+ visible_message(span_danger("[user] откусывает кусок от [src]!"), \
+ span_userdanger("ОНО ЕСТ МЕНЯ ЖИВЬЁМ!!"))
+ user.vurdalak_feed(src)
// both player and npc deadites can infect
if(user.mind.has_antag_datum(/datum/antagonist/zombie) || istype(user, /mob/living/carbon/human/species/deadite))
var/datum/antagonist/zombie/existing_zomble = mind?.has_antag_datum(/datum/antagonist/zombie)
diff --git a/code/datums/character_flaw/addiction.dm b/code/datums/character_flaw/addiction.dm
index 5b1ce3e4cfe..c08ec34cfb5 100644
--- a/code/datums/character_flaw/addiction.dm
+++ b/code/datums/character_flaw/addiction.dm
@@ -37,7 +37,7 @@
return
if(user.mind.antag_datums)
for(var/datum/antagonist/D in user.mind.antag_datums)
- if(istype(D, /datum/antagonist/vampirelord) || istype(D, /datum/antagonist/werewolf) || istype(D, /datum/antagonist/skeleton) || istype(D, /datum/antagonist/zombie) || istype(D, /datum/antagonist/lich))
+ if(istype(D, /datum/antagonist/vampirelord) || istype(D, /datum/antagonist/werewolf) || istype(D, /datum/antagonist/skeleton) || istype(D, /datum/antagonist/zombie) || istype(D, /datum/antagonist/lich) || istype(D, /datum/antagonist/vurdalak))
return
var/mob/living/carbon/human/H = user
var/oldsated = sated
diff --git a/code/game/gamemodes/roguetown/roguetown.dm b/code/game/gamemodes/roguetown/roguetown.dm
index dd839af3923..ea833ee17c0 100644
--- a/code/game/gamemodes/roguetown/roguetown.dm
+++ b/code/game/gamemodes/roguetown/roguetown.dm
@@ -131,7 +131,8 @@ var/global/list/roguegamemodes = list("Rebellion", "Vampires and Werewolves", "N
return TRUE
if(SSticker.manualmodes)
forcedmodes |= SSticker.manualmodes
-
+ if(num_players() < 20)
+ return TRUE // Убираем рол антагонистов, если низкий онлайн
if(forcedmodes.len)
message_admins("Manual gamemodes selected.")
for(var/G in forcedmodes)
@@ -162,7 +163,7 @@ var/global/list/roguegamemodes = list("Rebellion", "Vampires and Werewolves", "N
log_game("Major Antagonist: None")
return TRUE
- if(num_players() >= 64)
+ if(num_players() >= 50)
var/major_roll_highpop = pick(1,2,3,4)
switch(major_roll_highpop)
if(1)
@@ -178,7 +179,7 @@ var/global/list/roguegamemodes = list("Rebellion", "Vampires and Werewolves", "N
if(4)
pick_lich()
log_game("Major Antagonist: Lich")
- else if(num_players() >= 52)
+ else if(num_players() >= 40)
var/major_roll_midpop = pick(1,2,3)
switch(major_roll_midpop)
if(1)
@@ -208,6 +209,11 @@ var/global/list/roguegamemodes = list("Rebellion", "Vampires and Werewolves", "N
pick_bandits()
log_game("Minor Antagonist: Bandit")
+ if(num_players() >= 30)
+ if(prob(100))
+ pick_vurdalaks()
+ log_game("Minor Antagonist: Vurdalak")
+
if(prob(45))
pick_aspirants()
log_game("Minor Antagonist: Aspirant")
@@ -691,6 +697,14 @@ var/global/list/roguegamemodes = list("Rebellion", "Vampires and Werewolves", "N
rebelguy.add_antag_datum(new_antag)
GLOB.pre_setup_antags -= rebelguy
+///////////////// VURDALAK
+ for(var/datum/mind/vurdalak in pre_vurdalaks)
+ var/datum/antagonist/new_antag = new /datum/antagonist/vurdalak()
+ //addtimer(CALLBACK(werewolf, TYPE_PROC_REF(/datum/mind, add_antag_datum), new_antag), rand(10,100))
+ vurdalak.add_antag_datum(new_antag)
+ GLOB.pre_setup_antags -= vurdalak
+ vurdalaks += vurdalak
+
..()
//We're not actually ready until all traitors are assigned.
gamemode_ready = FALSE
diff --git a/code/modules/antagonists/roguetown/roleobjs/skeleton.dm b/code/modules/antagonists/roguetown/roleobjs/skeleton.dm
index 92c2b3bc092..9f6f0b6d932 100644
--- a/code/modules/antagonists/roguetown/roleobjs/skeleton.dm
+++ b/code/modules/antagonists/roguetown/roleobjs/skeleton.dm
@@ -12,6 +12,8 @@
return span_boldnotice("Another deadite.")
if(istype(examined_datum, /datum/antagonist/skeleton))
return span_boldnotice("Another deadite. My ally.")
+ if(istype(examined_datum, /datum/antagonist/vurdalak))
+ return span_boldwarning("Another deadite... May be hostile. Better not provoke.")
/datum/antagonist/skeleton/on_gain()
diff --git a/code/modules/antagonists/roguetown/villain/vampirelord.dm b/code/modules/antagonists/roguetown/villain/vampirelord.dm
index 36b9b3f95a4..2b59f6fc6a3 100644
--- a/code/modules/antagonists/roguetown/villain/vampirelord.dm
+++ b/code/modules/antagonists/roguetown/villain/vampirelord.dm
@@ -46,6 +46,8 @@ GLOBAL_LIST_EMPTY(vampire_objects)
return span_boldnotice("Another deadite.")
if(istype(examined_datum, /datum/antagonist/skeleton))
return span_boldnotice("Another deadite.")
+ if(istype(examined_datum, /datum/antagonist/vurdalak))
+ return span_boldwarning("Another deadite... A competitor for blood. Hunter of the terror bog.")
/datum/antagonist/vampirelord/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
diff --git a/code/modules/antagonists/roguetown/villain/werewolf/werewolf_spells.dm b/code/modules/antagonists/roguetown/villain/werewolf/werewolf_spells.dm
index 030c1a0dab2..1eaf3e1b1bd 100644
--- a/code/modules/antagonists/roguetown/villain/werewolf/werewolf_spells.dm
+++ b/code/modules/antagonists/roguetown/villain/werewolf/werewolf_spells.dm
@@ -102,6 +102,9 @@ var/sound_cooldown = 10 * 60 * 10 // cooldown in deciseconds (15 minutes)
if(target.mind.has_antag_datum(/datum/antagonist/vampirelord))
to_chat(src, span_warning("... What? Its an elder vampire!"))
return
+ if(target.mind.has_antag_datum(/datum/antagonist/vurdalak))
+ to_chat(src, span_warning("... What? Its an undead!"))
+ return
(!do_after(user, 7 SECONDS, target = target))
var/ramount = 20
var/rid = /datum/reagent/medicine/healthpot
diff --git a/code/modules/antagonists/roguetown/villain/zomble.dm b/code/modules/antagonists/roguetown/villain/zomble.dm
index 889b676ccb6..32c89f129a5 100644
--- a/code/modules/antagonists/roguetown/villain/zomble.dm
+++ b/code/modules/antagonists/roguetown/villain/zomble.dm
@@ -39,6 +39,8 @@
return span_boldnotice("Another deadite. [fellow_zombie.has_turned ? "My ally." : span_warning("Hasn't turned yet.")]")
if(istype(examined_datum, /datum/antagonist/skeleton))
return span_boldnotice("Another deadite.")
+ if(istype(examined_datum, /datum/antagonist/vurdalak))
+ return span_boldwarning("Another deadite. May be agressive...")
/datum/antagonist/zombie/on_gain()
var/mob/living/carbon/human/zombie = owner?.current
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 836275a9611..556d70a0ea9 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -178,7 +178,8 @@
else
if(mind && mind.special_role == "Vampire Lord")
. += "A MONSTER!"
-
+ else if(mind?.special_role == ROLE_VURDALAK)
+ . += span_userdanger("A MONSTER!")
var/commie_text
if(mind)
@@ -194,6 +195,9 @@
if(mind.special_role == "Vampire Lord")
. += span_userdanger("A MONSTER!")
+ if(mind.special_role == ROLE_VURDALAK)
+ . += span_userdanger("A MONSTER!")
+
if(mind.assigned_role == "Lunatic")
. += span_userdanger("LUNATIC!")
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 4d113a9ee51..9e14360d4ac 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -130,6 +130,8 @@
if(VD)
if(statpanel("Stats"))
stat("Vitae:",VD.vitae)
+ if(skin_armor)
+ stat("Skin Armor Integrity:", skin_armor.obj_integrity)
if((mind.assigned_role == "Confessor") || (mind.assigned_role == "Inquisitor"))
if(statpanel("Status"))
stat("Confessions sent: [GLOB.confessors.len]")
diff --git a/code/modules/mob/living/carbon/human/species_types/roguetown/other/werewolf.dm b/code/modules/mob/living/carbon/human/species_types/roguetown/other/werewolf.dm
index 5f609657258..514fdee30ba 100644
--- a/code/modules/mob/living/carbon/human/species_types/roguetown/other/werewolf.dm
+++ b/code/modules/mob/living/carbon/human/species_types/roguetown/other/werewolf.dm
@@ -30,6 +30,7 @@
TRAIT_HARDDISMEMBER, //Decapping Volfs causes them to bug out, badly, and need admin intervention to fix. Bandaid fix.
TRAIT_PIERCEIMMUNE, //Prevents weapon dusting and caltrop effects due to them transforming when killed/stepping on shards.
TRAIT_BOG_TREKKING,
+ TRAIT_GROUNDSLEEPER, // REDMOON ADD
TRAIT_IGNORESLOWDOWN
)
inherent_biotypes = MOB_HUMANOID
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 16a641310ba..8821566ddb1 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -727,5 +727,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
recovery_amt = max_energy * 0.005 // 7.5 минут на полный отдых за сон на земле
else
recovery_amt = max_energy * 0.0035 // REDMOON ADD END - 10 минут на полный отдых за лежание на земле без сна, чтобы был смысл искать кровати
+ if(HAS_TRAIT(src, TRAIT_GROUNDSLEEPER))
+ recovery_amt = max_energy * 0.01 // 3 минуты на полный отдых за сон на земле
energy_add(recovery_amt)
diff --git a/code/modules/mob/living/grabbing.dm b/code/modules/mob/living/grabbing.dm
index c2dc96c0445..62314f70178 100644
--- a/code/modules/mob/living/grabbing.dm
+++ b/code/modules/mob/living/grabbing.dm
@@ -536,6 +536,7 @@
if(user.mind && C.mind)
var/datum/antagonist/vampirelord/VDrinker = user.mind.has_antag_datum(/datum/antagonist/vampirelord)
+ var/datum/antagonist/vurdalak/vurdalak_drinker = user.mind.has_antag_datum(/datum/antagonist/vurdalak)
var/datum/antagonist/vampirelord/VVictim = C.mind.has_antag_datum(/datum/antagonist/vampirelord)
var/zomwerewolf = C.mind.has_antag_datum(/datum/antagonist/werewolf)
if(!zomwerewolf)
@@ -565,6 +566,16 @@
VDrinker.handle_vitae(500)
else
to_chat(user, span_warning("No more vitae from this blood..."))
+ else if(vurdalak_drinker)
+ if(C.vitae_bank > 500)
+ C.blood_volume = max(C.blood_volume-45, 0)
+ C.vitae_bank -= 1500
+ if(!C.vitae_bank)
+ if(!(C.real_name in vurdalak_drinker.unique_victims))
+ vurdalak_drinker.unique_victims += C.real_name
+ vurdalak_drinker.handle_power_up()
+ else
+ to_chat(user, span_warning("No more vitae from this blood..."))
else
if(VVictim)
to_chat(user, "A strange, sweet taste tickles my throat.")
@@ -581,6 +592,8 @@
VDrinker.handle_vitae(300, 300)
else
VDrinker.handle_vitae(300)
+ else if(user.mind.has_antag_datum(/datum/antagonist/vurdalak))
+ to_chat(user, span_warning("I feel no lifeforce in this blood... It's useless."))
C.blood_volume = max(C.blood_volume-5, 0)
C.handle_blood()
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index e2692c7586d..bf6fdf1f5f5 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -656,6 +656,9 @@
return
if(L.energy <= 0)
return
+ if(HAS_TRAIT(L, TRAIT_NORUN))
+ to_chat(L, span_warning("My joints have decayed too much for running!"))
+ return
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(!H.check_armor_skill() || H.legcuffed)
diff --git a/code/modules/roguetown/roguejobs/gravedigger/hole.dm b/code/modules/roguetown/roguejobs/gravedigger/hole.dm
index 784a1809bc1..a48a9752c15 100644
--- a/code/modules/roguetown/roguejobs/gravedigger/hole.dm
+++ b/code/modules/roguetown/roguejobs/gravedigger/hole.dm
@@ -24,6 +24,11 @@
faildirt = 3
icon_state = "grave"
+/obj/structure/closet/dirthole/grave/Initialize()
+ ..()
+ if(is_valid_hunting_area(get_area(src)))
+ GLOB.vurdalak_spawn_locations += get_turf(src)
+
/obj/structure/closet/dirthole/closed
desc = "A mound of dirt with something below."
stage = 4
diff --git a/code/modules/spells/roguetown/acolyte/pestra.dm b/code/modules/spells/roguetown/acolyte/pestra.dm
index 40b822dc11a..a7ba84ff7ae 100644
--- a/code/modules/spells/roguetown/acolyte/pestra.dm
+++ b/code/modules/spells/roguetown/acolyte/pestra.dm
@@ -230,7 +230,7 @@
revert_cast()
return FALSE
// If, for whatever reason, someone manages to capture a vampire with (somehow) rot??? This prevents them from losing their undead biotype.
- if(target.mind?.has_antag_datum(/datum/antagonist/vampire) || target.mind?.has_antag_datum(/datum/antagonist/vampire/lesser) || target.mind?.has_antag_datum(/datum/antagonist/vampirelord))
+ if(target.mind?.has_antag_datum(/datum/antagonist/vampire) || target.mind?.has_antag_datum(/datum/antagonist/vampire/lesser) || target.mind?.has_antag_datum(/datum/antagonist/vampirelord) || target.mind?.has_antag_datum(/datum/antagonist/vurdalak))
to_chat(user, span_warning("It's of an incurable evil, I can't."))
revert_cast()
return FALSE
diff --git a/code/modules/spells/roguetown/acolyte/sawbones.dm b/code/modules/spells/roguetown/acolyte/sawbones.dm
index b110e59f139..24148dbae54 100644
--- a/code/modules/spells/roguetown/acolyte/sawbones.dm
+++ b/code/modules/spells/roguetown/acolyte/sawbones.dm
@@ -175,7 +175,7 @@
return FALSE
// If, for whatever reason, someone manages to capture a vampire with (somehow) rot??? This prevents them from losing their undead biotype.
- if(target.mind?.has_antag_datum(/datum/antagonist/vampire) || target.mind?.has_antag_datum(/datum/antagonist/vampire/lesser) || target.mind?.has_antag_datum(/datum/antagonist/vampirelord))
+ if(target.mind?.has_antag_datum(/datum/antagonist/vampire) || target.mind?.has_antag_datum(/datum/antagonist/vampire/lesser) || target.mind?.has_antag_datum(/datum/antagonist/vampirelord) || target.mind?.has_antag_datum(/datum/antagonist/vurdalak))
to_chat(user, span_warning("It's of an incurable evil, I can't."))
revert_cast()
return FALSE
diff --git a/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak.dm b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak.dm
new file mode 100644
index 00000000000..ac77f7205d6
--- /dev/null
+++ b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak.dm
@@ -0,0 +1,131 @@
+/mob/living/carbon/human/proc/vurdalak_transform()
+ if(!mind)
+ log_runtime("NO MIND ON [src.name] WHEN TRANSFORMING")
+ Paralyze(1, ignore_canstun = TRUE)
+ for(var/obj/item/W in src)
+ qdel(W)
+ set_cmode(FALSE)
+ if(client)
+ SSdroning.play_area_sound(get_area(src), client)
+// stop_cmusic()
+
+ var/ww_path
+ if(gender == MALE)
+ ww_path = /mob/living/carbon/human/species/vurdalak/male
+ else
+ ww_path = /mob/living/carbon/human/species/vurdalak/female
+
+ var/mob/living/carbon/human/species/vurdalak/W = new ww_path(loc)
+
+ W.set_patron(/datum/patron/godless)
+ W.gender = gender
+ W.regenerate_icons()
+ W.limb_destroyer = TRUE
+
+ W.ambushable = FALSE
+ W.cmode_music = 'modular_redmoon/sounds/music/combat_vurdalak.ogg'
+ W.skin_armor = new /obj/item/clothing/suit/roguetown/armor/skin_armor/vurdalak_skin(W)
+
+ W.after_creation()
+ mind.transfer_to(W)
+ W.mind.known_skills = list()
+ W.mind.skill_experience = list()
+ W.real_name = W.dna.species.random_name()
+ W.name = W.real_name
+ W.mob_biotypes |= MOB_UNDEAD
+ W.faction = list("undead")
+
+ W.base_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB)
+ W.update_a_intents()
+ W.can_do_sex = FALSE
+ W.grant_all_languages(omnitongue = FALSE)
+
+ W.possible_rmb_intents = list(/datum/rmb_intent/feint,\
+ /datum/rmb_intent/riposte,\
+ /datum/rmb_intent/weak)
+
+ W.mind.adjust_skillrank(/datum/skill/combat/wrestling, 4, TRUE)
+ W.mind.adjust_skillrank(/datum/skill/combat/unarmed, 3, TRUE)
+ W.mind.adjust_skillrank(/datum/skill/misc/climbing, 6, TRUE)
+ W.mind.adjust_skillrank(/datum/skill/misc/sneaking, 5, TRUE)
+ W.mind.adjust_skillrank(/datum/skill/misc/swimming, 5, TRUE)
+
+ W.mind.RemoveAllSpells()
+ W.mind.AddSpell(new /obj/effect/proc_holder/spell/self/claws_vurdalak)
+ W.mind.AddSpell(new /obj/effect/proc_holder/spell/self/vurdalak_targets_search)
+ W.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/vurdalak_rejuv)
+ W.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/vurdalak_feast)
+
+ qdel(src)
+
+/mob/living/carbon/human/proc/vurdalak_feed(mob/living/carbon/human/target)
+ if(!istype(target))
+ return
+
+ to_chat(src, span_warning("I feed on succulent flesh. I feel reinvigorated."))
+ adjust_hydration(50)
+ adjust_nutrition(50)
+ return src.reagents.add_reagent(/datum/reagent/medicine/healthpot, 2)
+
+/obj/item/clothing/suit/roguetown/armor/skin_armor/vurdalak_skin
+ slot_flags = null
+ name = "vurdalak's skin"
+ desc = ""
+ icon_state = null
+ body_parts_covered = FULL_BODY
+ armor = list("blunt" = 100, "slash" = 100, "stab" = 100, "bullet" = 150, "laser" = 0,"energy" = 0, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+ prevent_crits = list(BCLASS_CUT, BCLASS_CHOP, BCLASS_STAB, BCLASS_BLUNT, BCLASS_SMASH, BCLASS_TWIST)
+ blocksound = SOFTHIT
+ blade_dulling = DULLING_BASHCHOP
+ sewrepair = FALSE
+ max_integrity = 200
+ item_flags = DROPDEL
+
+/datum/intent/simple/vurdalak
+ name = "claw"
+ icon_state = "inchop"
+ blade_class = BCLASS_CHOP
+ attack_verb = list("claws", "mauls", "eviscerates")
+ animname = "chop"
+ hitsound = "genslash"
+ candodge = TRUE
+ canparry = TRUE
+ miss_text = "slashes the air!"
+ miss_sound = "bluntwooshlarge"
+ item_d_type = "slash"
+
+/obj/item/rogueweapon/vurdalak_claw
+ name = "claws"
+ desc = ""
+ item_state = null
+ lefthand_file = null
+ righthand_file = null
+ icon = 'icons/roguetown/weapons/32.dmi'
+ max_blade_int = 999999
+ max_integrity = 999999
+ force = 20 // Penetration + strength
+ block_chance = 0
+ wdefense = 4
+ armor_penetration = 30
+ associated_skill = /datum/skill/combat/unarmed
+ wlength = WLENGTH_NORMAL
+ w_class = WEIGHT_CLASS_BULKY
+ can_parry = TRUE
+ sharpness = IS_SHARP
+ parrysound = "bladedmedium"
+ swingsound = BLADEWOOSH_MED
+ possible_item_intents = list(/datum/intent/simple/vurdalak)
+ parrysound = list('sound/combat/parry/parrygen.ogg')
+ embedding = list("embedded_pain_multiplier" = 0, "embed_chance" = 0, "embedded_fall_chance" = 0)
+ item_flags = DROPDEL
+
+/obj/item/rogueweapon/vurdalak_claw/Initialize()
+ . = ..()
+ ADD_TRAIT(src, TRAIT_NODROP, TRAIT_GENERIC)
+ ADD_TRAIT(src, TRAIT_NOEMBED, TRAIT_GENERIC)
+
+/obj/item/rogueweapon/vurdalak_claw/right
+ icon_state = "claw_r"
+
+/obj/item/rogueweapon/vurdalak_claw/left
+ icon_state = "claw_l"
diff --git a/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_datum.dm b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_datum.dm
new file mode 100644
index 00000000000..1f7d2731b3b
--- /dev/null
+++ b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_datum.dm
@@ -0,0 +1,277 @@
+GLOBAL_LIST_EMPTY(vurdalak_spawn_locations)
+
+/*
+ * ДАТУМ АНТАГОНИСТА
+ */
+
+/datum/antagonist/vurdalak
+ name = ROLE_VURDALAK
+ roundend_category = "Vurdalaks"
+ antagpanel_category = "Vurdalak"
+ job_rank = ROLE_VURDALAK
+ confess_lines = list(
+ "GHRAAA!",
+ "AAAGH!",
+ "SSSUN WILL MAKE ME CRY!!"
+ )
+ rogue_enabled = TRUE
+ var/day_debuff = TRUE
+ var/bog_bounded = TRUE
+ var/list/unique_victims = list()
+ var/last_sound = 0
+ var/hide_strength = 200
+ var/claws_armor_penetration = 30
+ var/last_tod = "day"
+
+/datum/antagonist/vurdalak/roundend_report()
+ var/traitorwin = TRUE
+
+ printplayer(owner)
+
+ var/count = 0
+ if(objectives.len)//If the traitor had no objectives, don't need to process this.
+ for(var/datum/objective/objective in objectives)
+ objective.update_explanation_text()
+ to_chat(world, "Times they have feasted: [unique_victims.len]")
+ if(objective.check_completion())
+ to_chat(world, "Goal #[count]: [objective.explanation_text] TRIUMPH!")
+ else
+ to_chat(world, "Goal #[count]: [objective.explanation_text] Failure.")
+ traitorwin = FALSE
+ count += objective.triumph_count
+
+ var/special_role_text = lowertext(name)
+ if(traitorwin)
+ if(count)
+ if(owner)
+ owner.adjust_triumphs(count)
+ to_chat(world, span_greentext("The [special_role_text] has TRIUMPHED!"))
+ if(owner?.current)
+ owner.current.playsound_local(get_turf(owner.current), 'sound/misc/triumph.ogg', 100, FALSE, pressure_affected = FALSE)
+ else
+ to_chat(world, span_redtext("The [special_role_text] has FAILED!"))
+ if(owner?.current)
+ owner.current.playsound_local(get_turf(owner.current), 'sound/misc/fail.ogg', 100, FALSE, pressure_affected = FALSE)
+
+
+
+/datum/antagonist/vurdalak/examine_friendorfoe(datum/antagonist/examined_datum,mob/examiner,mob/examined)
+ if(istype(examined_datum, /datum/antagonist/werewolf/lesser))
+ return span_boldwarning("I see Dendor's threads... Must be lupine. Dangerous foe.")
+ if(istype(examined_datum, /datum/antagonist/werewolf))
+ return span_boldwarning("I see strong Dendor's threads... Have to be old lupine. Dangerous foe.")
+ if(istype(examined_datum, /datum/antagonist/vampirelord/lesser))
+ return span_boldwarning("A lesser Vampire spawn... Another, weaker deadite.")
+ if(istype(examined_datum, /datum/antagonist/vampirelord))
+ return span_boldwarning("An Ancient Vampire... A powerful city predator.")
+ if(istype(examined_datum, /datum/antagonist/vurdalak))
+ return span_boldwarning("A cursed creature of Night... Just like me.")
+
+/datum/antagonist/vurdalak/on_gain()
+ owner.special_role = name
+ owner.assigned_role = name
+ move_to_spawn_location()
+
+ var/mob/living/carbon/human/H = owner.current
+ H.vurdalak_transform()
+ owner.name = H.real_name
+
+ forge_vurdalak_objectives()
+ greet()
+ return ..()
+
+/datum/antagonist/vurdalak/proc/move_to_spawn_location()
+ owner.current.forceMove(pick(GLOB.vurdalak_spawn_locations))
+
+/datum/antagonist/vurdalak/on_life(mob/user)
+ if(!user)
+ return
+ if(owner.current.stat == DEAD)
+ return
+ var/mob/living/carbon/human/vurdalak = owner.current
+ if(vurdalak.advsetup)
+ return
+ if(world.time % 5)
+ if(GLOB.tod != "night")
+ if(day_debuff)
+ if(isturf(vurdalak.loc))
+ var/turf/T = vurdalak.loc
+ if(T.can_see_sky())
+ if(T.get_lumcount() > 0.05)
+ vurdalak.apply_status_effect(/datum/status_effect/debuff/vurdalak_sunlight_exposed)
+ last_tod = ""
+ if(GLOB.tod == "night")
+ if(last_tod != "night")
+ last_tod = "night"
+ for(var/client/client in GLOB.clients - vurdalak.client)
+ if(!client.mob)
+ continue
+ if(!is_station_level(client.mob.z))
+ continue
+ if(client.mob.y > 298) // Довольно проклято
+ continue
+ var/distance = 20
+ if(client.mob.z == vurdalak.z)
+ distance = CLAMP(100 - get_dist(vurdalak, client.mob), 5, 80)
+ client.mob.playsound_local(client.mob, 'modular_redmoon/sounds/misc/vurdalak_far.ogg', distance, FALSE)
+ to_chat(client.mob, span_warning("Я слышу завывания болотного чудища[distance >= 50 ? " в далеке..." : "..."]"))
+ vurdalak.playsound_local(vurdalak, 'modular_redmoon/sounds/misc/vurdalak_far.ogg', 80, FALSE)
+ to_chat(vurdalak, span_notice("Я вою в ночь, чтобы показать, кому принадлежит это болото... Или же от бессилия сделать что-то с тем, кем я стал?"))
+
+ if(vurdalak.m_intent != MOVE_INTENT_SNEAK)
+ if(last_sound + 10 SECONDS <= world.time)
+ for(var/mob/living/carbon/human/target in range(4, user) - vurdalak)
+ if(target.stat)
+ continue
+ if(target.m_intent == MOVE_INTENT_SNEAK)
+ continue
+
+ var/sound_to_pick = pick('sound/vo/mobs/wwolf/pain (1).ogg', 'sound/vo/mobs/wwolf/pain (2).ogg', 'sound/vo/mobs/wwolf/pain (3).ogg', 'sound/vo/mobs/wwolf/roar.ogg')
+ playsound(vurdalak.loc, sound_to_pick, 80, 1)
+ last_sound = world.time
+ break
+
+ if(last_sound + 10 SECONDS <= world.time)
+ for(var/mob/living/carbon/human/target in range(7, user) - vurdalak)
+ if(target.stat)
+ continue
+ if(target.m_intent == MOVE_INTENT_SNEAK)
+ continue
+
+ playsound(vurdalak.loc, 'sound/vo/mobs/wwolf/sniff.ogg', 60, 1)
+ last_sound = world.time
+ break
+
+ if(bog_bounded)
+ if(vurdalak.y >= 194) // Супер-проклято. Нужны нормальные зоны для помещений в болоте, потому что они одни и те же, что и в деревне.
+ vurdalak.apply_status_effect(/datum/status_effect/debuff/vurdalak_church_exposed)
+
+ if(vurdalak.on_fire)
+ vurdalak.freak_out()
+
+/datum/antagonist/vurdalak/on_removal()
+ if(!silent && owner.current)
+ to_chat(owner.current, span_danger("I am no longer a [name]!"))
+ owner.special_role = null
+ owner.current = null
+ return ..()
+
+/datum/antagonist/vurdalak/proc/add_objective(datum/objective/O)
+ objectives += O
+
+/datum/antagonist/vurdalak/proc/remove_objective(datum/objective/O)
+ objectives -= O
+
+/datum/antagonist/vurdalak/proc/forge_vurdalak_objectives()
+ if(!(locate(/datum/objective/vurdalak) in objectives))
+ var/datum/objective/vurdalak/vurdalak_objective = new
+ vurdalak_objective.owner = owner
+ add_objective(vurdalak_objective)
+ return
+
+/datum/antagonist/vurdalak/greet()
+ to_chat(owner.current, span_biginfo("I had been cursed for ages ago..."))
+ to_chat(owner.current, span_biginfo("Astrata, the unforgiving ascended witch, had been dull to my pleads, while dark-minded folks mutilated my body for the knowledges I have tried to spread."))
+ to_chat(owner.current, span_biginfo("The mind of mine had been shaken, but not lost to time. I already cannot remember my name nor family, but can recognise what I have become."))
+ to_chat(owner.current, span_biginfo("With each night, I feel less and less disgust to myself, doing what I need to survive another dae."))
+
+ owner.current.playsound_local(get_turf(owner.current), 'modular_redmoon/sounds/music/intro_vurdalak.ogg', 80, FALSE, pressure_affected = FALSE)
+
+ owner.announce_objectives()
+
+ return ..()
+
+/datum/antagonist/vurdalak/proc/handle_power_up()
+ if(unique_victims.len <= 10)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Моя шкура станет плотнее, когда я регенерирую.") : span_cult("My hide will be more resilent after I regenerate myself."))
+ hide_strength += 20
+ switch(unique_victims.len)
+ if(1)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Я чувствую себя сильнее.") : span_cult("I feel myself more powerful."))
+ owner.current.change_stat(STAT_STRENGTH, 1)
+ if(2)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Я чувствую себя крепче.") : span_cult("I feel myself more resilent."))
+ owner.current.change_stat(STAT_CONSTITUTION, 1)
+ owner.current.adjust_triumphs(1)
+ if(3)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Необычная сила распространяется в моих ногах. Я могу двигаться быстрее.") : span_cult("Unusual power spreads in leg. I can move a bit faster now."))
+ owner.current.change_stat(STAT_SPEED, 1)
+ if(4)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Я чувствую себя сильнее.") : span_cult("I feel myself more powerful."))
+ owner.current.change_stat(STAT_STRENGTH, 1)
+ owner.current.adjust_triumphs(1)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Я ощущаю, что куда лучше орудую своими когтями.") : span_cult("I feel myself much more confident in claws combat."))
+ owner.adjust_skillrank(/datum/skill/combat/unarmed, 1, TRUE)
+ if(5)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Я чувствую себя крепче.") : span_cult("I feel myself more resilent."))
+ owner.current.change_stat(STAT_CONSTITUTION, 1)
+ if(6)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Необычная сила распространяется в моих ногах. Я могу двигаться быстрее!") : span_cult("Unusual power spreads in leg. I can move a bit faster now!"))
+ owner.current.change_stat(STAT_SPEED, 1)
+ owner.current.adjust_triumphs(1)
+ if(7)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Моя кровь... Моя кровь кипит! Жажда убивать становится сильнее... Я ощущаю, как думать становится сложнее.") : span_cult("My blood... My blood boils! The urge to kill is more than before... Do I lose myself?"))
+ owner.current.change_stat(STAT_ENDURANCE, 1)
+ owner.current.change_stat(STAT_INTELLIGENCE, -1)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Из моей хватки не вырваться!") : span_cult("My grasp is much stronger now!"))
+ owner.adjust_skillrank(/datum/skill/combat/wrestling, 1, TRUE)
+ if(8)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Я ЧУВСТВУЮ СЕБЯ ВЫНОСЛИВЕЕ, ЧЕМ КОГДА ЛИБО! Я МОГУ УБИВАТЬ БОЛЬШЕ! ЦЕРКОВЬ УМОЕТСЯ В КРОВИ!") : span_cult("I FEEL MYSELF LESS FATIGUE THAN EVER BEFORE! I CAN KILL MORE! THE CHURCH WILL BATH IN BLOOD!"))
+ owner.current.change_stat(STAT_ENDURANCE, 1)
+ owner.current.change_stat(STAT_INTELLIGENCE, -1)
+ owner.current.adjust_triumphs(1)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("В БОЮ КОГТЯМИ МНЕ НЕТ РАВНЫХ!") : span_cult("IN COMBAT WITH CLAWS NO ONE CAN MATCH ME!"))
+ owner.adjust_skillrank(/datum/skill/combat/unarmed, 1, TRUE)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("МОИ КОГТИ СОЗДАНЫ, ЧТОБЫ РАЗРЫВАТЬ ЖЕЛЕЗО!") : span_cult("MY CLAWS ARE FORMED TO BREAK THROUGH IRON!"))
+ claws_armor_penetration = 50
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("И я стал весить больше... Какое счастье, что мне теперь не так и сильно нужно прыгать по деревьям. Корм мне не угроза.") : span_cult("And I have become heavier... Lucky me I don't need to jump on trees anymore. A prey is not a threat to me."))
+ REMOVE_TRAIT(owner.current, TRAIT_ZJUMP, SPECIES_TRAIT)
+ if(9)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cult("Я ЧУВСТВУЮ... СОЛНЦЕ... ОНА НЕ ИМЕЕТ БОЛЕЕ ВЛАСТИ НАДО МНОЙ...") : span_cult("I FEEL... THE SUN... SHE HAS NO POWER OVER ME ANYMORE..."))
+ owner.current.change_stat(STAT_INTELLIGENCE, -2)
+ day_debuff = FALSE
+ if(10)
+ to_chat(owner.current, owner.current.client.prefs.be_russian ? span_cultbigbold("СИЛА ЦЕРКВИ БОЛЬШЕ НЕ СМОЖЕТ СДЕРЖАТЬ МЕНЯ! ЦЕРКОВЬ... НЕ СМОЖЕТ... СДЕРЖИВАТЬ МЕНЯ! КРОВЬ! СМЕРТЬ! Я САМА СМЕРТЬ!!!") : span_cultbigbold("THEIR LIFEFORCE DID LET ME TO PASS THE TERROR BOG! THE CHURCH... NO LONGER... HOLDS ME OFF... BLOOD! DEATH! AM THE DEATH ITSELF!!!"))
+ owner.current.change_stat(STAT_INTELLIGENCE, -4)
+ bog_bounded = FALSE
+
+/*
+ * ЗАДАЧИ
+ */
+
+/datum/objective/vurdalak
+ name = "drink_blood"
+ explanation_text = "With each and every dae, my lifeforce betrays me. I have to drink blood or feast on 10 victims, to sustain myself for a bit more."
+ triumph_count = 5
+
+/datum/objective/vurdalak/check_completion()
+ var/datum/antagonist/vurdalak/vurdalak_datum = owner.has_antag_datum(/datum/antagonist/vurdalak)
+ if(vurdalak_datum)
+ if(vurdalak_datum.unique_victims.len >= 10)
+ return TRUE
+
+/*
+ * СОСТОЯНИЯ
+ */
+
+/datum/status_effect/debuff/vurdalak_sunlight_exposed
+ id = "vurdalak_sunglight"
+ alert_type = /atom/movable/screen/alert/status_effect/debuff/vurdalak_sunlight_exposed
+ effectedstats = list("strength" = -5, "constitution" = -5, "speed" = -5)
+ duration = 10 SECONDS
+
+/datum/status_effect/debuff/vurdalak_church_exposed
+ id = "vurdalak_church"
+ alert_type = /atom/movable/screen/alert/status_effect/debuff/vurdalak_church_exposed
+ effectedstats = list("strength" = -8, "constitution" = -8, "speed" = -8) // Братан НЕ ДОЛЖЕН суваться в деревню
+ duration = 10 SECONDS
+
+/atom/movable/screen/alert/status_effect/debuff/vurdalak_sunlight_exposed
+ name = "SUNLIGHT!"
+ desc = "I feel myself sick of it!\n"
+ icon_state = "stressb"
+
+/atom/movable/screen/alert/status_effect/debuff/vurdalak_church_exposed
+ name = "Church!"
+ desc = "Their church weakens me... I need to get back to the bog.\n"
+ icon_state = "stressvb"
diff --git a/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_globals.dm b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_globals.dm
new file mode 100644
index 00000000000..eadb9fb5636
--- /dev/null
+++ b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_globals.dm
@@ -0,0 +1,60 @@
+/datum/game_mode
+ var/list/datum/mind/vurdalaks = list()
+ var/list/datum/mind/pre_vurdalaks = list()
+
+/datum/game_mode/chaosmode/proc/pick_vurdalaks()
+ // Ideally we want Refugees/Towners to roll it
+ restricted_jobs = list(
+ "Duke",
+ "Duke Consort",
+ "Dungeoneer",
+ "Inquisitor",
+ "Confessor",
+ "Watchman",
+ "Man at Arms",
+ "Priest",
+ "Acolyte",
+ "Cleric",
+ "Retinue Captain",
+ "Court Magos",
+ "Templar",
+ "Vanguard",
+ "Warden",
+ "Knight",
+ "Mortician",
+ "Mercenary",
+ "Bandit",
+ "Goblin Chief",
+ "Goblin Cook",
+ "Goblin Guard",
+ "Goblin Rabble",
+ "Goblin Smith",
+ "Goblin Shaman"
+ )
+
+// var/num_werewolves = rand(1)
+ antag_candidates = get_players_for_role(ROLE_VURDALAK)
+ antag_candidates = shuffle(antag_candidates)
+
+ for(var/datum/mind/vurdalak in antag_candidates)
+ var/blockme = FALSE
+ if(!(vurdalak in allantags))
+ blockme = TRUE
+ if(vurdalak.assigned_role in GLOB.noble_positions)
+ continue
+ if(vurdalak.assigned_role in GLOB.youngfolk_positions)
+ blockme = TRUE
+ if(blockme)
+ continue
+ allantags -= vurdalak
+ pre_vurdalaks += vurdalak
+ vurdalak.special_role = ROLE_VURDALAK
+ //vurdalak.assigned_role = ROLE_WEREWOLF
+ vurdalak.restricted_roles = restricted_jobs.Copy()
+ testing("[key_name(vurdalak)] has been selected as a VURDALAK")
+ log_game("[key_name(vurdalak)] has been selected as a [vurdalak.special_role]")
+ antag_candidates.Remove(vurdalak)
+ break
+ for(var/antag in pre_vurdalaks)
+ GLOB.pre_setup_antags |= antag
+ restricted_jobs = list()
diff --git a/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_species.dm b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_species.dm
new file mode 100644
index 00000000000..a9bcff8016e
--- /dev/null
+++ b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_species.dm
@@ -0,0 +1,127 @@
+/mob/living/carbon/human/species/vurdalak
+ race = /datum/species/vurdalak
+
+/mob/living/carbon/human/species/vurdalak/male
+ gender = MALE
+
+/mob/living/carbon/human/species/vurdalak/female
+ gender = FEMALE
+
+/datum/species/vurdalak
+ name = "vurdalak"
+ id = "vurdalak"
+ species_traits = list(NO_UNDERWEAR, NO_ORGAN_FEATURES, NO_BODYPART_FEATURES)
+ inherent_traits = list(
+ TRAIT_STRONGBITE,
+ TRAIT_ZJUMP,
+ TRAIT_NOFALLDAMAGE1,
+ TRAIT_STEELHEARTED,
+ TRAIT_TOXIMMUNE,
+ TRAIT_ORGAN_EATER,
+ TRAIT_NASTY_EATER,
+ TRAIT_NOSTINK,
+ TRAIT_CRITICAL_RESISTANCE,
+ TRAIT_HARDDISMEMBER, //Decapping Volfs causes them to bug out, badly, and need admin intervention to fix. Bandaid fix.
+// TRAIT_PIERCEIMMUNE, //Prevents weapon dusting and caltrop effects due to them transforming when killed/stepping on shards.
+ TRAIT_BOG_TREKKING,
+ TRAIT_IGNORESLOWDOWN,
+ TRAIT_NOPAINSTUN,
+ TRAIT_LIMPDICK,
+ TRAIT_NOMOOD,
+ TRAIT_NOSLEEP,
+ TRAIT_ZOMBIE_IMMUNE,
+ TRAIT_DODGEEXPERT,
+ TRAIT_GROUNDSLEEPER,
+ TRAIT_NORUN
+ )
+ inherent_biotypes = MOB_HUMANOID
+ armor = 30
+ no_equip = list(SLOT_SHIRT, SLOT_HEAD, SLOT_WEAR_MASK, SLOT_ARMOR, SLOT_GLOVES, SLOT_SHOES, SLOT_PANTS, SLOT_CLOAK, SLOT_BELT, SLOT_BACK_R, SLOT_BACK_L, SLOT_S_STORE)
+ nojumpsuit = 1
+ sexes = 0
+ offset_features = list(OFFSET_HANDS = list(0,2), OFFSET_HANDS_F = list(0,2))
+ soundpack_m = /datum/voicepack/werewolf
+ soundpack_f = /datum/voicepack/werewolf
+ specstats = list(
+ "strength" = 5,
+ "perception" = -2,
+ "intelligence" = -2,
+ "constitution" = 6,
+ "endurance" = 6,
+ "speed" = 2,
+ "fortune" = 0
+ )
+ enflamed_icon = "widefire"
+ organs = list(
+ ORGAN_SLOT_BRAIN = /obj/item/organ/brain,
+ ORGAN_SLOT_HEART = /obj/item/organ/heart,
+ ORGAN_SLOT_LUNGS = /obj/item/organ/lungs,
+ ORGAN_SLOT_EYES = /obj/item/organ/eyes/night_vision/zombie,
+ ORGAN_SLOT_EARS = /obj/item/organ/ears,
+ ORGAN_SLOT_LIVER = /obj/item/organ/liver,
+ ORGAN_SLOT_STOMACH = /obj/item/organ/stomach,
+ ORGAN_SLOT_APPENDIX = /obj/item/organ/appendix,
+ )
+ languages = list(
+ /datum/language/hellspeak,
+ )
+
+/datum/species/vurdalak/send_voice(mob/living/carbon/human/H)
+ playsound(get_turf(H), pick('sound/vo/mobs/wwolf/wolftalk1.ogg','sound/vo/mobs/wwolf/wolftalk2.ogg'), 100, TRUE, -1)
+
+/datum/species/vurdalak/regenerate_icons(mob/living/carbon/human/H)
+ H.icon = 'modular_redmoon/icons/mobs/vurdalak.dmi'
+ H.base_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB)
+ H.icon_state = "vurdalack"
+ H.update_damage_overlays()
+ return TRUE
+
+/datum/species/vurdalak/spec_life(mob/living/carbon/human/H)
+ ..()
+ H.blood_volume = min(H.blood_volume + 5, BLOOD_VOLUME_NORMAL)
+ H.heal_wounds(2)
+ H.adjustBruteLoss(-2, 0)
+ H.adjustFireLoss(-2, 0)
+ H.adjustOxyLoss(-0.5, 0)
+ H.adjustCloneLoss(-0.5, 0) //heals as half as health
+ H.update_damage_overlays()
+
+/datum/species/vurdalak/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ . = ..()
+ RegisterSignal(C, COMSIG_MOB_SAY, PROC_REF(handle_speech))
+
+/datum/species/vurdalak/update_damage_overlays(mob/living/carbon/human/H)
+ return TRUE // Временно отключено, до спрайтов дамага
+ H.remove_overlay(DAMAGE_LAYER)
+ var/list/hands = list()
+ var/mutable_appearance/inhand_overlay = mutable_appearance("[H.icon_state]-dam", layer=-DAMAGE_LAYER)
+ var/burnhead = 0
+ var/brutehead = 0
+ var/burnch = 0
+ var/brutech = 0
+ var/obj/item/bodypart/affecting = H.get_bodypart(BODY_ZONE_HEAD)
+ if(affecting)
+ burnhead = (affecting.burn_dam / affecting.max_damage)
+ brutehead = (affecting.brute_dam / affecting.max_damage)
+ affecting = H.get_bodypart(BODY_ZONE_CHEST)
+ if(affecting)
+ burnch = (affecting.burn_dam / affecting.max_damage)
+ brutech = (affecting.brute_dam / affecting.max_damage)
+ var/usedloss = 0
+ if(burnhead > usedloss)
+ usedloss = burnhead
+ if(brutehead > usedloss)
+ usedloss = brutehead
+ if(burnch > usedloss)
+ usedloss = burnch
+ if(brutech > usedloss)
+ usedloss = brutech
+ inhand_overlay.alpha = 255 * usedloss
+ testing("damalpha [inhand_overlay.alpha]")
+ hands += inhand_overlay
+ H.overlays_standing[DAMAGE_LAYER] = hands
+ H.apply_overlay(DAMAGE_LAYER)
+ return TRUE
+
+/datum/species/vurdalak/random_name(gender,unique,lastname)
+ return pick("Vurdalak", "Nightcurse", "Night Creature", "Abomination", "Creature", "Monster", "Beast", "Terrorbog Beast", "Rockhill Beast", "Nighthunter", "Nightshade", "Dreadclaw", "Nightstalker")
diff --git a/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_spells.dm b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_spells.dm
new file mode 100644
index 00000000000..ef4331bb68b
--- /dev/null
+++ b/modular_redmoon/code/modules/antagonists/roguetown/villian/vurdalak/vurdalak_spells.dm
@@ -0,0 +1,224 @@
+/obj/effect/proc_holder/spell/self/claws_vurdalak
+ name = "Extend Claws"
+ desc = "!"
+ overlay_state = "claws"
+ antimagic_allowed = TRUE
+ charge_max = 20 // 2 seconds
+ var/extended = FALSE
+
+/obj/effect/proc_holder/spell/self/claws_vurdalak/cast(mob/user = usr)
+ ..()
+ var/obj/item/rogueweapon/vurdalak_claw/left/l
+ var/obj/item/rogueweapon/vurdalak_claw/right/r
+ l = user.get_active_held_item()
+ r = user.get_inactive_held_item()
+
+ if (extended)
+ if (istype(user.get_active_held_item(), /obj/item/rogueweapon/vurdalak_claw))
+ user.dropItemToGround(l, TRUE)
+ user.dropItemToGround(r, TRUE)
+ qdel(l)
+ qdel(r)
+ // user.visible_message("Your claws retract.", "You feel your claws retracting.", "You hear a sound of claws retracting.")
+ extended = FALSE
+ else
+ var/obj
+ for(var/i = 0, i<2, i++)
+ switch(i)
+ if(0)
+ obj = user.get_active_held_item()
+ if(1)
+ obj = user.get_inactive_held_item()
+ user.dropItemToGround(obj, TRUE)
+ var/datum/antagonist/vurdalak/vurdalak_antag_datum = user.mind.has_antag_datum(/datum/antagonist/vurdalak)
+
+ l = new(user, 1)
+ r = new(user, 2)
+ user.put_in_hands(l, TRUE, FALSE, TRUE)
+ user.put_in_hands(r, TRUE, FALSE, TRUE)
+ l.armor_penetration = vurdalak_antag_datum.claws_armor_penetration
+ r.armor_penetration = vurdalak_antag_datum.claws_armor_penetration
+ // user.visible_message("Your claws extend.", "You feel your claws extending.", "You hear a sound of claws extending.")
+ extended = TRUE
+
+/obj/effect/proc_holder/spell/self/vurdalak_targets_search
+ name = "Seek for Prey"
+ desc = "!"
+ overlay_state = "transfix"
+ antimagic_allowed = TRUE
+ charge_max = 10 SECONDS
+
+/obj/effect/proc_holder/spell/self/vurdalak_targets_search/cast(mob/user = usr)
+ ..()
+ if(GLOB.tod != "night")
+ to_chat(user, user.client.prefs.be_russian ? span_warning("Ночь ещё не пришла... Мне нужно ждать, чтобы почувствовать добычу.") : span_warning("The night has not come... I need wait to look for the prey."))
+ revert_cast()
+ return
+ var/area/user_area = get_area(user)
+ if(!user_area.outdoors)
+ to_chat(user, user.client.prefs.be_russian ? span_warning("Для этого, мне сначала нужно видеть луну.") : span_warning("I need to be under the sky to see the moon for it."))
+ revert_cast()
+ return
+ var/mob/target = null
+ var/last_best_distance = 1000
+ for(var/mob/living/carbon/human/potential_victim in GLOB.human_list - user)
+ if(!is_valid_hunting_area(get_area(potential_victim)))
+ continue
+ if(potential_victim.stat)
+ continue
+ if(potential_victim.m_intent == MOVE_INTENT_SNEAK)
+ continue
+ if(!potential_victim.mind)
+ continue
+ if("undead" in potential_victim.faction)
+ continue
+ if(HAS_TRAIT(potential_victim, HUGBOX_TRAIT))
+ continue
+ var/distance_to_potential_victim = get_dist_euclidian(user, potential_victim)
+ if(distance_to_potential_victim < last_best_distance)
+ last_best_distance = distance_to_potential_victim
+ target = potential_victim
+
+ if(!target)
+ to_chat(user, user.client.prefs.be_russian ? span_warning("Нет живых на болоте... Кто-то может прятаться в подземелье, зданиях или красться.") : span_warning("There are no living beings in the wilderness... Some may hide in the underground, in huts or sneak around."))
+ revert_cast()
+ return
+
+ var/arrowpart
+ switch(get_dir(user, target))
+ if(NORTH)
+ arrowpart = " ⇑"
+ if(SOUTH)
+ arrowpart = " ⇓"
+ if(EAST)
+ arrowpart = " ⇒"
+ if(WEST)
+ arrowpart = " ⇐"
+ if(NORTHWEST)
+ arrowpart = " ⇖"
+ if(NORTHEAST)
+ arrowpart = " ⇗"
+ if(SOUTHWEST)
+ arrowpart = " ⇙"
+ if(SOUTHEAST)
+ arrowpart = " ⇘"
+
+ to_chat(user, user.client.prefs.be_russian ? span_cult("Чувствую... Бьется сердце в [FLOOR(last_best_distance*1.5, 1)] шагах от меня. ([arrowpart])") : span_cult("I feel it... A heart is beating [FLOOR(last_best_distance*1.5, 1)] steps away. ([arrowpart])"))
+ playsound(user.loc, 'sound/vo/mobs/wwolf/sniff.ogg', 60, 1)
+
+// Spells
+/obj/effect/proc_holder/spell/targeted/vurdalak_rejuv
+ name = "Undead Regeneration"
+ desc = "Regenerates my targeted limb and replenishes half my stamina. Recharges every 60 seconds. I must stand still."
+ overlay_state = "unrot"
+ action_icon = 'icons/mob/actions/roguespells.dmi'
+ releasedrain = 0
+ chargedrain = 0
+ chargetime = 0
+ range = -1
+ warnie = "sydwarning"
+ movement_interrupt = TRUE
+ chargedloop = null
+ invocation_type = "whisper"
+ associated_skill = /datum/skill/magic/druidic
+ antimagic_allowed = FALSE
+ charge_max = 3.5 MINUTES
+ cooldown_min = 3.5 MINUTES
+ include_user = TRUE
+ max_targets = 1
+
+/obj/effect/proc_holder/spell/targeted/vurdalak_rejuv/cast(list/targets, mob/user = usr)
+// if(GLOB.tod != "night")
+// to_chat(user, user.client.prefs.be_russian ? span_warning("Ночь ещё не пришла... Мне нужно ждать, чтобы регенерировать.") : span_warning("The night has not come... I need wait to regenerate myself."))
+// revert_cast()
+// return FALSE
+
+ if(user && ishuman(user))
+ var/mob/living/carbon/human/vurdalak = user
+ var/datum/antagonist/vurdalak/vurdalak_antag_datum = user.mind.has_antag_datum(/datum/antagonist/vurdalak)
+
+ var/silver_curse_status = FALSE // Fail to cast condition.
+ for(var/datum/status_effect/debuff/silver_curse/silver_curse in vurdalak.status_effects)
+ silver_curse_status = TRUE
+ break
+ if(silver_curse_status)
+ to_chat(vurdalak, user.client.prefs.be_russian ? span_danger("Моё ПРОКЛЯТИЕ не даёт мне восстановиться!") : span_danger("My BANE is not letting me rejuvenate!"))
+ revert_cast()
+ return FALSE
+
+ if(vurdalak_antag_datum)
+ to_chat(user, user.client.prefs.be_russian ? span_cult("Я чувствую, как моё тело быстро восстанавливается... Ровно как и моя шкура. Чем больше я загублю, тем сильнее стану.") : span_cult("I feel how my body regenerates quickly... As well as my hide. More I will feed myself, more I will restore."))
+ vurdalak.reagents.add_reagent(/datum/reagent/medicine/greaterhealthpot, length(vurdalak_antag_datum.unique_victims))
+ vurdalak.heal_wounds(vurdalak_antag_datum.unique_victims.len * 20)
+ vurdalak.blood_volume += BLOOD_VOLUME_SURVIVE
+ vurdalak.update_damage_overlays()
+ vurdalak.playsound_local(get_turf(vurdalak), 'sound/misc/vampirespell.ogg', 100, FALSE, pressure_affected = FALSE)
+
+ if(vurdalak.skin_armor)
+ qdel(vurdalak.skin_armor)
+ vurdalak.skin_armor = new /obj/item/clothing/suit/roguetown/armor/skin_armor/vurdalak_skin(vurdalak)
+ vurdalak.skin_armor.max_integrity = vurdalak_antag_datum.hide_strength
+ vurdalak.skin_armor.obj_integrity = vurdalak_antag_datum.hide_strength
+
+// Spells
+/obj/effect/proc_holder/spell/targeted/vurdalak_feast
+ name = "Feast"
+ desc = ""
+ overlay_state = "tamebeast"
+ action_icon = 'icons/mob/actions/roguespells.dmi'
+ releasedrain = 0
+ chargedrain = 0
+ chargetime = 30
+ range = 1
+ warnie = "sydwarning"
+ movement_interrupt = TRUE
+ chargedloop = null
+ invocation_type = "whisper"
+ associated_skill = /datum/skill/magic/druidic
+ antimagic_allowed = TRUE
+ charge_max = 15 SECONDS
+ cooldown_min = 15 SECONDS
+ include_user = FALSE
+ max_targets = 1
+
+/obj/effect/proc_holder/spell/targeted/vurdalak_feast/cast(list/targets, mob/user = usr)
+ if(iscarbon(targets[1]))
+ var/mob/living/carbon/target = targets[1]
+ if(ishuman(user))
+ var/mob/living/carbon/human/vurdalak = user
+ var/datum/antagonist/vurdalak/vurdalak_antag_datum = user.mind.has_antag_datum(/datum/antagonist/vurdalak)
+ if(target.vitae_bank <= 500)
+ to_chat(vurdalak, user.client.prefs.be_russian ? span_warning("Это тело уже лишилось своей жизненной силы...") : span_warning("This body has already lost its lifeforce..."))
+ revert_cast()
+ return
+ if(!target.mind)
+ to_chat(vurdalak, user.client.prefs.be_russian ? span_warning("Я не чувствую достаточно жизненной силы в этом теле... Это бесполезно.") : span_warning("I don't feel enought lifeforce in this body... It will be useless."))
+ revert_cast()
+ return
+
+ while(target.vitae_bank > 500)
+ var/obj/item = vurdalak.get_active_held_item()
+ if(!item || !(item.type in typesof(/obj/item/rogueweapon/vurdalak_claw)))
+ to_chat(vurdalak, user.client.prefs.be_russian ? span_warning("Мне нужно выпустить когти, чтобы приступить к трапезе.") : span_warning("I need to extend my claws to feast on them."))
+ revert_cast()
+ break
+ if(!do_after(user, 1.4 SECONDS, target = target))
+ break
+ if(prob(10))
+ user.emote("rage")
+ if(!target.stat)
+ target.emote("painscream")
+ vurdalak.ClickOn(target, list())
+ if(prob(10))
+ var/obj/O = new /obj/effect/decal/cleanable/blood/gibs (get_turf(target))
+ var/turf/target_turf = get_step(target, pick(alldirs))
+ O.forceMove(target_turf)
+ target.vitae_bank -= 500
+ if(target.vitae_bank <= 500)
+ vurdalak.visible_message(span_dead("[vurdalak] finishes with [target]..."), vurdalak.client.prefs.be_russian ? span_dead("Я закончил поглощать плоть... Жизненной силы достаточно.") : span_dead("I have consumed their flesh... The lifeforce is enough."))
+ if(!(target.real_name in vurdalak_antag_datum.unique_victims))
+ vurdalak_antag_datum.unique_victims += target.real_name
+ vurdalak_antag_datum.handle_power_up()
+ else
+ return FALSE
+ return TRUE
diff --git a/modular_redmoon/icons/mobs/ghoul.dmi b/modular_redmoon/icons/mobs/ghoul.dmi
new file mode 100644
index 00000000000..faab80181b4
Binary files /dev/null and b/modular_redmoon/icons/mobs/ghoul.dmi differ
diff --git a/modular_redmoon/icons/mobs/vurdalak.dmi b/modular_redmoon/icons/mobs/vurdalak.dmi
new file mode 100644
index 00000000000..58106b8e179
Binary files /dev/null and b/modular_redmoon/icons/mobs/vurdalak.dmi differ
diff --git a/modular_redmoon/sounds/misc/vurdalak_far.ogg b/modular_redmoon/sounds/misc/vurdalak_far.ogg
new file mode 100644
index 00000000000..8c5b6398e67
Binary files /dev/null and b/modular_redmoon/sounds/misc/vurdalak_far.ogg differ
diff --git a/modular_redmoon/sounds/music/combat_vurdalak.ogg b/modular_redmoon/sounds/music/combat_vurdalak.ogg
new file mode 100644
index 00000000000..c2454adf490
Binary files /dev/null and b/modular_redmoon/sounds/music/combat_vurdalak.ogg differ
diff --git a/modular_redmoon/sounds/music/intro_vurdalak.ogg b/modular_redmoon/sounds/music/intro_vurdalak.ogg
new file mode 100644
index 00000000000..43cbb4c6e5e
Binary files /dev/null and b/modular_redmoon/sounds/music/intro_vurdalak.ogg differ
diff --git a/roguetown.dme b/roguetown.dme
index b5f3284f481..342e2892c6e 100644
--- a/roguetown.dme
+++ b/roguetown.dme
@@ -18,6 +18,13 @@
#include "code\rt.dm"
#include "code\unit_tests.dm"
#include "code\world.dm"
+#include "code\___REDFINES\colors.dm"
+#include "code\___REDFINES\DNA.dm"
+#include "code\___REDFINES\mobs.dm"
+#include "code\___REDFINES\prefereces.dm"
+#include "code\___REDFINES\stats.dm"
+#include "code\___REDFINES\stress.dm"
+#include "code\___REDFINES\traits.dm"
#include "code\__DEFINES\_globals.dm"
#include "code\__DEFINES\_protect.dm"
#include "code\__DEFINES\_tick.dm"
@@ -199,13 +206,6 @@
#include "code\__HELPERS\sorts\InsertSort.dm"
#include "code\__HELPERS\sorts\MergeSort.dm"
#include "code\__HELPERS\sorts\TimSort.dm"
-#include "code\__REDFINES\colors.dm"
-#include "code\__REDFINES\DNA.dm"
-#include "code\__REDFINES\mobs.dm"
-#include "code\__REDFINES\prefereces.dm"
-#include "code\__REDFINES\stats.dm"
-#include "code\__REDFINES\stress.dm"
-#include "code\__REDFINES\traits.dm"
#include "code\_globalvars\bitfields.dm"
#include "code\_globalvars\configuration.dm"
#include "code\_globalvars\game_modes.dm"
@@ -2183,6 +2183,11 @@
#include "modular_redmoon\code\modules\antagonists\purishep.dm"
#include "modular_redmoon\code\modules\antagonists\_common\antag_datum.dm"
#include "modular_redmoon\code\modules\antagonists\roguetown\villian\vampirelord.dm"
+#include "modular_redmoon\code\modules\antagonists\roguetown\villian\vurdalak\vurdalak.dm"
+#include "modular_redmoon\code\modules\antagonists\roguetown\villian\vurdalak\vurdalak_datum.dm"
+#include "modular_redmoon\code\modules\antagonists\roguetown\villian\vurdalak\vurdalak_globals.dm"
+#include "modular_redmoon\code\modules\antagonists\roguetown\villian\vurdalak\vurdalak_species.dm"
+#include "modular_redmoon\code\modules\antagonists\roguetown\villian\vurdalak\vurdalak_spells.dm"
#include "modular_redmoon\code\modules\armor\rogueclothes\armor.dm"
#include "modular_redmoon\code\modules\cargo\packsrogue\_packs.dm"
#include "modular_redmoon\code\modules\cargo\packsrogue\bandit\brigand.dm"