Skip to content

Commit

Permalink
Fix wearing gloves causing bloody footprints to glitch out (#511)
Browse files Browse the repository at this point in the history
  • Loading branch information
MrMelbert authored Jun 28, 2024
1 parent 1e265e0 commit 6577a50
Show file tree
Hide file tree
Showing 25 changed files with 203 additions and 99 deletions.
3 changes: 3 additions & 0 deletions code/__HELPERS/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,6 @@ rough example of the "cone" made by the 3 dirs checked
"x" = icon_width > world.icon_size && pixel_x != 0 ? (icon_width - world.icon_size) * 0.5 : 0,
"y" = icon_height > world.icon_size && pixel_y != 0 ? (icon_height - world.icon_size) * 0.5 : 0,
)

/// Helper for easily adding blood from INSIDE a mob to an atom (NOT blood ON the mob)
#define add_mob_blood(from_who) add_blood_DNA(from_who.get_blood_dna_list())
36 changes: 20 additions & 16 deletions code/_onclick/item_attack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,21 @@
attacking_item.add_mob_blood(src)
add_splatter_floor(get_turf(src))
if(get_dist(attacker, src) <= 1)
attacker.add_mob_blood(src)
if(ishuman(attacker))
var/bloodied_things = ITEM_SLOT_GLOVES
if(damage_done >= 20 || (damage_done >= 15 && prob(25)))
bloodied_things |= ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING
if(prob(33) && damage_done >= 10)
bloodied_things |= ITEM_SLOT_FEET
if(prob(33) && damage_done >= 24) // fireaxe damage, because heeeeere's johnny
bloodied_things |= ITEM_SLOT_MASK
if(prob(33) && damage_done >= 30) // esword damage
bloodied_things |= ITEM_SLOT_HEAD

var/mob/living/carbon/human/human_attacker = attacker
human_attacker.add_blood_DNA_to_items(get_blood_dna_list(), bloodied_things)
else
attacker.add_mob_blood(src)
return TRUE

return FALSE
Expand Down Expand Up @@ -376,15 +390,10 @@
switch(hit_zone)
if(BODY_ZONE_HEAD)
if(.)
if(wear_mask)
wear_mask.add_mob_blood(src)
update_worn_mask()
if(head)
head.add_mob_blood(src)
update_worn_head()
if(glasses && prob(33))
glasses.add_mob_blood(src)
update_worn_glasses()
var/bloodied_things = ITEM_SLOT_MASK|ITEM_SLOT_HEAD
if(prob(33))
bloodied_things |= ITEM_SLOT_EYES
add_blood_DNA_to_items(get_blood_dna_list(), bloodied_things)

if(!attacking_item.get_sharpness() && armor_block < 50 && attacking_item.damtype == BRUTE)
if(prob(damage_done))
Expand All @@ -409,12 +418,7 @@

if(BODY_ZONE_CHEST)
if(.)
if(wear_suit)
wear_suit.add_mob_blood(src)
update_worn_oversuit()
if(w_uniform)
w_uniform.add_mob_blood(src)
update_worn_undersuit()
add_blood_DNA_to_items(get_blood_dna_list(), ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING)

if(stat == CONSCIOUS && !attacking_item.get_sharpness() && armor_block < 50 && attacking_item.damtype == BRUTE)
if(prob(damage_done))
Expand Down
2 changes: 0 additions & 2 deletions code/datums/components/blood_walk.dm
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@
// NON-MODULE CHANGE
if(transfer_blood_dna)
blood.add_blood_DNA(GET_ATOM_BLOOD_DNA(movable_source))
// if(isliving(movable_source))
// blood.transfer_mob_blood_dna(movable_source)
if(!isnull(sound_played))
playsound(movable_source, sound_played, sound_volume, TRUE, 2, TRUE)

Expand Down
9 changes: 7 additions & 2 deletions code/datums/components/bloody_spreader.dm
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@

/datum/component/bloody_spreader/proc/spread_yucky_blood(atom/parent, atom/bloody_fool)
SIGNAL_HANDLER
bloody_fool.add_blood_DNA(blood_dna, diseases)
blood_left -= ishuman(bloody_fool) ? 3 : 1
if(ishuman(bloody_fool))
var/mob/living/carbon/human/bloody_fool_human = bloody_fool
bloody_fool_human.add_blood_DNA_to_items(blood_dna, ITEM_SLOT_GLOVES)
blood_left -= 3
else
bloody_fool.add_blood_DNA(blood_dna, diseases)
blood_left -= 1
if(blood_left <= 0)
qdel(src)

