diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index dd5a25d8ff..2a35230794 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -127,6 +127,7 @@
#define TOXINLOVER 24
#define DIGITIGRADE 25 //Uses weird leg sprites. Optional for Lizards, required for ashwalkers. Don't give it to other races unless you make sprites for this (see human_parts_greyscale.dmi)
#define NO_UNDERWEAR 26
+<<<<<<< HEAD
#define MUTCOLORS2 27
#define MUTCOLORS3 28
#define NOLIVER 29
@@ -135,3 +136,31 @@
#define NOAROUSAL 29 //Stops all arousal effects
#define NOGENITALS 30 //Cannot create, use, or otherwise have genitals
#define NO_DNA_COPY 31
+=======
+#define NOLIVER 27
+#define NOSTOMACH 28
+#define NO_DNA_COPY 29
+#define DRINKSBLOOD 30
+
+#define ORGAN_SLOT_BRAIN "brain"
+#define ORGAN_SLOT_APPENDIX "appendix"
+#define ORGAN_SLOT_RIGHT_ARM_AUG "r_arm_device"
+#define ORGAN_SLOT_LEFT_ARM_AUG "l_arm_device"
+#define ORGAN_SLOT_STOMACH "stomach"
+#define ORGAN_SLOT_BREATHING_TUBE "breathing_tube"
+#define ORGAN_SLOT_EARS "ears"
+#define ORGAN_SLOT_EYES "eye_sight"
+#define ORGAN_SLOT_LUNGS "lungs"
+#define ORGAN_SLOT_HEART "heart"
+#define ORGAN_SLOT_ZOMBIE "zombie_infection"
+#define ORGAN_SLOT_THRUSTERS "thrusters"
+#define ORGAN_SLOT_HUD "eye_hud"
+#define ORGAN_SLOT_LIVER "liver"
+#define ORGAN_SLOT_TONGUE "tongue"
+#define ORGAN_SLOT_VOICE "vocal_cords"
+#define ORGAN_SLOT_ADAMANTINE_RESONATOR "adamantine_resonator"
+#define ORGAN_SLOT_HEART_AID "heartdrive"
+#define ORGAN_SLOT_BRAIN_ANTIDROP "brain_antidrop"
+#define ORGAN_SLOT_BRAIN_ANTISTUN "brain_antistun"
+#define ORGAN_SLOT_TAIL "tail"
+>>>>>>> ad30af5... Vampire species for halloween (#32096)
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
index 30d5652ab4..45f26d55c3 100644
--- a/code/modules/mob/living/blood.dm
+++ b/code/modules/mob/living/blood.dm
@@ -216,25 +216,23 @@
. = list()
if(!bloodtype)
return
- switch(bloodtype)
- if("A-")
- return list("A-", "O-")
- if("A+")
- return list("A-", "A+", "O-", "O+")
- if("B-")
- return list("B-", "O-")
- if("B+")
- return list("B-", "B+", "O-", "O+")
- if("AB-")
- return list("A-", "B-", "O-", "AB-")
- if("AB+")
- return list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+")
- if("O-")
- return list("O-")
- if("O+")
- return list("O-", "O+")
- if("L")
- return list("L")
+
+ var/static/list/bloodtypes_safe = list(
+ "A-" = list("A-", "O-"),
+ "A+" = list("A-", "A+", "O-", "O+"),
+ "B-" = list("B-", "O-"),
+ "B+" = list("B-", "B+", "O-", "O+"),
+ "AB-" = list("A-", "B-", "O-", "AB-"),
+ "AB+" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+"),
+ "O-" = list("O-"),
+ "O+" = list("O-", "O+"),
+ "L" = list("L"),
+ "U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U")
+ )
+
+ var/safe = bloodtypes_safe[bloodtype]
+ if(safe)
+ . = safe
//to add a splatter of blood or other mob liquid.
/mob/living/proc/add_splatter_floor(turf/T, small_drip)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 7a212d371b..8704abee83 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -65,6 +65,7 @@
var/breathid = "o2"
var/obj/item/organ/brain/mutant_brain = /obj/item/organ/brain
+ var/obj/item/organ/heart/mutant_heart = /obj/item/organ/heart
var/obj/item/organ/eyes/mutanteyes = /obj/item/organ/eyes
var/obj/item/organ/ears/mutantears = /obj/item/organ/ears
var/obj/item/mutanthands
@@ -154,7 +155,7 @@
heart.Remove(C,1)
QDEL_NULL(heart)
if(should_have_heart && !heart)
- heart = new()
+ heart = new mutant_heart()
heart.Insert(C)
if(lungs && (replace_current || !should_have_lungs))
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
new file mode 100644
index 0000000000..de0b5efdff
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -0,0 +1,130 @@
+/datum/species/vampire
+ name = "vampire"
+ id = "vampire"
+ default_color = "FFFFFF"
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NOHUNGER,NOBREATH,DRINKSBLOOD)
+ mutant_bodyparts = list("tail_human", "ears", "wings")
+ default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None")
+ exotic_bloodtype = "U"
+ use_skintones = TRUE
+ mutant_heart = /obj/item/organ/heart/vampire
+ mutanttongue = /obj/item/organ/tongue/vampire
+ blacklisted = TRUE
+ limbs_id = "human"
+ skinned_type = /obj/item/stack/sheet/animalhide/human
+ var/info_text = "You are a Vampire. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
+
+/datum/species/vampire/check_roundstart_eligible()
+ if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
+ return TRUE
+ return FALSE
+
+/datum/species/vampire/on_species_gain(mob/living/carbon/human/C, datum/species/old_species)
+ . = ..()
+ to_chat(C, "[info_text]")
+ C.skin_tone = "albino"
+ C.update_body(0)
+ if(C.mind)
+ var/obj/effect/proc_holder/spell/targeted/shapeshift/bat/B = new
+ C.mind.AddSpell(B)
+
+/datum/species/vampire/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ if(C.mind)
+ for(var/S in C.mind.spell_list)
+ var/obj/effect/proc_holder/spell/S2 = S
+ if(S2.type == /obj/effect/proc_holder/spell/targeted/shapeshift/bat)
+ C.mind.spell_list.Remove(S2)
+ qdel(S2)
+
+/datum/species/vampire/spec_life(mob/living/carbon/human/C)
+ . = ..()
+ if(istype(C.loc, /obj/structure/closet/coffin))
+ C.heal_overall_damage(4,4)
+ C.adjustToxLoss(-4)
+ C.adjustOxyLoss(-4)
+ C.adjustCloneLoss(-4)
+ return
+ C.blood_volume -= 1.5
+ if(C.blood_volume <= BLOOD_VOLUME_SURVIVE)
+ to_chat(C, "You ran out of blood!")
+ C.dust()
+ var/area/A = get_area(C)
+ if(istype(A, /area/chapel))
+ to_chat(C, "You don't belong here!")
+ C.adjustFireLoss(20)
+ C.adjust_fire_stacks(6)
+ C.IgniteMob()
+
+/obj/item/organ/tongue/vampire
+ name = "vampire tongue"
+ actions_types = list(/datum/action/item_action/organ_action/vampire)
+ color = "#1C1C1C"
+ var/drain_cooldown = 0
+
+#define VAMP_DRAIN_AMOUNT 50
+
+/datum/action/item_action/organ_action/vampire
+ name = "Drain Victim"
+ desc = "Leech blood from any carbon victim you are passively grabbing."
+
+/datum/action/item_action/organ_action/vampire/Trigger()
+ . = ..()
+ if(iscarbon(owner))
+ var/mob/living/carbon/H = owner
+ var/obj/item/organ/tongue/vampire/V = target
+ if(V.drain_cooldown >= world.time)
+ to_chat(H, "You just drained blood, wait a few seconds.")
+ return
+ if(H.pulling && iscarbon(H.pulling))
+ var/mob/living/carbon/victim = H.pulling
+ if(H.blood_volume >= BLOOD_VOLUME_MAXIMUM)
+ to_chat(H, "You're already full!")
+ return
+ if(victim.stat == DEAD)
+ to_chat(H, "You need a living victim!")
+ return
+ if(!victim.blood_volume || (victim.dna && ((NOBLOOD in victim.dna.species.species_traits) || victim.dna.species.exotic_blood)))
+ to_chat(H, "[victim] doesn't have blood!")
+ return
+ V.drain_cooldown = world.time + 30
+ if(!do_after(H, 30, target = victim))
+ return
+ var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood
+ var/drained_blood = min(victim.blood_volume, VAMP_DRAIN_AMOUNT, blood_volume_difference)
+ to_chat(victim, "[H] is draining your blood!")
+ to_chat(H, "You drain some blood!")
+ playsound(H, 'sound/items/drink.ogg', 30, 1, -2)
+ victim.blood_volume = Clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
+ H.blood_volume = Clamp(H.blood_volume + drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
+ if(!victim.blood_volume)
+ to_chat(H, "You finish off [victim]'s blood supply!")
+
+#undef VAMP_DRAIN_AMOUNT
+
+/obj/item/organ/heart/vampire
+ name = "vampire heart"
+ actions_types = list(/datum/action/item_action/organ_action/vampire_heart)
+ color = "#1C1C1C"
+
+/datum/action/item_action/organ_action/vampire_heart
+ name = "Check Blood Level"
+ desc = "Check how much blood you have remaining."
+
+/datum/action/item_action/organ_action/vampire_heart/Trigger()
+ . = ..()
+ if(iscarbon(owner))
+ var/mob/living/carbon/H = owner
+ to_chat(H, "Current blood level: [H.blood_volume]/[BLOOD_VOLUME_MAXIMUM].")
+
+/obj/effect/proc_holder/spell/targeted/shapeshift/bat
+ name = "Bat Form"
+ desc = "Take on the shape a space bat."
+ invocation = "Squeak!"
+ charge_max = 50
+ cooldown_min = 50
+
+ shapeshift_type = /mob/living/simple_animal/hostile/retaliate/bat
+ current_shapes = list(/mob/living/simple_animal/hostile/retaliate/bat)
+ current_casters = list()
+ possible_shapes = list(/mob/living/simple_animal/hostile/retaliate/bat)
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 0a437f120e..634e98fb2d 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -24,9 +24,9 @@
else //ingest, patch or inject
M.ForceContractDisease(D)
- if(method == INJECT && iscarbon(M))
+ if(iscarbon(M))
var/mob/living/carbon/C = M
- if(C.get_blood_id() == "blood")
+ if(C.get_blood_id() == "blood" && (method == INJECT || (method == INGEST && C.dna && C.dna.species && (DRINKSBLOOD in C.dna.species.species_traits))))
if(!data || !(data["blood_type"] in get_safe_blood(C.dna.blood_type)))
C.reagents.add_reagent("toxin", reac_volume * 0.5)
else
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index 2f2ef108ea..d4b8e165ee 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -65,6 +65,9 @@
/obj/item/reagent_containers/blood/lizard
blood_type = "L"
+/obj/item/reagent_containers/blood/universal
+ blood_type = "U"
+
/obj/item/reagent_containers/blood/empty
name = "blood pack"
icon_state = "empty"
diff --git a/tgstation.dme b/tgstation.dme
index 912f3cc89e..a07447e250 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1731,6 +1731,7 @@
#include "code\modules\mob\living\carbon\human\species_types\shadowpeople.dm"
#include "code\modules\mob\living\carbon\human\species_types\skeletons.dm"
#include "code\modules\mob\living\carbon\human\species_types\synths.dm"
+#include "code\modules\mob\living\carbon\human\species_types\vampire.dm"
#include "code\modules\mob\living\carbon\human\species_types\zombies.dm"
#include "code\modules\mob\living\carbon\monkey\combat.dm"
#include "code\modules\mob\living\carbon\monkey\death.dm"