Lambo Bloody Item Overlays (#36395)

* bloody item overlays use mutable appearances instead of icon cache

* lazylists
This commit is contained in:
13spacemen
2024-05-04 08:04:48 +05:00
committed by GitHub
parent 4101bfeb4f
commit 300cf616f5
25 changed files with 71 additions and 152 deletions

8
__DEFINES/flags.dm Normal file
View File

@@ -0,0 +1,8 @@
//setter for KEEP_TOGETHER to allow for multiple sources to set and unset it
#define ADD_KEEP_TOGETHER(x, source)\
LAZYADD(x.keep_together_sources, source);\
x.update_keep_together()
#define REMOVE_KEEP_TOGETHER(x, source)\
LAZYREMOVE(x.keep_together_sources, source);\
x.update_keep_together()

View File

@@ -10,6 +10,15 @@
* Misc
*/
///Initialize the lazylist
#define LAZYINITLIST(L) if (!L) { L = list(); }
///If the provided list is empty, set it to null
#define UNSETEMPTY(L) if (L && !length(L)) L = null
///Remove an item from the list, set the list to null if empty
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } }
///Add an item to the list, if the list is null it will initialize it
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
//Returns a list in plain english as a string
/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
var/total = input.len

View File

@@ -1979,7 +1979,7 @@ var/list/arcane_tomes = list()
i = 2
else i = 3
icon_state = "bloodcandle[i]"
update_blood_overlay()
set_blood_overlay()
if (lit)
var/image/I = image(icon,src,"[icon_state]_lit")
I.blend_mode = BLEND_ADD

View File

@@ -44,7 +44,8 @@ var/global/list/ghdel_profiling = list()
var/timestopped
appearance_flags = TILE_BOUND|LONG_GLIDE|TILE_MOVER
/// sources of setting KEEP_TOGETHER on an atom
var/list/keep_together_sources
var/slowdown_modifier //modified on how fast a person can move over the tile we are on, see turf.dm for more info
/// Last name used to calculate a color for the chatmessage overlays
var/chat_color_name
@@ -966,6 +967,11 @@ its easier to just keep the beam vertical.
/atom/proc/thermal_energy_transfer()
return
/atom/proc/update_keep_together()
appearance_flags &= ~KEEP_TOGETHER
if(length(keep_together_sources))
appearance_flags |= KEEP_TOGETHER
/atom/proc/suitable_colony()
return FALSE

View File

@@ -136,14 +136,7 @@
/obj/item/transfer_obj_blood_data(obj/item/A, obj/item/B)
..()
if(!blood_overlays[B.type]) //If there isn't a precreated blood overlay make one
B.set_blood_overlay()
if(B.blood_overlay != null) // Just if(blood_overlay) doesn't work. Have to use isnull here.
B.overlays.Remove(B.blood_overlay)
else
B.blood_overlay = blood_overlays["[B.type][B.icon_state]"]
B.blood_overlay.color = B.blood_color
B.overlays += B.blood_overlay
B.set_blood_overlay()
/obj/proc/generate_break_text(glanced = FALSE, suppress_glance_text) //Generates text for when an object is hit.
if(glanced)

View File

