Skip to content

Commit

Permalink
Optimizes blood drying effect (WIP port of MrMelbert/MapleStationCode…
Browse files Browse the repository at this point in the history
  • Loading branch information
Absolucy committed Nov 29, 2024
1 parent a13b5d6 commit e61e440
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 63 deletions.
4 changes: 4 additions & 0 deletions code/__DEFINES/gradient.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// spacemandmm doesn't really implement gradient() right, so let's just handle that here yeah?
#define rgb_gradient(index, args...) UNLINT(gradient(args, index))
#define hsl_gradient(index, args...) UNLINT(gradient(args, space = COLORSPACE_HSL, index))
#define hsv_gradient(index, args...) UNLINT(gradient(args, space = COLORSPACE_HSV, index))
11 changes: 0 additions & 11 deletions code/game/objects/effects/decals/cleanable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,8 @@
return FALSE

bloodiness = clamp((bloodiness + by_amount), 0, BLOOD_POOL_MAX)
update_appearance()
return TRUE

/// Called before attempting to scoop up reagents from this decal to only load reagents when necessary
/obj/effect/decal/cleanable/proc/lazy_init_reagents()
return

#ifdef TESTING
/obj/effect/decal/cleanable/update_overlays()
. = ..()
if(bloodiness)
var/mutable_appearance/blah_text = new()
blah_text.maptext = MAPTEXT_TINY_UNICODE("[bloodiness]")
blah_text.appearance_flags |= (KEEP_APART|RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM)
. += blah_text
#endif
106 changes: 63 additions & 43 deletions code/game/objects/effects/decals/cleanable/humans.dm
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,23 @@
/// How long it takes to dry out
var/drying_time = 5 MINUTES
/// The process to drying out, recorded in deciseconds
var/drying_progress = 0
/// Color matrix applied to dried blood via filter to make it look dried
var/static/list/blood_dry_filter_matrix = list(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
-0.5, -0.75, -0.75, 0,
)
VAR_FINAL/drying_progress = 0
/// For the actual animation, how long between steps?
/// This will determine how much it jumps when changing color or speed mid drying
var/step_period = 20 SECONDS
var/count = 0
var/footprint_sprite = null
var/glows = FALSE
var/handles_unique = FALSE

/obj/effect/decal/cleanable/blood/Initialize(mapload, blood_color = COLOR_BLOOD)
/obj/effect/decal/cleanable/blood/Initialize(mapload)
. = ..()
START_PROCESSING(SSblood_drying, src)
if(color && can_dry && !dried)
if(mapload)
add_blood_DNA(list("UNKNOWN DNA" = random_human_blood_type()))
if(dried)
dry()
else if(can_dry)
START_PROCESSING(SSblood_drying, src)
update_blood_drying_effect()

/obj/effect/decal/cleanable/blood/Destroy()
Expand All @@ -56,33 +55,58 @@
return
return ..()

#define DRY_FILTER_KEY "dry_effect"
/// Makes this decal undryable, then stops any ongoing drying
/// Does nothing if it's already undryable or dried
/obj/effect/decal/cleanable/blood/proc/make_undryable()
if(!can_dry || dried)
return
can_dry = FALSE
update_blood_drying_effect()

/obj/effect/decal/cleanable/blood/update_overlays()
. = ..()
if(glows && !handles_unique)
. += emissive_appearance(icon, icon_state, src)
/// Speeds up the drying time by a given amount,
/// then updates the effect, meaning the animation will speed up
/// Also forces drying if it progresses past the drying time
/obj/effect/decal/cleanable/blood/proc/speed_dry(by_amount)
drying_progress += by_amount
if(drying_progress >= drying_time)
dry()
return

update_blood_drying_effect()

/// Slows down the drying time by a given amount,
/// then updates the effect, meaning the animation will slow down
/obj/effect/decal/cleanable/blood/proc/slow_dry(by_amount)
drying_progress -= by_amount
update_blood_drying_effect()

// Modifiers to saturation and values of dried blood
#define BLOOD_SATURATION_MODIFIER (0.1 * 255)
#define BLOOD_VALUE_MODIFIER (0.4 * 255)

/// Updates the effect of blood drying
/obj/effect/decal/cleanable/blood/proc/update_blood_drying_effect()
animate(src)
if(!can_dry)
remove_filter(DRY_FILTER_KEY) // I GUESS
return

var/existing_filter = get_filter(DRY_FILTER_KEY)
if(dried)
if(existing_filter)
animate(existing_filter) // just stop existing animations and force it to the end state
return
add_filter(DRY_FILTER_KEY, 2, color_matrix_filter(blood_dry_filter_matrix))
return
var/starting_color = GET_ATOM_BLOOD_DNA_LENGTH(src) ? get_blood_dna_color() : COLOR_BLOOD
var/starting_color_hsv = ReadHSV(RGBtoHSV(starting_color))
var/dried_color = HSVtoRGB(hsv(
starting_color_hsv[1],
starting_color_hsv[2] - BLOOD_SATURATION_MODIFIER,
starting_color_hsv[3] - BLOOD_VALUE_MODIFIER,
))

if(existing_filter)
remove_filter(DRY_FILTER_KEY)
if(dried || drying_progress >= drying_time)
color = dried_color
return

add_filter(DRY_FILTER_KEY, 2, color_matrix_filter())
transition_filter(DRY_FILTER_KEY, color_matrix_filter(blood_dry_filter_matrix), drying_time - drying_progress)
color = hsv_gradient(round(drying_progress / drying_time, 0.01), 0, starting_color, 1, dried_color)
animate(src, time = drying_time - drying_progress, color = dried_color)

#undef DRY_FILTER_KEY
#undef BLOOD_SATURATION_MODIFIER
#undef BLOOD_VALUE_MODIFIER

/obj/effect/decal/cleanable/blood/proc/get_blood_string()
var/list/all_dna = GET_ATOM_BLOOD_DNA(src)
Expand All @@ -100,8 +124,11 @@
return PROCESS_KILL

adjust_bloodiness(-0.4 * BLOOD_PER_UNIT_MODIFIER * seconds_per_tick)
// does not use speed_dry because we're not actually speeding up, just keeping a running tally
// (we don't want to mess with the animation, it's already in sync - theoretically)
drying_progress += (seconds_per_tick * 1 SECONDS)
if(drying_progress >= drying_time + SSblood_drying.wait) // Do it next tick when we're done
// Do it next tick when we're done
if(drying_progress >= drying_time + SSblood_drying.wait)
dry()

/obj/effect/decal/cleanable/blood/update_name(updates)
Expand All @@ -123,7 +150,6 @@
dried = TRUE
reagents?.clear_reagents()
update_appearance()
update_blood_drying_effect()
STOP_PROCESSING(SSblood_drying, src)
return TRUE

Expand All @@ -147,17 +173,12 @@
. = ..()
merger.add_blood_DNA(GET_ATOM_BLOOD_DNA(src))
merger.adjust_bloodiness(bloodiness)
merger.drying_progress -= (bloodiness * BLOOD_PER_UNIT_MODIFIER) // goes negative = takes longer to dry
merger.update_blood_drying_effect()
merger.slow_dry(1 SECONDS * bloodiness * BLOOD_PER_UNIT_MODIFIER)

/obj/effect/decal/cleanable/blood/old
bloodiness = 0
icon_state = "floor1-old"

/obj/effect/decal/cleanable/blood/old/Initialize(mapload, list/datum/disease/diseases)
add_blood_DNA(list("UNKNOWN DNA" = random_human_blood_type()))
. = ..()
dry()
dried = TRUE
icon_state = "floor1-old" // just for mappers. overrided in init

/obj/effect/decal/cleanable/blood/splatter
icon_state = "gibbl1"
Expand Down Expand Up @@ -297,17 +318,16 @@
/obj/effect/decal/cleanable/blood/gibs/old
name = "old rotting gibs"
desc = "Space Jesus, why didn't anyone clean this up? They smell terrible."
icon_state = "gib1-old"
icon_state = "gib1-old" // just for mappers. overrided in init
bloodiness = 0
dried = TRUE
dry_prefix = ""
dry_desc = ""

/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases)
add_blood_DNA(list("UNKNOWN DNA" = random_human_blood_type()))
. = ..()
setDir(pick(GLOB.cardinals))
AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 10)
dry()

