From 8dbfc8ee1d8a7701a2729f7ed985e964d6b5cbae Mon Sep 17 00:00:00 2001 From: KasparoVy Date: Sat, 22 Jul 2017 19:55:21 -0400 Subject: [PATCH] Respects Windows and our Inability to Pass Them Blood that would splatter onto windows is now pixel-shifted and renders above them so you can A: Clean it with ease and B: See it in all its gorey glory. I had to get creative with how I detected structures blocking blood splatter. Janiborgs riding, sprayers spraying and cleaner grenades foaming over adjacent tiles won't clean off wall/windowblood. You have to use soap and click on the blood. --- code/game/atoms.dm | 9 ++++---- .../effects/decals/Cleanable/humans.dm | 3 ++- .../modules/mob/living/silicon/robot/robot.dm | 10 +++++++-- code/modules/projectiles/projectile.dm | 19 +++++++++++++---- .../reagents/chemistry/reagents/water.dm | 21 +++++++++++++------ code/modules/surgery/organs/blood.dm | 9 ++++++++ 6 files changed, 54 insertions(+), 17 deletions(-) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 8c12e452d1d..06f6ca8a631 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -512,10 +512,11 @@ var/list/blood_splatter_icons = list() overlays += blood_overlay /atom/proc/clean_blood() - germ_level = 0 - if(islist(blood_DNA)) - blood_DNA = null - return 1 + if(!istype(src, /obj/effect/decal/cleanable/blood)) + germ_level = 0 + if(islist(blood_DNA)) + blood_DNA = null + return 1 /obj/item/clean_blood() diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index bb8436340a6..cba5d3f733c 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -23,6 +23,7 @@ var/global/list/image/splatter_cache=list() var/amount = 5 appearance_flags = NO_CLIENT_COLOR var/dry_timer = 0 + var/off_floor = FALSE /obj/effect/decal/cleanable/blood/New() ..() @@ -89,7 +90,7 @@ var/global/list/image/splatter_cache=list() //Add "bloodiness" of this blood's type, to the human's shoes /obj/effect/decal/cleanable/blood/Crossed(atom/movable/O) - if(ishuman(O)) + if(!off_floor && ishuman(O)) var/mob/living/carbon/human/H = O var/obj/item/organ/external/l_foot = H.get_organ("l_foot") var/obj/item/organ/external/r_foot = H.get_organ("r_foot") diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 3de8b868430..3f756f465f1 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1157,14 +1157,18 @@ var/list/robot_verbs_default = list( if(module.type == /obj/item/weapon/robot_module/janitor) var/turf/tile = loc if(isturf(tile)) - tile.clean_blood() + var/floor_only = TRUE if(istype(tile, /turf/simulated)) var/turf/simulated/S = tile S.dirt = 0 for(var/A in tile) if(istype(A, /obj/effect)) if(is_cleanable(A)) - qdel(A) + var/obj/effect/decal/cleanable/blood/B = A + if(istype(B) && B.off_floor) + floor_only = FALSE + else + qdel(A) else if(istype(A, /obj/item)) var/obj/item/cleaned_item = A cleaned_item.clean_blood() @@ -1185,6 +1189,8 @@ var/list/robot_verbs_default = list( cleaned_human.update_inv_shoes(0,0) cleaned_human.clean_blood() to_chat(cleaned_human, "[src] cleans your face!") + if(floor_only) + tile.clean_blood() return #undef BORG_CAMERA_BUFFER diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index fa73cfab29f..07ca1d02f27 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -86,10 +86,12 @@ new /obj/effect/overlay/temp/dir_setting/bloodsplatter(target_loca, splatter_dir, blood_color) if(prob(33)) var/list/shift = list("x" = 0, "y" = 0) - if(!istype(get_step(target_loca, splatter_dir), /turf/simulated/floor)) //If one step in the splatter direction isn't a floor... - shift = pixel_shift_dir(splatter_dir) - else //Pixel shift the blood there instead (so you can't see wallsplatter through walls). - target_loca = get_step(target_loca, splatter_dir) + var/turf/step_over = get_step(target_loca, splatter_dir) + + if(get_splatter_blockage(step_over, target, splatter_dir, target_loca)) //If you can't cross the tile or any of its relevant obstacles... + shift = pixel_shift_dir(splatter_dir) //Pixel shift the blood there instead (so you can't see wallsplatter through walls). + else + target_loca = step_over L.add_splatter_floor(target_loca, shift_x = shift["x"], shift_y = shift["y"]) var/organ_hit_text = "" @@ -115,6 +117,15 @@ add_logs(firer, L, "shot", src, reagent_note) return L.apply_effects(stun, weaken, paralyze, irradiate, slur, stutter, eyeblur, drowsy, blocked, stamina, jitter) +/obj/item/projectile/proc/get_splatter_blockage(var/turf/step_over, var/atom/target, var/splatter_dir, var/target_loca) //Check whether the place we want to splatter blood is blocked (i.e. by windows). + var/turf/step_cardinal = !(splatter_dir in list(NORTH, SOUTH, EAST, WEST)) ? get_step(target_loca, get_cardinal_dir(target_loca, step_over)) : null + + if(step_over.density && !step_over.CanPass(target, step_over, 1)) //Preliminary simple check. + return 1 + for(var/atom/movable/border_obstacle in step_over) //Check to see if we're blocked by a (non-full) window or some such. Do deeper investigation if we're splattering blood diagonally. + if(border_obstacle.flags&ON_BORDER && get_dir(step_cardinal ? step_cardinal : target_loca, step_over) == turn(border_obstacle.dir, 180)) + return 1 + /obj/item/projectile/proc/vol_by_damage() if(damage) return Clamp((damage) * 0.67, 30, 100)// Multiply projectile damage by 0.67, then clamp the value between 30 and 100 diff --git a/code/modules/reagents/chemistry/reagents/water.dm b/code/modules/reagents/chemistry/reagents/water.dm index c1c3191c5ba..afc7e805e0d 100644 --- a/code/modules/reagents/chemistry/reagents/water.dm +++ b/code/modules/reagents/chemistry/reagents/water.dm @@ -132,18 +132,27 @@ taste_message = "floor cleaner" /datum/reagent/space_cleaner/reaction_obj(obj/O, volume) - if(istype(O, /obj/effect/decal/cleanable)) - qdel(O) + if(is_cleanable(O)) + var/obj/effect/decal/cleanable/blood/B = O + if(!(istype(B) && B.off_floor)) + qdel(O) else - O.color = initial(O.color) + if(!istype(O, /atom/movable/lighting_overlay)) + O.color = initial(O.color) O.clean_blood() /datum/reagent/space_cleaner/reaction_turf(turf/T, volume) if(volume >= 1) - T.color = initial(T.color) - T.clean_blood() + var/floor_only = TRUE for(var/obj/effect/decal/cleanable/C in src) - qdel(C) + var/obj/effect/decal/cleanable/blood/B = C + if(istype(B) && B.off_floor) + floor_only = FALSE + else + qdel(C) + T.color = initial(T.color) + if(floor_only) + T.clean_blood() for(var/mob/living/carbon/slime/M in T) M.adjustToxLoss(rand(5,10)) diff --git a/code/modules/surgery/organs/blood.dm b/code/modules/surgery/organs/blood.dm index ba27270d63b..bc19b6c6159 100644 --- a/code/modules/surgery/organs/blood.dm +++ b/code/modules/surgery/organs/blood.dm @@ -271,6 +271,9 @@ B.pixel_x = (shift_x) B.pixel_y = (shift_y) B.update_icon() + if(shift_x || shift_y) + B.off_floor = TRUE + B.layer = BELOW_MOB_LAYER //So the blood lands ontop of things like posters, windows, etc. /mob/living/carbon/human/add_splatter_floor(turf/T, small_drip, shift_x, shift_y) if(!(NO_BLOOD in species.species_traits)) @@ -287,6 +290,9 @@ B.blood_DNA["UNKNOWN DNA"] = "X*" B.pixel_x = (shift_x) B.pixel_y = (shift_y) + if(shift_x || shift_y) + B.off_floor = TRUE + B.layer = BELOW_MOB_LAYER /mob/living/silicon/robot/add_splatter_floor(turf/T, small_drip, shift_x, shift_y) if(!T) @@ -298,3 +304,6 @@ B = locate() in T B.pixel_x = (shift_x) B.pixel_y = (shift_y) + if(shift_x || shift_y) + B.off_floor = TRUE + B.layer = BELOW_MOB_LAYER