Skip to content

Commit

Permalink
fix(atoms): reworks bloody overlays
Browse files Browse the repository at this point in the history
12-yeard-old code bad
PR #11113
  • Loading branch information
TobyThorne authored Nov 30, 2023
1 parent da512e0 commit 507073b
Show file tree
Hide file tree
Showing 18 changed files with 185 additions and 156 deletions.
3 changes: 1 addition & 2 deletions code/datums/outfits/horror_killers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@

/decl/hierarchy/outfit/masked_killer/post_equip(mob/living/carbon/human/H)
..()
var/victim = get_mannequin(H.ckey)
for(var/obj/item/carried_item in H.get_equipped_items(TRUE))
carried_item.add_blood(victim) //Oh yes, there will be blood.. just not blood from the killer because that's odd
carried_item.add_blood() //Oh yes, there will be blood.. just not blood from the killer because that's odd

/decl/hierarchy/outfit/reaper
name = "Reaper"
Expand Down
41 changes: 25 additions & 16 deletions code/game/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var/atom_flags
var/effect_flags
var/list/blood_DNA
var/is_bloodied
var/was_bloodied
var/blood_color
var/last_bumped = 0
Expand Down Expand Up @@ -296,7 +297,7 @@ its easier to just keep the beam vertical.
/atom/proc/_examine_text(mob/user, infix = "", suffix = "")
// This reformat names to get a/an properly working on item descriptions when they are bloody
var/f_name = "\a [SPAN("info", "<em>[src][infix]</em>")]."
if(src.blood_DNA && !istype(src, /obj/effect/decal))
if(is_bloodied && !istype(src, /obj/effect/decal))
if(gender == PLURAL)
f_name = "some "
else
Expand Down Expand Up @@ -393,24 +394,30 @@ its easier to just keep the beam vertical.
playsound(src, hitby_sound, sound_loudness, 1)


//returns 1 if made bloody, returns 0 otherwise
/atom/proc/add_blood(mob/living/carbon/human/M as mob)
// returns TRUE if made bloody, returns FALSE otherwise
// accepts either a human or a hex color
/atom/proc/add_blood(source)
if(atom_flags & ATOM_FLAG_NO_BLOOD)
return 0
return FALSE

if(!blood_DNA || !istype(blood_DNA, /list)) //if our list of DNA doesn't exist yet (or isn't a list) initialise it.
if(!islist(blood_DNA)) // if our list of DNA doesn't exist yet (or isn't a list) initialise it.
blood_DNA = list()

was_bloodied = 1
blood_color = COLOR_BLOOD_HUMAN
if(istype(M))
if (!istype(M.dna, /datum/dna))
is_bloodied = TRUE
was_bloodied = TRUE

if(ishuman(source))
var/mob/living/carbon/human/M = source
if(!istype(M.dna, /datum/dna))
M.dna = new /datum/dna(null)
M.dna.real_name = M.real_name
M.check_dna()
blood_color = M.species.get_blood_colour(M)
. = 1
return 1
else if(istext(source))
blood_color = source
else
blood_color = COLOR_BLOOD_HUMAN
return TRUE

/atom/proc/add_vomit_floor(mob/living/carbon/M, toxvomit = 0, datum/reagents/inject_reagents)
if(istype(src, /turf/simulated))
Expand All @@ -424,12 +431,14 @@ its easier to just keep the beam vertical.

/atom/proc/clean_blood()
if(!simulated)
return
return FALSE
is_bloodied = FALSE
fluorescent = 0
src.germ_level = 0
if(istype(blood_DNA, /list))
blood_DNA = null
return 1
germ_level = 0
if(islist(blood_DNA))
blood_DNA.Cut()
blood_color = null
return TRUE