/obj/effect/decal/cleanable/blood/drip
name = "drips of blood"
Expand Down
14 changes: 5 additions & 9 deletions monkestation/code/modules/blood_datum/blood.dm
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,9 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
if(isnull(drop))
var/obj/effect/decal/cleanable/blood/splatter = locate() in blood_turf
if(!QDELETED(splatter))
splatter.adjust_bloodiness(new_blood)
splatter.drying_progress -= (new_blood * BLOOD_PER_UNIT_MODIFIER)
splatter.update_blood_drying_effect()
splatter.transfer_mob_blood_dna(bleeding)
splatter.adjust_bloodiness(new_blood)
splatter.speed_dry(1 SECONDS * new_blood * BLOOD_PER_UNIT_MODIFIER)
return splatter

drop = new(blood_turf, bleeding.get_static_viruses())
Expand Down Expand Up @@ -151,8 +150,7 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
return null
else
splatter.adjust_bloodiness(BLOOD_AMOUNT_PER_DECAL)
splatter.drying_progress -= (BLOOD_AMOUNT_PER_DECAL * BLOOD_PER_UNIT_MODIFIER)
splatter.update_blood_drying_effect()
splatter.speed_dry(1 SECONDS * BLOOD_AMOUNT_PER_DECAL * BLOOD_PER_UNIT_MODIFIER)
splatter.transfer_mob_blood_dna(bleeding) //give blood info to the blood decal.
if(temp_blood_DNA)
splatter.add_blood_DNA(temp_blood_DNA)
Expand Down Expand Up @@ -251,8 +249,7 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
blood.update_appearance()
if(!new_splat)
return
blood.can_dry = FALSE
blood.update_blood_drying_effect()
blood.make_undryable()
RegisterSignals(blood, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACKBY_SECONDARY), PROC_REF(on_cleaned))

