diff --git a/code/datums/wounds/blunt.dm b/code/datums/wounds/blunt.dm
index 219b7dd8805c..e47fce542056 100644
--- a/code/datums/wounds/blunt.dm
+++ b/code/datums/wounds/blunt.dm
@@ -1,3 +1,10 @@
/datum/wound/blunt
name = "Blunt Wound"
sound_effect = 'sound/effects/wounds/crack1.ogg'
+
+/datum/wound/blunt/wound_injury(datum/wound/old_wound, attack_direction)
+ if(!old_wound && limb.current_gauze && (wound_flags & ACCEPTS_GAUZE))
+ // oops your bone injury knocked off your gauze, gotta re-apply it
+ limb.remove_gauze(limb.drop_location())
+
+ return ..()
diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm
index 415113c3bd77..7f6bb8e8b72d 100644
--- a/code/datums/wounds/burns.dm
+++ b/code/datums/wounds/burns.dm
@@ -9,6 +9,15 @@
a_or_from = "from"
sound_effect = 'sound/effects/wounds/sizzle1.ogg'
+/datum/wound/burn/wound_injury(datum/wound/old_wound, attack_direction)
+ if(!old_wound && limb.current_gauze && (wound_flags & ACCEPTS_GAUZE))
+ qdel(limb.remove_gauze())
+ // oops your existing gauze got burned, need a new one now
+ var/obj/effect/decal/cleanable/ash/ash = new(limb.drop_location())
+ ash.desc += " It looks like it used to be some kind of bandage."
+
+ return ..()
+
/datum/wound/burn/flesh
name = "Burn (Flesh) Wound"
a_or_from = "from"
@@ -149,7 +158,7 @@
if(4 to INFINITY)
bandage_condition = "clean"
- condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]"
+ condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]."
else
switch(infestation)
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm
index f80d2adf453c..9a33c6b11cb0 100644
--- a/code/datums/wounds/pierce.dm
+++ b/code/datums/wounds/pierce.dm
@@ -4,6 +4,12 @@
*/
/datum/wound/pierce
+/datum/wound/pierce/wound_injury(datum/wound/old_wound, attack_direction)
+ if(!old_wound && limb.current_gauze && (wound_flags & ACCEPTS_GAUZE))
+ // oops your existing gauze got penetrated through! need a new one now
+ limb.seep_gauze(initial(limb.current_gauze.absorption_capacity) * 0.8)
+ return ..()
+
/datum/wound/pierce/bleed
name = "Piercing Wound"
sound_effect = 'sound/weapons/slice.ogg'
@@ -29,7 +35,6 @@
set_blood_flow(initial_flow)
if(limb.can_bleed() && attack_direction && victim.blood_volume > BLOOD_VOLUME_OKAY)
victim.spray_blood(attack_direction, severity)
-
return ..()
/datum/wound/pierce/bleed/receive_damage(wounding_type, wounding_dmg, wound_bonus)
@@ -82,8 +87,9 @@
adjust_blood_flow(0.25 * seconds_per_tick) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first
if(limb.current_gauze)
- adjust_blood_flow(-limb.current_gauze.absorption_rate * gauzed_clot_rate * seconds_per_tick)
- limb.current_gauze.absorption_capacity -= limb.current_gauze.absorption_rate * seconds_per_tick
+ var/amt_blocking = limb.current_gauze.absorption_rate * seconds_per_tick
+ adjust_blood_flow(-1 * amt_blocking * gauzed_clot_rate)
+ limb.seep_gauze(amt_blocking)
if(blood_flow <= 0)
qdel(src)
diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm
index 980cb7124845..8f5b589e7482 100644
--- a/code/datums/wounds/slash.dm
+++ b/code/datums/wounds/slash.dm
@@ -7,6 +7,12 @@
name = "Slashing (Cut) Wound"
sound_effect = 'sound/weapons/slice.ogg'
+/datum/wound/slash/wound_injury(datum/wound/old_wound, attack_direction)
+ if(!old_wound && limb.current_gauze && (wound_flags & ACCEPTS_GAUZE))
+ // oops your existing gauze got cut through! need a new one now
+ limb.seep_gauze(initial(limb.current_gauze.absorption_capacity) * 0.8)
+ return ..()
+
/datum/wound_pregen_data/flesh_slash
abstract = TRUE
diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm
index 8a80692f1a9a..c3b81fd58c03 100644
--- a/code/game/objects/effects/decals/cleanable/misc.dm
+++ b/code/game/objects/effects/decals/cleanable/misc.dm
@@ -241,7 +241,7 @@
pixel_x = rand(-10, 10)
pixel_y = rand(-10, 10)
if(!isnull(oldname))
- desc = "The sad remains of what used to be [oldname]"
+ desc = "The sad remains of what used to be [oldname]."
. = ..()
/obj/effect/decal/cleanable/glitter
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 4713c9523390..84661e487676 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -17,6 +17,8 @@
source = /datum/robot_energy_storage/medical
merge_type = /obj/item/stack/medical
pickup_sound = 'maplestation_modules/sound/items/pickup/surgery_cloth.ogg'
+ /// Sound played when heal doafter begins
+ var/heal_sound
/// How long it takes to apply it to yourself
var/self_delay = 5 SECONDS
/// How long it takes to apply it to someone else
@@ -86,6 +88,8 @@
if(iscarbon(patient))
new_self_delay = looping ? clamp((self_delay - assessing_injury_delay), 0, self_delay) : self_delay
new_other_delay = looping ? clamp((other_delay - assessing_injury_delay), 0, other_delay) : other_delay
+ if(heal_sound)
+ playsound(patient, heal_sound, 33, FALSE)
if(patient == user)
if(!silent)
user.visible_message(
@@ -231,15 +235,48 @@
burn_cleanliness_bonus = 0.35
merge_type = /obj/item/stack/medical/gauze
drop_sound = 'sound/items/handling/cloth_drop.ogg'
- var/obj/item/bodypart/gauzed_bodypart
+ /// tracks how many times we've been scrubbed thoroughly
+ var/times_cleaned = 0
-/obj/item/stack/medical/gauze/Destroy(force)
+/obj/item/stack/medical/gauze/update_name(updates)
. = ..()
+ var/base_cap = initial(absorption_capacity)
+ if(!base_cap)
+ return
+
+ if(absorption_capacity <= 0)
+ name = "used [initial(name)]"
+ else if(absorption_capacity <= base_cap * 0.2)
+ name = "dirty [initial(name)]"
+ else if(absorption_capacity <= base_cap * 0.8)
+ name = "worn [initial(name)]"
+ else
+ name = initial(name)
- if (gauzed_bodypart)
- gauzed_bodypart.current_gauze = null
- SEND_SIGNAL(gauzed_bodypart, COMSIG_BODYPART_UNGAUZED, src)
- gauzed_bodypart = null
+/obj/item/stack/medical/gauze/can_merge(obj/item/stack/medical/gauze/check, inhand)
+ . = ..()
+ if(!.)
+ return .
+ // need to be in +- 0.5 dirtiness of each other
+ // otherwise you can merge a completely used bandage with a brand new one, which would magically unuse it
+ if(check.absorption_capacity < absorption_capacity - 0.25 || check.absorption_capacity > absorption_capacity + 0.25)
+ return FALSE
+ return .
+
+/obj/item/stack/medical/gauze/wash(clean_types)
+ . = ..()
+ if(.)
+ return .
+ if(!(clean_types & CLEAN_TYPE_HARD_DECAL)) // gotta scrub realllly hard to clean gauze
+ return .
+ times_cleaned += 1
+ var/clean_to = initial(absorption_capacity) * (3 / (times_cleaned + 3))
+ if(absorption_capacity < clean_to)
+ absorption_capacity = clean_to
+ update_appearance(UPDATE_NAME)
+ . = TRUE
+
+ return .
// gauze is only relevant for wounds, which are handled in the wounds themselves
/obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/user, silent, looping)
@@ -248,40 +285,62 @@
var/obj/item/bodypart/limb = patient.get_bodypart(check_zone(user.zone_selected))
if(!limb)
- patient.balloon_alert(user, "missing limb!")
- return
- if(!LAZYLEN(limb.wounds))
- patient.balloon_alert(user, "no wounds!") // good problem to have imo
- return
-
- var/gauzeable_wound = FALSE
- var/datum/wound/woundies
- for(var/i in limb.wounds)
- woundies = i
- if(woundies.wound_flags & ACCEPTS_GAUZE)
- gauzeable_wound = TRUE
- break
- if(!gauzeable_wound)
- patient.balloon_alert(user, "can't heal those!")
+ patient.balloon_alert(user, "no limb!")
return
if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 1.2 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row
patient.balloon_alert(user, pick("already bandaged!", "bandage is clean!")) // good enough
return
- if(HAS_TRAIT(woundies, TRAIT_WOUND_SCANNED))
+ var/boosted = FALSE
+ if(LAZYLEN(limb.wounds))
+ for(var/datum/wound/wound as anything in limb.wounds)
+ if(HAS_TRAIT(wound, TRAIT_WOUND_SCANNED))
+ boosted = TRUE
+ break
+ else
+ // gives you extra time so you realize you're not treating a wound
+ treatment_delay *= 2
+
+ var/whose = user == patient ? "your" : "[patient]'s"
+ var/theirs = user == patient ? patient.p_their() : "[patient]'s"
+ var/wrap_or_replace = limb.current_gauze ? "replacing [limb.current_gauze] on" : "wrapping"
+ var/with_what = limb.current_gauze?.type == type ? "more of [src]" : src
+ if(boosted)
treatment_delay *= 0.5
- if(user == patient)
- to_chat(user, span_notice("You keep in mind the indications from the holo-image about your injury, and expertly begin wrapping your wounds with [src]."))
- else
- user.visible_message(span_warning("[user] begins expertly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin quickly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src], keeping the holo-image indications in mind..."))
+ user.visible_message(
+ span_notice("[user] begins expertly [wrap_or_replace] [theirs] [limb.plaintext_zone] with [with_what]."),
+ span_notice("You begin quickly [wrap_or_replace] [whose] [limb.plaintext_zone] with [with_what], keeping the holo-image indications in mind..."),
+ )
else
- user.visible_message(span_warning("[user] begins wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin wrapping the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]..."))
+ user.visible_message(
+ span_notice("[user] begins [wrap_or_replace] [theirs] [limb.plaintext_zone] with [with_what]."),
+ span_notice("You begin [wrap_or_replace] [whose] [limb.plaintext_zone] with [with_what]..."),
+ )
+ user.balloon_alert(user, "applying gauze...")
+ if(user != patient)
+ user.balloon_alert(patient, "applying gauze...")
+
+ playsound(patient, pick(
+ 'maplestation_modules/sound/items/rip1.ogg',
+ 'maplestation_modules/sound/items/rip2.ogg',
+ 'maplestation_modules/sound/items/rip3.ogg',
+ 'maplestation_modules/sound/items/rip4.ogg',
+ ), 33)
if(!do_after(user, treatment_delay, target = patient))
+ user.balloon_alert(user, "interrupted!")
return
+ if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 1.2 > absorption_capacity)) // double check for sanity
+ return
+ user.balloon_alert(user, "gauze applied")
+ if(user != patient)
+ user.balloon_alert(patient, "gauze applied")
- user.visible_message("[user] applies [src] to [patient]'s [limb.plaintext_zone].", "You bandage the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone].")
+ user.visible_message(
+ span_infoplain(span_green("[user] applies [src] to [theirs] [limb.plaintext_zone].")),
+ span_infoplain(span_green("You [limb.current_gauze?.type == type ? "replace" : "bandage"] the wounds on [whose] [limb.plaintext_zone].")),
+ )
limb.apply_gauze(src)
/obj/item/stack/medical/gauze/twelve
@@ -343,6 +402,7 @@
stop_bleeding = 0.6
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
merge_type = /obj/item/stack/medical/suture
+ heal_sound = 'maplestation_modules/sound/items/snip.ogg'
/obj/item/stack/medical/suture/emergency
name = "emergency suture"
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index e4516eb4d22a..209789b8fb15 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -211,6 +211,14 @@
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
return
+ if(href_list["gauze_limb"])
+ var/obj/item/bodypart/gauzed = locate(href_list["gauze_limb"]) in bodyparts
+ if(isnull(gauzed?.current_gauze))
+ return
+ // rest of the sanity is handled in the proc itself
+ gauzed.help_remove_gauze(usr)
+ return
+
if(href_list["show_paper_note"])
var/obj/item/paper/paper_note = locate(href_list["show_paper_note"])
if(!paper_note)
diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm
index 5cbc3072877a..5071bdcbc1ea 100644
--- a/code/modules/mob/living/carbon/carbon_update_icons.dm
+++ b/code/modules/mob/living/carbon/carbon_update_icons.dm
@@ -332,20 +332,13 @@
remove_overlay(DAMAGE_LAYER)
var/mutable_appearance/damage_overlay
- var/digi_filter = FALSE
for(var/obj/item/bodypart/iter_part as anything in bodyparts)
- if(!iter_part.dmg_overlay_type)
+ var/list/part_overlays = iter_part.get_bodypart_damage_state()
+ if(!LAZYLEN(part_overlays))
continue
- if(iter_part.brutestate || iter_part.burnstate)
- damage_overlay ||= mutable_appearance('icons/mob/effects/dam_mob.dmi', "blank", -DAMAGE_LAYER, appearance_flags = KEEP_TOGETHER)
- if(iter_part.brutestate)
- damage_overlay.add_overlay("[iter_part.dmg_overlay_type]_[iter_part.body_zone]_[iter_part.brutestate]0") //we're adding icon_states of the base image as overlays
- damage_overlay.color = iter_part.damage_color
- if(iter_part.burnstate)
- damage_overlay.add_overlay("[iter_part.dmg_overlay_type]_[iter_part.body_zone]_0[iter_part.burnstate]")
- if(!digi_filter && damage_overlay && (iter_part.bodytype & BODYTYPE_DIGITIGRADE))
- iter_part.apply_digitigrade_filters(damage_overlay, src)
- digi_filter = TRUE
+
+ damage_overlay ||= mutable_appearance(layer = -DAMAGE_LAYER)
+ damage_overlay.overlays += part_overlays
if(isnull(damage_overlay))
return
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 1325587a5e4b..6b28e33c06b4 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -138,23 +138,27 @@
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/list/disabled = list()
- for(var/X in bodyparts)
- var/obj/item/bodypart/body_part = X
+ var/adjacent = user.Adjacent(src)
+ for(var/obj/item/bodypart/body_part as anything in bodyparts)
if(body_part.bodypart_disabled)
disabled += body_part
missing -= body_part.body_zone
- for(var/obj/item/I in body_part.embedded_objects)
- if(I.isEmbedHarmless())
- msg += "[t_He] [t_has] [icon2html(I, user)] \a [I] stuck to [t_his] [body_part.plaintext_zone]!\n"
- else
- msg += "[t_He] [t_has] [icon2html(I, user)] \a [I] embedded in [t_his] [body_part.plaintext_zone]!\n"
-
- for(var/i in body_part.wounds)
- var/datum/wound/iter_wound = i
+ for(var/obj/item/leftover in body_part.embedded_objects)
+ var/stuck_or_embedded = "embedded in"
+ if(leftover.isEmbedHarmless())
+ stuck_or_embedded = "stuck to"
+ msg += "[t_He] [t_has] [icon2html(leftover, user)] \a [leftover] [stuck_or_embedded] [t_his] [body_part.plaintext_zone]!\n"
+
+ if(body_part.current_gauze)
+ var/gauze_href = body_part.current_gauze.name
+ if(adjacent && isliving(user)) // only shows the href if we're adjacent
+ gauze_href = "[gauze_href]"
+ msg += span_notice("There is some [icon2html(body_part.current_gauze, user)] [gauze_href] wrapped around [t_his] [body_part.plaintext_zone].\n")
+
+ for(var/datum/wound/iter_wound as anything in body_part.wounds)
msg += "[iter_wound.get_examine_description(user)]\n"
- for(var/X in disabled)
- var/obj/item/bodypart/body_part = X
+ for(var/obj/item/bodypart/body_part as anything in disabled)
var/damage_text
if(HAS_TRAIT(body_part, TRAIT_DISABLED_BY_WOUND))
continue // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!)
diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm
index fa96a721c8c7..82676f62eca0 100644
--- a/code/modules/mob/living/carbon/human/human_update_icons.dm
+++ b/code/modules/mob/living/carbon/human/human_update_icons.dm
@@ -845,7 +845,7 @@ generate/load female uniform sprites matching all previously decided variables
return appearance
-/obj/item/proc/apply_digitigrade_filters(mutable_appearance/appearance, mob/living/carbon/human/wearer = loc)
+/obj/item/proc/apply_digitigrade_filters(mutable_appearance/appearance, mob/living/carbon/wearer = loc)
if(!istype(wearer) || !(wearer.bodytype & BODYTYPE_DIGITIGRADE) || wearer.is_digitigrade_squished())
return
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 357b69e59a2d..50ac0e5021ac 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -361,6 +361,9 @@
var/stuck_word = embedded_thing.isEmbedHarmless() ? "stuck" : "embedded"
check_list += "\t There is \a [embedded_thing] [stuck_word] in your [name]!"
+ if(current_gauze)
+ check_list += span_notice("\t There is some [current_gauze.name] wrapped around your [name].")
+
/obj/item/bodypart/blob_act()
receive_damage(max_damage, wound_bonus = CANT_WOUND)
@@ -894,8 +897,8 @@
set_can_be_disabled(initial(can_be_disabled))
-//Updates an organ's brute/burn states for use by update_damage_overlays()
-//Returns 1 if we need to update overlays. 0 otherwise.
+/// Updates an organ's brute/burn states for use by update_damage_overlays().
+/// Returns TRUE if state changed (IE, an update is needed)
/obj/item/bodypart/proc/update_bodypart_damage_state()
SHOULD_CALL_PARENT(TRUE)
@@ -907,6 +910,45 @@
return TRUE
return FALSE
+/// Gets overlays to apply to the mob when damaged.
+/obj/item/bodypart/proc/get_bodypart_damage_state()
+ if(!dmg_overlay_type)
+ return
+
+ var/list/overlays
+ if(brutestate)
+ var/mutable_appearance/brute_overlay = mutable_appearance(
+ icon = 'icons/mob/effects/dam_mob.dmi',
+ icon_state = "[dmg_overlay_type]_[body_zone]_[brutestate]0",
+ layer = -DAMAGE_LAYER,
+ )
+ brute_overlay.color = damage_color
+ LAZYADD(overlays, brute_overlay)
+ if(burnstate)
+ var/mutable_appearance/burn_overlay = mutable_appearance(
+ icon = 'icons/mob/effects/dam_mob.dmi',
+ icon_state = "[dmg_overlay_type]_[body_zone]_0[burnstate]",
+ layer = -DAMAGE_LAYER,
+ )
+ LAZYADD(overlays, burn_overlay)
+ if(current_gauze)
+ var/mutable_appearance/gauze_overlay = current_gauze.build_worn_icon(
+ default_layer = DAMAGE_LAYER - 0.1, // proc inverts it for us
+ override_file = 'maplestation_modules/icons/mob/bandage.dmi',
+ override_state = current_gauze.worn_icon_state, // future todo : icon states for dirty bandages as well
+ )
+ LAZYADD(overlays, gauze_overlay)
+ return overlays
+
+/obj/item/bodypart/leg/get_bodypart_damage_state()
+ if(!(bodytype & BODYTYPE_DIGITIGRADE) || (owner.is_digitigrade_squished()))
+ return ..()
+
+ . = ..()
+ for(var/mutable_appearance/appearance in .)
+ apply_digitigrade_filters(appearance, owner)
+ return .
+
//we inform the bodypart of the changes that happened to the owner, or give it the informations from a source mob.
//set is_creating to true if you want to change the appearance of the limb outside of mutation changes or forced changes.
/obj/item/bodypart/proc/update_limb(dropping_limb = FALSE, is_creating = FALSE)
@@ -1234,46 +1276,6 @@
return ((biological_state & BIO_BLOODED) && (!owner || !HAS_TRAIT(owner, TRAIT_NOBLOOD)))
-/**
- * apply_gauze() is used to- well, apply gauze to a bodypart
- *
- * As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons).
- * The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze
- * applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared,
- * the gauze falls off.
- *
- * Arguments:
- * * gauze- Just the gauze stack we're taking a sheet from to apply here
- */
-/obj/item/bodypart/proc/apply_gauze(obj/item/stack/medical/gauze/new_gauze)
- if(!istype(new_gauze) || !new_gauze.absorption_capacity)
- return
- var/newly_gauzed = FALSE
- if(!current_gauze)
- newly_gauzed = TRUE
- QDEL_NULL(current_gauze)
- current_gauze = new new_gauze.type(src, 1)
- new_gauze.use(1)
- current_gauze.gauzed_bodypart = src
- if(newly_gauzed)
- SEND_SIGNAL(src, COMSIG_BODYPART_GAUZED, current_gauze, new_gauze)
-
-/**
- * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity.
- *
- * The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandages falls off and we're left with nothing.
- *
- * Arguments:
- * * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?)
- */
-/obj/item/bodypart/proc/seep_gauze(seep_amt = 0)
- if(!current_gauze)
- return
- current_gauze.absorption_capacity -= seep_amt
- if(current_gauze.absorption_capacity <= 0)
- owner.visible_message(span_danger("\The [current_gauze.name] on [owner]'s [name] falls away in rags."), span_warning("\The [current_gauze.name] on your [name] falls away in rags."), vision_distance=COMBAT_MESSAGE_RANGE)
- QDEL_NULL(current_gauze)
-
///Loops through all of the bodypart's external organs and update's their color.
/obj/item/bodypart/proc/recolor_external_organs()
for(var/datum/bodypart_overlay/mutant/overlay in bodypart_overlays)
diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm
index e65177cbe544..c389537d156f 100644
--- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm
@@ -43,7 +43,7 @@
limb_id = SPECIES_LIZARD
/// Checks if this mob is wearing anything that does not have a valid sprite set for digitigrade legs
-/mob/living/carbon/human/proc/is_digitigrade_squished()
+/mob/living/carbon/proc/is_digitigrade_squished()
var/obj/item/clothing/shoes/worn_shoes = get_item_by_slot(ITEM_SLOT_FEET)
var/obj/item/clothing/under/worn_suit = get_item_by_slot(ITEM_SLOT_OCLOTHING)
var/obj/item/clothing/under/worn_uniform = get_item_by_slot(ITEM_SLOT_ICLOTHING)
@@ -70,9 +70,7 @@
/obj/item/bodypart/leg/left/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE)
. = ..()
- if(ishuman(owner))
- var/mob/living/carbon/human/human_owner = owner
- limb_id = human_owner.is_digitigrade_squished() ? SPECIES_LIZARD : BODYPART_ID_DIGITIGRADE
+ limb_id = owner.is_digitigrade_squished() ? SPECIES_LIZARD : BODYPART_ID_DIGITIGRADE
/obj/item/bodypart/leg/right/digitigrade
icon_greyscale = 'icons/mob/human/species/lizard/bodyparts.dmi'
@@ -82,6 +80,4 @@
/obj/item/bodypart/leg/right/digitigrade/update_limb(dropping_limb = FALSE, is_creating = FALSE)
. = ..()
- if(ishuman(owner))
- var/mob/living/carbon/human/human_owner = owner
- limb_id = human_owner.is_digitigrade_squished() ? SPECIES_LIZARD : BODYPART_ID_DIGITIGRADE
+ limb_id = owner.is_digitigrade_squished() ? SPECIES_LIZARD : BODYPART_ID_DIGITIGRADE
diff --git a/code/modules/surgery/bodyparts/wounds.dm b/code/modules/surgery/bodyparts/wounds.dm
index 1fc16c7ca8f8..20764da41e72 100644
--- a/code/modules/surgery/bodyparts/wounds.dm
+++ b/code/modules/surgery/bodyparts/wounds.dm
@@ -316,9 +316,109 @@
for(var/datum/wound/iter_wound as anything in wounds)
dam_mul *= iter_wound.damage_multiplier_penalty
- if(!LAZYLEN(wounds) && current_gauze && !replaced) // no more wounds = no need for the gauze anymore
- owner.visible_message(span_notice("\The [current_gauze.name] on [owner]'s [name] falls away."), span_notice("The [current_gauze.name] on your [parse_zone(body_zone)] falls away."))
- QDEL_NULL(current_gauze)
-
wound_damage_multiplier = dam_mul
refresh_bleed_rate()
+
+/**
+ * apply_gauze() is used to- well, apply gauze to a bodypart
+ *
+ * As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons).
+ * The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze
+ * applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared,
+ * the gauze falls off.
+ *
+ * Arguments:
+ * * gauze- Just the gauze stack we're taking a sheet from to apply here
+ */
+/obj/item/bodypart/proc/apply_gauze(obj/item/stack/medical/gauze/new_gauze)
+ if(!istype(new_gauze) || !new_gauze.absorption_capacity || !new_gauze.use(1))
+ return
+ if(!isnull(current_gauze))
+ remove_gauze(drop_location())
+
+ current_gauze = new new_gauze.type(src, 1)
+ current_gauze.worn_icon_state = "[body_zone][rand(1, 3)]"
+ if(can_bleed() && (generic_bleedstacks || cached_bleed_rate))
+ current_gauze.add_mob_blood(owner)
+ if(!QDELETED(new_gauze))
+ new_gauze.add_mob_blood(owner)
+ SEND_SIGNAL(src, COMSIG_BODYPART_GAUZED, current_gauze, new_gauze)
+ owner.update_damage_overlays()
+
+/obj/item/bodypart/proc/remove_gauze(atom/remove_to)
+ SEND_SIGNAL(src, COMSIG_BODYPART_UNGAUZED, current_gauze)
+ if(remove_to)
+ current_gauze.forceMove(remove_to)
+ else
+ current_gauze.moveToNullspace()
+ if(can_bleed() && (generic_bleedstacks || cached_bleed_rate))
+ current_gauze.add_mob_blood(owner)
+ current_gauze.worn_icon_state = initial(current_gauze.worn_icon_state)
+ current_gauze.update_appearance()
+ . = current_gauze
+ current_gauze = null
+ owner.update_damage_overlays()
+ return .
+
+/**
+ * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity.
+ *
+ * The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandages falls off and we're left with nothing.
+ *
+ * Arguments:
+ * * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?)
+ */
+/obj/item/bodypart/proc/seep_gauze(seep_amt = 0)
+ if(!current_gauze)
+ return
+ current_gauze.absorption_capacity -= seep_amt
+ current_gauze.update_appearance(UPDATE_NAME)
+ if(current_gauze.absorption_capacity > 0)
+ return
+ owner.visible_message(
+ span_danger("[current_gauze] on [owner]'s [name] falls away in rags."),
+ span_warning("[current_gauze] on your [name] falls away in rags."),
+ vision_distance = COMBAT_MESSAGE_RANGE,
+ )
+ remove_gauze(drop_location())
+ owner.update_damage_overlays()
+
+/**
+ * Helper for someone helping to remove our gauze
+ */
+/obj/item/bodypart/proc/help_remove_gauze(mob/living/helper)
+ if(!istype(helper))
+ return
+ if(helper.incapacitated())
+ return
+ if(!helper.can_perform_action(owner, NEED_HANDS|FORBID_TELEKINESIS_REACH)) // telekinetic removal can be added later
+ return
+
+ var/whose = helper == owner ? "your" : "[owner]'s"
+ helper.visible_message(
+ span_notice("[helper] starts carefully removing [current_gauze] from [whose] [plaintext_zone]."),
+ span_notice("You start carefully removing [current_gauze] from [whose] [plaintext_zone]..."),
+ vision_distance = COMBAT_MESSAGE_RANGE,
+ )
+ helper.balloon_alert(helper, "removing gauze...")
+ if(helper != owner)
+ helper.balloon_alert(owner, "removing your gauze...")
+
+ if(!do_after(helper, 3 SECONDS, owner))
+ return
+
+ if(!current_gauze)
+ return
+
+ var/theirs = helper == owner ? helper.p_their() : "[owner]'s"
+ helper.visible_message(
+ span_notice("[helper] finishes removing [current_gauze] from [theirs] [plaintext_zone]."),
+ span_notice("You finish removing [current_gauze] from [theirs] [plaintext_zone]."),
+ vision_distance = COMBAT_MESSAGE_RANGE,
+ )
+
+ helper.balloon_alert(helper, "gauzed removed")
+ if(helper != owner)
+ helper.balloon_alert(owner, "gauze removed")
+
+ helper.put_in_hands(remove_gauze())
diff --git a/maplestation_modules/icons/mob/bandage.dmi b/maplestation_modules/icons/mob/bandage.dmi
new file mode 100644
index 000000000000..24b65c9c48ef
Binary files /dev/null and b/maplestation_modules/icons/mob/bandage.dmi differ
diff --git a/maplestation_modules/sound/attribution.txt b/maplestation_modules/sound/attribution.txt
index daf8aa0c80fa..7d52f1491f43 100644
--- a/maplestation_modules/sound/attribution.txt
+++ b/maplestation_modules/sound/attribution.txt
@@ -5,6 +5,7 @@
- jackboot2.ogg
- cig_light.ogg
- cig_snuff.ogg
+- rip1.ogg through rip4.ogg
- inhale.ogg
- the contents of `item/ambience`
- the contents of `item/drop`
@@ -13,10 +14,14 @@
- the contents of `item/pickup`
- all healthscanner_x.oggs
-Have been ported from other stations, and given a lack of existing attribution,
+Have been ported from other stations, and given a lack of existing attribution,
are assumed to be CC-BY-SA 3.0 unless stated otherwise below
-- device2.ogg
+- device2.ogg
-was sampled from https://freesound.org/people/Nagwense/sounds/535375/
-and is licensed under CC-BY-SA 4.0
\ No newline at end of file
+was sampled from https://freesound.org/people/Nagwense/sounds/535375/
+and is licensed under CC-BY-SA 4.0
+
+- snip.ogg
+
+from Scissor Snip 2 by Aesterial-Arts -- https://freesound.org/s/633925/ -- License: Attribution 4.0
diff --git a/maplestation_modules/sound/items/rip1.ogg b/maplestation_modules/sound/items/rip1.ogg
new file mode 100644
index 000000000000..ab0fabbb3d69
Binary files /dev/null and b/maplestation_modules/sound/items/rip1.ogg differ
diff --git a/maplestation_modules/sound/items/rip2.ogg b/maplestation_modules/sound/items/rip2.ogg
new file mode 100644
index 000000000000..93a5cec50f8a
Binary files /dev/null and b/maplestation_modules/sound/items/rip2.ogg differ
diff --git a/maplestation_modules/sound/items/rip3.ogg b/maplestation_modules/sound/items/rip3.ogg
new file mode 100644
index 000000000000..82d93582923e
Binary files /dev/null and b/maplestation_modules/sound/items/rip3.ogg differ
diff --git a/maplestation_modules/sound/items/rip4.ogg b/maplestation_modules/sound/items/rip4.ogg
new file mode 100644
index 000000000000..32c594b688d7
Binary files /dev/null and b/maplestation_modules/sound/items/rip4.ogg differ
diff --git a/maplestation_modules/sound/items/snip.ogg b/maplestation_modules/sound/items/snip.ogg
new file mode 100644
index 000000000000..9f499b9a2abe
Binary files /dev/null and b/maplestation_modules/sound/items/snip.ogg differ