/atom/proc/get_global_map_pos()
if(!islist(GLOB.global_map) || isemptylist(GLOB.global_map)) return
Expand Down
50 changes: 19 additions & 31 deletions code/game/objects/effects/decals/Cleanable/humans.dm
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var/global/list/image/splatter_cache=list()
if(invisibility != 100)
set_invisibility(100)
amount = 0
..(ignore = 1)
..(ignore = TRUE)

/obj/effect/decal/cleanable/blood/hide()
return
Expand Down Expand Up @@ -73,32 +73,22 @@ var/global/list/image/splatter_cache=list()

var/obj/item/organ/external/l_foot = perp.get_organ(BP_L_FOOT)
var/obj/item/organ/external/r_foot = perp.get_organ(BP_R_FOOT)
var/hasfeet = 1
var/hasfeet = TRUE
if((!l_foot || l_foot.is_stump()) && (!r_foot || r_foot.is_stump()))
hasfeet = 0
hasfeet = FALSE
if(perp.shoes && !perp.buckled)//Adding blood to shoes
var/obj/item/clothing/shoes/S = perp.shoes
if(istype(S))
S.blood_color = basecolor
S.track_blood = max(amount,S.track_blood)
if(!S.blood_overlay)
S.generate_blood_overlay()
if(!S.blood_DNA)
S.blood_DNA = list()
S.blood_overlay.color = basecolor
S.AddOverlays(S.blood_overlay)
if(S.blood_overlay && S.blood_overlay.color != basecolor)
S.blood_overlay.color = basecolor
S.ClearOverlays()
S.AddOverlays(S.blood_overlay)
S.blood_DNA |= blood_DNA.Copy()

else if (hasfeet)//Or feet
S.add_blood(basecolor, amount)
S.blood_DNA |= blood_DNA

else if(hasfeet)//Or feet
perp.feet_blood_color = basecolor
perp.track_blood = max(amount,perp.track_blood)
if(!perp.feet_blood_DNA)
perp.feet_blood_DNA = list()
perp.feet_blood_DNA |= blood_DNA.Copy()

else if (perp.buckled && istype(perp.buckled, /obj/structure/bed/chair/wheelchair))
var/obj/structure/bed/chair/wheelchair/W = perp.buckled
W.bloodiness = 4
Expand All @@ -115,19 +105,17 @@ var/global/list/image/splatter_cache=list()

/obj/effect/decal/cleanable/blood/attack_hand(mob/living/carbon/human/user)
..()
if(amount && istype(user))
if(user.gloves)
return
var/taken = rand(1, amount)
amount -= taken
to_chat(user, "<span class='notice'>You get some of \the [src] on your hands.</span>")
if(!user.blood_DNA)
user.blood_DNA = list()
user.blood_DNA |= blood_DNA.Copy()
user.bloody_hands = taken
user.hand_blood_color = basecolor
user.update_inv_gloves(1)
user.verbs += /mob/living/carbon/human/proc/bloody_doodle

if(!amount || !istype(user) || !user.gloves)
return

var/taken = rand(1, amount)
amount -= taken
to_chat(user, SPAN("notice", "You get some of \the [src] on your hands."))
user.add_blood(basecolor)
user.blood_DNA |= blood_DNA.Copy()
user.bloody_hands = taken
user.verbs += /mob/living/carbon/human/proc/bloody_doodle

