Files
SmArtKar d841c9df40 [MDB IGNORE] Blood Refactor Chapter 2: Collector's Edition (#91054)
Refactors most of blood handling code untouched by #90593 and completely
rewrites all blood decals, components and reagents.

- Blood types now have behavioral flags which allow them to control
where they leave decals/DNA/viruses. Oil no longer transfers DNA and
viruses with it, while podpeople water-blood doesn't leave visible
decals on turfs and items, but still can be picked up by DNA scanners.
- Multiple blood types have received unique handling - liquid
electricity blood now glows in the dark, oil trails are flammable and
lube ones are slippery. Oil blood can be restored with fuel, lube with
silicon and slime with stable plasma (as normal plasma already passively
regenerates their blood), instead of everything using iron. Saline
solution only supplements on iron-based blood and won't do anything to
help with bloodloss for species who rely on different blood types.
(Roundstart this applies only to Ethereals)
- All blood logic has been moved away from the blood reagent itself into
a blood element that is assigned to the blood reagent by default, and to
any reagent that's drawn from a mob as their "blood" (in
``transfer_blood_to``). This means that blood you draw from lizards will
be green and have lizard's blood description instead of mentioning red
blood cells, Ethereal "blood" will actually contain their DNA and genes,
etc.
- Refactored all blood decals. Blood states are no more, everything is
now handled via blood DNA. Credits to MrMelbert and Maplestation, as a
significant amount of code has been taken from
https://github.com/MrMelbert/MapleStationCode/pull/436 and many of his
followup PRs. Oil and xenomorph splatters are now subtypes of blood,
blood drying is now animated, blood trails now curve and can be
diagonal.
- Rewrote bloodysoles and bloody_spreader components, credits to Melbert
again for the former, while latter now makes more sense with its
interactions. Bloody soles no longer share blood DNA with your hands.
- Ported Melbert's bloody footprint sprites and bot-blood-spreading
functionality.
- Removed all species-side reagent interactions, instead they're handled
by said species' livers. (This previously included exotic blood
handling, thus the removal)
- Slightly optimized human rendering by removing inbetween overlay
holders for clothing when they're not needed.
- Blood-transmitted diseases will now get added to many more decals than
before.
- Cleaned up and partially refactored replica pods, fixed an issue where
monkeys/manipulators were unable to harvest mindless pods.
- Exotic bloodtype on species now automatically assigns their blood
reagent, without the need to assign them separately.
- Clown mobs now bleed (with colorful reagent instead of blood during
april fools), and so do vatbeasts (lizard blood)
- Implemented generic procs for handling bleeding checks, all sorts of
scanners now also correctly call your blood for what it is.
- Podpeople's guts are now lime-green like their organs, instead of
being weirdly greyish like their water-blood. (Their bleeding overlays
are still grey, as they're bleeding water)
- Slimepeople now can bleed. Their jelly is pale purple in color, but
their wound overlays copy their body color.
- Injecting/spraying/splashing/etc mob with a reagent preserves its
data, so you could theoretically recycle fine wines from someone's
bloodstream
- Fixed burdened chaplain's sect never actually giving a blessing when
applying effects, and giving a blessing when nothing can be healed.
Inverted check strikes again.

- Closes #91039

A lot of blood here has dried, visually the blood colors are almost
exactly the same as before either of the blood refactors.

![dreamseeker_BSP7FE9pRB](https://github.com/user-attachments/assets/45711fa0-ae65-4ec2-9e89-753fa7dd876f)

![dreamseeker_zyv9ssh5VN](https://github.com/user-attachments/assets/7b112854-b7e3-4bfe-b78b-199a55b5b051)
2025-06-05 19:47:01 -04:00

108 lines
3.3 KiB
Plaintext

///Blood walk, a component that causes you to make blood wherever you walk.
/datum/component/blood_walk
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
///How many blood pools can we create?
///If we reach 0, we will stop leaving blood and self delete
var/blood_remaining = 0
///Typepath of what blood decal we create on walk
var/blood_type
///The sound that plays when we spread blood.
var/sound_played
///How loud will the sound be, if there is one.
var/sound_volume
///The chance of spawning blood whenever walking
var/blood_spawn_chance
///Should the decal face the direction of the parent
var/target_dir_change
///Should we transfer the parent's blood DNA to created blood decal
var/transfer_blood_dna
///List of additional blood DNA we're adding to the decal
var/list/blood_dna_info
/datum/component/blood_walk/Initialize(
blood_type = /obj/effect/decal/cleanable/blood,
sound_played,
sound_volume = 80,
blood_spawn_chance = 100,
target_dir_change = FALSE,
transfer_blood_dna = FALSE,
max_blood = INFINITY,
list/blood_dna_info = list("meaty DNA" = get_blood_type(BLOOD_TYPE_MEAT))
)
if(!ismovable(parent))
return COMPONENT_INCOMPATIBLE
src.blood_type = blood_type
src.sound_played = sound_played
src.sound_volume = sound_volume
src.blood_spawn_chance = blood_spawn_chance
src.target_dir_change = target_dir_change
src.transfer_blood_dna = transfer_blood_dna
src.blood_dna_info = blood_dna_info.Copy()
blood_remaining = max_blood
/datum/component/blood_walk/RegisterWithParent()
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(spread_blood))
/datum/component/blood_walk/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_MOVABLE_MOVED)
/datum/component/blood_walk/InheritComponent(
datum/component/pricetag/new_comp,
i_am_original,
blood_type = /obj/effect/decal/cleanable/blood,
sound_played,
sound_volume = 80,
blood_spawn_chance = 100,
target_dir_change = FALSE,
transfer_blood_dna = FALSE,
max_blood = INFINITY,
)
if(!i_am_original)
return
if(max_blood >= INFINITY || blood_remaining >= INFINITY)
return
// Applying a new version of the blood walk component will add the new version's step count to our's.
// We will completely disregard any other arguments passed, because we already have arguments set.
blood_remaining += max_blood
///Spawns blood (if possible) under the source, and plays a sound effect (if any)
/datum/component/blood_walk/proc/spread_blood(atom/movable/source)
SIGNAL_HANDLER
var/turf/current_turf = source.loc
if(!isturf(current_turf) || isclosedturf(current_turf) || isgroundlessturf(current_turf))
return
if(!prob(blood_spawn_chance))
return
var/list/blood_DNA = blood_dna_info.Copy()
if(transfer_blood_dna && GET_ATOM_BLOOD_DNA_LENGTH(source))
blood_DNA = GET_ATOM_BLOOD_DNA(source) | blood_DNA
if(!has_blood_flag(blood_DNA, BLOOD_COVER_TURFS))
if (has_blood_flag(blood_DNA, BLOOD_ADD_DNA))
current_turf.add_blood_DNA(blood_DNA)
return
var/obj/effect/decal/cleanable/blood/blood = new blood_type(current_turf, null, blood_DNA)
if(QDELETED(blood)) // Our blood was placed on somewhere it shouldn't be and qdeleted in init.
return
if(target_dir_change)
blood.setDir(source.dir)
if(!isnull(sound_played))
playsound(source, sound_played, sound_volume, TRUE, 2, TRUE)
blood_remaining = max(blood_remaining - 1, 0)
if(blood_remaining <= 0)
qdel(src)