@@ -1258,31 +1258,19 @@ var/global/objects_thrown_when_explode = FALSE
/obj/item/clean_blood()
. = ..()
remove_disease2()
if (blood_overlay)
overlays.Remove(blood_overlay)
if (had_blood)
REMOVE_KEEP_TOGETHER(src, "bloody_item")
if(blood_overlay)
overlays -= blood_overlay
if(had_blood)
clear_luminol()
if (istype(src, /obj/item/clothing/gloves))
if(istype(src, /obj/item/clothing/gloves))
var/obj/item/clothing/gloves/G = src
G.transfer_blood = 0
/obj/item/add_blood(var/mob/living/carbon/human/M)
if (!..())
return FALSE
//if we haven't made our blood_overlay already
if(!blood_overlays["[type][icon_state]"])
set_blood_overlay()
if(!blood_overlay)
blood_overlay = blood_overlays["[type][icon_state]"]
else
overlays.Remove(blood_overlay)
//apply the blood-splatter overlay if it isn't already in there, else it updates it.
blood_overlay.color = blood_color
overlays += blood_overlay
set_blood_overlay()
//if this blood isn't already in the list, add it
if(!M)
return
@@ -1307,19 +1295,7 @@ var/global/objects_thrown_when_explode = FALSE
/obj/item/add_blood_from_data(var/list/blood_data)
if (!..())
return FALSE
//if we haven't made our blood_overlay already
if(!blood_overlays["[type][icon_state]"])
set_blood_overlay()
if(!blood_overlay)
blood_overlay = blood_overlays["[type][icon_state]"]
else
overlays.Remove(blood_overlay)
//apply the blood-splatter overlay if it isn't already in there, else it updates it.
blood_overlay.color = blood_color
overlays += blood_overlay
set_blood_overlay()
//if this blood isn't already in the list, add it
if(!blood_data)
return
@@ -1347,50 +1323,20 @@ var/global/objects_thrown_when_explode = FALSE
blood_color = other_item.blood_color
blood_DNA = other_item.blood_DNA.Copy()
had_blood = TRUE
if(!blood_overlays["[type][icon_state]"])
set_blood_overlay()
if(!blood_overlay)
blood_overlay = blood_overlays["[type][icon_state]"]
else
overlays.Remove(blood_overlay)
blood_overlay.color = blood_color
overlays += blood_overlay
set_blood_overlay()
var/global/list/image/blood_overlays = list()
/obj/item/proc/set_blood_overlay() /* If your item needs to update its blood overlay when its icon_state changes, use this one. update_blood_overlay() is simply a helper proc for this one. */
if(update_blood_overlay())
return
var/icon/I = new /icon(icon, icon_state)
I.Blend(rgb(255,255,255),ICON_ADD) //fills the icon_state with white (except where it's transparent)
I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
var/image/img = image(I)
img.name = "blood_overlay"
img.appearance_flags = RESET_COLOR|RESET_ALPHA
blood_overlays["[type][icon_state]"] = img
update_blood_overlay()
/obj/item/proc/update_blood_overlay() /* See comment on set_blood_overlay() - this shouldn't be used outside of that proc! */
if(blood_overlays["[type][icon_state]"] && blood_overlay)
overlays -= blood_overlay
blood_overlay = blood_overlays["[type][icon_state]"]
blood_overlay.color = blood_color
overlays += blood_overlay
return 1
/obj/item/proc/set_blood_overlay(passed_color = blood_color)
overlays -= blood_overlay
var/mutable_appearance/item_blood_overlay = mutable_appearance('icons/effects/blood.dmi', "itemblood", appearance_flags = RESET_COLOR|RESET_ALPHA)
ADD_KEEP_TOGETHER(src, "bloody_item")
item_blood_overlay.blend_mode = BLEND_INSET_OVERLAY
item_blood_overlay.color = passed_color
overlays += blood_overlay = item_blood_overlay
/obj/item/apply_luminol()
if(!..())
return FALSE
if(!blood_overlays["[type][icon_state]"]) //Blood overlay generation if it lacks one.
set_blood_overlay()
if(blood_overlay)
overlays.Remove(blood_overlay)
else
blood_overlay = blood_overlays["[type][icon_state]"]
var/image/luminol_overlay = blood_overlay
luminol_overlay.color = LIGHT_COLOR_CYAN
overlays += luminol_overlay
set_blood_overlay(LIGHT_COLOR_CYAN)
var/obj/effect/decal/cleanable/blueglow/BG
if(istype(had_blood,/obj/effect/decal/cleanable/blueglow))
BG = had_blood

View File

@@ -60,7 +60,7 @@
icon_state = "candle[i]"
wick.icon_state = "[icon_state]-wick"
overlays += wick
update_blood_overlay()
set_blood_overlay()
if (lit)
var/image/I = image(icon,src,"[icon_state]_lit")
I.appearance_flags = RESET_COLOR

View File

@@ -212,15 +212,8 @@
return
if(H.shoes)
var/obj/item/clothing/shoes/S = H.shoes
if(!blood_overlays[S.type]) //If there isn't a precreated blood overlay make one
S.set_blood_overlay()
if(S.blood_overlay != null) // Just if(blood_overlay) doesn't work. Have to use isnull here.
S.overlays.Remove(S.blood_overlay)
else
S.blood_overlay = blood_overlays["[S.type][S.icon_state]"]
S.blood_overlay.color = "#FFB2C4"
S.overlays += S.blood_overlay
S.blood_color = "#FFB2C4"
S.set_blood_overlay()
H.update_inv_shoes(1)
else
H.feet_blood_color = "#FFB2C4"

View File

@@ -83,7 +83,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM
overlays.len = 0
dynamic_overlay["[HAND_LAYER]-[GRASP_LEFT_HAND]"] = null
dynamic_overlay["[HAND_LAYER]-[GRASP_RIGHT_HAND]"] = null
update_blood_overlay()
set_blood_overlay()
switch(lit)
if(1)
@@ -260,7 +260,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM
dynamic_overlay["[FACEMASK_LAYER]"] = null
dynamic_overlay["[HAND_LAYER]-[GRASP_LEFT_HAND]"] = null
dynamic_overlay["[HAND_LAYER]-[GRASP_RIGHT_HAND]"] = null
update_blood_overlay()
set_blood_overlay()
switch(lit)
if(1)
@@ -958,7 +958,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM
overlays.len = 0
dynamic_overlay["[HAND_LAYER]-[GRASP_LEFT_HAND]"] = null
dynamic_overlay["[HAND_LAYER]-[GRASP_RIGHT_HAND]"] = null
update_blood_overlay()
set_blood_overlay()
switch(lit)
if(1)