Expand Down
13 changes: 11 additions & 2 deletions code/datums/components/bloodysoles.dm
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,17 @@
pool.adjust_bloodiness(-1 * delta)
change_blood_amount(delta)

var/atom/parent_atom = parent
parent_atom.add_blood_DNA(GET_ATOM_BLOOD_DNA(pool))
if(ishuman(parent))
var/bloody_slots = ITEM_SLOT_OCLOTHING|ITEM_SLOT_ICLOTHING|ITEM_SLOT_FEET
var/mob/living/carbon/human/to_bloody = parent
if(to_bloody.body_position == LYING_DOWN)
bloody_slots |= ITEM_SLOT_HEAD|ITEM_SLOT_MASK|ITEM_SLOT_GLOVES

to_bloody.add_blood_DNA_to_items(GET_ATOM_BLOOD_DNA(pool), bloody_slots)
return

var/atom/to_bloody = parent
to_bloody.add_blood_DNA(GET_ATOM_BLOOD_DNA(pool))

/**
* Adds blood to an existing (or new) footprint
Expand Down
19 changes: 0 additions & 19 deletions code/game/atom/_atom.dm
Original file line number Diff line number Diff line change
Expand Up @@ -502,25 +502,6 @@

// NON-MODULE CHANGE END

///to add a mob's dna info into an object's blood_dna list.
/atom/proc/transfer_mob_blood_dna(mob/living/injected_mob)
// Returns 0 if we have that blood already
var/new_blood_dna = injected_mob.get_blood_dna_list()
if(!new_blood_dna)
return FALSE
var/old_length = GET_ATOM_BLOOD_DNA_LENGTH(src)
add_blood_DNA(new_blood_dna)
if(GET_ATOM_BLOOD_DNA_LENGTH(src) == old_length)
return FALSE
return TRUE

///to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/injected_mob)
var/list/blood_dna = injected_mob.get_blood_dna_list()
if(!blood_dna)
return FALSE
return add_blood_DNA(blood_dna)

///Is this atom in space
/atom/proc/isinspace()
if(isspaceturf(get_turf(src)))
Expand Down
35 changes: 14 additions & 21 deletions code/game/objects/effects/decals/cleanable/humans.dm
Original file line number Diff line number Diff line change
Expand Up @@ -431,12 +431,12 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
if(splatter_strength)
src.splatter_strength = splatter_strength

/obj/effect/decal/cleanable/blood/hitsplatter/Destroy()
/obj/effect/decal/cleanable/blood/hitsplatter/proc/expire()
if(isturf(loc) && !skip)
playsound(src, 'sound/effects/wounds/splatter.ogg', 60, TRUE, -1)
if(blood_dna_info)
loc.add_blood_DNA(blood_dna_info)
return ..()
qdel(src)

/// Set the splatter up to fly through the air until it rounds out of steam or hits something
/obj/effect/decal/cleanable/blood/hitsplatter/proc/fly_towards(turf/target_turf, range)
Expand All @@ -452,42 +452,35 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)

/obj/effect/decal/cleanable/blood/hitsplatter/proc/post_move(datum/move_loop/source)
SIGNAL_HANDLER
for(var/atom/iter_atom in get_turf(src))
for(var/atom/movable/iter_atom in loc)
if(hit_endpoint)
return
if(iter_atom == src || iter_atom.invisibility || iter_atom.alpha <= 0 || (isobj(iter_atom) && !iter_atom.density))
continue
if(splatter_strength <= 0)
break

if(isitem(iter_atom))
iter_atom.add_blood_DNA(blood_dna_info)
splatter_strength--
else if(ishuman(iter_atom))
var/mob/living/carbon/human/splashed_human = iter_atom
if(splashed_human.wear_suit)
splashed_human.wear_suit.add_blood_DNA(blood_dna_info)
splashed_human.update_worn_oversuit() //updates mob overlays to show the new blood (no refresh)
if(splashed_human.w_uniform)
splashed_human.w_uniform.add_blood_DNA(blood_dna_info)
splashed_human.update_worn_undersuit() //updates mob overlays to show the new blood (no refresh)
splatter_strength--
iter_atom.add_blood_DNA(blood_dna_info)
splatter_strength--

if(splatter_strength <= 0) // we used all the puff so we delete it.
qdel(src)
expire()

/obj/effect/decal/cleanable/blood/hitsplatter/proc/loop_done(datum/source)
SIGNAL_HANDLER
if(!QDELETED(src))
qdel(src)
expire()

/obj/effect/decal/cleanable/blood/hitsplatter/Bump(atom/bumped_atom)
if(!iswallturf(bumped_atom) && !istype(bumped_atom, /obj/structure/window))
qdel(src)
expire()
return

if(istype(bumped_atom, /obj/structure/window))
var/obj/structure/window/bumped_window = bumped_atom
if(!bumped_window.fulltile)
hit_endpoint = TRUE
qdel(src)
expire()
return

hit_endpoint = TRUE
Expand All @@ -505,7 +498,7 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
final_splatter.add_blood_DNA(blood_dna_info)
else // This will only happen if prev_loc is not even a turf, which is highly unlikely.
abstract_move(bumped_atom)
qdel(src)
expire()

/// A special case for hitsplatters hitting windows, since those can actually be moved around, store it in the window and slap it in the vis_contents
/obj/effect/decal/cleanable/blood/hitsplatter/proc/land_on_window(obj/structure/window/the_window)
Expand All @@ -517,4 +510,4 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
final_splatter.forceMove(the_window)
the_window.vis_contents += final_splatter
the_window.bloodied = TRUE
qdel(src)
expire()
2 changes: 1 addition & 1 deletion code/modules/antagonists/changeling/powers/mutations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@
C.visible_message(span_danger("[H] impales [C] with [H.p_their()] [I.name]!"), span_userdanger("[H] impales you with [H.p_their()] [I.name]!"))
C.apply_damage(I.force, BRUTE, BODY_ZONE_CHEST, attacking_item = I)
H.do_item_attack_animation(C, used_item = I)
H.add_mob_blood(C)
H.add_blood_DNA_to_items(C.get_blood_dna_list(), ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING)
playsound(get_turf(H),I.hitsound,75,TRUE)
return

Expand Down
2 changes: 1 addition & 1 deletion code/modules/clothing/head/_head.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
righthand_file = 'icons/mob/inhands/clothing/hats_righthand.dmi'
body_parts_covered = HEAD
slot_flags = ITEM_SLOT_HEAD
blood_overlay_type = "helmetblood" // NON-MODULE CHANGE reworking clothing blood overlays
blood_overlay_type = "helmet" // NON-MODULE CHANGE reworking clothing blood overlays
drop_sound = 'maplestation_modules/sound/items/pickup/hat.ogg'
pickup_sound = 'maplestation_modules/sound/items/pickup/hat.ogg'

Expand Down
57 changes: 44 additions & 13 deletions code/modules/forensics/forensics_helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -150,27 +150,57 @@
/turf/closed/add_blood_DNA(list/blood_dna, list/datum/disease/diseases)
return FALSE

/obj/item/clothing/under/add_blood_DNA(list/blood_DNA_to_add)
. = ..()
if(!.)
return
for(var/obj/item/clothing/accessory/thing_accessory as anything in attached_accessories)
if(prob(66))
continue
thing_accessory.add_blood_DNA(blood_DNA_to_add)

/mob/living/carbon/human/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases)
return add_blood_DNA_to_items(blood_DNA_to_add)

/// Adds blood DNA to certain slots the mob is wearing
/mob/living/carbon/human/proc/add_blood_DNA_to_items(
list/blood_DNA_to_add,
target_flags = ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING|ITEM_SLOT_GLOVES|ITEM_SLOT_HEAD|ITEM_SLOT_MASK,
)
if(QDELING(src))
return FALSE
if(!length(blood_DNA_to_add))
return FALSE
if(wear_suit)
wear_suit.add_blood_DNA(blood_DNA_to_add)
update_worn_oversuit()
else if(w_uniform)
w_uniform.add_blood_DNA(blood_DNA_to_add)
update_worn_undersuit()
if(gloves)
var/obj/item/clothing/gloves/mob_gloves = gloves
mob_gloves.add_blood_DNA(blood_DNA_to_add)
else if(length(blood_DNA_to_add))
if (isnull(forensics))

// Don't messy up our jumpsuit if we're got a coat
if((target_flags & ITEM_SLOT_OCLOTHING) && (wear_suit?.body_parts_covered & CHEST))
target_flags &= ~ITEM_SLOT_ICLOTHING

var/dirty_hands = !!(target_flags & (ITEM_SLOT_GLOVES|ITEM_SLOT_HANDS))
var/dirty_feet = !!(target_flags & ITEM_SLOT_FEET)
var/slots_to_bloody = target_flags & ~check_obscured_slots()
var/list/all_worn = get_equipped_items()
for(var/obj/item/thing as anything in all_worn)
if(thing.slot_flags & slots_to_bloody)
thing.add_blood_DNA(blood_DNA_to_add)
if(thing.body_parts_covered & HANDS)
dirty_hands = FALSE
if(thing.body_parts_covered & FEET)
dirty_feet = FALSE

if(slots_to_bloody & ITEM_SLOT_HANDS)
for(var/obj/item/thing in held_items)
thing.add_blood_DNA(blood_DNA_to_add)

if(dirty_hands || dirty_feet || !length(all_worn))
if(isnull(forensics))
forensics = new(src)
forensics.inherit_new(blood_DNA = blood_DNA_to_add)
blood_in_hands = rand(2, 4)
if(dirty_hands)
blood_in_hands = rand(2, 4)

cached_blood_dna_color = null
update_worn_gloves()
update_clothing(slots_to_bloody)
return TRUE

/mob/living/add_blood_DNA(list/blood_DNA_to_add)
Expand All @@ -181,6 +211,7 @@
if(isnull(forensics))
forensics = new(src)
forensics.inherit_new(blood_DNA = blood_DNA_to_add)
cached_blood_dna_color = null
return TRUE

/*
Expand Down
7 changes: 7 additions & 0 deletions code/modules/mob/living/basic/ruin_defender/wizard/wizard.dm
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
)
/// A specified wizard corpse spawner to use. If null, picks from the list above instead.
var/selected_outfit
/// What's our "blood type"? So fake-humans splash blood on people in combat
var/fake_blood_type

/// Typepath for the wizard's targeted spell. If null, selects randomly.
var/targeted_spell_path
Expand Down Expand Up @@ -83,6 +85,11 @@
blink_spell.Grant(src)
ai_controller.set_blackboard_key(BB_WIZARD_BLINK_SPELL, blink_spell)

/mob/living/basic/wizard/get_blood_type()
if(!fake_blood_type)
fake_blood_type = random_human_blood_type()
return GLOB.blood_types[fake_blood_type]

/// Uses the colors and loadout of the original wizard simplemob
/mob/living/basic/wizard/classic
selected_outfit = /obj/effect/mob_spawn/corpse/human/wizard
Expand Down
7 changes: 7 additions & 0 deletions code/modules/mob/living/basic/space_fauna/cat_surgeon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
/obj/effect/mob_spawn/corpse/human/cat_butcher,
/obj/item/circular_saw,
)
/// What's our "blood type"? So fake-humans splash blood on people in combat
var/fake_blood_type

/mob/living/basic/cat_butcherer/Initialize(mapload)
. = ..()
Expand All @@ -44,6 +46,11 @@
AddElement(/datum/element/death_drops, drop_on_death)
RegisterSignal(src, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(after_attack))

/mob/living/basic/cat_butcherer/get_blood_type()
if(!fake_blood_type)
fake_blood_type = random_human_blood_type()
return GLOB.blood_types[fake_blood_type]

/mob/living/basic/cat_butcherer/proc/after_attack(mob/living/basic/attacker, atom/target)
SIGNAL_HANDLER

Expand Down
3 changes: 3 additions & 0 deletions code/modules/mob/living/basic/trooper/abductor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
loot = list(/obj/effect/mob_spawn/corpse/human/abductor)
mob_spawner = /obj/effect/mob_spawn/corpse/human/abductor

/mob/living/basic/trooper/abductor/get_blood_type()
return null // Ayys are noblooded

/mob/living/basic/trooper/abductor/melee
melee_damage_lower = 15
melee_damage_upper = 15
Expand Down
7 changes: 7 additions & 0 deletions code/modules/mob/living/basic/trooper/trooper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
var/r_hand
/// Path of the left hand held item we give to the mob's visuals.
var/l_hand
/// What's our "blood type"? So fake-humans splash blood on people in combat
var/fake_blood_type

/mob/living/basic/trooper/Initialize(mapload)
. = ..()
Expand All @@ -34,3 +36,8 @@
loot = string_list(loot)
AddElement(/datum/element/death_drops, loot)
AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_SHOE)

/mob/living/basic/trooper/get_blood_type()
if(!fake_blood_type)
fake_blood_type = random_human_blood_type()
return GLOB.blood_types[fake_blood_type]
Loading

0 comments on commit 6577a50

Please sign in to comment.