[MIRROR] [TEST-MERGE FIRST] Allows all limbs to be dismembered and significantly refactors wounds [MDB IGNORE] (#23407)

* [TEST-MERGE FIRST] Allows all limbs to be dismembered and significantly refactors wounds

* ah fuck it

* test

* edaawdawd

* Revert "edaawdawd"

This reverts commit 47be710fe61a1f4ca79212b29b3e88bf05ec9a3a.

* nothing but sheer hatred

* freaawd

* dzfxg

* Fixing some diffs here while we are at it.

* These are deprecated and should be removed

---------

Co-authored-by: nikothedude <59709059+nikothedude@users.noreply.github.com>
Co-authored-by: nikothedude <simon.prouty@gmail.com>
Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-09-05 19:24:22 +02:00
committed by GitHub
parent 02f66628e2
commit 2bcbb36ab9
84 changed files with 1974 additions and 2797 deletions
+3 -2
View File
@@ -92,8 +92,9 @@
H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD, wound_bonus=CANT_WOUND) // easy tiger, we'll get to that in a sec
var/obj/item/bodypart/slit_throat = H.get_bodypart(BODY_ZONE_HEAD)
if(slit_throat)
var/datum/wound/slash/critical/screaming_through_a_slit_throat = new
screaming_through_a_slit_throat.apply_wound(slit_throat, wound_source = "throat slit")
var/datum/wound/slash/flesh/critical/screaming_through_a_slit_throat = new
if (!screaming_through_a_slit_throat.apply_wound(slit_throat, wound_source = "throat slit"))
qdel(screaming_through_a_slit_throat)
H.apply_status_effect(/datum/status_effect/neck_slice)
/**
+1 -1
View File
@@ -303,7 +303,7 @@
return
var/damage = weapon.w_class * remove_pain_mult
limb.receive_damage(brute=(1-pain_stam_pct) * damage * 1.5, sharpness=SHARP_EDGED) // Performs exit wounds and flings the user to the caster if nearby
limb.force_wound_upwards(/datum/wound/pierce/moderate)
limb.force_wound_upwards(/datum/wound/pierce/bleed/moderate)
victim.adjustStaminaLoss(pain_stam_pct * damage)
playsound(get_turf(victim), 'sound/effects/wounds/blood2.ogg', 50, TRUE)
+2 -2
View File
@@ -80,8 +80,8 @@
if(do_after(attacker, 3 SECONDS, target, interaction_key = weapon))
attacker.visible_message(span_warning("[attacker] swings [attacker.p_their()] [weapon] at [target]'s kneecaps!"), span_danger("You swing \the [weapon] at [target]'s kneecaps!"))
var/datum/wound/blunt/severe/severe_wound_type = /datum/wound/blunt/severe
var/datum/wound/blunt/critical/critical_wound_type = /datum/wound/blunt/critical
var/datum/wound/blunt/bone/severe/severe_wound_type = /datum/wound/blunt/bone/severe
var/datum/wound/blunt/bone/critical/critical_wound_type = /datum/wound/blunt/bone/critical
leg.receive_damage(brute = weapon.force, wound_bonus = rand(initial(severe_wound_type.threshold_minimum), initial(critical_wound_type.threshold_minimum) + 10), damage_source = "kneecapping")
target.emote("scream")
log_combat(attacker, target, "broke the kneecaps of", weapon)
+3 -3
View File
@@ -65,11 +65,11 @@
/datum/mutation/human/hulk/proc/break_an_arm(obj/item/bodypart/arm)
switch(arm.brute_dam)
if(45 to 50)
arm.force_wound_upwards(/datum/wound/blunt/critical, wound_source = "hulk smashing")
arm.force_wound_upwards(/datum/wound/blunt/bone/critical, wound_source = "hulk smashing")
if(41 to 45)
arm.force_wound_upwards(/datum/wound/blunt/severe, wound_source = "hulk smashing")
arm.force_wound_upwards(/datum/wound/blunt/bone/severe, wound_source = "hulk smashing")
if(35 to 41)
arm.force_wound_upwards(/datum/wound/blunt/moderate, wound_source = "hulk smashing")
arm.force_wound_upwards(/datum/wound/blunt/bone/moderate, wound_source = "hulk smashing")
/datum/mutation/human/hulk/on_life(seconds_per_tick, times_fired)
if(owner.health < owner.crit_threshold)
+1 -1
View File
@@ -216,7 +216,7 @@
var/mob/living/carbon/carbon_victim = victim
var/obj/item/bodypart/chest = carbon_victim.get_bodypart(BODY_ZONE_CHEST)
if(chest)
chest.force_wound_upwards(/datum/wound/blunt/severe, wound_source = "human force to the chest")
chest.force_wound_upwards(/datum/wound/blunt/bone/severe, wound_source = "human force to the chest")
playsound(owner, 'sound/creatures/crack_vomit.ogg', 120, extrarange = 5, falloff_exponent = 4)
vomit_up()
+2 -2
View File
@@ -66,7 +66,7 @@
playsound(human_owner, SFX_SEAR, 50, TRUE)
var/obj/item/bodypart/affecting = human_owner.get_active_hand()
branded_hand = affecting
affecting.force_wound_upwards(/datum/wound/burn/severe/cursed_brand, wound_source = "curse of the slot machine")
affecting.force_wound_upwards(/datum/wound/burn/flesh/severe/cursed_brand, wound_source = "curse of the slot machine")
messages += span_boldwarning("Your hand burns, and you quickly let go of the lever! You feel a little sick as the nerves deaden in your hand...")
messages += span_boldwarning("Some smoke appears to be coming out of your hand now, but it's not too bad...")
@@ -116,7 +116,7 @@
SIGNAL_HANDLER
if(!isnull(branded_hand))
var/datum/wound/brand = branded_hand.get_wound_type(/datum/wound/burn/severe/cursed_brand)
var/datum/wound/brand = branded_hand.get_wound_type(/datum/wound/burn/flesh/severe/cursed_brand)
brand?.remove_wound()
owner.visible_message(
+16 -14
View File
@@ -167,20 +167,20 @@
// bones
/datum/status_effect/wound/blunt
/datum/status_effect/wound/blunt/bone
/datum/status_effect/wound/blunt/on_apply()
/datum/status_effect/wound/blunt/bone/on_apply()
. = ..()
RegisterSignal(owner, COMSIG_MOB_SWAP_HANDS, PROC_REF(on_swap_hands))
on_swap_hands()
/datum/status_effect/wound/blunt/on_remove()
/datum/status_effect/wound/blunt/bone/on_remove()
. = ..()
UnregisterSignal(owner, COMSIG_MOB_SWAP_HANDS)
var/mob/living/carbon/wound_owner = owner
wound_owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/blunt_wound)
/datum/status_effect/wound/blunt/proc/on_swap_hands()
/datum/status_effect/wound/blunt/bone/proc/on_swap_hands()
SIGNAL_HANDLER
var/mob/living/carbon/wound_owner = owner
@@ -189,7 +189,7 @@
else
wound_owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/blunt_wound)
/datum/status_effect/wound/blunt/nextmove_modifier()
/datum/status_effect/wound/blunt/bone/nextmove_modifier()
var/mob/living/carbon/C = owner
if(C.get_active_hand() == linked_limb)
@@ -198,18 +198,20 @@
return 1
// blunt
/datum/status_effect/wound/blunt/moderate
/datum/status_effect/wound/blunt/bone/moderate
id = "disjoint"
/datum/status_effect/wound/blunt/severe
/datum/status_effect/wound/blunt/bone/severe
id = "hairline"
/datum/status_effect/wound/blunt/critical
/datum/status_effect/wound/blunt/bone/critical
id = "compound"
// slash
/datum/status_effect/wound/slash/moderate
/datum/status_effect/wound/slash/flesh/moderate
id = "abrasion"
/datum/status_effect/wound/slash/severe
/datum/status_effect/wound/slash/flesh/severe
id = "laceration"
/datum/status_effect/wound/slash/critical
/datum/status_effect/wound/slash/flesh/critical
id = "avulsion"
// pierce
/datum/status_effect/wound/pierce/moderate
@@ -219,9 +221,9 @@
/datum/status_effect/wound/pierce/critical
id = "rupture"
// burns
/datum/status_effect/wound/burn/moderate
/datum/status_effect/wound/burn/flesh/moderate
id = "seconddeg"
/datum/status_effect/wound/burn/severe
/datum/status_effect/wound/burn/flesh/severe
id = "thirddeg"
/datum/status_effect/wound/burn/critical
/datum/status_effect/wound/burn/flesh/critical
id = "fourthdeg"
+136
View File
@@ -0,0 +1,136 @@
// This datum is merely a singleton instance that allows for custom "can be applied" behaviors without instantiating a wound instance.
// For example: You can make a pregen_data subtype for your wound that overrides can_be_applied_to to only apply to specifically slimeperson limbs.
// Without this, youre stuck with very static initial variables.
GLOBAL_LIST_INIT_TYPED(all_wound_pregen_data, /datum/wound_pregen_data, generate_wound_static_data())
/proc/generate_wound_static_data()
RETURN_TYPE(/list/datum/wound_pregen_data)
var/list/datum/wound_pregen_data/data = list()
for (var/datum/wound_pregen_data/path as anything in typecacheof(path = /datum/wound_pregen_data, ignore_root_path = TRUE))
if (initial(path.abstract))
continue
if (!isnull(data[initial(path.wound_path_to_generate)]))
stack_trace("pre-existing pregen data for [initial(path.wound_path_to_generate)] when [path] was being considered: [data[initial(path.wound_path_to_generate)]]. \
this is definitely a bug, and is probably because one of the two pregen data have the wrong wound typepath defined. [path] will not be instantiated")
continue
var/datum/wound_pregen_data/pregen_data = new path
data[pregen_data.wound_path_to_generate] = pregen_data
return data
/// A singleton datum that holds pre-gen and static data about a wound. Each wound datum should have a corresponding wound_pregen_data.
/datum/wound_pregen_data
/// The typepath of the wound we will be handling and storing data of. NECESSARY IF THIS IS A NON-ABSTRACT TYPE!
var/datum/wound/wound_path_to_generate
/// Will this be instantiated?
var/abstract = FALSE
/// If true, our wound can be selected in ordinary wound rolling. If this is set to false, our wound can only be directly instantiated by use of specific typepath.
var/can_be_randomly_generated = TRUE
/// A list of biostates a limb must have to receive our wound, in wounds.dm.
var/required_limb_biostate
/// If false, we will check if the limb has all of our required biostates instead of just any.
var/check_for_any = FALSE
/// If false, we will iterate through wounds on a given limb, and if any match our type, we wont add our wound.
var/duplicates_allowed = FALSE
/// If we require BIO_BLOODED, we will not add our wound if this is true and the limb cannot bleed.
var/ignore_cannot_bleed = TRUE // a lot of bleed wounds should still be applied for purposes of mangling flesh
/// A list of bodyzones we are applicable to.
var/list/viable_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
/datum/wound_pregen_data/New()
. = ..()
if (!abstract)
if (required_limb_biostate == null)
stack_trace("required_limb_biostate null - please set it! occured on: [src.type]")
if (wound_path_to_generate == null)
stack_trace("wound_path_to_generate null - please set it! occured on: [src.type]")
// this proc is the primary reason this datum exists - a singleton instance so we can always run this proc even without the wound existing
/**
* Args:
* * obj/item/bodypart/limb: The limb we are considering.
* * wound_type: The type of the "wound acquisition attempt". Example: A slashing attack cannot proc a blunt wound, so wound_type = WOUND_SLASH would
* fail if we expect WOUND_BLUNT. Defaults to the wound type we expect.
* * datum/wound/old_wound: If we would replace a wound, this would be said wound. Nullable.
* * random_roll = FALSE: If this is in the context of a random wound generation, and this wound wasn't specifically checked.
*
* Returns:
* FALSE if the limb cannot be wounded, if wound_type is not ours, if we have a higher severity wound already in our series,
* if we have a biotype mismatch, if the limb isnt in a viable zone, or if theres any duplicate wound types.
* TRUE otherwise.
*/
/datum/wound_pregen_data/proc/can_be_applied_to(obj/item/bodypart/limb, wound_type = initial(wound_path_to_generate.wound_type), datum/wound/old_wound, random_roll = FALSE)
SHOULD_BE_PURE(TRUE)
if (!istype(limb) || !limb.owner)
return FALSE
if (random_roll && !can_be_randomly_generated)
return FALSE
if (HAS_TRAIT(limb.owner, TRAIT_NEVER_WOUNDED) || (limb.owner.status_flags & GODMODE))
return FALSE
if (wound_type != initial(wound_path_to_generate.wound_type))
return
else
for (var/datum/wound/preexisting_wound as anything in limb.wounds)
if (preexisting_wound.wound_series == initial(wound_path_to_generate.wound_series))
if (preexisting_wound.severity >= initial(wound_path_to_generate.severity))
return FALSE
if (!ignore_cannot_bleed && ((required_limb_biostate & BIO_BLOODED) && !limb.can_bleed()))
return FALSE
if (!biostate_valid(limb.biological_state))
return FALSE
if (!(limb.body_zone in viable_zones))
return FALSE
// we accept promotions and demotions, but no point in redundancy. This should have already been checked wherever the wound was rolled and applied for (see: bodypart damage code), but we do an extra check
// in case we ever directly add wounds
if (!duplicates_allowed)
for (var/datum/wound/preexisting_wound as anything in limb.wounds)
if (preexisting_wound.type == wound_path_to_generate && (preexisting_wound != old_wound))
return FALSE
return TRUE
/// Returns true if we have the given biostates, or any biostate in it if check_for_any is true. False otherwise.
/datum/wound_pregen_data/proc/biostate_valid(biostate)
if (check_for_any)
if (!(biostate & required_limb_biostate))
return FALSE
else if (!((biostate & required_limb_biostate) == required_limb_biostate)) // check for all
return FALSE
return TRUE
/// Returns a new instance of our wound datum.
/datum/wound_pregen_data/proc/generate_instance(obj/item/bodypart/limb, ...)
RETURN_TYPE(/datum/wound)
return new wound_path_to_generate
/datum/wound_pregen_data/Destroy(force, ...)
stack_trace("[src], a singleton wound pregen data instance, was destroyed! This should not happen!")
if (!force)
return
. = ..()
GLOB.all_wound_pregen_data[wound_path_to_generate] = new src.type //recover
+144 -67
View File
@@ -14,6 +14,8 @@
deciding what specific wound will be applied. I'd like to have a few different types of wounds for at least some of the choices, but I'm just doing rough generals for now. Expect polishing
*/
#define WOUND_CRITICAL_BLUNT_DISMEMBER_BONUS 15
/datum/wound
/// What it's named
var/name = "Wound"
@@ -24,23 +26,31 @@
/// What the limb looks like on a cursory examine
var/examine_desc = "is badly hurt"
/// If this wound can generate a scar.
var/can_scar = TRUE
/// The file we take our scar descriptions from.
var/scar_file
/// needed for "your arm has a compound fracture" vs "your arm has some third degree burns"
var/a_or_from = "a"
/// The visible message when this happens
var/occur_text = ""
/// This sound will be played upon the wound being applied
var/sound_effect
/// The volume of [sound_effect]
var/sound_volume = 70
/// Either WOUND_SEVERITY_TRIVIAL (meme wounds like stubbed toe), WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_SEVERE, or WOUND_SEVERITY_CRITICAL (or maybe WOUND_SEVERITY_LOSS)
var/severity = WOUND_SEVERITY_MODERATE
/// The list of wounds it belongs in, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN
/// The type of attack that can generate this wound. E.g. WOUND_SLASH = A sword can cause us, or WOUND_BLUNT = a hammer can cause us/a sword attacking mangled flesh.
var/wound_type
/// The series of wounds this is in. See wounds.dm (the defines file) for a more detailed explanation - but tldr is that no 2 wounds of the same series can be on a limb.
var/wound_series
/// What body zones can we affect
var/list/viable_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
/// Who owns the body part that we're wounding
var/mob/living/carbon/victim = null
/// The bodypart we're parented to
/// The bodypart we're parented to. Not guaranteed to be non-null, especially after/during removal or if we haven't been applied
var/obj/item/bodypart/limb = null
/// Specific items such as bandages or sutures that can try directly treating this wound
@@ -90,14 +100,13 @@
var/wound_source
/// What flags apply to this wound
var/wound_flags = (FLESH_WOUND | BONE_WOUND | ACCEPTS_GAUZE)
var/wound_flags = (ACCEPTS_GAUZE)
/datum/wound/Destroy()
if(attached_surgery)
QDEL_NULL(attached_surgery)
remove_wound()
set_limb(null)
victim = null
if (limb)
remove_wound()
return ..()
// Applied into wounds when they're scanned with the wound analyzer, halves time to treat them manually.
@@ -118,22 +127,10 @@
* * wound_source: The source of the wound, such as a weapon.
*/
/datum/wound/proc/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE, attack_direction = null, wound_source = "Unknown")
if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || !IS_ORGANIC_LIMB(L) || HAS_TRAIT(L.owner, TRAIT_NEVER_WOUNDED) || (L.owner.status_flags & GODMODE))
qdel(src)
return
// Checks for biological state, to ensure only valid wounds are applied on the limb
if(((wound_flags & BONE_WOUND) && !(L.biological_state & BIO_BONE)) || ((wound_flags & FLESH_WOUND) && !(L.biological_state & BIO_FLESH)))
if (!can_be_applied_to(L, old_wound))
qdel(src)
return
// we accept promotions and demotions, but no point in redundancy. This should have already been checked wherever the wound was rolled and applied for (see: bodypart damage code), but we do an extra check
// in case we ever directly add wounds
for(var/i in L.wounds)
var/datum/wound/preexisting_wound = i
if((preexisting_wound.type == type) && (preexisting_wound != old_wound))
qdel(src)
return
return FALSE
if(isitem(wound_source))
var/obj/item/wound_item = wound_source
@@ -171,12 +168,35 @@
victim.visible_message(msg, span_userdanger("Your [limb.plaintext_zone] [occur_text]!"), vision_distance = vis_dist)
if(sound_effect)
playsound(L.owner, sound_effect, 70 + 20 * severity, TRUE)
playsound(L.owner, sound_effect, sound_volume + (20 * severity), TRUE)
wound_injury(old_wound, attack_direction = attack_direction)
if(!demoted)
second_wind()
return TRUE
/// Returns TRUE if we can be applied to the limb.
/datum/wound/proc/can_be_applied_to(obj/item/bodypart/L, datum/wound/old_wound)
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[type]
// We assume we aren't being randomly applied - we have no reason to believe we are
// And, besides, if we were, you could just as easily check our pregen data rather than run this proc
// Generally speaking this proc is called in apply_wound, which is called when the caller is already confidant in its ability to be applied
return pregen_data.can_be_applied_to(L, wound_type, old_wound)
/// Returns the zones we can be applied to.
/datum/wound/proc/get_viable_zones()
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[type]
return pregen_data.viable_zones
/// Returns the biostate we require to be applied.
/datum/wound/proc/get_required_biostate()
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[type]
return pregen_data.required_limb_biostate
// Updates descriptive texts for the wound, in case it can get altered for whatever reason
/datum/wound/proc/update_descriptions()
return
@@ -201,14 +221,16 @@
/datum/wound/proc/remove_wound(ignore_limb, replaced = FALSE)
//TODO: have better way to tell if we're getting removed without replacement (full heal) scar stuff
set_disabling(FALSE)
if(limb && !already_scarred && !replaced)
if(limb && can_scar && !already_scarred && !replaced)
already_scarred = TRUE
var/datum/scar/new_scar = new
new_scar.generate(limb, src)
remove_wound_from_victim()
null_victim() // we use the proc here because some behaviors may depend on changing victim to some new value
if(limb && !ignore_limb)
LAZYREMOVE(limb.wounds, src)
limb.update_wounds(replaced)
set_limb(null, replaced) // since we're removing limb's ref to us, we should do the same
// if you want to keep the ref, do it externally, theres no reason for us to remember it
/datum/wound/proc/remove_wound_from_victim()
if(!victim)
@@ -221,17 +243,15 @@
/**
* replace_wound() is used when you want to replace the current wound with a new wound, presumably of the same category, just of a different severity (either up or down counts)
*
* This proc actually instantiates the new wound based off the specific type path passed, then returns the new instantiated wound datum.
*
* Arguments:
* * new_type- The TYPE PATH of the wound you want to replace this, like /datum/wound/slash/severe
* * new_wound- The wound instance you want to replace this
* * smited- If this is a smite, we don't care about this wound for stat tracking purposes (not yet implemented)
*/
/datum/wound/proc/replace_wound(new_type, smited = FALSE, attack_direction = attack_direction)
var/datum/wound/new_wound = new new_type
/datum/wound/proc/replace_wound(datum/wound/new_wound, smited = FALSE, attack_direction = attack_direction)
already_scarred = TRUE
var/obj/item/bodypart/cached_limb = limb // remove_wound() nulls limb so we have to track it locally
remove_wound(replaced=TRUE)
new_wound.apply_wound(limb, old_wound = src, smited = smited, attack_direction = attack_direction, wound_source = wound_source)
new_wound.apply_wound(cached_limb, old_wound = src, smited = smited, attack_direction = attack_direction, wound_source = wound_source)
. = new_wound
qdel(src)
@@ -239,24 +259,28 @@
/datum/wound/proc/wound_injury(datum/wound/old_wound = null, attack_direction = null)
return
/// Proc called to change the variable `limb` and react to the event.
/datum/wound/proc/set_limb(new_value)
/datum/wound/proc/set_limb(obj/item/bodypart/new_value, replaced = FALSE)
if(limb == new_value)
return FALSE //Limb can either be a reference to something or `null`. Returning the number variable makes it clear no change was made.
. = limb
if(limb)
if(limb) // if we're nulling limb, we're basically detaching from it, so we should remove ourselves in that case
UnregisterSignal(limb, COMSIG_QDELETING)
LAZYREMOVE(limb.wounds, src)
limb.update_wounds(replaced)
if (disabling)
limb.remove_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src))
limb = new_value
RegisterSignal(new_value, COMSIG_QDELETING, PROC_REF(source_died))
if(. && disabling)
var/obj/item/bodypart/old_limb = .
old_limb.remove_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src))
// POST-CHANGE
if (limb)
RegisterSignal(limb, COMSIG_QDELETING, PROC_REF(source_died))
if(limb)
if(disabling)
limb.add_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src))
/// Proc called to change the variable `disabling` and react to the event.
/datum/wound/proc/set_disabling(new_value)
if(disabling == new_value)
@@ -304,25 +328,7 @@
if(I.force && tendee.combat_mode)
return FALSE
var/allowed = FALSE
// check if we have a valid treatable tool
if(I.tool_behaviour == treatable_tool)
allowed = TRUE
else if(treatable_tool == TOOL_CAUTERY && I.get_temperature() && user == victim) // allow improvised cauterization on yourself without an aggro grab
allowed = TRUE
// failing that, see if we're aggro grabbing them and if we have an item that works for aggro grabs only
else if(user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE && check_grab_treatments(I, user))
allowed = TRUE
// failing THAT, we check if we have a generally allowed item
else
for(var/allowed_type in treatable_by)
if(istype(I, allowed_type))
allowed = TRUE
break
// if none of those apply, we return false to avoid interrupting
if(!allowed)
if(!item_can_treat(I, user))
return FALSE
// now that we've determined we have a valid attempt at treating, we can stomp on their dreams if we're already interacting with the patient or if their part is obscured
@@ -338,8 +344,22 @@
return TRUE
// lastly, treat them
treat(I, user)
return TRUE
return treat(I, user) // we allow treat to return a value so it can control if the item does its normal interaction or not
/// Returns TRUE if the item can be used to treat our wounds. Hooks into treat() - only things that return TRUE here may be used there.
/datum/wound/proc/item_can_treat(obj/item/potential_treater, mob/user)
// check if we have a valid treatable tool
if(potential_treater.tool_behaviour == treatable_tool)
return TRUE
if(treatable_tool == TOOL_CAUTERY && potential_treater.get_temperature() && user == victim) // allow improvised cauterization on yourself without an aggro grab
return TRUE
// failing that, see if we're aggro grabbing them and if we have an item that works for aggro grabs only
if(user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE && check_grab_treatments(potential_treater, user))
return TRUE
// failing THAT, we check if we have a generally allowed item
for(var/allowed_type in treatable_by)
if(istype(potential_treater, allowed_type))
return TRUE
/// Return TRUE if we have an item that can only be used while aggro grabbed (unhanded aggro grab treatments go in [/datum/wound/proc/try_handling]). Treatment is still is handled in [/datum/wound/proc/treat]
/datum/wound/proc/check_grab_treatments(obj/item/I, mob/user)
@@ -361,8 +381,8 @@
/datum/wound/proc/still_exists()
return (!QDELETED(src) && limb)
/// When our parent bodypart is hurt
/datum/wound/proc/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction)
/// When our parent bodypart is hurt.
/datum/wound/proc/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction, damage_source)
return
/// Called from cryoxadone and pyroxadone when they're proc'ing. Wounds will slowly be fixed separately from other methods when these are in effect. crappy name but eh
@@ -427,9 +447,43 @@
return .
/datum/wound/proc/get_wound_description(mob/user)
. = "[victim.p_Their()] [limb.plaintext_zone] [examine_desc]"
. = severity <= WOUND_SEVERITY_MODERATE ? "[.]." : "<B>[.]!</B>"
return .
var/desc
if ((wound_flags & ACCEPTS_GAUZE) && limb.current_gauze)
var/sling_condition = get_gauze_condition()
desc = "[victim.p_Their()] [limb.plaintext_zone] is [sling_condition] fastened in a sling of [limb.current_gauze.name]"
else
desc = "[victim.p_Their()] [limb.plaintext_zone] [examine_desc]"
desc = modify_desc_before_span(desc, user)
return get_desc_intensity(desc)
/// A hook proc used to modify desc before it is spanned via [get_desc_intensity]. Useful for inserting spans yourself.
/datum/wound/proc/modify_desc_before_span(desc, mob/user)
return desc
/datum/wound/proc/get_gauze_condition()
SHOULD_BE_PURE(TRUE)
if (!limb.current_gauze)
return null
switch(limb.current_gauze.absorption_capacity)
if(0 to 1.25)
return "just barely"
if(1.25 to 2.75)
return "loosely"
if(2.75 to 4)
return "mostly"
if(4 to INFINITY)
return "tightly"
/// Spans [desc] based on our severity.
/datum/wound/proc/get_desc_intensity(desc)
SHOULD_BE_PURE(TRUE)
if (severity > WOUND_SEVERITY_MODERATE)
return span_bold("[desc]!")
return "[desc]."
/datum/wound/proc/get_scanner_description(mob/user)
return "Type: [name]\nSeverity: [severity_text()]\nDescription: [desc]\nRecommended Treatment: [treat_text]"
@@ -445,7 +499,30 @@
if(WOUND_SEVERITY_CRITICAL)
return "Critical"
/// Returns TRUE if our limb is the head or chest, FALSE otherwise.
/// Essential in the sense of "we cannot live without it".
/datum/wound/proc/limb_essential()
return (limb.body_zone == BODY_ZONE_HEAD || limb.body_zone == BODY_ZONE_CHEST)
/// Getter proc for our scar_keyword, in case we might have some custom scar gen logic.
/datum/wound/proc/get_scar_keyword(obj/item/bodypart/scarred_limb, add_to_scars)
return scar_keyword
/// Getter proc for our scar_file, in case we might have some custom scar gen logic.
/datum/wound/proc/get_scar_file(obj/item/bodypart/scarred_limb, add_to_scars)
return scar_file
/// Returns what string is displayed when a limb that has sustained this wound is examined
/// (This is examining the LIMB ITSELF, when it's not attached to someone.)
/datum/wound/proc/get_limb_examine_description()
return
/// Gets the flat percentage chance increment of a dismember occuring, if a dismember is attempted (requires mangled flesh and bone). returning 15 = +15%.
/datum/wound/proc/get_dismember_chance_bonus(existing_chance)
SHOULD_BE_PURE(TRUE)
if (wound_type == WOUND_BLUNT && severity >= WOUND_SEVERITY_CRITICAL)
return WOUND_CRITICAL_BLUNT_DISMEMBER_BONUS // we only require mangled bone (T2 blunt), but if there's a critical blunt, we'll add 15% more
#undef WOUND_CRITICAL_BLUNT_DISMEMBER_BONUS
+4
View File
@@ -0,0 +1,4 @@
/datum/wound/blunt
name = "Blunt Wound"
sound_effect = 'sound/effects/wounds/crack1.ogg'
wound_type = WOUND_BLUNT
+112 -87
View File
@@ -1,16 +1,17 @@
//SKYRAT EDIT REMOVAL - MOVED - MEDICINE
/*
/*
Blunt/Bone wounds
*/
// TODO: well, a lot really, but i'd kill to get overlays and a bonebreaking effect like Blitz: The League, similar to electric shock skeletons
/datum/wound/blunt
/datum/wound_pregen_data/bone
abstract = TRUE
required_limb_biostate = BIO_BONE
/datum/wound/blunt/bone
name = "Blunt (Bone) Wound"
sound_effect = 'sound/effects/wounds/crack1.ogg'
wound_type = WOUND_BLUNT
wound_flags = (BONE_WOUND | ACCEPTS_GAUZE)
wound_flags = (ACCEPTS_GAUZE | SPLINT_OVERLAY) // SKYRAT EDIT: MEDICAL -- Makes bone wounds have a splint overlay
scar_file = BONE_SCAR_FILE
/// Have we been bone gel'd?
var/gelled
@@ -31,19 +32,18 @@
/// If this is a chest wound and this is set, we have this chance to cough up blood when hit in the chest
var/internal_bleeding_chance = 0
wound_series = WOUND_SERIES_BONE_BLUNT_BASIC
/*
Overwriting of base procs
*/
/datum/wound/blunt/wound_injury(datum/wound/old_wound = null, attack_direction = null)
/datum/wound/blunt/bone/wound_injury(datum/wound/old_wound = null, attack_direction = null)
// hook into gaining/losing gauze so crit bone wounds can re-enable/disable depending if they're slung or not
RegisterSignals(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED), PROC_REF(update_inefficiencies))
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group)
processes = TRUE
active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND)
next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown)
RegisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand))
if(limb.held_index && victim.get_item_for_held_index(limb.held_index) && (disabling || prob(30 * severity)))
var/obj/item/I = victim.get_item_for_held_index(limb.held_index)
if(istype(I, /obj/item/offhand))
@@ -53,19 +53,37 @@
victim.visible_message(span_danger("[victim] drops [I] in shock!"), span_warning("<b>The force on your [limb.plaintext_zone] causes you to drop [I]!</b>"), vision_distance=COMBAT_MESSAGE_RANGE)
update_inefficiencies()
return ..()
/datum/wound/blunt/remove_wound(ignore_limb, replaced)
/datum/wound/blunt/bone/set_victim(new_victim)
if (victim)
UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK)
if (new_victim)
RegisterSignal(new_victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand))
return ..()
/datum/wound/blunt/bone/set_limb(obj/item/bodypart/new_value)
if (limb)
UnregisterSignal(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED))
if (new_value)
RegisterSignals(new_value, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED), PROC_REF(update_inefficiencies))
return ..()
/datum/wound/blunt/bone/remove_wound(ignore_limb, replaced)
limp_slowdown = 0
limp_chance = 0
QDEL_NULL(active_trauma)
if(limb)
UnregisterSignal(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED))
if(victim)
UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK)
return ..()
/datum/wound/blunt/handle_process(seconds_per_tick, times_fired)
/datum/wound/blunt/bone/handle_process(seconds_per_tick, times_fired)
. = ..()
if (!victim || IS_IN_STASIS(victim))
return
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle)
if(active_trauma)
QDEL_NULL(active_trauma)
@@ -98,7 +116,7 @@
remove_wound()
/// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so
/datum/wound/blunt/proc/attack_with_hurt_hand(mob/M, atom/target, proximity)
/datum/wound/blunt/bone/proc/attack_with_hurt_hand(mob/M, atom/target, proximity)
SIGNAL_HANDLER
if(victim.get_active_hand() != limb || !victim.combat_mode || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE)
@@ -119,7 +137,7 @@
return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/wound/blunt/receive_damage(wounding_type, wounding_dmg, wound_bonus)
/datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus)
if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE)
return
if(ishuman(victim))
@@ -145,45 +163,23 @@
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.add_splatter_floor(get_step(victim.loc, victim.dir))
/datum/wound/blunt/bone/modify_desc_before_span(desc)
. = ..()
/datum/wound/blunt/get_wound_description(mob/user)
if(!limb.current_gauze && !gelled && !taped)
return ..()
var/list/msg = list()
if(!limb.current_gauze)
msg += "[victim.p_Their()] [limb.plaintext_zone] [examine_desc]"
else
var/sling_condition = ""
// how much life we have left in these bandages
switch(limb.current_gauze.absorption_capacity)
if(0 to 1.25)
sling_condition = "just barely"
if(1.25 to 2.75)
sling_condition = "loosely"
if(2.75 to 4)
sling_condition = "mostly"
if(4 to INFINITY)
sling_condition = "tightly"
msg += "[victim.p_Their()] [limb.plaintext_zone] is [sling_condition] fastened in a sling of [limb.current_gauze.name]"
if(taped)
msg += ", [span_notice("and appears to be reforming itself under some surgical tape!")]"
else if(gelled)
msg += ", [span_notice("with fizzing flecks of blue bone gel sparking off the bone!")]"
else
msg += "!"
return "<B>[msg.Join()]</B>"
if (!limb.current_gauze)
if(taped)
. += ", [span_notice("and appears to be reforming itself under some surgical tape!")]"
else if(gelled)
. += ", [span_notice("with fizzing flecks of blue bone gel sparking off the bone!")]"
/datum/wound/blunt/get_limb_examine_description()
return span_warning("The bones in this limb appear badly cracked.")
/*
New common procs for /datum/wound/blunt/
New common procs for /datum/wound/blunt/bone/
*/
/datum/wound/blunt/proc/update_inefficiencies()
/datum/wound/blunt/bone/proc/update_inefficiencies()
SIGNAL_HANDLER
if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
@@ -205,42 +201,60 @@
limb.update_wounds()
/datum/wound/blunt/bone/get_scar_file(obj/item/bodypart/scarred_limb, add_to_scars)
if (scarred_limb.biological_state & BIO_BONE && (!(scarred_limb.biological_state & BIO_FLESH))) // only bone
return BONE_SCAR_FILE
else if (scarred_limb.biological_state & BIO_FLESH && (!(scarred_limb.biological_state & BIO_BONE)))
return FLESH_SCAR_FILE
return ..()
/// Joint Dislocation (Moderate Blunt)
/datum/wound/blunt/moderate
/datum/wound/blunt/bone/moderate
name = "Joint Dislocation"
desc = "Patient's bone has been unset from socket, causing pain and reduced motor function."
desc = "Patient's limb has been unset from socket, causing pain and reduced motor function."
treat_text = "Recommended application of bonesetter to affected limb, though manual relocation by applying an aggressive grab to the patient and helpfully interacting with afflicted limb may suffice."
examine_desc = "is awkwardly janked out of place"
occur_text = "janks violently and becomes unseated"
severity = WOUND_SEVERITY_MODERATE
viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
interaction_efficiency_penalty = 1.3
limp_slowdown = 3
limp_chance = 50
threshold_minimum = 35
threshold_penalty = 15
treatable_tool = TOOL_BONESET
wound_flags = (BONE_WOUND)
status_effect_type = /datum/status_effect/wound/blunt/moderate
status_effect_type = /datum/status_effect/wound/blunt/bone/moderate
scar_keyword = "bluntmoderate"
/datum/wound/blunt/moderate/Destroy()
/datum/wound_pregen_data/bone/dislocate
abstract = FALSE
wound_path_to_generate = /datum/wound/blunt/bone/moderate
required_limb_biostate = BIO_JOINTED
/datum/wound/blunt/bone/moderate/Destroy()
if(victim)
UnregisterSignal(victim, COMSIG_LIVING_DOORCRUSHED)
return ..()
/datum/wound/blunt/moderate/wound_injury(datum/wound/old_wound, attack_direction = null)
. = ..()
RegisterSignal(victim, COMSIG_LIVING_DOORCRUSHED, PROC_REF(door_crush))
/datum/wound/blunt/bone/moderate/set_victim(new_victim)
if (victim)
UnregisterSignal(victim, COMSIG_LIVING_DOORCRUSHED)
if (new_victim)
RegisterSignal(new_victim, COMSIG_LIVING_DOORCRUSHED, PROC_REF(door_crush))
return ..()
/// Getting smushed in an airlock/firelock is a last-ditch attempt to try relocating your limb
/datum/wound/blunt/moderate/proc/door_crush()
/datum/wound/blunt/bone/moderate/proc/door_crush()
SIGNAL_HANDLER
if(prob(40))
victim.visible_message(span_danger("[victim]'s dislocated [limb.plaintext_zone] pops back into place!"), span_userdanger("Your dislocated [limb.plaintext_zone] pops back into place! Ow!"))
remove_wound()
/datum/wound/blunt/moderate/try_handling(mob/living/carbon/human/user)
/datum/wound/blunt/bone/moderate/try_handling(mob/living/carbon/human/user)
if(user.pulling != victim || user.zone_selected != limb.body_zone)
return FALSE
@@ -258,7 +272,7 @@
return TRUE
/// If someone is snapping our dislocated joint back into place by hand with an aggro grab and help intent
/datum/wound/blunt/moderate/proc/chiropractice(mob/living/carbon/human/user)
/datum/wound/blunt/bone/moderate/proc/chiropractice(mob/living/carbon/human/user)
var/time = base_treat_time
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
@@ -277,7 +291,7 @@
chiropractice(user)
/// If someone is snapping our dislocated joint into a fracture by hand with an aggro grab and harm or disarm intent
/datum/wound/blunt/moderate/proc/malpractice(mob/living/carbon/human/user)
/datum/wound/blunt/bone/moderate/proc/malpractice(mob/living/carbon/human/user)
var/time = base_treat_time
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
@@ -295,7 +309,7 @@
malpractice(user)
/datum/wound/blunt/moderate/treat(obj/item/I, mob/user)
/datum/wound/blunt/bone/moderate/treat(obj/item/I, mob/user)
var/scanned = HAS_TRAIT(src, TRAIT_WOUND_SCANNED)
var/self_penalty_mult = user == victim ? 1.5 : 1
var/scanned_mult = scanned ? 0.5 : 1
@@ -324,7 +338,7 @@
Severe (Hairline Fracture)
*/
/datum/wound/blunt/severe
/datum/wound/blunt/bone/severe
name = "Hairline Fracture"
desc = "Patient's bone has suffered a crack in the foundation, causing serious pain and reduced limb functionality."
treat_text = "Recommended light surgical application of bone gel, though a sling of medical gauze will prevent worsening situation."
@@ -338,16 +352,21 @@
threshold_minimum = 60
threshold_penalty = 30
treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel)
status_effect_type = /datum/status_effect/wound/blunt/severe
status_effect_type = /datum/status_effect/wound/blunt/bone/severe
scar_keyword = "bluntsevere"
brain_trauma_group = BRAIN_TRAUMA_MILD
trauma_cycle_cooldown = 1.5 MINUTES
internal_bleeding_chance = 40
wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE)
wound_flags = (ACCEPTS_GAUZE | MANGLES_BONE | SPLINT_OVERLAY) // SKYRAT EDIT - MEDICAL (SPLINT_OVERLAY)
regen_ticks_needed = 120 // ticks every 2 seconds, 240 seconds, so roughly 4 minutes default
/datum/wound_pregen_data/bone/hairline
abstract = FALSE
wound_path_to_generate = /datum/wound/blunt/bone/severe
/// Compound Fracture (Critical Blunt)
/datum/wound/blunt/critical
/datum/wound/blunt/bone/critical
name = "Compound Fracture"
desc = "Patient's bones have suffered multiple gruesome fractures, causing significant pain and near uselessness of limb."
treat_text = "Immediate binding of affected limb, followed by surgical intervention ASAP."
@@ -363,36 +382,40 @@
threshold_penalty = 50
disabling = TRUE
treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel)
status_effect_type = /datum/status_effect/wound/blunt/critical
status_effect_type = /datum/status_effect/wound/blunt/bone/critical
scar_keyword = "bluntcritical"
brain_trauma_group = BRAIN_TRAUMA_SEVERE
trauma_cycle_cooldown = 2.5 MINUTES
internal_bleeding_chance = 60
wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE)
wound_flags = (ACCEPTS_GAUZE | MANGLES_BONE | SPLINT_OVERLAY) // SKYRAT EDIT - MEDICAL (SPLINT_OVERLAY)
regen_ticks_needed = 240 // ticks every 2 seconds, 480 seconds, so roughly 8 minutes default
/datum/wound_pregen_data/bone/compound
abstract = FALSE
wound_path_to_generate = /datum/wound/blunt/bone/critical
// doesn't make much sense for "a" bone to stick out of your head
/datum/wound/blunt/critical/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE, attack_direction = null, wound_source = "Unknown")
/datum/wound/blunt/bone/critical/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE, attack_direction = null, wound_source = "Unknown")
if(L.body_zone == BODY_ZONE_HEAD)
occur_text = "splits open, exposing a bare, cracked skull through the flesh and blood"
examine_desc = "has an unsettling indent, with bits of skull poking out"
. = ..()
/// if someone is using bone gel on our wound
/datum/wound/blunt/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user)
/datum/wound/blunt/bone/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user)
// skellies get treated nicer with bone gel since their "reattach dismembered limbs by hand" ability sucks when it's still critically wounded
if((limb.biological_state & BIO_BONE) && !(limb.biological_state & BIO_FLESH))
skelly_gel(I, user)
return
return skelly_gel(I, user)
if(gelled)
to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] is already coated with bone gel!"))
return
return TRUE
user.visible_message(span_danger("[user] begins hastily applying [I] to [victim]'s' [limb.plaintext_zone]..."), span_warning("You begin hastily applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone], disregarding the warning label..."))
if(!do_after(user, base_treat_time * 1.5 * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists))))
return
return TRUE
I.use(1)
victim.emote("scream")
@@ -415,15 +438,16 @@
if(prob(25 + (20 * (severity - 2)) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers
victim.visible_message(span_danger("[victim] fails to finish applying [I] to [victim.p_their()] [limb.plaintext_zone], passing out from the pain!"), span_notice("You pass out from the pain of applying [I] to your [limb.plaintext_zone] before you can finish!"))
victim.AdjustUnconscious(5 SECONDS)
return
return TRUE
victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [limb.plaintext_zone], grimacing from the pain!"), span_notice("You finish applying [I] to your [limb.plaintext_zone], and your bones explode in pain!"))
limb.receive_damage(25, wound_bonus=CANT_WOUND)
victim.adjustStaminaLoss(100)
gelled = TRUE
return TRUE
/// skellies are less averse to bone gel, since they're literally all bone
/datum/wound/blunt/proc/skelly_gel(obj/item/stack/medical/bone_gel/I, mob/user)
/datum/wound/blunt/bone/proc/skelly_gel(obj/item/stack/medical/bone_gel/I, mob/user)
if(gelled)
to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] is already coated with bone gel!"))
return
@@ -442,20 +466,21 @@
gelled = TRUE
processes = TRUE
return TRUE
/// if someone is using surgical tape on our wound
/datum/wound/blunt/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user)
/datum/wound/blunt/bone/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user)
if(!gelled)
to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] must be coated with bone gel to perform this emergency operation!"))
return
return TRUE
if(taped)
to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] is already wrapped in [I.name] and reforming!"))
return
return TRUE
user.visible_message(span_danger("[user] begins applying [I] to [victim]'s' [limb.plaintext_zone]..."), span_warning("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]..."))
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists))))
return
return TRUE
if(victim == user)
regen_ticks_needed *= 1.5
@@ -469,14 +494,15 @@
taped = TRUE
processes = TRUE
return TRUE
/datum/wound/blunt/treat(obj/item/I, mob/user)
/datum/wound/blunt/bone/treat(obj/item/I, mob/user)
if(istype(I, /obj/item/stack/medical/bone_gel))
gel(I, user)
return gel(I, user)
else if(istype(I, /obj/item/stack/sticky_tape/surgical))
tape(I, user)
return tape(I, user)
/datum/wound/blunt/get_scanner_description(mob/user)
/datum/wound/blunt/bone/get_scanner_description(mob/user)
. = ..()
. += "<div class='ml-3'>"
@@ -500,4 +526,3 @@
else if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume)
. += "Ribcage Trauma Detected: Further trauma to chest is likely to worsen internal bleeding until bone is repaired."
. += "</div>"
*/
+73 -32
View File
@@ -1,6 +1,3 @@
//SKYRAT EDIT REMOVAL - MOVED - MEDICINE
/*
/*
Burn wounds
*/
@@ -10,9 +7,17 @@
name = "Burn Wound"
a_or_from = "from"
wound_type = WOUND_BURN
processes = TRUE
sound_effect = 'sound/effects/wounds/sizzle1.ogg'
wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE)
/datum/wound/burn/flesh
name = "Burn (Flesh) Wound"
a_or_from = "from"
wound_type = WOUND_BURN
processes = TRUE
scar_file = FLESH_SCAR_FILE
wound_series = WOUND_SERIES_FLESH_BURN_BASIC
treatable_by = list(/obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon
@@ -33,8 +38,11 @@
/// Once we reach infestation beyond WOUND_INFESTATION_SEPSIS, we get this many warnings before the limb is completely paralyzed (you'd have to ignore a really bad burn for a really long time for this to happen)
var/strikes_to_lose_limb = 3
/datum/wound/burn/flesh/handle_process(seconds_per_tick, times_fired)
if (!victim || IS_IN_STASIS(victim))
return
/datum/wound/burn/handle_process(seconds_per_tick, times_fired)
. = ..()
if(strikes_to_lose_limb == 0) // we've already hit sepsis, nothing more to do
victim.adjustToxLoss(0.25 * seconds_per_tick)
@@ -130,7 +138,7 @@
var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone)
victim.gain_trauma(sepsis)
/datum/wound/burn/get_wound_description(mob/user)
/datum/wound/burn/flesh/get_wound_description(mob/user)
if(strikes_to_lose_limb <= 0)
return span_deadsay("<B>[victim.p_Their()] [limb.plaintext_zone] has locked up completely and is non-functional.</B>")
@@ -163,7 +171,7 @@
return "<B>[condition.Join()]</B>"
/datum/wound/burn/get_scanner_description(mob/user)
/datum/wound/burn/flesh/get_scanner_description(mob/user)
if(strikes_to_lose_limb <= 0) // Unclear if it can go below 0, best to not take the chance
var/oopsie = "Type: [name]\nSeverity: [severity_text()]"
oopsie += "<div class='ml-3'>Infection Level: [span_deadsay("The body part has suffered complete sepsis and must be removed. Amputate or augment limb immediately, or place the patient in a cryotube.")]</div>"
@@ -196,12 +204,12 @@
*/
/// if someone is using ointment or mesh on our burns
/datum/wound/burn/proc/ointmentmesh(obj/item/stack/medical/I, mob/user)
/datum/wound/burn/flesh/proc/ointmentmesh(obj/item/stack/medical/I, mob/user)
user.visible_message(span_notice("[user] begins applying [I] to [victim]'s [limb.plaintext_zone]..."), span_notice("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]..."))
if (I.amount <= 0)
return
return TRUE
if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
return TRUE
limb.heal_damage(I.heal_brute, I.heal_burn)
user.visible_message(span_green("[user] applies [I] to [victim]."), span_green("You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]."))
@@ -211,36 +219,38 @@
if((infestation <= 0 || sanitization >= infestation) && (flesh_damage <= 0 || flesh_healing > flesh_damage))
to_chat(user, span_notice("You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.plaintext_zone] to recover."))
return TRUE
else
try_treating(I, user)
return try_treating(I, user)
/// Paramedic UV penlights
/datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user)
/datum/wound/burn/flesh/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user)
if(!COOLDOWN_FINISHED(I, uv_cooldown))
to_chat(user, span_notice("[I] is still recharging!"))
return
return TRUE
if(infestation <= 0 || infestation < sanitization)
to_chat(user, span_notice("There's no infection to treat on [victim]'s [limb.plaintext_zone]!"))
return
return TRUE
user.visible_message(span_notice("[user] flashes the burns on [victim]'s [limb] with [I]."), span_notice("You flash the burns on [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]."), vision_distance=COMBAT_MESSAGE_RANGE)
sanitization += I.uv_power
COOLDOWN_START(I, uv_cooldown, I.uv_cooldown_length)
return TRUE
/datum/wound/burn/treat(obj/item/I, mob/user)
/datum/wound/burn/flesh/treat(obj/item/I, mob/user)
if(istype(I, /obj/item/stack/medical/ointment))
ointmentmesh(I, user)
return ointmentmesh(I, user)
else if(istype(I, /obj/item/stack/medical/mesh))
var/obj/item/stack/medical/mesh/mesh_check = I
if(!mesh_check.is_open)
to_chat(user, span_warning("You need to open [mesh_check] first."))
return
ointmentmesh(mesh_check, user)
return ointmentmesh(mesh_check, user)
else if(istype(I, /obj/item/flashlight/pen/paramedic))
uv(I, user)
return uv(I, user)
// people complained about burns not healing on stasis beds, so in addition to checking if it's cured, they also get the special ability to very slowly heal on stasis beds if they have the healing effects stored
/datum/wound/burn/on_stasis(seconds_per_tick, times_fired)
/datum/wound/burn/flesh/on_stasis(seconds_per_tick, times_fired)
. = ..()
if(strikes_to_lose_limb == 0) // we've already hit sepsis, nothing more to do
if(SPT_PROB(0.5, seconds_per_tick))
@@ -255,14 +265,19 @@
if(sanitization > 0)
infestation = max(infestation - (0.1 * WOUND_BURN_SANITIZATION_RATE * seconds_per_tick), 0)
/datum/wound/burn/on_synthflesh(amount)
/datum/wound/burn/flesh/on_synthflesh(amount)
flesh_healing += amount * 0.5 // 20u patch will heal 10 flesh standard
/datum/wound_pregen_data/flesh_burn
abstract = TRUE
required_limb_biostate = BIO_FLESH
/datum/wound/burn/get_limb_examine_description()
return span_warning("The flesh on this limb appears badly cooked.")
// we don't even care about first degree burns, straight to second
/datum/wound/burn/moderate
/datum/wound/burn/flesh/moderate
name = "Second Degree Burns"
desc = "Patient is suffering considerable burns with mild skin penetration, weakening limb integrity and increased burning sensations."
treat_text = "Recommended application of topical ointment or regenerative mesh to affected region."
@@ -272,11 +287,16 @@
damage_mulitplier_penalty = 1.1
threshold_minimum = 40
threshold_penalty = 30 // burns cause significant decrease in limb integrity compared to other wounds
status_effect_type = /datum/status_effect/wound/burn/moderate
status_effect_type = /datum/status_effect/wound/burn/flesh/moderate
flesh_damage = 5
scar_keyword = "burnmoderate"
/datum/wound/burn/severe
/datum/wound_pregen_data/flesh_burn/second_degree
abstract = FALSE
wound_path_to_generate = /datum/wound/burn/flesh/moderate
/datum/wound/burn/flesh/severe
name = "Third Degree Burns"
desc = "Patient is suffering extreme burns with full skin penetration, creating serious risk of infection and greatly reduced limb integrity."
treat_text = "Recommended immediate disinfection and excision of any infected skin, followed by bandaging and ointment. If the limb has locked up, it must be amputated, augmented or treated with cryogenics."
@@ -286,13 +306,18 @@
damage_mulitplier_penalty = 1.2
threshold_minimum = 80
threshold_penalty = 40
status_effect_type = /datum/status_effect/wound/burn/severe
status_effect_type = /datum/status_effect/wound/burn/flesh/severe
treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
infestation_rate = 0.07 // appx 9 minutes to reach sepsis without any treatment
flesh_damage = 12.5
scar_keyword = "burnsevere"
/datum/wound/burn/critical
/datum/wound_pregen_data/flesh_burn/third_degree
abstract = FALSE
wound_path_to_generate = /datum/wound/burn/flesh/severe
/datum/wound/burn/flesh/critical
name = "Catastrophic Burns"
desc = "Patient is suffering near complete loss of tissue and significantly charred muscle and bone, creating life-threatening risk of infection and negligible limb integrity."
treat_text = "Immediate surgical debriding of any infected skin, followed by potent tissue regeneration formula and bandaging. If the limb has locked up, it must be amputated, augmented or treated with cryogenics."
@@ -303,26 +328,42 @@
sound_effect = 'sound/effects/wounds/sizzle2.ogg'
threshold_minimum = 140
threshold_penalty = 80
status_effect_type = /datum/status_effect/wound/burn/critical
status_effect_type = /datum/status_effect/wound/burn/flesh/critical
treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
infestation_rate = 0.075 // appx 4.33 minutes to reach sepsis without any treatment
flesh_damage = 20
scar_keyword = "burncritical"
/datum/wound_pregen_data/flesh_burn/fourth_degree
abstract = FALSE
wound_path_to_generate = /datum/wound/burn/flesh/critical
///special severe wound caused by sparring interference or other god related punishments.
/datum/wound/burn/severe/brand
/datum/wound/burn/flesh/severe/brand
name = "Holy Brand"
desc = "Patient is suffering extreme burns from a strange brand marking, creating serious risk of infection and greatly reduced limb integrity."
examine_desc = "appears to have holy symbols painfully branded into their flesh, leaving severe burns."
occur_text = "chars rapidly into a strange pattern of holy symbols, burned into the flesh."
/datum/wound_pregen_data/flesh_burn/holy
abstract = FALSE
can_be_randomly_generated = FALSE
wound_path_to_generate = /datum/wound/burn/flesh/severe/brand
/// special severe wound caused by the cursed slot machine.
/datum/wound/burn/severe/cursed_brand
/datum/wound/burn/flesh/severe/cursed_brand
name = "Ancient Brand"
desc = "Patient is suffering extreme burns with oddly ornate brand markings, creating serious risk of infection and greatly reduced limb integrity."
desc = "Patient is suffering extreme burns with oddly ornate brand markings, creating serious risk of infection and greatly reduced limb integrity."
examine_desc = "appears to have ornate symbols painfully branded into their flesh, leaving severe burns"
occur_text = "chars rapidly into a pattern that can only be described as an agglomeration of several financial symbols, burned into the flesh"
/datum/wound/burn/severe/cursed_brand/get_limb_examine_description()
/datum/wound/burn/flesh/severe/cursed_brand/get_limb_examine_description()
return span_warning("The flesh on this limb has several ornate symbols burned into it, with pitting throughout.")
*/
/datum/wound_pregen_data/flesh_burn/cursed_brand
abstract = FALSE
can_be_randomly_generated = FALSE
wound_path_to_generate = /datum/wound/burn/flesh/severe/cursed_brand
+55 -16
View File
@@ -1,3 +1,9 @@
/datum/wound_pregen_data/loss
abstract = FALSE
wound_path_to_generate = /datum/wound/loss
required_limb_biostate = NONE
check_for_any = TRUE
/datum/wound/loss
name = "Dismemberment Wound"
@@ -11,9 +17,12 @@
wound_flags = null
already_scarred = TRUE // We manually assign scars for dismembers through endround missing limbs and aheals
/// The wound_type of the attack that caused us. Used to generate the description of our scar. Currently unused, but primarily exists in case non-biological wounds are added.
var/loss_wound_type
/// Our special proc for our special dismembering, the wounding type only matters for what text we have
/datum/wound/loss/proc/apply_dismember(obj/item/bodypart/dismembered_part, wounding_type=WOUND_SLASH, outright = FALSE, attack_direction)
if(!istype(dismembered_part) || !dismembered_part.owner || !(dismembered_part.body_zone in viable_zones) || isalien(dismembered_part.owner) || !dismembered_part.can_dismember())
/datum/wound/loss/proc/apply_dismember(obj/item/bodypart/dismembered_part, wounding_type = WOUND_SLASH, outright = FALSE, attack_direction)
if(!istype(dismembered_part) || !dismembered_part.owner || !(dismembered_part.body_zone in get_viable_zones()) || isalien(dismembered_part.owner) || !dismembered_part.can_dismember())
qdel(src)
return
@@ -23,7 +32,28 @@
if(dismembered_part.body_zone == BODY_ZONE_CHEST)
occur_text = "is split open, causing [victim.p_their()] internal organs to spill out!"
self_msg = "is split open, causing your internal organs to spill out!"
else if(outright)
else
occur_text = dismembered_part.get_dismember_message(wounding_type, outright)
var/msg = span_bolddanger("[victim]'s [dismembered_part.plaintext_zone] [occur_text]")
victim.visible_message(msg, span_userdanger("Your [dismembered_part.plaintext_zone] [self_msg ? self_msg : occur_text]"))
loss_wound_type = wounding_type
set_limb(dismembered_part)
second_wind()
log_wound(victim, src)
if(dismembered_part.can_bleed() && wounding_type != WOUND_BURN && victim.blood_volume)
victim.spray_blood(attack_direction, severity)
dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE, wound_type = wounding_type)
qdel(src)
return TRUE
/obj/item/bodypart/proc/get_dismember_message(wounding_type, outright)
var/occur_text
if(outright)
switch(wounding_type)
if(WOUND_BLUNT)
occur_text = "is outright smashed to a gross pulp, severing it completely!"
@@ -34,25 +64,34 @@
if(WOUND_BURN)
occur_text = "is outright incinerated, falling to dust!"
else
var/bone_text
if (biological_state & BIO_BONE)
bone_text = "bone"
else if (biological_state & BIO_METAL)
bone_text = "metal"
var/tissue_text
if (biological_state & BIO_FLESH)
tissue_text = "flesh"
else if (biological_state & BIO_WIRED)
tissue_text = "wire"
switch(wounding_type)
if(WOUND_BLUNT)
occur_text = "is shattered through the last bone holding it together, severing it completely!"
occur_text = "is shattered through the last [bone_text] holding it together, severing it completely!"
if(WOUND_SLASH)
occur_text = "is slashed through the last tissue holding it together, severing it completely!"
occur_text = "is slashed through the last [tissue_text] holding it together, severing it completely!"
if(WOUND_PIERCE)
occur_text = "is pierced through the last tissue holding it together, severing it completely!"
occur_text = "is pierced through the last [tissue_text] holding it together, severing it completely!"
if(WOUND_BURN)
occur_text = "is completely incinerated, falling to dust!"
var/msg = span_bolddanger("[victim]'s [dismembered_part.plaintext_zone] [occur_text]")
return occur_text
victim.visible_message(msg, span_userdanger("Your [dismembered_part.plaintext_zone] [self_msg ? self_msg : occur_text]"))
/datum/wound/loss/get_scar_file(obj/item/bodypart/scarred_limb, add_to_scars)
if (scarred_limb.biological_state & BIO_FLESH)
return FLESH_SCAR_FILE
if (scarred_limb.biological_state & BIO_BONE)
return BONE_SCAR_FILE
set_limb(dismembered_part)
second_wind()
log_wound(victim, src)
if(wounding_type != WOUND_BURN && victim.blood_volume)
victim.spray_blood(attack_direction, severity)
dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE)
qdel(src)
return TRUE
return ..()
+63 -32
View File
@@ -1,19 +1,22 @@
//SKYRAT EDIT REMOVAL - MOVED - MEDICINE
/*
/*
Piercing wounds
*/
/datum/wound/pierce
wound_type = WOUND_PIERCE
/datum/wound/pierce/bleed
name = "Piercing Wound"
sound_effect = 'sound/weapons/slice.ogg'
processes = TRUE
wound_type = WOUND_PIERCE
treatable_by = list(/obj/item/stack/medical/suture)
treatable_tool = TOOL_CAUTERY
base_treat_time = 3 SECONDS
wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE)
wound_flags = (ACCEPTS_GAUZE)
wound_series = WOUND_SERIES_FLESH_SLASH_BLEED
scar_file = FLESH_SCAR_FILE
/// How much blood we start losing when this wound is first applied
var/initial_flow
@@ -25,12 +28,14 @@
/// If we let off blood when hit, the max blood lost is this * the incoming damage
var/internal_bleeding_coefficient
/datum/wound/pierce/wound_injury(datum/wound/old_wound = null, attack_direction = null)
/datum/wound/pierce/bleed/wound_injury(datum/wound/old_wound = null, attack_direction = null)
set_blood_flow(initial_flow)
if(!no_bleeding && attack_direction && victim.blood_volume > BLOOD_VOLUME_OKAY)
victim.spray_blood(attack_direction, severity)
/datum/wound/pierce/receive_damage(wounding_type, wounding_dmg, wound_bonus)
return ..()
/datum/wound/pierce/bleed/receive_damage(wounding_type, wounding_dmg, wound_bonus)
if(victim.stat == DEAD || (wounding_dmg < 5) || no_bleeding || !victim.blood_volume || !prob(internal_bleeding_chance + wounding_dmg))
return
if(limb.current_gauze?.splint_factor)
@@ -52,7 +57,7 @@
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.add_splatter_floor(get_step(victim.loc, victim.dir))
/datum/wound/pierce/get_bleed_rate_of_change()
/datum/wound/pierce/bleed/get_bleed_rate_of_change()
//basically if a species doesn't bleed, the wound is stagnant and will not heal on it's own (nor get worse)
if(no_bleeding)
return BLOOD_FLOW_STEADY
@@ -62,7 +67,10 @@
return BLOOD_FLOW_DECREASING
return BLOOD_FLOW_STEADY
/datum/wound/pierce/handle_process(seconds_per_tick, times_fired)
/datum/wound/pierce/bleed/handle_process(seconds_per_tick, times_fired)
if (!victim || IS_IN_STASIS(victim))
return
set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW))
if(!no_bleeding)
@@ -81,31 +89,33 @@
if(blood_flow <= 0)
qdel(src)
/datum/wound/pierce/on_stasis(seconds_per_tick, times_fired)
/datum/wound/pierce/bleed/on_stasis(seconds_per_tick, times_fired)
. = ..()
if(blood_flow <= 0)
qdel(src)
/datum/wound/pierce/check_grab_treatments(obj/item/I, mob/user)
/datum/wound/pierce/bleed/check_grab_treatments(obj/item/I, mob/user)
if(I.get_temperature()) // if we're using something hot but not a cautery, we need to be aggro grabbing them first, so we don't try treating someone we're eswording
return TRUE
/datum/wound/pierce/treat(obj/item/I, mob/user)
/datum/wound/pierce/bleed/treat(obj/item/I, mob/user)
if(istype(I, /obj/item/stack/medical/suture))
suture(I, user)
return suture(I, user)
else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature())
tool_cauterize(I, user)
return tool_cauterize(I, user)
/datum/wound/pierce/on_xadone(power)
/datum/wound/pierce/bleed/on_xadone(power)
. = ..()
adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort
/datum/wound/pierce/on_synthflesh(power)
if (limb) // parent can cause us to be removed, so its reasonable to check if we're still applied
adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort
/datum/wound/pierce/bleed/on_synthflesh(power)
. = ..()
adjust_blood_flow(-0.025 * power) // 20u * 0.05 = -1 blood flow, less than with slashes but still good considering smaller bleed rates
/// If someone is using a suture to close this puncture
/datum/wound/pierce/proc/suture(obj/item/stack/medical/suture/I, mob/user)
/datum/wound/pierce/bleed/proc/suture(obj/item/stack/medical/suture/I, mob/user)
var/self_penalty_mult = (user == victim ? 1.4 : 1)
var/treatment_delay = base_treat_time * self_penalty_mult
@@ -116,7 +126,7 @@
user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]..."))
if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
return TRUE
var/bleeding_wording = (no_bleeding ? "holes" : "bleeding")
user.visible_message(span_green("[user] stitches up some of the [bleeding_wording] on [victim]."), span_green("You stitch up some of the [bleeding_wording] on [user == victim ? "yourself" : "[victim]"]."))
var/blood_sutured = I.stop_bleeding / self_penalty_mult
@@ -125,12 +135,13 @@
I.use(1)
if(blood_flow > 0)
try_treating(I, user)
return try_treating(I, user)
else
to_chat(user, span_green("You successfully close the hole in [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]."))
return TRUE
/// If someone is using either a cautery tool or something with heat to cauterize this pierce
/datum/wound/pierce/proc/tool_cauterize(obj/item/I, mob/user)
/datum/wound/pierce/bleed/proc/tool_cauterize(obj/item/I, mob/user)
var/improv_penalty_mult = (I.tool_behaviour == TOOL_CAUTERY ? 1 : 1.25) // 25% longer and less effective if you don't use a real cautery
var/self_penalty_mult = (user == victim ? 1.5 : 1) // 50% longer and less effective if you do it to yourself
@@ -144,7 +155,7 @@
user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]..."))
if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
return TRUE
var/bleeding_wording = (no_bleeding ? "holes" : "bleeding")
user.visible_message(span_green("[user] cauterizes some of the [bleeding_wording] on [victim]."), span_green("You cauterize some of the [bleeding_wording] on [victim]."))
@@ -155,13 +166,19 @@
adjust_blood_flow(-blood_cauterized)
if(blood_flow > 0)
try_treating(I, user)
return try_treating(I, user)
return TRUE
/datum/wound_pregen_data/flesh_pierce
abstract = TRUE
required_limb_biostate = (BIO_FLESH)
/datum/wound/pierce/get_limb_examine_description()
return span_warning("The flesh on this limb appears badly perforated.")
/datum/wound/pierce/moderate
name = "Minor Breakage"
/datum/wound/pierce/bleed/moderate
name = "Minor Skin Breakage"
desc = "Patient's skin has been broken open, causing severe bruising and minor internal bleeding in affected area."
treat_text = "Treat affected site with bandaging or exposure to extreme cold. In dire cases, brief exposure to vacuum may suffice." // space is cold in ss13, so it's like an ice pack!
examine_desc = "has a small, circular hole, gently bleeding"
@@ -177,12 +194,17 @@
status_effect_type = /datum/status_effect/wound/pierce/moderate
scar_keyword = "piercemoderate"
/datum/wound/pierce/moderate/update_descriptions()
/datum/wound_pregen_data/flesh_pierce/breakage
abstract = FALSE
wound_path_to_generate = /datum/wound/pierce/bleed/moderate
/datum/wound/pierce/bleed/moderate/update_descriptions()
if(no_bleeding)
examine_desc = "has a small, circular hole"
occur_text = "splits a small hole open"
/datum/wound/pierce/severe
/datum/wound/pierce/bleed/severe
name = "Open Puncture"
desc = "Patient's internal tissue is penetrated, causing sizeable internal bleeding and reduced limb stability."
treat_text = "Repair punctures in skin by suture or cautery, extreme cold may also work."
@@ -199,11 +221,16 @@
status_effect_type = /datum/status_effect/wound/pierce/severe
scar_keyword = "piercesevere"
/datum/wound/pierce/severe/update_descriptions()
/datum/wound_pregen_data/flesh_pierce/open_puncture
abstract = FALSE
wound_path_to_generate = /datum/wound/pierce/bleed/severe
/datum/wound/pierce/bleed/severe/update_descriptions()
if(no_bleeding)
occur_text = "tears a hole open"
/datum/wound/pierce/critical
/datum/wound/pierce/bleed/critical
name = "Ruptured Cavity"
desc = "Patient's internal tissue and circulatory system is shredded, causing significant internal bleeding and damage to internal organs."
treat_text = "Surgical repair of puncture wound, followed by supervised resanguination."
@@ -219,5 +246,9 @@
threshold_penalty = 50
status_effect_type = /datum/status_effect/wound/pierce/critical
scar_keyword = "piercecritical"
wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH)
*/
wound_flags = (ACCEPTS_GAUZE | MANGLES_FLESH)
/datum/wound_pregen_data/flesh_pierce/cavity
abstract = FALSE
wound_path_to_generate = /datum/wound/pierce/bleed/critical
+40 -17
View File
@@ -22,11 +22,14 @@
var/visibility = 2
/// Whether this scar can actually be covered up by clothing
var/coverable = TRUE
/// Obviously, scars that describe damaged flesh wouldn't apply to a skeleton (in some cases like bone wounds, there can be different descriptions for skeletons and fleshy humanoids)
var/biology = BIO_FLESH_BONE
/// If we're a persistent scar or may become one, we go in this character slot
var/persistent_character_slot = 0
/// The biostates we require from a limb to give them our scar.
var/required_limb_biostate
/// If false, we will only check to see if a limb has ALL our biostates, instead of just any.
var/check_any_biostates
/datum/scar/Destroy(force, ...)
if(limb)
LAZYREMOVE(limb.scars, src)
@@ -47,6 +50,19 @@
* * add_to_scars- Should always be TRUE unless you're just storing a scar for later usage, like how cuts want to store a scar for the highest severity of cut, rather than the severity when the wound is fully healed (probably demoted to moderate)
*/
/datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE)
if (!W.can_scar)
qdel(src)
return
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[W.type]
if (!pregen_data)
qdel(src)
return
required_limb_biostate = pregen_data.required_limb_biostate
check_any_biostates = pregen_data.check_for_any
limb = BP
RegisterSignal(limb, COMSIG_QDELETING, PROC_REF(limb_gone))
@@ -59,12 +75,13 @@
if(victim)
LAZYADD(victim.all_scars, src)
biology = limb?.biological_state || BIO_FLESH_BONE
var/scar_file = W.get_scar_file(BP, add_to_scars)
var/scar_keyword = W.get_scar_keyword(BP, add_to_scars)
if (!scar_file || !scar_keyword)
qdel(src)
return
if((biology & BIO_BONE) && !(biology & BIO_FLESH))
description = pick_list(BONE_SCAR_FILE, W.scar_keyword) || "general disfigurement"
else // no specific support for flesh w/o bone scars since it's not really useful
description = pick_list(FLESH_SCAR_FILE, W.scar_keyword) || "general disfigurement"
description = pick_list(W.get_scar_file(BP, add_to_scars), W.get_scar_keyword(BP, add_to_scars)) || "general disfigurement"
precise_location = pick_list_replacements(SCAR_LOC_FILE, limb.body_zone)
switch(W.severity)
@@ -86,22 +103,28 @@
LAZYADD(victim.all_scars, src)
/// Used to "load" a persistent scar
/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity=WOUND_SEVERITY_SEVERE, biology=BIO_FLESH_BONE, char_slot)
if(!IS_ORGANIC_LIMB(BP))
/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity = WOUND_SEVERITY_SEVERE, required_limb_biostate = BIO_STANDARD, char_slot, check_any_biostates = FALSE)
if(!BP.scarrable)
qdel(src)
return
limb = BP
RegisterSignal(limb, COMSIG_QDELETING, PROC_REF(limb_gone))
if(limb.owner)
victim = limb.owner
if(limb.biological_state != biology)
if (isnull(check_any_biostates)) // so we dont break old scars. NOTE: REMOVE AFTER VERSION NUMBER MOVES PAST 3
check_any_biostates = FALSE
if (check_any_biostates)
if (!(limb.biological_state & required_limb_biostate))
qdel(src)
return
else if (!((limb.biological_state & required_limb_biostate) == required_limb_biostate)) // check for all
qdel(src)
return
if(limb.owner)
victim = limb.owner
LAZYADD(victim.all_scars, src)
src.severity = severity
src.biology = biology
src.required_limb_biostate = required_limb_biostate
persistent_character_slot = char_slot
LAZYADD(limb.scars, src)
@@ -163,9 +186,9 @@
/// Used to format a scar to save for either persistent scars, or for changeling disguises
/datum/scar/proc/format()
return "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]|[biology]|[persistent_character_slot]"
return "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]|[required_limb_biostate]|[persistent_character_slot]|[check_any_biostates]"
/// Used to format a scar to save in preferences for persistent scars
/datum/scar/proc/format_amputated(body_zone)
description = pick_list(FLESH_SCAR_FILE, "dismember")
return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]|[BIO_FLESH_BONE]|[persistent_character_slot]"
/datum/scar/proc/format_amputated(body_zone, scar_file = FLESH_SCAR_FILE)
description = pick_list(scar_file, "dismember")
return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]|[required_limb_biostate]|[persistent_character_slot]|[check_any_biostates]"
@@ -0,0 +1,20 @@
GLOBAL_LIST_INIT_TYPED(all_static_scar_data, /datum/static_scar_data, generate_static_scar_data())
/proc/generate_static_scar_data()
RETURN_TYPE(/list/datum/static_scar_data)
var/list/datum/wound_pregen_data/data = list()
for (var/datum/wound_pregen_data/path as anything in typecacheof(path = /datum/static_scar_data, ignore_root_path = TRUE))
if (initial(path.abstract))
continue
var/datum/wound_pregen_data/pregen_data = new path
data[pregen_data.wound_path_to_generate] = pregen_data
return data
/datum/static_scar_data
var/abstract = FALSE
+100 -48
View File
@@ -1,5 +1,3 @@
//SKYRAT EDIT REMOVAL - MOVED - MEDICINE
/*
/*
Slashing wounds
@@ -8,13 +6,26 @@
/datum/wound/slash
name = "Slashing (Cut) Wound"
sound_effect = 'sound/weapons/slice.ogg'
wound_type = WOUND_SLASH
/datum/wound_pregen_data/flesh_slash
abstract = TRUE
required_limb_biostate = BIO_FLESH
/datum/wound/slash/flesh
name = "Slashing (Cut) Flesh Wound"
processes = TRUE
wound_type = WOUND_SLASH
treatable_by = list(/obj/item/stack/medical/suture)
treatable_by_grabbed = list(/obj/item/gun/energy/laser)
treatable_tool = TOOL_CAUTERY
base_treat_time = 3 SECONDS
wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE)
wound_flags = (ACCEPTS_GAUZE)
scar_file = FLESH_SCAR_FILE
wound_series = WOUND_SERIES_FLESH_SLASH_BLEED
/// How much blood we start losing when this wound is first applied
var/initial_flow
@@ -32,7 +43,7 @@
/// A bad system I'm using to track the worst scar we earned (since we can demote, we want the biggest our wound has been, not what it was when it was cured (probably moderate))
var/datum/scar/highest_scar
/datum/wound/slash/wound_injury(datum/wound/slash/old_wound = null, attack_direction = null)
/datum/wound/slash/flesh/wound_injury(datum/wound/slash/flesh/old_wound = null, attack_direction = null)
if(old_wound)
set_blood_flow(max(old_wound.blood_flow, initial_flow))
if(old_wound.severity > severity && old_wound.highest_scar)
@@ -48,24 +59,26 @@
set_highest_scar(new_scar)
new_scar.generate(limb, src, add_to_scars=FALSE)
/datum/wound/slash/proc/set_highest_scar(datum/scar/new_scar)
return ..()
/datum/wound/slash/flesh/proc/set_highest_scar(datum/scar/new_scar)
if(highest_scar)
UnregisterSignal(highest_scar, COMSIG_QDELETING)
if(new_scar)
RegisterSignal(new_scar, COMSIG_QDELETING, PROC_REF(clear_highest_scar))
highest_scar = new_scar
/datum/wound/slash/proc/clear_highest_scar(datum/source)
/datum/wound/slash/flesh/proc/clear_highest_scar(datum/source)
SIGNAL_HANDLER
set_highest_scar(null)
/datum/wound/slash/remove_wound(ignore_limb, replaced)
/datum/wound/slash/flesh/remove_wound(ignore_limb, replaced)
if(!replaced && highest_scar)
already_scarred = TRUE
highest_scar.lazy_attach(limb)
return ..()
/datum/wound/slash/get_wound_description(mob/user)
/datum/wound/slash/flesh/get_wound_description(mob/user)
if(!limb.current_gauze)
return ..()
@@ -84,11 +97,16 @@
return "<B>[msg.Join()]</B>"
/datum/wound/slash/receive_damage(wounding_type, wounding_dmg, wound_bonus)
/datum/wound/slash/flesh/receive_damage(wounding_type, wounding_dmg, wound_bonus)
if (!victim) // if we are dismembered, we can still take damage, its fine to check here
return
if(victim.stat != DEAD && wound_bonus != CANT_WOUND && wounding_type == WOUND_SLASH) // can't stab dead bodies to make it bleed faster this way
adjust_blood_flow(WOUND_SLASH_DAMAGE_FLOW_COEFF * wounding_dmg)
/datum/wound/slash/drag_bleed_amount()
return ..()
/datum/wound/slash/flesh/drag_bleed_amount()
// say we have 3 severe cuts with 3 blood flow each, pretty reasonable
// compare with being at 100 brute damage before, where you bled (brute/100 * 2), = 2 blood per tile
var/bleed_amt = min(blood_flow * 0.1, 1) // 3 * 3 * 0.1 = 0.9 blood total, less than before! the share here is .3 blood of course.
@@ -99,7 +117,7 @@
return bleed_amt
/datum/wound/slash/get_bleed_rate_of_change()
/datum/wound/slash/flesh/get_bleed_rate_of_change()
//basically if a species doesn't bleed, the wound is stagnant and will not heal on it's own (nor get worse)
if(no_bleeding)
return BLOOD_FLOW_STEADY
@@ -110,7 +128,11 @@
if(clot_rate < 0)
return BLOOD_FLOW_INCREASING
/datum/wound/slash/handle_process(seconds_per_tick, times_fired)
/datum/wound/slash/flesh/handle_process(seconds_per_tick, times_fired)
if (!victim || IS_IN_STASIS(victim))
return
// in case the victim has the NOBLOOD trait, the wound will simply not clot on it's own
if(!no_bleeding)
set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW))
@@ -133,36 +155,36 @@
if(blood_flow < minimum_flow)
if(demotes_to)
replace_wound(demotes_to)
replace_wound(new demotes_to)
else
to_chat(victim, span_green("The cut on your [limb.plaintext_zone] has [no_bleeding ? "healed up" : "stopped bleeding"]!"))
qdel(src)
/datum/wound/slash/on_stasis(seconds_per_tick, times_fired)
/datum/wound/slash/flesh/on_stasis(seconds_per_tick, times_fired)
if(blood_flow >= minimum_flow)
return
if(demotes_to)
replace_wound(demotes_to)
replace_wound(new demotes_to)
return
qdel(src)
/* BEWARE, THE BELOW NONSENSE IS MADNESS. bones.dm looks more like what I have in mind and is sufficiently clean, don't pay attention to this messiness */
/datum/wound/slash/check_grab_treatments(obj/item/I, mob/user)
/datum/wound/slash/flesh/check_grab_treatments(obj/item/I, mob/user)
if(istype(I, /obj/item/gun/energy/laser))
return TRUE
if(I.get_temperature()) // if we're using something hot but not a cautery, we need to be aggro grabbing them first, so we don't try treating someone we're eswording
return TRUE
/datum/wound/slash/treat(obj/item/I, mob/user)
/datum/wound/slash/flesh/treat(obj/item/I, mob/user)
if(istype(I, /obj/item/gun/energy/laser))
las_cauterize(I, user)
return las_cauterize(I, user)
else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature())
tool_cauterize(I, user)
return tool_cauterize(I, user)
else if(istype(I, /obj/item/stack/medical/suture))
suture(I, user)
return suture(I, user)
/datum/wound/slash/try_handling(mob/living/carbon/human/user)
/datum/wound/slash/flesh/try_handling(mob/living/carbon/human/user)
if(user.pulling != victim || user.zone_selected != limb.body_zone || !isfelinid(user) || !victim.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
return FALSE
if(DOING_INTERACTION_WITH_TARGET(user, victim))
@@ -179,7 +201,7 @@
return TRUE
/// if a felinid is licking this cut to reduce bleeding
/datum/wound/slash/proc/lick_wounds(mob/living/carbon/human/user)
/datum/wound/slash/flesh/proc/lick_wounds(mob/living/carbon/human/user)
// transmission is one way patient -> felinid since google said cat saliva is antiseptic or whatever, and also because felinids are already risking getting beaten for this even without people suspecting they're spreading a deathvirus
for(var/i in victim.diseases)
var/datum/disease/iter_disease = i
@@ -201,16 +223,18 @@
else if(demotes_to)
to_chat(user, span_green("You successfully lower the severity of [victim]'s cuts."))
/datum/wound/slash/on_xadone(power)
/datum/wound/slash/flesh/on_xadone(power)
. = ..()
adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort
/datum/wound/slash/on_synthflesh(power)
if (limb) // parent can cause us to be removed, so its reasonable to check if we're still applied
adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort
/datum/wound/slash/flesh/on_synthflesh(power)
. = ..()
adjust_blood_flow(-0.075 * power) // 20u * 0.075 = -1.5 blood flow, pretty good for how little effort it is
/// If someone's putting a laser gun up to our cut to cauterize it
/datum/wound/slash/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user)
/datum/wound/slash/flesh/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user)
var/self_penalty_mult = (user == victim ? 1.25 : 1)
user.visible_message(span_warning("[user] begins aiming [lasgun] directly at [victim]'s [limb.plaintext_zone]..."), span_userdanger("You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]..."))
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
@@ -223,9 +247,10 @@
victim.emote("scream")
adjust_blood_flow(-1 * (damage / (5 * self_penalty_mult))) // 20 / 5 = 4 bloodflow removed, p good
victim.visible_message(span_warning("The cuts on [victim]'s [limb.plaintext_zone] scar over!"))
return TRUE
/// If someone is using either a cautery tool or something with heat to cauterize this cut
/datum/wound/slash/proc/tool_cauterize(obj/item/I, mob/user)
/datum/wound/slash/flesh/proc/tool_cauterize(obj/item/I, mob/user)
var/improv_penalty_mult = (I.tool_behaviour == TOOL_CAUTERY ? 1 : 1.25) // 25% longer and less effective if you don't use a real cautery
var/self_penalty_mult = (user == victim ? 1.5 : 1) // 50% longer and less effective if you do it to yourself
@@ -248,12 +273,14 @@
adjust_blood_flow(-blood_cauterized)
if(blood_flow > minimum_flow)
try_treating(I, user)
return try_treating(I, user)
else if(demotes_to)
to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts."))
return TRUE
return FALSE
/// If someone is using a suture to close this cut
/datum/wound/slash/proc/suture(obj/item/stack/medical/suture/I, mob/user)
/datum/wound/slash/flesh/proc/suture(obj/item/stack/medical/suture/I, mob/user)
var/self_penalty_mult = (user == victim ? 1.4 : 1)
var/treatment_delay = base_treat_time * self_penalty_mult
@@ -264,7 +291,7 @@
user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]..."))
if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
return TRUE
var/bleeding_wording = (no_bleeding ? "cuts" : "bleeding")
user.visible_message(span_green("[user] stitches up some of the [bleeding_wording] on [victim]."), span_green("You stitch up some of the [bleeding_wording] on [user == victim ? "yourself" : "[victim]"]."))
var/blood_sutured = I.stop_bleeding / self_penalty_mult
@@ -273,14 +300,16 @@
I.use(1)
if(blood_flow > minimum_flow)
try_treating(I, user)
return try_treating(I, user)
else if(demotes_to)
to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts."))
return TRUE
return TRUE
/datum/wound/slash/get_limb_examine_description()
return span_warning("The flesh on this limb appears badly lacerated.")
/datum/wound/slash/moderate
/datum/wound/slash/flesh/moderate
name = "Rough Abrasion"
desc = "Patient's skin has been badly scraped, generating moderate blood loss."
treat_text = "Application of clean bandages or first-aid grade sutures, followed by food and rest."
@@ -293,14 +322,19 @@
clot_rate = 0.05
threshold_minimum = 20
threshold_penalty = 10
status_effect_type = /datum/status_effect/wound/slash/moderate
status_effect_type = /datum/status_effect/wound/slash/flesh/moderate
scar_keyword = "slashmoderate"
/datum/wound/slash/moderate/update_descriptions()
/datum/wound/slash/flesh/moderate/update_descriptions()
if(no_bleeding)
occur_text = "is cut open"
/datum/wound/slash/severe
/datum/wound_pregen_data/flesh_slash/abrasion
abstract = FALSE
wound_path_to_generate = /datum/wound/slash/flesh/moderate
/datum/wound/slash/flesh/severe
name = "Open Laceration"
desc = "Patient's skin is ripped clean open, allowing significant blood loss."
treat_text = "Speedy application of first-aid grade sutures and clean bandages, followed by vitals monitoring to ensure recovery."
@@ -313,22 +347,25 @@
clot_rate = 0.03
threshold_minimum = 50
threshold_penalty = 25
demotes_to = /datum/wound/slash/moderate
status_effect_type = /datum/status_effect/wound/slash/severe
demotes_to = /datum/wound/slash/flesh/moderate
status_effect_type = /datum/status_effect/wound/slash/flesh/severe
scar_keyword = "slashsevere"
/datum/wound/slash/severe/update_descriptions()
/datum/wound_pregen_data/flesh_slash/laceration
abstract = FALSE
wound_path_to_generate = /datum/wound/slash/flesh/severe
/datum/wound/slash/flesh/severe/update_descriptions()
if(no_bleeding)
occur_text = "is ripped open"
/datum/wound/slash/critical
/datum/wound/slash/flesh/critical
name = "Weeping Avulsion"
desc = "Patient's skin is completely torn open, along with significant loss of tissue. Extreme blood loss will lead to quick death without intervention."
treat_text = "Immediate bandaging and either suturing or cauterization, followed by supervised resanguination."
examine_desc = "is carved down to the bone, spraying blood wildly"
examine_desc = "is carved down to the bone"
occur_text = "is torn open, spraying blood wildly"
occur_text = "is torn open"
sound_effect = 'sound/effects/wounds/blood3.ogg'
severity = WOUND_SEVERITY_CRITICAL
initial_flow = 4
@@ -336,25 +373,40 @@
clot_rate = -0.015 // critical cuts actively get worse instead of better
threshold_minimum = 80
threshold_penalty = 40
demotes_to = /datum/wound/slash/severe
status_effect_type = /datum/status_effect/wound/slash/critical
demotes_to = /datum/wound/slash/flesh/severe
status_effect_type = /datum/status_effect/wound/slash/flesh/critical
scar_keyword = "slashcritical"
wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH)
wound_flags = (ACCEPTS_GAUZE | MANGLES_FLESH)
/datum/wound/slash/moderate/many_cuts
/datum/wound_pregen_data/flesh_slash/avulsion
abstract = FALSE
wound_path_to_generate = /datum/wound/slash/flesh/critical
/datum/wound/slash/flesh/moderate/many_cuts
name = "Numerous Small Slashes"
desc = "Patient's skin has numerous small slashes and cuts, generating moderate blood loss."
examine_desc = "has a ton of small cuts"
occur_text = "is cut numerous times, leaving many small slashes."
/datum/wound_pregen_data/flesh_slash/cuts
abstract = FALSE
can_be_randomly_generated = FALSE
wound_path_to_generate = /datum/wound/slash/flesh/moderate/many_cuts
// Subtype for cleave (heretic spell)
/datum/wound/slash/critical/cleave
/datum/wound/slash/flesh/critical/cleave
name = "Burning Avulsion"
examine_desc = "is ruptured, spraying blood wildly"
clot_rate = 0.01
/datum/wound/slash/critical/cleave/update_descriptions()
/datum/wound/slash/flesh/critical/cleave/update_descriptions()
if(no_bleeding)
occur_text = "is ruptured"
*/
/datum/wound_pregen_data/flesh_slash/cleave
abstract = FALSE
can_be_randomly_generated = FALSE
wound_path_to_generate = /datum/wound/slash/flesh/critical/cleave