View File

@@ -83,12 +83,7 @@
steam_spawn_adjust(average_chem_temp)
/obj/item/weapon/reagent_containers/pan/update_icon()
overlays.len = 0
if(blood_overlay)
overlays += blood_overlay
//reagents:
if(reagents.total_volume)
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "pan20")
@@ -126,17 +121,6 @@
//put a front over the ingredients where they're occluded from view by the side of the pan
var/image/pan_front = image('icons/obj/pan.dmi', src, "pan_front")
overlays += pan_front
//put blood back onto the pan front
if(blood_overlay)
var/icon/I = new /icon('icons/obj/pan.dmi', "pan_front")
I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) //fills the icon_state with white (except where it's transparent)
I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
var/image/frontblood = image(I)
frontblood.color = blood_color
overlays += frontblood
update_temperature_overlays()
else
remove_particles(PS_STEAM)
@@ -144,6 +128,7 @@
//Note: an alternative to the above might be to overlay all of the non-reagent ingredients onto a single icon, then mask it with the "pan_mask" icon_state.
//This would obviate the need to regenerate the blood overlay, and help avoid anomalies with large ingredient sprites.
//However I'm not totally sure how to do this nicely.
set_blood_overlay()
/////////////////////Dumping-and-splashing-related stuff/////////////////////

View File

@@ -162,7 +162,7 @@
I.pixel_x = (i%5)*3
overlays += I
overlays += "[icon_state]_cover"
update_blood_overlay()
set_blood_overlay()
//dynamic in-hands
var/inhand_candles = 0

View File

@@ -200,7 +200,7 @@ LINEN BINS
var/image/I = image(icon, src, "sheet-overlay")
I.appearance_flags = RESET_COLOR
overlays += I
update_blood_overlay()
set_blood_overlay()
user.update_inv_hands()
return TRUE
@@ -219,7 +219,7 @@ LINEN BINS
if (icon_state in plaid_sheet_colors)
icon_state = "plaid[icon_state]"
overlays.len = 0
update_blood_overlay()
set_blood_overlay()
return PLAIDPATTERN_TO_PLAID
else if (copytext(icon_state, 1, 6) == "plaid")
icon_state = copytext(icon_state, 6)

View File

@@ -303,23 +303,13 @@
for (var/obj/abstract/paint_light/PL in paintlights)
if (PL.light_color == wet_color)
S.luminous_paint = TRUE
if(!blood_overlays["[S.type][S.icon_state]"])
S.set_blood_overlay()
if(S.blood_overlay != null)
S.overlays.Remove(S.blood_overlay)
else
S.blood_overlay = blood_overlays["[S.type][S.icon_state]"]
if(!S.blood_DNA)
S.blood_DNA = list()
S.blood_DNA |= blood_DNA.Copy()
var/newcolor = (S.blood_color && S.blood_DNA.len) ? BlendRYB(S.blood_color, wet_color, 0.5) : wet_color
S.blood_overlay.color = newcolor
S.overlays += S.blood_overlay
S.blood_color = newcolor
S.set_blood_overlay()
H.update_inv_shoes(1)
else

View File

@@ -154,7 +154,7 @@
dynamic_overlay["[HAND_LAYER]-[GRASP_RIGHT_HAND]"] = clothright
else
dynamic_overlay = list()
update_blood_overlay()
set_blood_overlay()
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()

View File

@@ -741,7 +741,7 @@
overlays.len = 0//no choice here but to redraw everything in the correct order so filling doesn't appear over ice, blood and fire.
overlays += filling
update_temperature_overlays()
update_blood_overlay()//re-applying blood stains
set_blood_overlay()//re-applying blood stains
if (on_fire && fire_overlay)
overlays += fire_overlay

View File

@@ -1014,23 +1014,11 @@
var/obj/item/clothing/shoes/S = shoes
S.track_blood = max(0, _amount, S.track_blood) //Adding blood to shoes
S.luminous_paint = luminous
if(!blood_overlays["[S.type][S.icon_state]"]) //If there isn't a precreated blood overlay make one
S.set_blood_overlay()
if(S.blood_overlay != null) // Just if(blood_overlay) doesn't work. Have to use isnull here.
S.overlays.Remove(S.blood_overlay)
else
S.blood_overlay = blood_overlays["[S.type][S.icon_state]"]
if(!S.blood_DNA)
S.blood_DNA = list()
var/newcolor = (S.blood_color && S.blood_DNA.len) ? BlendRYB(S.blood_color, _color, 0.5) : _color
S.blood_overlay.color = newcolor
S.overlays += S.blood_overlay
S.blood_color = newcolor
S.set_blood_overlay()
if(_blood_DNA)
S.blood_DNA |= _blood_DNA.Copy()
update_inv_shoes(1)

