diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index e736ad1130e4..7e36059f03e2 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -109,7 +109,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
return
destination.dna.unique_enzymes = unique_enzymes
destination.dna.unique_identity = unique_identity
- destination.dna.human_blood_type = human_blood_type
+ destination.dna.set_human_blood_type(human_blood_type)
destination.dna.unique_features = unique_features
destination.dna.features = features.Copy()
destination.dna.real_name = real_name
@@ -126,7 +126,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
new_dna.default_mutation_genes = default_mutation_genes
new_dna.unique_identity = unique_identity
new_dna.unique_features = unique_features
- new_dna.human_blood_type = human_blood_type
+ new_dna.set_human_blood_type(human_blood_type)
new_dna.features = features.Copy()
//if the new DNA has a holder, transform them immediately, otherwise save it
if(new_dna.holder)
@@ -481,7 +481,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
*/
/datum/dna/proc/initialize_dna(newblood_type = random_human_blood_type(), create_mutation_blocks = TRUE, randomize_features = TRUE) // NON-MODULE CHANGE
if(newblood_type)
- human_blood_type = newblood_type
+ set_human_blood_type(newblood_type)
if(create_mutation_blocks) //I hate this
generate_dna_blocks(mutation_blacklist = list(/datum/mutation/human/headless))
if(randomize_features)
@@ -494,6 +494,18 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
update_dna_identity()
+/// Updates human blood type and updates the holder's blood type if the holder is human
+/datum/dna/proc/set_human_blood_type(new_type, update = TRUE)
+ var/datum/blood_type/found = find_blood_type(new_type)
+ if(!found)
+ CRASH("Tried to set blood type to an invalid blood type [new_type]")
+ var/found_key = found.type_key()
+ if(human_blood_type == found_key)
+ return
+ human_blood_type = found_key
+ if(istype(holder.blood_type, /datum/blood_type/crew/human))
+ holder.set_blood_type(new_type, update)
+
/datum/dna/stored //subtype used by brain mob's stored_dna
/datum/dna/stored/add_mutation(mutation_name) //no mutation changes on stored dna.
@@ -594,7 +606,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
dna.generate_unique_enzymes()
if(newblood_type)
- dna.human_blood_type = newblood_type
+ dna.set_human_blood_type(newblood_type)
if(unique_identity)
dna.unique_identity = unique_identity
@@ -621,6 +633,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
if(!dna.species)
var/rando_race = pick(get_selectable_species())
dna.species = new rando_race()
+ initial_blood_type = dna.human_blood_type
//proc used to update the mob's appearance after its dna UI has been changed
/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0)
diff --git a/code/datums/quirks/negative_quirks/blood_deficiency.dm b/code/datums/quirks/negative_quirks/blood_deficiency.dm
index b7c2e0bedd60..4ec31d7eab50 100644
--- a/code/datums/quirks/negative_quirks/blood_deficiency.dm
+++ b/code/datums/quirks/negative_quirks/blood_deficiency.dm
@@ -46,7 +46,7 @@
mail_goodies.Cut()
- var/datum/blood_type/new_type = quirk_holder.get_blood_type()
+ var/datum/blood_type/new_type = quirk_holder.blood_type
if(isnull(new_type))
return
diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm
index ac0e3e19e46e..46114f717948 100644
--- a/code/datums/records/manifest.dm
+++ b/code/datums/records/manifest.dm
@@ -118,7 +118,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new)
var/datum/record/locked/lockfile = new(
age = person.age,
- blood_type = "[person.get_blood_type() || "None"]", // NON-MODULE CHANGE / NEEDS TESTING
+ blood_type = "[person.blood_type || "None"]", // NON-MODULE CHANGE / NEEDS TESTING
character_appearance = character_appearance,
dna_string = record_dna.unique_enzymes,
fingerprint = md5(record_dna.unique_identity),
@@ -135,7 +135,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new)
new /datum/record/crew(
age = person.age,
- blood_type = "[person.get_blood_type() || "None"]", // NON-MODULE CHANGE / NEEDS TESTING
+ blood_type = "[person.blood_type || "None"]", // NON-MODULE CHANGE / NEEDS TESTING
character_appearance = character_appearance,
dna_string = record_dna.unique_enzymes,
fingerprint = md5(record_dna.unique_identity),
diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm
index 94be1bb55890..111b13ece34f 100644
--- a/code/game/atom/_atom.dm
+++ b/code/game/atom/_atom.dm
@@ -503,19 +503,20 @@
///returns the mob's dna info as a list, to be inserted in an object's blood_DNA list
/mob/living/proc/get_blood_dna_list()
- var/datum/blood_type/blood = get_blood_type()
- if(!isnull(blood))
- return list("UNKNOWN DNA" = blood.type_key())
- return null
+ if(!has_blood())
+ return null
+ return list("UNKNOWN DNA" = blood_type.type_key())
///Get the mobs dna list
/mob/living/carbon/get_blood_dna_list()
- if(isnull(dna)) // Xenos
+ if(isnull(dna)) // ???
return ..()
- var/datum/blood_type/blood = get_blood_type()
- if(isnull(blood)) // Skeletons?
+ if(!has_blood())
return null
- return list("[dna.unique_enzymes]" = blood.type_key())
+ return list("[dna.unique_enzymes]" = blood_type.type_key())
+
+/mob/living/carbon/alien/get_blood_dna_list()
+ return list("UNKNOWN ALIEN DNA" = blood_type.type_key())
// NON-MODULE CHANGE END
diff --git a/code/game/atom/atom_examine.dm b/code/game/atom/atom_examine.dm
index e12a0ff25641..15a149001646 100644
--- a/code/game/atom/atom_examine.dm
+++ b/code/game/atom/atom_examine.dm
@@ -279,7 +279,7 @@
if(iscarbon(old_wearer))
var/mob/living/carbon/carbon_wearer = old_wearer
id_species ||= carbon_wearer.dna.species.name
- id_blood_type ||= find_blood_type(carbon_wearer.dna?.species?.exotic_bloodtype || carbon_wearer.dna?.human_blood_type)?.name
+ id_blood_type ||= "[find_blood_type(carbon_wearer.dna?.species?.exotic_bloodtype || carbon_wearer.dna?.human_blood_type || random_human_blood_type())]"
var/id_examine = span_slightly_larger(separator_hr("This is [old_wearer]'s ID card."))
id_examine += "
"
diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm
index e057c957d3cc..c28e915c6cab 100644
--- a/code/game/machinery/computer/dna_console.dm
+++ b/code/game/machinery/computer/dna_console.dm
@@ -1770,7 +1770,7 @@
scanner_occupant.real_name = buffer_slot["name"]
scanner_occupant.name = buffer_slot["name"]
scanner_occupant.dna.unique_enzymes = buffer_slot["UE"]
- scanner_occupant.dna.human_blood_type = find_blood_type(buffer_slot["blood_type"]).type_key()
+ scanner_occupant.dna.set_human_blood_type(buffer_slot["blood_type"])
scanner_occupant.apply_status_effect(/datum/status_effect/genetic_damage, damage_increase)
scanner_occupant.domutcheck()
return TRUE
@@ -1788,7 +1788,7 @@
scanner_occupant.real_name = buffer_slot["name"]
scanner_occupant.name = buffer_slot["name"]
scanner_occupant.dna.unique_enzymes = buffer_slot["UE"]
- scanner_occupant.dna.human_blood_type = find_blood_type(buffer_slot["blood_type"]).type_key()
+ scanner_occupant.dna.set_human_blood_type(buffer_slot["blood_type"])
scanner_occupant.apply_status_effect(/datum/status_effect/genetic_damage, damage_increase)
scanner_occupant.domutcheck()
return TRUE
diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm
index 5b956472e3a0..daece6511d14 100644
--- a/code/game/machinery/computer/operating_computer.dm
+++ b/code/game/machinery/computer/operating_computer.dm
@@ -202,7 +202,7 @@
data["patient"]["health"] = patient.health
// check here to see if the patient has standard blood reagent, or special blood (like how ethereals bleed liquid electricity) to show the proper name in the computer
- data["patient"]["blood_type"] = "[patient.get_blood_type() || "None"]" // NON-MODULE CHANGE
+ data["patient"]["blood_type"] = "[patient.blood_type || "None"]" // NON-MODULE CHANGE
data["patient"]["maxHealth"] = patient.maxHealth
data["patient"]["minHealth"] = -1 * patient.maxHealth
data["patient"]["bruteLoss"] = patient.getBruteLoss()
diff --git a/code/game/machinery/computer/records/medical.dm b/code/game/machinery/computer/records/medical.dm
index 8bb09e4aef5c..c99cb2b337b6 100644
--- a/code/game/machinery/computer/records/medical.dm
+++ b/code/game/machinery/computer/records/medical.dm
@@ -140,7 +140,7 @@
return FALSE
target.age = 18
- target.blood_type = "[find_blood_type(random_human_blood_type())]" // NON-MODULE CHANGE
+ target.blood_type = "O-" // NON-MODULE CHANGE
target.dna_string = "Unknown"
target.gender = "Unknown"
target.major_disabilities = ""
diff --git a/code/game/machinery/medical_kiosk.dm b/code/game/machinery/medical_kiosk.dm
index f95e64454bc4..8b21b944b345 100644
--- a/code/game/machinery/medical_kiosk.dm
+++ b/code/game/machinery/medical_kiosk.dm
@@ -237,7 +237,7 @@
var/bleed_status = "Patient is not currently bleeding."
var/blood_status = " Patient either has no blood, or does not require it to function."
var/blood_percent = round((patient.blood_volume / BLOOD_VOLUME_NORMAL)*100)
- var/blood_type = "[patient.get_blood_type() || "None"]" // NON-MODULE CHANGE
+ var/blood_type = "[patient.blood_type || "None"]" // NON-MODULE CHANGE
var/blood_warning = " "
var/blood_alcohol = patient.get_blood_alcohol_content()
diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm
index 735509c7518f..a0e67558a189 100644
--- a/code/game/objects/effects/decals/cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/cleanable/aliens.dm
@@ -14,7 +14,7 @@
/obj/effect/decal/cleanable/xenoblood/Initialize(mapload)
. = ..()
- add_blood_DNA(list("UNKNOWN DNA" = /datum/blood_type/xenomorph)) // NON-MODULE CHANGE
+ add_blood_DNA(list("UNKNOWN ALIEN DNA" = /datum/blood_type/xenomorph)) // NON-MODULE CHANGE
/obj/effect/decal/cleanable/xenoblood/xsplatter
random_icon_states = list("xgibbl1", "xgibbl2", "xgibbl3", "xgibbl4", "xgibbl5")
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index cfc2be19b775..1bbd94510b3c 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -37,7 +37,7 @@
/obj/effect/decal/cleanable/blood/Initialize(mapload, list/datum/disease/diseases)
. = ..()
if(mapload)
- add_blood_DNA(list("UNKNOWN DNA" = random_human_blood_type()))
+ add_blood_DNA(list("UNKNOWN HUMAN DNA" = random_human_blood_type()))
if(dried)
dry()
else if(can_dry)
@@ -683,17 +683,17 @@
/// Subtype which has random DNA baked in OUTSIDE of mapload.
/// For testing, mapping, or badmins
/obj/effect/decal/cleanable/blood/pre_dna
- var/list/dna_types = list("UNKNOWN DNA A" = /datum/blood_type/crew/human/a_minus)
+ var/list/dna_types = list("UNKNOWN HUMAN DNA" = /datum/blood_type/crew/human/a_minus)
/obj/effect/decal/cleanable/blood/pre_dna/Initialize(mapload)
. = ..()
add_blood_DNA(dna_types)
/obj/effect/decal/cleanable/blood/pre_dna/lizard
- dna_types = list("UNKNOWN DNA A" = /datum/blood_type/crew/lizard)
+ dna_types = list("UNKNOWN TIZIRAN DNA" = /datum/blood_type/crew/lizard)
/obj/effect/decal/cleanable/blood/pre_dna/lizhuman
- dna_types = list("UNKNOWN DNA A" = /datum/blood_type/crew/human/a_minus, "UNKNOWN DNA B" = /datum/blood_type/crew/lizard)
+ dna_types = list("UNKNOWN HUMAN DNA" = /datum/blood_type/crew/human/a_minus, "UNKNOWN TIZIRAN DNA" = /datum/blood_type/crew/lizard)
/obj/effect/decal/cleanable/blood/pre_dna/ethereal
- dna_types = list("UNKNOWN DNA A" = /datum/blood_type/crew/ethereal)
+ dna_types = list("UNKNOWN ETHEREAL DNA" = /datum/blood_type/crew/ethereal)
diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm
index b4d58fc9dfc9..afad1e81c11f 100644
--- a/code/game/objects/effects/spawners/gibspawner.dm
+++ b/code/game/objects/effects/spawners/gibspawner.dm
@@ -39,7 +39,7 @@
dna_to_add = temp_mob.get_blood_dna_list()
qdel(temp_mob)
else
- dna_to_add = list("UNKNOWN DNA" = random_human_blood_type()) //else, generate a random bloodtype for it. // NON-MODULE CHANGE
+ dna_to_add = list("UNKNOWN HUMAN DNA" = random_human_blood_type()) //else, generate a random bloodtype for it. // NON-MODULE CHANGE
for(var/i in 1 to gibtypes.len)
diff --git a/code/game/objects/items/devices/scanners/autopsy_scanner.dm b/code/game/objects/items/devices/scanners/autopsy_scanner.dm
index dbeb0444d45c..2ed434342deb 100644
--- a/code/game/objects/items/devices/scanners/autopsy_scanner.dm
+++ b/code/game/objects/items/devices/scanners/autopsy_scanner.dm
@@ -92,7 +92,7 @@
else
autopsy_information += "Severe burns."
else if(!HAS_TRAIT(scanned, TRAIT_NOBLOOD))
- autopsy_information += "Blood Type: [scanned.get_blood_type() || "None"]
"
+ autopsy_information += "Blood Type: [scanned.blood_type || "None"]
"
autopsy_information += "Blood Volume: [scanned.blood_volume] cl ([round((scanned.blood_volume / BLOOD_VOLUME_NORMAL) * 100)]%)
"
for(var/datum/disease/diseases as anything in scanned.diseases)
diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm
index d3182df4b34c..83d672f8d6e8 100644
--- a/code/game/objects/items/devices/scanners/health_analyzer.dm
+++ b/code/game/objects/items/devices/scanners/health_analyzer.dm
@@ -370,8 +370,8 @@
render_list += "[body_temperature_message]
"
// Blood Level
- var/datum/blood_type/target_blood_type = target.get_blood_type()
- if(target_blood_type)
+ var/datum/blood_type/target_blood_type = target.blood_type
+ if(target_blood_type && target.has_blood())
var/bpm = target.get_bpm()
var/needs_heart = TRUE
if(ishuman(target))
diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm
index 1d4423284936..b615503cb7b5 100644
--- a/code/game/objects/items/dna_injector.dm
+++ b/code/game/objects/items/dna_injector.dm
@@ -59,7 +59,7 @@
target.real_name = fields["name"]
target.dna.unique_enzymes = fields["UE"]
target.name = target.real_name
- target.dna.human_blood_type = find_blood_type(fields["blood_type"]).type_key()
+ target.dna.set_human_blood_type(fields["blood_type"], update = (!fields["UI"] && !fields["UF"])) // only cause an update if we're not gonna do one later
if(fields["UI"]) //UI+UE
target.dna.unique_identity = merge_text(target.dna.unique_identity, fields["UI"])
if(fields["UF"])
@@ -136,7 +136,7 @@
target.real_name = fields["name"]
target.dna.unique_enzymes = fields["UE"]
target.name = target.real_name
- target.dna.human_blood_type = find_blood_type(fields["blood_type"]).type_key()
+ target.dna.set_human_blood_type(fields["blood_type"], update = (!fields["UI"] && !fields["UF"])) // only cause an update if we're not gonna do one later
target.dna.temporary_mutations[UE_CHANGED] = endtime
if(fields["UI"]) //UI+UE
if(!target.dna.previous["UI"])
diff --git a/code/modules/admin/verbs/list_exposer.dm b/code/modules/admin/verbs/list_exposer.dm
index 13461fcff272..ef89b5ba3de0 100644
--- a/code/modules/admin/verbs/list_exposer.dm
+++ b/code/modules/admin/verbs/list_exposer.dm
@@ -33,7 +33,7 @@
for(var/entry in GLOB.human_list)
var/mob/living/carbon/human/subject = entry
if(subject.ckey)
- data += "
| [subject] | [subject.dna.unique_enzymes] | [subject.get_blood_type()] |
" // NON-MODULE CHANGE
+ data += "| [subject] | [subject.dna.unique_enzymes] | [subject.blood_type] |
" // NON-MODULE CHANGE
data += ""
usr << browse(data, "window=DNA;size=440x410")
diff --git a/code/modules/antagonists/abductor/equipment/glands/blood.dm b/code/modules/antagonists/abductor/equipment/glands/blood.dm
index 1ab7df8d4b3c..7f6ae6ae01e1 100644
--- a/code/modules/antagonists/abductor/equipment/glands/blood.dm
+++ b/code/modules/antagonists/abductor/equipment/glands/blood.dm
@@ -16,13 +16,13 @@
/obj/item/organ/heart/gland/blood/activate()
to_chat(owner, span_warning("You feel your blood heat up for a moment."))
new_bloodtype = get_random_reagent_id()
- owner.dna.species.exotic_bloodtype = new_bloodtype
+ owner.set_blood_type(new_bloodtype)
/obj/item/organ/heart/gland/blood/on_mob_remove(mob/living/carbon/organ_owner, special)
. = ..()
- organ_owner.dna?.species?.exotic_bloodtype = initial(organ_owner.dna.species.exotic_bloodtype)
+ organ_owner.reset_blood_type()
/obj/item/organ/heart/gland/blood/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
. = ..()
if(new_bloodtype)
- organ_owner.dna?.species?.exotic_bloodtype = new_bloodtype
+ organ_owner.set_blood_type(new_bloodtype)
diff --git a/code/modules/bitrunning/antagonists/netguardian.dm b/code/modules/bitrunning/antagonists/netguardian.dm
index 2830ee138d6f..048753f80bcd 100644
--- a/code/modules/bitrunning/antagonists/netguardian.dm
+++ b/code/modules/bitrunning/antagonists/netguardian.dm
@@ -48,6 +48,7 @@
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
bodytemp_cold_damage_limit = TCMB
ai_controller = /datum/ai_controller/basic_controller/netguardian
+ initial_blood_type = /datum/blood_type/oil
/mob/living/basic/netguardian/Initialize(mapload)
. = ..()
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index fad1334e7c6b..260e7f37f0d0 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -142,7 +142,7 @@
// BUT letting players scan blood and read "There is no blood detected on the blood" is very ???
// So we'll just throw in a random blood type for filler
if(!length(blood) && istype(scanned_atom, /obj/effect/decal/cleanable/blood))
- scanned_atom.add_blood_DNA(list("UNKNOWN DNA" = random_human_blood_type()))
+ scanned_atom.add_blood_DNA(list("UNKNOWN HUMAN DNA" = random_human_blood_type()))
blood = GET_ATOM_BLOOD_DNA(scanned_atom)
det_data[DETSCAN_CATEGORY_FINGERS] = GET_ATOM_FINGERPRINTS(scanned_atom)
diff --git a/code/modules/forensics/forensics_helpers.dm b/code/modules/forensics/forensics_helpers.dm
index 9f23c04849fd..38cb4f0e76ae 100644
--- a/code/modules/forensics/forensics_helpers.dm
+++ b/code/modules/forensics/forensics_helpers.dm
@@ -108,7 +108,7 @@
/obj/add_blood_DNA(list/blood_DNA_to_add)
if (QDELING(src))
return FALSE
- if (isnull(blood_DNA_to_add))
+ if (!length(blood_DNA_to_add))
return FALSE
if (forensics)
forensics.inherit_new(blood_DNA = blood_DNA_to_add)
diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm
index 381d829961fa..1b7ec1799e68 100644
--- a/code/modules/hydroponics/grown/replicapod.dm
+++ b/code/modules/hydroponics/grown/replicapod.dm
@@ -213,7 +213,7 @@
//if there's none: get water
most_plentiful_reagent ||= /datum/reagent/water
- podman.dna.species.exotic_bloodtype = most_plentiful_reagent
+ podman.set_blood_type(most_plentiful_reagent)
investigate_log("[key_name(mind)] cloned as a podman via [src] in [parent]", INVESTIGATE_BOTANY)
parent.update_tray(user, 1)
return result
diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm
index d9862fa391cf..5461169bceb1 100644
--- a/code/modules/mining/lavaland/megafauna_loot.dm
+++ b/code/modules/mining/lavaland/megafauna_loot.dm
@@ -604,6 +604,7 @@
mob_biotypes = MOB_SPIRIT
faction = list()
weather_immunities = list(TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE)
+ initial_blood_type = null
/// Blood level, used for movement and abilities in a soulscythe
var/blood_level = MAX_BLOOD_LEVEL
diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm
index 8ad488d1efd0..4d51f48f6198 100644
--- a/code/modules/mob/living/basic/basic.dm
+++ b/code/modules/mob/living/basic/basic.dm
@@ -8,6 +8,7 @@
living_flags = MOVES_ON_ITS_OWN
status_flags = CANPUSH
fire_stack_decay_rate = -5 // Reasonably fast as NPCs will not usually actively extinguish themselves
+ initial_blood_type = /datum/blood_type/animal
var/basic_mob_flags = NONE
diff --git a/code/modules/mob/living/basic/blob_minions/blob_mob.dm b/code/modules/mob/living/basic/blob_minions/blob_mob.dm
index 6869608f7d06..d78430d44892 100644
--- a/code/modules/mob/living/basic/blob_minions/blob_mob.dm
+++ b/code/modules/mob/living/basic/blob_minions/blob_mob.dm
@@ -17,6 +17,7 @@
lighting_cutoff_green = 40
lighting_cutoff_blue = 30
initial_language_holder = /datum/language_holder/empty
+ initial_blood_type = /datum/blood_type/animal/blob
/mob/living/basic/blob_minion/Initialize(mapload)
. = ..()
diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm
index f6e4967cf4e8..b796a9ab52e4 100644
--- a/code/modules/mob/living/basic/bots/_bots.dm
+++ b/code/modules/mob/living/basic/bots/_bots.dm
@@ -40,6 +40,7 @@ GLOBAL_LIST_INIT(command_strings, list(
light_range = 3
light_power = 0.6
speed = 3
+ initial_blood_type = /datum/blood_type/oil
///Access required to access this Bot's maintenance protocols
var/maints_access_required = list(ACCESS_ROBOTICS)
interaction_flags_click = ALLOW_SILICON_REACH
diff --git a/code/modules/mob/living/basic/clown/clown.dm b/code/modules/mob/living/basic/clown/clown.dm
index 23781d8e3e30..e99a6092e44e 100644
--- a/code/modules/mob/living/basic/clown/clown.dm
+++ b/code/modules/mob/living/basic/clown/clown.dm
@@ -43,6 +43,8 @@
var/waddles = TRUE
/mob/living/basic/clown/Initialize(mapload)
+ if(check_holidays(APRIL_FOOLS))
+ initial_blood_type = /datum/blood_type/clown
. = ..()
AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_SHOE)
AddComponent(/datum/component/ai_retaliate_advanced, CALLBACK(src, PROC_REF(retaliate_callback)))
diff --git a/code/modules/mob/living/basic/cult/constructs/_construct.dm b/code/modules/mob/living/basic/cult/constructs/_construct.dm
index eb4fb5224dc5..a0ed4c28340d 100644
--- a/code/modules/mob/living/basic/cult/constructs/_construct.dm
+++ b/code/modules/mob/living/basic/cult/constructs/_construct.dm
@@ -23,6 +23,7 @@
response_harm_continuous = "punches"
response_harm_simple = "punch"
melee_attack_cooldown = CLICK_CD_MELEE
+ initial_blood_type = null
// Vivid red, cause cult theme
lighting_cutoff_red = 30
diff --git a/code/modules/mob/living/basic/cult/shade.dm b/code/modules/mob/living/basic/cult/shade.dm
index bf6fbe13944a..ca9b735c1bd0 100644
--- a/code/modules/mob/living/basic/cult/shade.dm
+++ b/code/modules/mob/living/basic/cult/shade.dm
@@ -27,6 +27,7 @@
faction = list(FACTION_CULT)
basic_mob_flags = DEL_ON_DEATH
initial_language_holder = /datum/language_holder/construct
+ initial_blood_type = null
/// Theme controls color. THEME_CULT is red THEME_WIZARD is purple and THEME_HOLY is blue
var/theme = THEME_CULT
/// The different flavors of goop shades can drop, depending on theme.
diff --git a/code/modules/mob/living/basic/drone/_drone.dm b/code/modules/mob/living/basic/drone/_drone.dm
index c7e54f0bc7eb..835574bf568f 100644
--- a/code/modules/mob/living/basic/drone/_drone.dm
+++ b/code/modules/mob/living/basic/drone/_drone.dm
@@ -47,6 +47,7 @@
lighting_cutoff_red = 30
lighting_cutoff_green = 35
lighting_cutoff_blue = 25
+ initial_blood_type = /datum/blood_type/oil
can_be_held = TRUE
worn_slot_flags = ITEM_SLOT_HEAD
diff --git a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm
index 761fe26c3c97..f02aef0c2bd8 100644
--- a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm
+++ b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm
@@ -46,6 +46,7 @@
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
basic_mob_flags = DEL_ON_DEATH
ai_controller = /datum/ai_controller/basic_controller/bee
+ initial_blood_type = /datum/blood_type/animal/bug
///the reagent the bee has
var/datum/reagent/beegent = null
///the house we live in
diff --git a/code/modules/mob/living/basic/festivus_pole.dm b/code/modules/mob/living/basic/festivus_pole.dm
index 210dd5df789c..6edd22649f0f 100644
--- a/code/modules/mob/living/basic/festivus_pole.dm
+++ b/code/modules/mob/living/basic/festivus_pole.dm
@@ -41,6 +41,7 @@
death_message = "is hacked into pieces!"
ai_controller = /datum/ai_controller/basic_controller/festivus_pole
+ initial_blood_type = null
/mob/living/basic/festivus/Initialize(mapload)
. = ..()
diff --git a/code/modules/mob/living/basic/heretic/maid_in_the_mirror.dm b/code/modules/mob/living/basic/heretic/maid_in_the_mirror.dm
index 6f8c2e5c96f0..7436f8907fd1 100644
--- a/code/modules/mob/living/basic/heretic/maid_in_the_mirror.dm
+++ b/code/modules/mob/living/basic/heretic/maid_in_the_mirror.dm
@@ -16,6 +16,7 @@
melee_damage_upper = 16
sight = SEE_MOBS | SEE_OBJS | SEE_TURFS
death_message = "shatters and vanishes, releasing a gust of cold air."
+ initial_blood_type = null
/// Whether we take damage when someone looks at us
var/harmed_by_examine = TRUE
/// How often being examined by a specific mob can hurt us
diff --git a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon.dm b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon.dm
index af3540c3fb5f..93045bf476b8 100644
--- a/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon.dm
+++ b/code/modules/mob/living/basic/icemoon/ice_demon/ice_demon.dm
@@ -28,6 +28,7 @@
ai_controller = /datum/ai_controller/basic_controller/ice_demon
death_message = "fades as the energies that tied it to this world dissipate."
death_sound = 'sound/magic/demon_dies.ogg'
+ initial_blood_type = /datum/reagent/bluespace
/mob/living/basic/mining/ice_demon/Initialize(mapload)
. = ..()
@@ -52,9 +53,6 @@
new /obj/item/raw_anomaly_core/bluespace(loc)
return ..()
-/mob/living/basic/mining/ice_demon/get_blood_type()
- return null
-
/mob/living/basic/mining/demon_afterimage
name = "afterimage demonic watcher"
desc = "Is this some sort of illusion?"
@@ -75,6 +73,7 @@
attack_sound = 'sound/weapons/bladeslice.ogg'
alpha = 80
ai_controller = /datum/ai_controller/basic_controller/ice_demon/afterimage
+ initial_blood_type = null
///how long do we exist for
var/existence_period = 15 SECONDS
@@ -91,6 +90,3 @@
melee_damage_lower = 10
melee_damage_upper = 10
existence_period = 7 SECONDS
-
-/mob/living/basic/mining/demon_afterimage/get_blood_type()
- return null
diff --git a/code/modules/mob/living/basic/jungle/seedling/seedling.dm b/code/modules/mob/living/basic/jungle/seedling/seedling.dm
index 08e562a75eab..0f0b7f9ad59b 100644
--- a/code/modules/mob/living/basic/jungle/seedling/seedling.dm
+++ b/code/modules/mob/living/basic/jungle/seedling/seedling.dm
@@ -35,6 +35,7 @@
sharpness = SHARP_EDGED
wound_bonus = -10
ai_controller = /datum/ai_controller/basic_controller/seedling
+ initial_blood_type = /datum/blood_type/water
///the state of combat we are in
var/combatant_state = SEEDLING_STATE_NEUTRAL
///the colors our petals can have
diff --git a/code/modules/mob/living/basic/jungle/venus_human_trap.dm b/code/modules/mob/living/basic/jungle/venus_human_trap.dm
index 01de4fa898e9..854afafef7c2 100644
--- a/code/modules/mob/living/basic/jungle/venus_human_trap.dm
+++ b/code/modules/mob/living/basic/jungle/venus_human_trap.dm
@@ -162,6 +162,7 @@
speed = 1.2
melee_attack_cooldown = 1.2 SECONDS
ai_controller = /datum/ai_controller/basic_controller/human_trap
+ initial_blood_type = /datum/blood_type/water
///how much damage we take out of weeds
var/no_weed_damage = 12.5
///how much do we heal in weeds
diff --git a/code/modules/mob/living/basic/minebots/minebot.dm b/code/modules/mob/living/basic/minebots/minebot.dm
index 911458d782a2..33c3fbc3cd09 100644
--- a/code/modules/mob/living/basic/minebots/minebot.dm
+++ b/code/modules/mob/living/basic/minebots/minebot.dm
@@ -31,6 +31,7 @@
light_on = FALSE
combat_mode = FALSE
ai_controller = /datum/ai_controller/basic_controller/minebot
+ initial_blood_type = /datum/blood_type/oil
///the access card we use to access mining
var/obj/item/card/id/access_card
///the gun we use to kill
diff --git a/code/modules/mob/living/basic/pets/orbie/orbie.dm b/code/modules/mob/living/basic/pets/orbie/orbie.dm
index bf834365c6bd..61fdcdd36732 100644
--- a/code/modules/mob/living/basic/pets/orbie/orbie.dm
+++ b/code/modules/mob/living/basic/pets/orbie/orbie.dm
@@ -25,6 +25,7 @@
bodytemp_heat_damage_limit = INFINITY // Non-module change
death_message = "fades out of existence!"
ai_controller = /datum/ai_controller/basic_controller/orbie
+ initial_blood_type = null
///are we happy or not?
var/happy_state = FALSE
///overlay for our neutral eyes
diff --git a/code/modules/mob/living/basic/ruin_defender/skeleton.dm b/code/modules/mob/living/basic/ruin_defender/skeleton.dm
index b10646f916e7..def8238f1e2c 100644
--- a/code/modules/mob/living/basic/ruin_defender/skeleton.dm
+++ b/code/modules/mob/living/basic/ruin_defender/skeleton.dm
@@ -19,6 +19,7 @@
attack_vis_effect = ATTACK_EFFECT_CLAW
sharpness = SHARP_EDGED
wound_bonus = -5
+ initial_blood_type = null
faction = list(FACTION_SKELETON)
// Going for a sort of pale bluegreen here, shooting for boneish
lighting_cutoff_red = 15
diff --git a/code/modules/mob/living/basic/ruin_defender/stickman.dm b/code/modules/mob/living/basic/ruin_defender/stickman.dm
index 588a75c63464..4531f0ee1cf0 100644
--- a/code/modules/mob/living/basic/ruin_defender/stickman.dm
+++ b/code/modules/mob/living/basic/ruin_defender/stickman.dm
@@ -20,6 +20,7 @@
unsuitable_atmos_damage = 7.5
unsuitable_cold_damage = 7.5
unsuitable_heat_damage = 7.5
+ initial_blood_type = null
ai_controller = /datum/ai_controller/basic_controller/stickman
diff --git a/code/modules/mob/living/basic/ruin_defender/wizard/wizard.dm b/code/modules/mob/living/basic/ruin_defender/wizard/wizard.dm
index a4eca5e03c52..5c2f9003ee9c 100644
--- a/code/modules/mob/living/basic/ruin_defender/wizard/wizard.dm
+++ b/code/modules/mob/living/basic/ruin_defender/wizard/wizard.dm
@@ -33,8 +33,6 @@
)
/// A specified wizard corpse spawner to use. If null, picks from the list above instead.
var/selected_outfit
- /// What's our "blood type"? So fake-humans splash blood on people in combat
- var/fake_blood_type
/// Typepath for the wizard's targeted spell. If null, selects randomly.
var/targeted_spell_path
@@ -55,6 +53,7 @@
)
/mob/living/basic/wizard/Initialize(mapload)
+ initial_blood_type = random_human_blood_type()
. = ..()
if(!selected_outfit)
selected_outfit = pick_weight(wizard_outfits)
@@ -85,11 +84,6 @@
blink_spell.Grant(src)
ai_controller.set_blackboard_key(BB_WIZARD_BLINK_SPELL, blink_spell)
-/mob/living/basic/wizard/get_blood_type()
- if(!fake_blood_type)
- fake_blood_type = random_human_blood_type()
- return find_blood_type(fake_blood_type)
-
/mob/living/basic/wizard/init_unconscious_appearance()
add_generic_humanoid_static_appearance()
diff --git a/code/modules/mob/living/basic/space_fauna/cat_surgeon.dm b/code/modules/mob/living/basic/space_fauna/cat_surgeon.dm
index ab0f5c843b90..3658ca31182b 100644
--- a/code/modules/mob/living/basic/space_fauna/cat_surgeon.dm
+++ b/code/modules/mob/living/basic/space_fauna/cat_surgeon.dm
@@ -36,21 +36,15 @@
/obj/effect/mob_spawn/corpse/human/cat_butcher,
/obj/item/circular_saw,
)
- /// What's our "blood type"? So fake-humans splash blood on people in combat
- var/fake_blood_type
/mob/living/basic/cat_butcherer/Initialize(mapload)
+ initial_blood_type = random_human_blood_type()
. = ..()
apply_dynamic_human_appearance(src, mob_spawn_path = /obj/effect/mob_spawn/corpse/human/cat_butcher, l_hand = /obj/item/circular_saw, bloody_slots = ITEM_SLOT_GLOVES|ITEM_SLOT_OCLOTHING)
AddElement(/datum/element/ai_retaliate)
AddElement(/datum/element/death_drops, drop_on_death)
RegisterSignal(src, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(after_attack))
-/mob/living/basic/cat_butcherer/get_blood_type()
- if(!fake_blood_type)
- fake_blood_type = random_human_blood_type()
- return find_blood_type(fake_blood_type)
-
/mob/living/basic/cat_butcherer/init_unconscious_appearance()
add_generic_humanoid_static_appearance()
diff --git a/code/modules/mob/living/basic/space_fauna/ghost.dm b/code/modules/mob/living/basic/space_fauna/ghost.dm
index 19e6797431f1..228aac2430f9 100644
--- a/code/modules/mob/living/basic/space_fauna/ghost.dm
+++ b/code/modules/mob/living/basic/space_fauna/ghost.dm
@@ -26,6 +26,7 @@
light_range = 2.5 // same glowing as visible player ghosts
light_power = 0.6
ai_controller = /datum/ai_controller/basic_controller/ghost
+ initial_blood_type = null
///What hairstyle will this ghost have
var/ghost_hairstyle
diff --git a/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm b/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm
index b7813b75e232..90baac645c76 100644
--- a/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm
+++ b/code/modules/mob/living/basic/space_fauna/hivebot/_hivebot.dm
@@ -34,6 +34,8 @@
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
bodytemp_cold_damage_limit = TCMB
ai_controller = /datum/ai_controller/basic_controller/hivebot
+ initial_blood_type = /datum/blood_type/oil
+
///does this type do range attacks?
var/ranged_attacker = FALSE
/// How often can we shoot?
diff --git a/code/modules/mob/living/basic/space_fauna/mushroom.dm b/code/modules/mob/living/basic/space_fauna/mushroom.dm
index 0a543821cfec..b2e655a5c5f1 100644
--- a/code/modules/mob/living/basic/space_fauna/mushroom.dm
+++ b/code/modules/mob/living/basic/space_fauna/mushroom.dm
@@ -25,6 +25,7 @@
faction = list(FACTION_MUSHROOM)
speak_emote = list("squeaks")
death_message = "fainted!"
+ initial_blood_type = /datum/blood_type/water
ai_controller = /datum/ai_controller/basic_controller/mushroom
var/cap_color = "#ffffff"
diff --git a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
index 2f5bc61b5973..a051318ea6da 100644
--- a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
+++ b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
@@ -46,6 +46,7 @@
unique_name = TRUE
hud_possible = list(ANTAG_HUD)
hud_type = /datum/hud/revenant
+ initial_blood_type = null
/// The icon we use while just floating around.
var/icon_idle = "revenant_idle"
diff --git a/code/modules/mob/living/basic/space_fauna/robot_customer.dm b/code/modules/mob/living/basic/space_fauna/robot_customer.dm
index 802d75479c83..e8c5f765b94a 100644
--- a/code/modules/mob/living/basic/space_fauna/robot_customer.dm
+++ b/code/modules/mob/living/basic/space_fauna/robot_customer.dm
@@ -20,6 +20,7 @@
bodytemp_heat_damage_limit = T0C + 1000
ai_controller = /datum/ai_controller/robot_customer
+ initial_blood_type = /datum/blood_type/oil
/// The clothes that we draw on this tourist.
var/clothes_set = "amerifat_clothes"
diff --git a/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm b/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm
index 6e9943aa67db..20117239284c 100644
--- a/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm
+++ b/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm
@@ -46,6 +46,7 @@
death_sound = 'sound/creatures/space_dragon_roar.ogg'
death_message = "screeches in agony as it collapses to the floor, its life extinguished."
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30)
+ initial_blood_type = /datum/blood_type/crew/lizard
/// The colour of the space dragon
var/chosen_colour
diff --git a/code/modules/mob/living/basic/space_fauna/spider/spider.dm b/code/modules/mob/living/basic/space_fauna/spider/spider.dm
index 2b4b4b88d549..9dade5af59e0 100644
--- a/code/modules/mob/living/basic/space_fauna/spider/spider.dm
+++ b/code/modules/mob/living/basic/space_fauna/spider/spider.dm
@@ -19,6 +19,7 @@
status_flags = NONE
unsuitable_cold_damage = 4
unsuitable_heat_damage = 4
+ initial_blood_type = /datum/blood_type/animal/bug
combat_mode = TRUE
faction = list(FACTION_SPIDER)
pass_flags = PASSTABLE
diff --git a/code/modules/mob/living/basic/space_fauna/statue/statue.dm b/code/modules/mob/living/basic/space_fauna/statue/statue.dm
index cdc8b1e18aff..036b5093a94e 100644
--- a/code/modules/mob/living/basic/space_fauna/statue/statue.dm
+++ b/code/modules/mob/living/basic/space_fauna/statue/statue.dm
@@ -36,6 +36,7 @@
unsuitable_atmos_damage = 0
unsuitable_cold_damage = 0
unsuitable_heat_damage = 0
+ initial_blood_type = null
animate_movement = NO_STEPS // Do not animate movement, you jump around as you're a scary statue.
hud_possible = list(ANTAG_HUD)
diff --git a/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm b/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm
index a8ce1c93be4e..e51af9355bcf 100644
--- a/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm
+++ b/code/modules/mob/living/basic/space_fauna/supermatter_spider.dm
@@ -26,6 +26,7 @@
bodytemp_heat_damage_limit = T0C + 1250
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
death_message = "falls to the ground, its shard dulling to a miserable grey!"
+ initial_blood_type = null
faction = list(FACTION_HOSTILE)
diff --git a/code/modules/mob/living/basic/trader/trader.dm b/code/modules/mob/living/basic/trader/trader.dm
index 1ae52ef68852..c6586c9f3ee2 100644
--- a/code/modules/mob/living/basic/trader/trader.dm
+++ b/code/modules/mob/living/basic/trader/trader.dm
@@ -80,3 +80,4 @@
held_weapon_visual = /obj/item/gun/ballistic/revolver
trader_data_path = /datum/trader_data/mr_bones
+ initial_blood_type = null
diff --git a/code/modules/mob/living/basic/tree.dm b/code/modules/mob/living/basic/tree.dm
index 8f6d06c98fd2..4fd30a983b2b 100644
--- a/code/modules/mob/living/basic/tree.dm
+++ b/code/modules/mob/living/basic/tree.dm
@@ -30,6 +30,7 @@
attack_verb_simple = "bite"
attack_sound = 'sound/weapons/bite.ogg'
attack_vis_effect = ATTACK_EFFECT_BITE
+ initial_blood_type = null
faction = list(FACTION_HOSTILE)
speak_emote = list("pines")
diff --git a/code/modules/mob/living/basic/trooper/abductor.dm b/code/modules/mob/living/basic/trooper/abductor.dm
index 349e64ac9d6c..bfabd8150709 100644
--- a/code/modules/mob/living/basic/trooper/abductor.dm
+++ b/code/modules/mob/living/basic/trooper/abductor.dm
@@ -6,7 +6,7 @@
mob_spawner = /obj/effect/mob_spawn/corpse/human/abductor
corpse = /obj/effect/mob_spawn/corpse/human/abductor
-/mob/living/basic/trooper/abductor/get_blood_type()
+/mob/living/basic/trooper/abductor/get_fake_blood_type()
return null // Ayys are noblooded
/mob/living/basic/trooper/abductor/melee
diff --git a/code/modules/mob/living/basic/trooper/syndicate.dm b/code/modules/mob/living/basic/trooper/syndicate.dm
index baf6677700d3..fa0e032b99ed 100644
--- a/code/modules/mob/living/basic/trooper/syndicate.dm
+++ b/code/modules/mob/living/basic/trooper/syndicate.dm
@@ -247,6 +247,7 @@
gold_core_spawnable = HOSTILE_SPAWN
death_message = "is smashed into pieces!"
ai_controller = /datum/ai_controller/basic_controller/trooper/viscerator
+ initial_blood_type = /datum/blood_type/oil
/mob/living/basic/viscerator/Initialize(mapload)
. = ..()
diff --git a/code/modules/mob/living/basic/trooper/trooper.dm b/code/modules/mob/living/basic/trooper/trooper.dm
index 4d8d39b6bf91..040137df6dc8 100644
--- a/code/modules/mob/living/basic/trooper/trooper.dm
+++ b/code/modules/mob/living/basic/trooper/trooper.dm
@@ -28,10 +28,9 @@
var/r_hand
/// Path of the left hand held item we give to the mob's visuals.
var/l_hand
- /// What's our "blood type"? So fake-humans splash blood on people in combat
- var/fake_blood_type
/mob/living/basic/trooper/Initialize(mapload)
+ initial_blood_type = get_fake_blood_type()
. = ..()
apply_dynamic_human_appearance(src, mob_spawn_path = mob_spawner, r_hand = r_hand, l_hand = l_hand)
if(LAZYLEN(loot) || corpse)
@@ -40,10 +39,8 @@
AddElement(/datum/element/death_drops, loot)
AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_SHOE)
-/mob/living/basic/trooper/get_blood_type()
- if(!fake_blood_type)
- fake_blood_type = random_human_blood_type()
- return find_blood_type(fake_blood_type)
+/mob/living/basic/trooper/proc/get_fake_blood_type()
+ return random_human_blood_type()
/mob/living/basic/trooper/init_unconscious_appearance()
add_generic_humanoid_static_appearance()
diff --git a/code/modules/mob/living/basic/vermin/butterfly.dm b/code/modules/mob/living/basic/vermin/butterfly.dm
index cbc847aa9e89..5c90b2ebfb68 100644
--- a/code/modules/mob/living/basic/vermin/butterfly.dm
+++ b/code/modules/mob/living/basic/vermin/butterfly.dm
@@ -25,6 +25,7 @@
gold_core_spawnable = FRIENDLY_SPAWN
ai_controller = /datum/ai_controller/basic_controller/butterfly
+ initial_blood_type = /datum/blood_type/animal/bug
/mob/living/basic/butterfly/Initialize(mapload)
. = ..()
diff --git a/code/modules/mob/living/basic/vermin/cockroach.dm b/code/modules/mob/living/basic/vermin/cockroach.dm
index 04aecc9eb475..dc4fb887e782 100644
--- a/code/modules/mob/living/basic/vermin/cockroach.dm
+++ b/code/modules/mob/living/basic/vermin/cockroach.dm
@@ -32,6 +32,7 @@
bodytemp_heat_damage_limit = INFINITY
ai_controller = /datum/ai_controller/basic_controller/cockroach
+ initial_blood_type = /datum/blood_type/animal/bug
var/cockroach_cell_line = CELL_LINE_TABLE_COCKROACH
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
index 913857bb6082..4d7a7256f584 100644
--- a/code/modules/mob/living/blood.dm
+++ b/code/modules/mob/living/blood.dm
@@ -222,8 +222,7 @@
//Gets blood from mob to a container or other mob, preserving all data in it.
/mob/living/proc/transfer_blood_to(atom/movable/AM, amount, forced)
- var/datum/blood_type/blood = get_blood_type()
- if(isnull(blood) || !AM.reagents)
+ if(!has_blood() || !AM.reagents)
return FALSE
if(blood_volume < BLOOD_VOLUME_BAD && !forced)
return FALSE
@@ -232,57 +231,84 @@
amount = blood_volume
blood_volume -= amount
- AM.reagents.add_reagent(blood.reagent_type, amount, blood.get_blood_data(src), body_temperature)
+ AM.reagents.add_reagent(blood_type.reagent_type, amount, blood_type.get_blood_data(src), body_temperature)
return TRUE
-/mob/living/proc/get_blood_type()
- RETURN_TYPE(/datum/blood_type)
- if(HAS_TRAIT(src, TRAIT_NOBLOOD))
- return null
- return find_blood_type(/datum/blood_type/animal)
-
-/mob/living/basic/get_blood_type()
- // All basic mobs are noblood but we should still pretend
- return find_blood_type(/datum/blood_type/animal)
+/// Updates the blood_type variable with a blood_type singleton
+/mob/living/proc/set_blood_type(input_type, update = TRUE)
+ var/new_blood = find_blood_type(input_type)
+ if(isnull(new_blood) || blood_type == new_blood)
+ return FALSE
-/mob/living/simple_animal/get_blood_type()
- // Same here
- return find_blood_type(/datum/blood_type/animal)
+ blood_type = new_blood
+ return TRUE
-/mob/living/silicon/get_blood_type()
- return find_blood_type(/datum/blood_type/oil)
+/mob/living/carbon/set_blood_type(input_type, update = TRUE)
+ . = ..()
+ if(!.)
+ return
-/mob/living/simple_animal/bot/get_blood_type()
- return find_blood_type(/datum/blood_type/oil)
+ var/update_needed = FALSE
+ for(var/obj/item/bodypart/part as anything in bodyparts)
+ for(var/obj/item/organ/organ_bit in part)
+ organ_bit.set_organ_blood(src)
+ if(part.damage_color == blood_type.color)
+ continue
+ part.damage_color = blood_type.color
+ // only these vars are affected by damage color so we can skip updates if none of them are set
+ if(part.brutestate || part.is_husked || part.cached_bleed_rate)
+ update_needed = TRUE
+
+ if(update && update_needed)
+ update_body_parts()
+
+/mob/living/carbon/human/set_blood_type(input_type, update = TRUE)
+ // force clowns to always have clown blood on april fools
+ if(check_holidays(APRIL_FOOLS) && is_clown_job(mind?.assigned_role))
+ input_type = /datum/blood_type/clown
-/mob/living/basic/bot/get_blood_type()
- return find_blood_type(/datum/blood_type/oil)
+ return ..()
-/mob/living/basic/drone/get_blood_type()
- return find_blood_type(/datum/blood_type/oil)
+/// Resets the blood type to the initial blood type, which is determined by species and DNA.
+/mob/living/proc/reset_blood_type(update = TRUE)
+ set_blood_type(initial_blood_type, update)
-/mob/living/basic/hivebot/get_blood_type()
- return find_blood_type(/datum/blood_type/oil)
+/mob/living/carbon/reset_blood_type(update = TRUE)
+ set_blood_type(initial(dna.species.exotic_bloodtype) || dna.human_blood_type || random_human_blood_type(), update)
-/mob/living/carbon/alien/get_blood_type()
+/// Do we have (mechanical) blood?
+/mob/living/proc/has_blood()
if(HAS_TRAIT(src, TRAIT_HUSK) || HAS_TRAIT(src, TRAIT_NOBLOOD))
- return null
- return find_blood_type(/datum/blood_type/xenomorph)
-
-/mob/living/carbon/human/get_blood_type()
- if(HAS_TRAIT(src, TRAIT_HUSK) || isnull(dna) || HAS_TRAIT(src, TRAIT_NOBLOOD))
- return null
- if(check_holidays(APRIL_FOOLS) && is_clown_job(mind?.assigned_role))
- return find_blood_type(/datum/blood_type/clown)
- return find_blood_type(dna.species.exotic_bloodtype || dna.human_blood_type)
+ return FALSE
+ if(isnull(blood_type))
+ return FALSE
+ return TRUE
-//to add a splatter of blood or other mob liquid.
+/**
+ * Create a splat of this mob's life juice
+ * Does nothing if the mob does not have a blood type set
+ * DOES work if the mob does not actually have blood but does have a blood type
+ *
+ * * blood_turf - where to make the splatter. defaults to the current turf
+ * * small_drip - whether to make a small drip or a big splat
+ */
/mob/living/proc/add_splatter_floor(turf/blood_turf = get_turf(src), small_drip)
- return get_blood_type()?.make_blood_splatter(blood_turf, small_drip, get_blood_dna_list(), get_static_viruses())
+ if(isnull(blood_type))
+ return
+ return blood_type.make_blood_splatter(blood_turf, small_drip, get_blood_dna_list(), get_static_viruses())
+/**
+ * Create a visual effect of this mob's blood splattering in a direction
+ * Does nothing if the mob does not have a blood type set
+ * DOES work if the mob does not actually have blood but does have a blood type
+ *
+ * * splat_dir - the direction to splatter in. defaults to a random cardinal direction
+ */
/mob/living/proc/do_splatter_effect(splat_dir = pick(GLOB.cardinals))
+ if(isnull(blood_type))
+ return
var/obj/effect/temp_visual/dir_setting/bloodsplatter/splatter = new(get_turf(src), splat_dir)
- splatter.color = get_blood_type()?.color
+ splatter.color = blood_type.color
// NON-MODULE CHANGE END
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index e8d5fcb2ce69..868c56c500a8 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -15,6 +15,7 @@
temperature_insulation = 0.5 // minor heat insulation
bodytemp_heat_damage_limit = CELCIUS_TO_KELVIN(85 CELCIUS)
+ initial_blood_type = /datum/blood_type/xenomorph
///Whether or not the alien is leaping. Only used by hunters.
var/leaping = FALSE
@@ -29,8 +30,8 @@
add_verb(src, /mob/living/proc/mob_sleep)
add_verb(src, /mob/living/proc/toggle_resting)
+ set_blood_type(initial_blood_type) // needs to be done before bodyparts and organs
create_bodyparts() //initialize bodyparts
-
create_internal_organs()
add_traits(list(TRAIT_NEVER_WOUNDED, TRAIT_VENTCRAWLER_ALWAYS), INNATE_TRAIT)
diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm
index e9947b2b405e..5d570c3ec12f 100644
--- a/code/modules/mob/living/carbon/human/_species.dm
+++ b/code/modules/mob/living/carbon/human/_species.dm
@@ -396,14 +396,9 @@ GLOBAL_LIST_EMPTY(features_by_species)
// Drop the items the new species can't wear
INVOKE_ASYNC(src, PROC_REF(worn_items_fit_body_check), human_who_gained_species, TRUE)
- // NON-MODULE CHANGE
- // //Assigns exotic blood type if the species has one
- // if(exotic_bloodtype && human_who_gained_species.dna.blood_type != exotic_bloodtype)
- // human_who_gained_species.dna.blood_type = exotic_bloodtype
- // //Otherwise, check if the previous species had an exotic bloodtype and we do not have one and assign a random blood type
- // //(why the fuck is blood type not tied to a fucking DNA block?)
- // else if(old_species.exotic_bloodtype && !exotic_bloodtype)
- // human_who_gained_species.dna.blood_type = random_blood_type()
+ //Assigns exotic blood type if the species has one
+ if(exotic_bloodtype)
+ human_who_gained_species.set_blood_type(exotic_bloodtype, update = FALSE)
if(isnum(species_pain_mod) && species_pain_mod != 1)
human_who_gained_species.set_pain_mod(PAIN_MOD_SPECIES, species_pain_mod)
@@ -467,12 +462,14 @@ GLOBAL_LIST_EMPTY(features_by_species)
clear_tail_moodlets(C)
+ C.reset_blood_type(update = FALSE)
+
C.unset_pain_mod(PAIN_MOD_SPECIES)
C.physiology?.cold_mod /= coldmod
C.physiology?.heat_mod /= heatmod
- remove_body_markings(C)
+ remove_body_markings(C, update = FALSE)
// Removes all languages previously associated with [LANGUAGE_SPECIES], gaining our new species will add new ones back
var/datum/language_holder/losing_holder = GLOB.prototype_language_holders[species_language_holder]
@@ -762,7 +759,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
// Cringe but blood handles this on its own
// This also has problems of its own but that's better fixed later I think
if(!istype(chem, /datum/reagent/blood))
- var/datum/blood_type/blood = affected.get_blood_type()
+ var/datum/blood_type/blood = affected.blood_type
if(chem.type == blood?.reagent_type)
affected.blood_volume = min(affected.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM)
affected.reagents.del_reagent(chem.type)
@@ -1644,10 +1641,10 @@ GLOBAL_LIST_EMPTY(features_by_species)
qdel(markings)
/// Remove body markings
-/datum/species/proc/remove_body_markings(mob/living/carbon/human/hooman)
+/datum/species/proc/remove_body_markings(mob/living/carbon/human/hooman, update = TRUE)
for(var/obj/item/bodypart/part as anything in hooman.bodyparts)
for(var/datum/bodypart_overlay/simple/body_marking/marking in part.bodypart_overlays)
- part.remove_bodypart_overlay(marking)
+ part.remove_bodypart_overlay(marking, update = update)
/**
* Calculates the expected height values for this species
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index c70a0cd66fd9..355f402a842e 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -18,6 +18,7 @@
bodytemp_cold_damage_limit = BODYTEMP_COLD_DAMAGE_LIMIT
bodytemp_heat_damage_limit = BODYTEMP_HEAT_DAMAGE_LIMIT
+ initial_blood_type = /datum/blood_type/crew/human/o_minus
//Hair colour and style
var/hair_color = COLOR_BLACK
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index 8fe6c4075921..445474c229ae 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -218,7 +218,7 @@
if(victim.stat == DEAD)
to_chat(user, span_warning("You need a living victim!"))
return FALSE
- if(!istype(victim.get_blood_type(), /datum/blood_type/crew/human)) // NON-MODULE CHANGE
+ if(!istype(victim.blood_type, /datum/blood_type/crew/human)) // NON-MODULE CHANGE
to_chat(user, span_warning("[victim] doesn't have valid blood!")) // NON-MODULE CHANGE
return FALSE
COOLDOWN_START(licker_drinker, drain_cooldown, 3 SECONDS)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 9280dda8afe6..07c3c87d030b 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -250,7 +250,7 @@
dna.unique_enzymes = dna.previous["UE"]
dna.previous.Remove("UE")
if(dna.previous["blood_type"])
- dna.human_blood_type = find_blood_type(dna.previous["blood_type"])
+ dna.set_human_blood_type(dna.previous["blood_type"])
dna.previous.Remove("blood_type")
dna.temporary_mutations.Remove(mut)
continue
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index bf11c7d9cf4b..0dc3d9b16ec2 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -16,6 +16,8 @@
update_fov()
gravity_setup()
ADD_TRAIT(src, TRAIT_UNIQUE_IMMERSE, INNATE_TRAIT)
+ if(initial_blood_type && isnull(blood_type))
+ set_blood_type(initial_blood_type)
if(!blood_volume)
ADD_TRAIT(src, TRAIT_NOBLOOD, INNATE_TRAIT)
init_unconscious_appearance()
@@ -2101,6 +2103,10 @@ GLOBAL_LIST_EMPTY(fire_appearances)
return FALSE
update_transform(var_value/current_size)
. = TRUE
+ if(NAMEOF(src, blood_type))
+ . = set_blood_type(var_value)
+ if(!.)
+ return
if(!isnull(.))
datum_flags |= DF_VAR_EDITED
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 776b22320414..31a072bb1048 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -176,8 +176,16 @@
///effectiveness prob. is modified negatively by this amount; positive numbers make it more difficult, negative ones make it easier
var/butcher_difficulty = 0
- ///how much blood the mob has
+ /// How much blood the mob has.
+ /// If initially 0, the mob gains TRAIT_NOBLOOD permanently.
var/blood_volume = 0
+ /// What blood type do we set on init.
+ /// This can be set even on mobs that don't mechanically have blood,
+ /// allowing them to create blood decals to sell the illusion of them really having blood.
+ var/initial_blood_type = null
+ /// Blood type singleton this mob currently has.
+ /// If null, the mob doesn't have blood.
+ VAR_FINAL/datum/blood_type/blood_type = null
///a list of all status effects the mob has
var/list/status_effects
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 907bff9b8b32..5678b0877935 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -14,6 +14,8 @@
examine_cursor_icon = null
fire_stack_decay_rate = -0.55
tts_silicon_voice_effect = TRUE
+ initial_blood_type = /datum/blood_type/oil
+
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
var/last_lawchange_announce = 0
var/list/alarms_to_show = list()
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index fa93f7b02978..de0bdcb86322 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -28,6 +28,7 @@
light_power = 0.6
del_on_death = TRUE
interaction_flags_click = ALLOW_SILICON_REACH
+ initial_blood_type = /datum/blood_type/oil
///Will other (noncommissioned) bots salute this bot?
var/commissioned = FALSE
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 19effd123aa9..1fee1fdc2ad2 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -39,6 +39,7 @@
death_sound = 'sound/voice/hiss6.ogg'
death_message = "lets out a waning guttural screech, green blood bubbling from its maw..."
footstep_type = FOOTSTEP_MOB_CLAW
+ initial_blood_type = /datum/blood_type/xenomorph
/mob/living/simple_animal/hostile/alien/drone
name = "alien drone"
diff --git a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
index 54285d545680..b8b11c512d5e 100644
--- a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
+++ b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
@@ -34,6 +34,7 @@
del_on_death = TRUE
/mob/living/simple_animal/hostile/dark_wizard/Initialize(mapload)
+ initial_blood_type = random_human_blood_type()
. = ..()
apply_dynamic_human_appearance(src, mob_spawn_path = /obj/effect/mob_spawn/corpse/human/wizard/dark, r_hand = /obj/item/staff)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index 8b18a0969755..89c76ad7eab4 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -68,6 +68,8 @@ Difficulty: Hard
death_message = "sinks into a pool of blood, fleeing the battle. You've won, for now... "
death_sound = 'sound/magic/enter_blood.ogg'
faction = list(FACTION_MINING, FACTION_BOSS, FACTION_HELL)
+ initial_blood_type = /datum/blood_type/animal/bubblegum
+
/// Check to see if we should spawn blood
var/spawn_blood = TRUE
/// Actual time where enrage ends
@@ -328,6 +330,7 @@ Difficulty: Hard
death_message = "Explodes into a pool of blood!"
death_sound = 'sound/effects/splat.ogg'
true_spawn = FALSE
+ initial_blood_type = null
var/move_through_mob
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/Initialize(mapload)
@@ -361,7 +364,7 @@ Difficulty: Hard
/obj/effect/decal/cleanable/blood/bubblegum/Initialize(mapload, list/datum/disease/diseases)
. = ..()
- add_blood_DNA(list("DEMON BLOOD" = /datum/blood_type/animal))
+ add_blood_DNA(list("UNKNOWN DEMON BLOOD" = /datum/blood_type/animal))
/obj/effect/decal/cleanable/blood/bubblegum/can_bloodcrawl_in()
return TRUE
@@ -376,7 +379,7 @@ Difficulty: Hard
/obj/effect/decal/cleanable/blood/gibs/bubblegum/Initialize(mapload, list/datum/disease/diseases)
. = ..()
- add_blood_DNA(list("DEMON BLOOD" = /datum/blood_type/animal))
+ add_blood_DNA(list("UNKNOWN DEMON BLOOD" = /datum/blood_type/animal))
/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
return TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/clockwork_knight.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/clockwork_knight.dm
index f58fc0669c04..571257ab498d 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/clockwork_knight.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/clockwork_knight.dm
@@ -42,6 +42,7 @@ I'd rather there be something than the clockwork ruin be entirely empty though s
death_sound = SFX_BODYFALL
footstep_type = FOOTSTEP_MOB_HEAVY
attack_action_types = list()
+ initial_blood_type = /datum/blood_type/oil
/mob/living/simple_animal/hostile/megafauna/clockwork_defender/Initialize(mapload)
. = ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 96b1003aa2bf..44a902acc4d1 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -67,6 +67,7 @@ Difficulty: Hard
score_achievement_type = /datum/award/score/hierophant_score
del_on_death = TRUE
death_sound = 'sound/magic/repulse.ogg'
+ initial_blood_type = null
attack_action_types = list(/datum/action/innate/megafauna_attack/blink,
/datum/action/innate/megafauna_attack/chaser_swarm,
/datum/action/innate/megafauna_attack/cross_blasts,
@@ -501,9 +502,6 @@ Difficulty: Hard
burst_range = initial(burst_range) + round(anger_modifier * 0.08)
beam_range = initial(beam_range) + round(anger_modifier * 0.12)
-/mob/living/simple_animal/hostile/megafauna/hierophant/get_blood_type()
- return null
-
//Hierophant overlays
/obj/effect/temp_visual/hierophant
name = "vortex energy"
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index eda344ad1daa..a730b783445a 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -57,6 +57,7 @@
elimination = TRUE
appearance_flags = LONG_GLIDE
mouse_opacity = MOUSE_OPACITY_ICON
+ initial_blood_type = null
attack_action_types = list(/datum/action/innate/megafauna_attack/create_skull,
/datum/action/innate/megafauna_attack/charge_target,
/datum/action/innate/megafauna_attack/create_turrets)
diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm
index e6bc24e14d3e..8b73e06beef0 100644
--- a/code/modules/mob/living/simple_animal/hostile/mimic.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm
@@ -38,6 +38,8 @@ GLOBAL_LIST_INIT(animatable_blacklist, typecacheof(list(
faction = list(FACTION_MIMIC)
move_to_delay = 9
del_on_death = 1
+ initial_blood_type = null
+
///A cap for items in the mimic. Prevents the mimic from eating enough stuff to cause lag when opened.
var/storage_capacity = 50
///A cap for mobs. Mobs count towards the item cap. Same purpose as above.
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm
index 5a4514d073bd..45db7c80f565 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm
@@ -42,6 +42,7 @@
death_sound = 'sound/magic/curse.ogg'
death_message = "'s arms reach out before it falls apart onto the floor, lifeless."
loot_drop = /obj/item/crusher_trophy/legionnaire_spine
+ initial_blood_type = null
attack_action_types = list(/datum/action/innate/elite_attack/legionnaire_charge,
/datum/action/innate/elite_attack/head_detach,
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
index 162aaa15fdef..6363f4d17b3b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
@@ -40,6 +40,7 @@
death_sound = 'sound/magic/repulse.ogg'
death_message = "'s lights flicker, before its top part falls down."
loot_drop = /obj/item/clothing/accessory/pandora_hope
+ initial_blood_type = null
attack_action_types = list(/datum/action/innate/elite_attack/singular_shot,
/datum/action/innate/elite_attack/magic_box,
diff --git a/code/modules/mob/living/simple_animal/hostile/ooze.dm b/code/modules/mob/living/simple_animal/hostile/ooze.dm
index 7cd6f7d13d6e..1b3cbb8c164a 100644
--- a/code/modules/mob/living/simple_animal/hostile/ooze.dm
+++ b/code/modules/mob/living/simple_animal/hostile/ooze.dm
@@ -27,6 +27,7 @@
mob_size = MOB_SIZE_LARGE
initial_language_holder = /datum/language_holder/slime
footstep_type = FOOTSTEP_MOB_SLIME
+ initial_blood_type = /datum/blood_type/slime
///Oozes have their own nutrition. Changes based on them eating
var/ooze_nutrition = 50
var/ooze_nutrition_loss = -0.15
diff --git a/code/modules/mob/living/simple_animal/hostile/zombie.dm b/code/modules/mob/living/simple_animal/hostile/zombie.dm
index 7e43fb1859ce..f81868c9e423 100644
--- a/code/modules/mob/living/simple_animal/hostile/zombie.dm
+++ b/code/modules/mob/living/simple_animal/hostile/zombie.dm
@@ -26,18 +26,12 @@
var/infection_chance = 0
/// Outfit the zombie spawns with for visuals.
var/outfit = /datum/outfit/corpse_doctor
- /// What's our "blood type"? So fake-humans splash blood on people in combat
- var/fake_blood_type
/mob/living/simple_animal/hostile/zombie/Initialize(mapload)
+ initial_blood_type = random_human_blood_type()
. = ..()
apply_dynamic_human_appearance(src, outfit, /datum/species/zombie, bloody_slots = ITEM_SLOT_OCLOTHING)
-/mob/living/simple_animal/hostile/zombie/get_blood_type()
- if(!fake_blood_type)
- fake_blood_type = random_human_blood_type()
- return find_blood_type(fake_blood_type)
-
/mob/living/simple_animal/hostile/zombie/init_unconscious_appearance()
add_generic_humanoid_static_appearance()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index b482c9c340f6..20bd1943ef0a 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -7,6 +7,7 @@
gender = PLURAL //placeholder
living_flags = MOVES_ON_ITS_OWN
status_flags = CANPUSH
+ initial_blood_type = /datum/blood_type/animal
var/icon_living = ""
///Icon when the animal is dead. Don't use animated icons for this.
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index f2d9b9c88a0c..1d49d5b2be2c 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -26,6 +26,7 @@
speak_emote = list("blorbles")
bubble_icon = "slime"
initial_language_holder = /datum/language_holder/slime
+ initial_blood_type = /datum/blood_type/slime
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 07b5c24561b0..50ec56c61f7f 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -314,7 +314,7 @@
if(blocked != 100) // not completely blocked
var/obj/item/bodypart/hit_bodypart = living_target.get_bodypart(def_zone)
if (damage && damage_type == BRUTE)
- if (living_target.get_blood_type() && (isnull(hit_bodypart) || hit_bodypart.can_bleed()))
+ if (hit_bodypart?.can_bleed())
living_target.do_splatter_effect(dir) // NON-MODULE CHANGE
if(prob(33))
living_target.add_splatter_floor(target_turf)
diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm
index 62f98f0f2d20..44aabc73783e 100644
--- a/code/modules/reagents/chemistry/machinery/pandemic.dm
+++ b/code/modules/reagents/chemistry/machinery/pandemic.dm
@@ -148,7 +148,7 @@
data["has_blood"] = TRUE
data["blood"] = list()
data["blood"]["dna"] = blood.data["blood_DNA"] || "none"
- data["blood"]["type"] = blood.data["blood_type"] || "none"
+ data["blood"]["type"] = find_blood_type(blood.data["blood_type"])?.name || "none"
data["viruses"] = get_viruses_data(blood)
data["resistances"] = get_resistance_data(blood)
return data
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 3302889c883f..7fbc49258ec6 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -74,7 +74,7 @@
if(!infection.bypasses_immunity)
infection.cure(add_resistance = FALSE)
- var/datum/blood_type/blood = exposed_mob.get_blood_type()
+ var/datum/blood_type/blood = exposed_mob.blood_type
if(blood?.reagent_type == type && ((methods & INJECT) || ((methods & INGEST) && HAS_TRAIT(exposed_mob, TRAIT_DRINKS_BLOOD))))
if(data["blood_type"] in blood.compatible_types)
exposed_mob.blood_volume = min(exposed_mob.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM)
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index f99bb59314bd..67b74e80b910 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -58,8 +58,12 @@
volume = vol
create_reagents(volume, reagent_flags)
if(spawned_disease)
- var/datum/disease/F = new spawned_disease()
- var/list/data = list("viruses"= list(F))
+ var/list/data = list(
+ "viruses"= new spawned_disease(),
+ "blood_DNA" = "UNKNOWN HUMAN DNA",
+ "blood_type" = random_human_blood_type(),
+ "resistances" = null,
+ )
reagents.add_reagent(/datum/reagent/blood, disease_amount, data)
add_initial_reagents()
diff --git a/code/modules/religion/religion_sects.dm b/code/modules/religion/religion_sects.dm
index 67b5968c22c5..1b9007aa8c3e 100644
--- a/code/modules/religion/religion_sects.dm
+++ b/code/modules/religion/religion_sects.dm
@@ -363,8 +363,8 @@
chaplain.adjustOxyLoss(suffocation_damage * burden_modifier, forced = TRUE)
// NON-MODULE CHANGE : Blood rework
- var/datum/blood_type/our_blood = chaplain.get_blood_type()
- var/datum/blood_type/their_blood = target.get_blood_type()
+ var/datum/blood_type/our_blood = chaplain.blood_type
+ var/datum/blood_type/their_blood = target.blood_type
if(our_blood && their_blood)
// melbert todo ?? logic
if(target.blood_volume < BLOOD_VOLUME_SAFE)
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index ec67b2cb6dba..3faa79950536 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -929,6 +929,7 @@
item_flags |= ABSTRACT
ADD_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT)
+ damage_color ||= new_owner.blood_type?.color || COLOR_BLOOD
/// Called on removal of a bodypart.
/obj/item/bodypart/proc/on_removal(mob/living/carbon/old_owner)
@@ -1077,8 +1078,6 @@
else
draw_color = null
- damage_color = owner?.get_blood_type()?.color || COLOR_BLOOD // NON-MODULE CHANGE
-
if(!is_creating || !owner)
return
diff --git a/code/modules/surgery/operations/operation_generic.dm b/code/modules/surgery/operations/operation_generic.dm
index 603f7216a9f9..fcfae06fda02 100644
--- a/code/modules/surgery/operations/operation_generic.dm
+++ b/code/modules/surgery/operations/operation_generic.dm
@@ -64,7 +64,7 @@
if(!limb.can_bleed())
return
- var/blood_name = limb.owner.get_blood_type()?.name || "Blood"
+ var/blood_name = limb.owner.blood_type?.name || "Blood"
display_results(
surgeon,
limb.owner,
diff --git a/code/modules/surgery/operations/operation_organ_repair.dm b/code/modules/surgery/operations/operation_organ_repair.dm
index 18e1983f66a8..e20b80e95438 100644
--- a/code/modules/surgery/operations/operation_organ_repair.dm
+++ b/code/modules/surgery/operations/operation_organ_repair.dm
@@ -261,7 +261,7 @@
/datum/surgery_operation/organ/repair/coronary_bypass/on_failure(obj/item/organ/organ, mob/living/surgeon, obj/item/tool, list/operation_args)
. = ..()
organ.bodypart_owner.adjustBleedStacks(30)
- var/blood_name = LOWER_TEXT(organ.owner.get_blood_type()?.name) || "blood"
+ var/blood_name = LOWER_TEXT(organ.owner.blood_type?.name) || "blood"
display_results(
surgeon,
organ.owner,
diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm
index 5122f5156521..9d81b974f2c0 100644
--- a/code/modules/surgery/organs/_organ.dm
+++ b/code/modules/surgery/organs/_organ.dm
@@ -8,7 +8,7 @@
/// Reference to the limb we're inside of
var/obj/item/bodypart/bodypart_owner
/// The cached info about the blood this organ belongs to
- var/list/blood_dna_info = list("Synthetic DNA" = /datum/blood_type/crew/human/o_minus) // not every organ spawns inside a person
+ var/list/blood_dna_info
/// The body zone this organ is supposed to inhabit.
var/zone = BODY_ZONE_CHEST
/**
@@ -77,6 +77,9 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
/obj/item/organ/Initialize(mapload)
. = ..()
+ if(!IS_ROBOTIC_ORGAN(src))
+ blood_dna_info = list("UNKNOWN DNA" = /datum/blood_type/crew/human/o_minus)
+ add_blood_DNA(blood_dna_info)
if(organ_flags & ORGAN_EDIBLE)
AddComponent(/datum/component/edible,\
initial_reagents = food_reagents, \
@@ -135,11 +138,20 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
/obj/item/organ/proc/on_find(mob/living/finder)
return
+/// Setup blood info
+/obj/item/organ/proc/set_organ_blood(mob/living/carbon/receiver)
+ if(IS_ROBOTIC_ORGAN(src))
+ return
+ LAZYREMOVE(forensics?.blood_DNA, blood_dna_info)
+ blood_dna_info = receiver.get_blood_dna_list()
+ if(!LAZYLEN(blood_dna_info))
+ return
+ add_blood_DNA(blood_dna_info)
+
/obj/item/organ/wash(clean_types)
. = ..()
-
- // always add the original dna to the organ after it's washed
- if(!IS_ROBOTIC_ORGAN(src) && (clean_types & CLEAN_TYPE_BLOOD))
+ // ensure we keep the blood info even if someone scrubs the organ
+ if(LAZYLEN(blood_dna_info) && (clean_types & CLEAN_TYPE_BLOOD))
add_blood_DNA(blood_dna_info)
/obj/item/organ/process(seconds_per_tick, times_fired)
diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm
index 7d21d27f7370..23d290451692 100644
--- a/code/modules/surgery/organs/internal/heart/_heart.dm
+++ b/code/modules/surgery/organs/internal/heart/_heart.dm
@@ -14,7 +14,6 @@
zone = BODY_ZONE_CHEST
slot = ORGAN_SLOT_HEART
- item_flags = NO_BLOOD_ON_ITEM
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = 2.5 * STANDARD_ORGAN_DECAY //designed to fail around 6 minutes after death
diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm
index 62fbac434973..4ac86af09ea5 100644
--- a/code/modules/surgery/organs/organ_movement.dm
+++ b/code/modules/surgery/organs/organ_movement.dm
@@ -79,10 +79,7 @@
replaced.forceMove(get_turf(receiver))
if(!IS_ROBOTIC_ORGAN(src) && (organ_flags & ORGAN_VIRGIN))
- blood_dna_info = receiver.get_blood_dna_list()
- // need to remove the synethic blood DNA that is initialized
- // wash also adds the blood dna again
- wash(CLEAN_TYPE_BLOOD)
+ set_organ_blood(receiver)
organ_flags &= ~ORGAN_VIRGIN
if(external_bodytypes)
@@ -243,7 +240,6 @@
SHOULD_CALL_PARENT(TRUE)
if(!IS_ROBOTIC_ORGAN(src) && !(item_flags & NO_BLOOD_ON_ITEM) && !QDELING(src))
- add_blood_DNA(blood_dna_info)
AddElement(/datum/element/decal/blood)
item_flags &= ~ABSTRACT
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index f122dd3cf702..dd26f7dddb21 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -602,7 +602,7 @@
cell.maxcharge -= min(damage_energy_consumption, cell.maxcharge)
if((internal_damage & MECHA_INT_FUEL_LINE) && oil_pool >= 0.5 && isturf(loc) && SPT_PROB(round(oil_pool / 2, 0.1), seconds_per_tick))
- find_blood_type(oil_type)?.make_blood_splatter(loc, TRUE, list("[oil_name]" = oil_type))
+ find_blood_type(oil_type).make_blood_splatter(loc, TRUE, list("[oil_name]" = oil_type))
oil_pool -= 0.5
/obj/vehicle/sealed/mecha/proc/process_cabin_air(seconds_per_tick)
diff --git a/maplestation_modules/code/modules/client/preferences/species/synth.dm b/maplestation_modules/code/modules/client/preferences/species/synth.dm
index 7abfb5581d47..06152c33a063 100644
--- a/maplestation_modules/code/modules/client/preferences/species/synth.dm
+++ b/maplestation_modules/code/modules/client/preferences/species/synth.dm
@@ -65,13 +65,7 @@
return "As Disguise"
/datum/preference/choiced/synth_blood/apply_to_human(mob/living/carbon/human/target, value)
- var/datum/species/synth/synth = target.dna?.species
- if(!istype(synth))
- return
- if(value == "As Disguise" && synth.disguise_species)
- synth.exotic_bloodtype = synth.disguise_species.exotic_bloodtype
- else
- synth.exotic_bloodtype = /datum/blood_type/oil
+ return
/datum/preference/choiced/synth_blood/is_accessible(datum/preferences/preferences)
return ..() && ispath(preferences.read_preference(/datum/preference/choiced/species), /datum/species/synth)
diff --git a/maplestation_modules/code/modules/mob/living/blood.dm b/maplestation_modules/code/modules/mob/living/blood.dm
index cff19989b1ed..dfd8f2e85180 100644
--- a/maplestation_modules/code/modules/mob/living/blood.dm
+++ b/maplestation_modules/code/modules/mob/living/blood.dm
@@ -400,6 +400,16 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
/datum/blood_type/animal
name = "Y-"
+/// For the megafauna. Future todo, make it spawn the special blood decals.
+/datum/blood_type/animal/bubblegum
+ color = "#690000"
+
+/// For spiders and insects. Future todo, make it spawn the bug guts decal
+/datum/blood_type/animal/bug
+
+/// For blob monsters. Future todo, make it the color of the og blob
+/datum/blood_type/animal/blob
+
/// An abstract-ish blood type used particularly for species with blood set to random reagents, such as podpeople
/datum/blood_type/random_chemical
diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/animid/animid_bat.dm b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/animid/animid_bat.dm
index 93522b7609e3..37868660196a 100644
--- a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/animid/animid_bat.dm
+++ b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/animid/animid_bat.dm
@@ -16,7 +16,7 @@
icon = FA_ICON_DROPLET
/datum/animid_type/bat/pre_species_gain(datum/species/human/animid/species, mob/living/carbon/human/new_animid)
- species.exotic_bloodtype = /datum/blood_type/universal
+ species.exotic_bloodtype = /datum/blood_type/universal // set_blood_type has yet to be called so this is safe
/datum/animid_type/bat/get_extra_perks()
var/list/to_add = list()
diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/silverscale.dm b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/silverscale.dm
index 60d6604bf696..cce363e90528 100644
--- a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/silverscale.dm
+++ b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/silverscale.dm
@@ -75,7 +75,7 @@
update_glint()
he_who_was_blessed_with_silver.physiology?.damage_resistance += 10
- he_who_was_blessed_with_silver.dna.species.exotic_bloodtype = /datum/blood_type/silver/lizard
+ he_who_was_blessed_with_silver.set_blood_type(/datum/blood_type/silver/lizard, update = FALSE)
organ_owner.update_body(TRUE)
/obj/item/organ/tongue/lizard/silver/on_mob_remove(mob/living/carbon/organ_owner, special)
@@ -106,7 +106,7 @@
old_eye_color_right = null
he_who_has_been_outcast.physiology?.damage_resistance -= 10
- he_who_has_been_outcast.dna.species.exotic_bloodtype = initial(he_who_has_been_outcast.dna.species.exotic_bloodtype)
+ he_who_has_been_outcast.reset_blood_type(update = FALSE)
organ_owner.update_body(TRUE)
diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/synth/synth.dm b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/synth/synth.dm
index e33acb334c64..60150c139004 100644
--- a/maplestation_modules/code/modules/mob/living/carbon/human/species_types/synth/synth.dm
+++ b/maplestation_modules/code/modules/mob/living/carbon/human/species_types/synth/synth.dm
@@ -171,7 +171,7 @@
hair_color_mode = disguise_species.hair_color_mode
if(isnull(synth.client?.prefs) || synth.client.prefs.read_preference(/datum/preference/choiced/synth_blood) == "As Disguise")
- exotic_bloodtype = disguise_species.exotic_bloodtype
+ synth.set_blood_type(disguise_species.exotic_bloodtype || synth.dna.human_blood_type)
synth.add_traits(disguise_species.inherent_traits, "synth_disguise_[SPECIES_TRAIT]")
@@ -195,7 +195,7 @@
fixed_mut_color = initial(fixed_mut_color)
hair_color_mode = initial(hair_color_mode)
- exotic_bloodtype = /datum/blood_type/oil
+ synth.reset_blood_type(update = FALSE)
synth.remove_traits(disguise_species.inherent_traits, "synth_disguise_[SPECIES_TRAIT]")