/datum/blood_type/crew/ethereal/proc/on_cleaned(obj/effect/decal/cleanable/source, mob/living/user, obj/item/tool, ...)
Expand Down Expand Up @@ -284,8 +281,7 @@ PROCESSING_SUBSYSTEM_DEF(blood_drying)
if(!new_splat)
return
// Oil blood will never dry and can be ignited with fire
blood.can_dry = FALSE
blood.update_blood_drying_effect()
blood.make_undryable()
blood.AddElement(/datum/element/easy_ignite)

/// A universal blood type which accepts everything
Expand Down
3 changes: 3 additions & 0 deletions monkestation/code/modules/blood_datum/forensics_helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
var/first_dna = GET_ATOM_BLOOD_DNA_LENGTH(src)
if(!..())
return FALSE
if(dried)
return TRUE

color = get_blood_dna_color()
// Imperfect, ends up with some blood types being double-set-up, but harmless (for now)
Expand All @@ -36,4 +38,5 @@
continue
blood.set_up_blood(src, first_dna == 0)
update_appearance()
update_blood_drying_effect()
return TRUE
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
#include "code\__DEFINES\fov.dm"
#include "code\__DEFINES\generators.dm"
#include "code\__DEFINES\ghost.dm"
#include "code\__DEFINES\gradient.dm"
#include "code\__DEFINES\gravity.dm"
#include "code\__DEFINES\guardian_defines.dm"
#include "code\__DEFINES\holiday.dm"
Expand Down

0 comments on commit e61e440

Please sign in to comment.