View File

@@ -57,7 +57,7 @@
dynamic_overlay["[HAND_LAYER]-[GRASP_RIGHT_HAND]"] = paintright
else
dynamic_overlay = list()
update_blood_overlay()
set_blood_overlay()
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
@@ -319,7 +319,7 @@
dynamic_overlay["[HAND_LAYER]-[GRASP_RIGHT_HAND]"] = paintright
else
dynamic_overlay = list()
update_blood_overlay()
set_blood_overlay()
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
@@ -521,7 +521,7 @@
dynamic_overlay["[HAND_LAYER]-[GRASP_LEFT_HAND]"] = rollerhandleft
dynamic_overlay["[HAND_LAYER]-[GRASP_RIGHT_HAND]"] = rollerhandright
update_blood_overlay()
set_blood_overlay()
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()

View File

@@ -25,7 +25,7 @@
..()
overlays.len = 0
update_temperature_overlays()
update_blood_overlay()//re-applying blood stains
set_blood_overlay()//re-applying blood stains
if (on_fire && fire_overlay)
overlays += fire_overlay

View File

@@ -345,7 +345,7 @@
overlays.len = 0//no choice here but to redraw everything in the correct order so condiments etc don't appear over ice and fire.
overlays += extra_condiment_overlay
update_temperature_overlays()
update_blood_overlay()//re-applying blood stains
set_blood_overlay()//re-applying blood stains
if (on_fire && fire_overlay)
overlays += fire_overlay

View File

@@ -869,7 +869,7 @@
..()
if (flags & OPENCONTAINER)
overlays += image(icon = icon, icon_state = "soda_open")
update_blood_overlay()
set_blood_overlay()
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/attack_self(var/mob/user)
if(!is_open_container())
@@ -1013,7 +1013,7 @@
overlays.len = 0
if (!(flags & OPENCONTAINER))
overlays += image(icon = icon, icon_state = "bottle_cap")
update_blood_overlay()
set_blood_overlay()
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/quantum
name = "Nuka Cola Quantum"
@@ -1043,7 +1043,7 @@
overlays.len = 0
if (!(flags & OPENCONTAINER))
overlays += image(icon = icon, icon_state = "bottle_cap")
update_blood_overlay()
set_blood_overlay()
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/sportdrink
name = "Brawndo"
@@ -1661,7 +1661,7 @@
..()
if (reagents.reagent_list.len > 0)
mug_reagent_overlay()
update_blood_overlay()
set_blood_overlay()
/obj/item/weapon/reagent_containers/food/drinks/flagmug/britcup
name = "\improper cup"

View File

@@ -91,7 +91,7 @@
M.update_inv_hands()
update_temperature_overlays()
update_blood_overlay()
set_blood_overlay()
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/attack_self(mob/user)
if(switching)

View File

@@ -284,7 +284,7 @@
overlays += I
update_temperature_overlays()
update_blood_overlay()//re-applying blood stains
set_blood_overlay()//re-applying blood stains
if (on_fire && fire_overlay)
overlays += fire_overlay

View File

@@ -208,7 +208,7 @@
overlays += lid
update_temperature_overlays()
update_blood_overlay()//re-applying blood stains
set_blood_overlay()//re-applying blood stains
/obj/item/weapon/reagent_containers/glass/beaker/erlenmeyer
name = "small erlenmeyer flask"
@@ -489,7 +489,7 @@
overlays += filling
update_temperature_overlays()
update_blood_overlay()//re-applying blood stains
set_blood_overlay()//re-applying blood stains
/obj/item/weapon/reagent_containers/glass/bucket/water_filled/New()
..()
@@ -524,7 +524,7 @@
overlays += filling
update_temperature_overlays()
update_blood_overlay()//re-applying blood stains
set_blood_overlay()//re-applying blood stains
/*
/obj/item/weapon/reagent_containers/glass/blender_jug

View File

@@ -93,7 +93,7 @@
..()
overlays.len = 0
update_temperature_overlays()
update_blood_overlay()//re-applying blood stains
set_blood_overlay()//re-applying blood stains
//OOP, HO!
/obj/item/weapon/reagent_containers/pill/proc/ingest(mob/M as mob)

View File

@@ -34,6 +34,7 @@
#include "__DEFINES\dates.dm"
#include "__DEFINES\disease2.dm"
#include "__DEFINES\error_hander.dm"
#include "__DEFINES\flags.dm"
#include "__DEFINES\game.dm"
#include "__DEFINES\gases.dm"
#include "__DEFINES\global.dm"