/obj/effect/decal/cleanable/blood/splatter
random_icon_states = list("mfloor3", "mfloor7", "mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/effects/decals/cleanable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
if(!ignore)
qdel(src)
return
..()
. = ..()

/obj/effect/decal/cleanable/Initialize()
if (random_icon_states && length(src.random_icon_states) > 0)
Expand Down
62 changes: 36 additions & 26 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -697,11 +697,10 @@ var/list/global/slot_flags_enumeration = list(

/obj/item/clean_blood()
. = ..()
if(!.)
return
if(blood_overlay)
CutOverlays(blood_overlay)
if(istype(src, /obj/item/clothing/gloves))
var/obj/item/clothing/gloves/G = src
G.transfer_blood = 0
CutOverlays(blood_overlay, ATOM_ICON_CACHE_PROTECTED)

/obj/item/reveal_blood()
if(was_bloodied && !fluorescent)
Expand All @@ -710,42 +709,53 @@ var/list/global/slot_flags_enumeration = list(
blood_overlay.color = COLOR_LUMINOL
update_icon()

/obj/item/add_blood(mob/living/carbon/human/M)
if (!..())
return 0

if(istype(src, /obj/item/melee/energy))
/obj/item/add_blood(source)
var/bloodied_check = is_bloodied
var/old_blood_color = blood_color
. = ..()
if(!.)
return

//if we haven't made our blood_overlay already
if( !blood_overlay )
// if we haven't made our blood_overlay already
if(!blood_overlay)
generate_blood_overlay()

//apply the blood-splatter overlay if it isn't already in there
if(!blood_DNA.len)
blood_overlay.color = blood_color
AddOverlays(blood_overlay)
// apply the blood-splatter overlay if it wasn't there
if(!bloodied_check)
AddOverlays(blood_overlay, ATOM_ICON_CACHE_PROTECTED)
else if(blood_color != old_blood_color)
update_blood_overlay()

//if this blood isn't already in the list, add it
if(istype(M))
if(blood_DNA[M.dna.unique_enzymes])
return 0 //already bloodied with this blood. Cannot add more.
blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
return 1 //we applied blood to the item
// if this blood isn't already in the list, add it
if(ishuman(source))
var/mob/living/carbon/human/M = source
if(!blood_DNA[M.dna.unique_enzymes])
blood_DNA[M.dna.unique_enzymes] = M.dna.b_type

GLOBAL_LIST_EMPTY(blood_overlay_cache)

/obj/item/proc/generate_blood_overlay(force = FALSE)
if(blood_overlay && !force)
return
if(GLOB.blood_overlay_cache["[icon]" + icon_state])
blood_overlay = GLOB.blood_overlay_cache["[icon]" + icon_state]
if(GLOB.blood_overlay_cache["[icon]/[icon_state]/[blood_color]"])
blood_overlay = GLOB.blood_overlay_cache["[icon]/[icon_state]/[blood_color]"]
return
var/image/blood = image(icon = 'icons/effects/blood.dmi', icon_state = "itemblood")
var/image/blood = overlay_image('icons/effects/blood.dmi', "itemblood", color = blood_color, flags = DEFAULT_APPEARANCE_FLAGS|RESET_COLOR)
blood.filters += filter(type = "alpha", icon = icon(icon, icon_state))
GLOB.blood_overlay_cache["[icon]" + icon_state] = blood
GLOB.blood_overlay_cache["[icon]/[icon_state]/[blood_color]"] = blood
blood_overlay = blood

// Regenerates the bloodiness, to be used when the item's icon_state get changed to something of another shape.
/obj/item/proc/update_blood_overlay()
if(!blood_overlay)
return // nah
if(is_bloodied)
CutOverlays(blood_overlay, ATOM_ICON_CACHE_PROTECTED)
generate_blood_overlay(TRUE) // Force recheck.
AddOverlays(blood_overlay, ATOM_ICON_CACHE_PROTECTED)
else
generate_blood_overlay(TRUE) // Just updating it, no need in actual overlaying.

/obj/item/proc/showoff(mob/user)
for (var/mob/M in view(user))
M.show_message("[user] holds up [src]. <a HREF=?src=\ref[M];lookitem=\ref[src]>Take a closer look.</a>",1)
Expand Down Expand Up @@ -921,7 +931,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
return ret_overlay

/obj/item/proc/get_examine_line()
if(blood_DNA)
if(is_bloodied)
. = SPAN("warning", "\icon[src] [gender==PLURAL?"some":"a"] [(blood_color != SYNTH_BLOOD_COLOUR) ? "blood" : "oil"]-stained [SPAN("info", "<em>[src]</em>")]")
else
. = "\icon[src] \a [SPAN("info", "<em>[src]</em>")]"
Expand Down
5 changes: 1 addition & 4 deletions code/game/objects/items/melee/telescopic_baton.dm
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@
else
icon_state = "telebaton_0"
item_state = "telebaton_0"
if(length(blood_DNA))
generate_blood_overlay(TRUE) // Force recheck.
ClearOverlays()
AddOverlays(blood_overlay)
update_blood_overlay()

/obj/item/melee/telebaton/attack(mob/target as mob, mob/living/user as mob)
if(on)
Expand Down
4 changes: 4 additions & 0 deletions code/game/objects/items/stacks/stack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@
S.add(transfer)
if (prob(transfer/orig_amount * 100))
transfer_fingerprints_to(S)
if(is_bloodied)
S.add_blood(blood_color)
if(blood_DNA)
S.blood_DNA |= blood_DNA
return transfer
Expand All @@ -311,6 +313,8 @@
newstack.color = color
if (prob(transfer/orig_amount * 100))
transfer_fingerprints_to(newstack)
if(is_bloodied)
newstack.add_blood(blood_color)
if(blood_DNA)
newstack.blood_DNA |= blood_DNA
return newstack
Expand Down
45 changes: 24 additions & 21 deletions code/game/turfs/simulated.dm
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
/turf/simulated/clean_blood()
for(var/obj/effect/decal/cleanable/blood/B in contents)
B.clean_blood()
..()
return ..()

/turf/simulated/New()
..()
Expand Down Expand Up @@ -102,13 +102,15 @@
var/obj/item/clothing/shoes/S = H.shoes
if(istype(S))
S.handle_movement(src,(H.m_intent == M_RUN ? 1 : 0))
if(S.track_blood && S.blood_DNA)
bloodDNA = S.blood_DNA
bloodcolor=S.blood_color
if(S.track_blood)
if(S.blood_DNA)
bloodDNA = S.blood_DNA
bloodcolor = S.blood_color
S.track_blood--
else
if(H.track_blood && H.feet_blood_DNA)
bloodDNA = H.feet_blood_DNA
if(H.track_blood)
if(H.feet_blood_DNA)
bloodDNA = H.feet_blood_DNA
bloodcolor = H.feet_blood_color
H.track_blood--

Expand Down Expand Up @@ -146,21 +148,22 @@
..()

//returns 1 if made bloody, returns 0 otherwise
/turf/simulated/add_blood(mob/living/carbon/human/M as mob)
if (!..())
return 0

if(istype(M))
for(var/obj/effect/decal/cleanable/blood/B in contents)
if(!B.blood_DNA)
B.blood_DNA = list()
if(!B.blood_DNA[M.dna.unique_enzymes])
B.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
B.virus2 = virus_copylist(M.virus2)
return 1 //we bloodied the floor
blood_splatter(src,M.get_blood(M.vessel),1)
return 1 //we bloodied the floor
return 0
/turf/simulated/add_blood(source)
if(!ishuman(source))
return FALSE // Meh, fuck it, if you'll ever need the add_blood("#abcdef") behavior - just go ahead code it yourself. ~ToTh
. = ..()
if(!.)
return

var/mob/living/carbon/human/M = source
for(var/obj/effect/decal/cleanable/blood/B in contents)
if(!B.blood_DNA)
B.blood_DNA = list()
if(!B.blood_DNA[M.dna.unique_enzymes])
B.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
B.virus2 = virus_copylist(M.virus2)
return
blood_splatter(src, M.get_blood(M.vessel), 1)

// Only adds blood on the floor -- Skie
/turf/simulated/proc/add_blood_floor(mob/living/carbon/M as mob)
Expand Down
Loading

0 comments on commit 507073b

Please sign in to comment.