[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
@@ -6,6 +6,8 @@
#define COMSIG_ATOM_EXPOSE_REAGENTS "atom_expose_reagents"
/// Prevents the atom from being exposed to reagents if returned on [COMSIG_ATOM_EXPOSE_REAGENTS]
#define COMPONENT_NO_EXPOSE_REAGENTS (1<<0)
///from base of atom/expose_reagents(): (/list, /datum/reagents, methods, volume_modifier, show_message)
#define COMSIG_ATOM_AFTER_EXPOSE_REAGENTS "atom_after_expose_reagents"
///from base of [/datum/reagent/proc/expose_atom]: (/datum/reagent, reac_volume)
#define COMSIG_ATOM_EXPOSE_REAGENT "atom_expose_reagent"
///from base of [/datum/reagent/proc/expose_atom]: (/atom, reac_volume)
+56 -59
View File
@@ -32,11 +32,6 @@
#define WOUND_PIERCE 3
/// any concentrated burn attack (lasers really). rolls for burning wounds
#define WOUND_BURN 4
//SKYRAT EDIT ADDITION BEGIN - MEDICAL
/// any brute attacks, rolled on a chance
#define WOUND_MUSCLE 5
//SKYRAT EDIT ADDITION END
// ~determination second wind defines
// How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind]
@@ -50,36 +45,57 @@
/// While someone has determination in their system, their bleed rate is slightly reduced
#define WOUND_DETERMINATION_BLEED_MOD 0.85
// ~wound global lists
// list in order of highest severity to lowest
GLOBAL_LIST_INIT(global_wound_types, list(
WOUND_BLUNT = list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate),
WOUND_SLASH = list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate),
WOUND_PIERCE = list(/datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate),
WOUND_BURN = list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate),
WOUND_MUSCLE = list(/datum/wound/muscle/severe, /datum/wound/muscle/moderate), /* SKYRAT EDIT ADD */
))
// every single type of wound that can be rolled naturally, in case you need to pull a random one
GLOBAL_LIST_INIT(global_all_wound_types, list(
/datum/wound/blunt/critical,
/datum/wound/blunt/severe,
/datum/wound/blunt/moderate,
/datum/wound/slash/critical,
/datum/wound/slash/severe,
/datum/wound/slash/moderate,
/datum/wound/pierce/critical,
/datum/wound/pierce/severe,
/datum/wound/pierce/moderate,
/datum/wound/burn/critical,
/datum/wound/burn/severe,
/datum/wound/burn/moderate,
/* SKYRAT EDIT ADD START */
/datum/wound/muscle/severe,
/datum/wound/muscle/moderate,
/* SKYRAT EDIT ADD END */
// ~biology defines
// What kind of biology a limb has, and what wounds it can suffer
/// Has absolutely fucking nothing, no wounds
#define BIO_INORGANIC NONE
/// Has bone - allows the victim to suffer T2-T3 bone blunt wounds
#define BIO_BONE (1<<0)
/// Has flesh - allows the victim to suffer fleshy slash pierce and burn wounds
#define BIO_FLESH (1<<1)
/// Self explanatory
#define BIO_FLESH_BONE (BIO_BONE | BIO_FLESH)
/// Has metal - allows the victim to suffer robotic blunt and burn wounds
#define BIO_METAL (1<<2)
/// Is wired internally - allows the victim to suffer electrical wounds (robotic T1-T3 slash/pierce)
#define BIO_WIRED (1<<3)
/// Robotic: shit like cyborg limbs, mostly
#define BIO_ROBOTIC (BIO_METAL|BIO_WIRED)
/// Has bloodflow - can suffer bleeding wounds and can bleed
#define BIO_BLOODED (1<<4)
/// Is connected by a joint - can suffer T1 bone blunt wounds (dislocation)
#define BIO_JOINTED (1<<5)
/// Standard humanoid - can suffer all flesh wounds, such as: T1-3 slash/pierce/burn/blunt. Can also bleed
#define BIO_STANDARD (BIO_FLESH_BONE|BIO_BLOODED)
// "Where" a specific "bio" feature is within a given limb
// Exterior is hard shit, the last line, shit lines bones
// Interior is soft shit, targetted by slashes and pierces (usually), protects exterior
// Yes, it makes no sense
/// The given biostate is on the "exterior" of the limb - hard shit, protected by interior
#define BIO_EXTERIOR (1<<0)
/// The given biostate is on the "exterior" of the limb - soft shit, protects exterior
#define BIO_INTERIOR (1<<1)
#define BIO_EXTERIOR_AND_INTERIOR (BIO_EXTERIOR|BIO_INTERIOR)
GLOBAL_LIST_INIT(bio_state_states, list(
"[BIO_WIRED]" = BIO_INTERIOR,
"[BIO_METAL]" = BIO_EXTERIOR,
"[BIO_FLESH]" = BIO_INTERIOR,
"[BIO_BONE]" = BIO_EXTERIOR,
))
// Wound series
// A "wound series" is just a family of wounds that logically follow eachother
// Multiple wounds in a single series cannot be on a limb - the highest severity will always be prioritized, and lower ones will be skipped
/// T1-T3 Bleeding slash wounds. Requires flesh. Can cause bleeding, but doesn't require it. From: slash.dm
#define WOUND_SERIES_FLESH_SLASH_BLEED 1
/// T1-T3 Basic blunt wounds. T1 requires jointed, but 2-3 require bone. From: bone.dm
#define WOUND_SERIES_BONE_BLUNT_BASIC 2
/// T1-T3 Basic burn wounds. Requires flesh. From: burns.dm
#define WOUND_SERIES_FLESH_BURN_BASIC 3
/// T1-3 Bleeding puncture wounds. Requires flesh. Can cause bleeding, but doesn't require it. From: pierce.dm
#define WOUND_SERIES_FLESH_PUNCTURE_BLEED 4
// ~burn wound infection defines
// Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse
@@ -116,34 +132,13 @@ GLOBAL_LIST_INIT(global_all_wound_types, list(
#define BODYPART_MANGLED_FLESH (1<<1)
#define BODYPART_MANGLED_BOTH (BODYPART_MANGLED_BONE | BODYPART_MANGLED_FLESH)
// ~biology defines
// What kind of biology a limb has, and what wounds it can suffer
/// golems and androids, cannot suffer any wounds
#define BIO_INORGANIC NONE
/// skeletons and plasmemes, can only suffer bone wounds, only needs mangled bone to be able to dismember
#define BIO_BONE (1<<0)
/// nothing right now, maybe slimepeople in the future, can only suffer slashing, piercing, and burn wounds
#define BIO_FLESH (1<<1)
/// standard humanoids, can suffer all wounds, needs mangled bone and flesh to dismember. conveniently, what you get when you combine BIO_BONE and BIO_FLESH
#define BIO_FLESH_BONE (BIO_BONE | BIO_FLESH)
// ~wound flag defines
/// If this wound requires having the BIO_FLESH biological_state on the limb
#define FLESH_WOUND (1<<0)
/// If this wound requires having the BIO_BONE biological_state on the limb
#define BONE_WOUND (1<<1)
/// If having this wound counts as mangled flesh for dismemberment
#define MANGLES_FLESH (1<<2)
#define MANGLES_FLESH (1<<0)
/// If having this wound counts as mangled bone for dismemberment
#define MANGLES_BONE (1<<3)
#define MANGLES_BONE (1<<1)
/// If this wound marks the limb as being allowed to have gauze applied
#define ACCEPTS_GAUZE (1<<4)
//SKYRAT EDIT ADDITION BEGIN - MEDICAL
/// If this wound marks the limb as being allowed to have gauze applied as a splint
#define ACCEPTS_SPLINT (1<<5)
//SKYRAT EDIT ADDITION END
#define ACCEPTS_GAUZE (1<<2)
// ~scar persistence defines
// The following are the order placements for persistent scar save formats
@@ -161,11 +156,13 @@ GLOBAL_LIST_INIT(global_all_wound_types, list(
#define SCAR_SAVE_BIOLOGY 6
/// Which character slot this was saved to
#define SCAR_SAVE_CHAR_SLOT 7
/// if the scar will check for any or all biostates on the limb (defaults to FALSE, so all)
#define SCAR_SAVE_CHECK_ANY_BIO 8
///how many fields we save for each scar (so the number of above fields)
#define SCAR_SAVE_LENGTH 7
#define SCAR_SAVE_LENGTH 8
/// saved scars with a version lower than this will be discarded, increment when you update the persistent scarring format in a way that invalidates previous saved scars (new fields, reordering, etc)
#define SCAR_CURRENT_VERSION 3
#define SCAR_CURRENT_VERSION 4
/// how many scar slots, per character slot, we have to cycle through for persistent scarring, if enabled in character prefs
#define PERSISTENT_SCAR_SLOTS 3
+11 -1
View File
@@ -173,6 +173,16 @@
/// Attempts to perform a limb dislocation, with the user violently twisting one of target's limbs (as passed in). Only useful for extremities, because only extremities can eat dislocations.
/datum/species/proc/try_dislocate(mob/living/carbon/human/user, mob/living/carbon/human/target, obj/item/bodypart/affecting)
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[/datum/wound/blunt/bone/moderate]
if (!pregen_data)
stack_trace("/datum/wound/blunt/bone/moderate has no pregen data!")
return FALSE // shouldnt happen but sanity
if (!pregen_data.can_be_applied_to(affecting, random_roll = FALSE))
if (!(affecting.biological_state & BIO_JOINTED))
to_chat(user, span_warning("[target]'s [affecting.plaintext_zone] has no joint to dislocate!"))
return FALSE
user.changeNext_move(4 SECONDS)
target.visible_message(span_danger("[user.name] twists [target.name]'s [affecting.name] violently!"), \
span_userdanger("[user.name] twists your [affecting.name] violently!"), ignored_mobs=user)
@@ -182,7 +192,7 @@
target.visible_message(span_danger("[user.name] dislocates [target.name]'s [affecting.name]!"), \
span_userdanger("[user.name] dislocates your [affecting.name]!"), ignored_mobs=user)
to_chat(user, span_danger("You dislocate [target.name]'s [affecting.name]!"))
affecting.force_wound_upwards(/datum/wound/blunt/moderate)
affecting.force_wound_upwards(/datum/wound/blunt/bone/moderate)
log_combat(user, target, "dislocates", "the [affecting.name]")
return TRUE
+5
View File
@@ -0,0 +1,5 @@
/// See muscle.dm
#define WOUND_SERIES_MUSCLE_DAMAGE 10000 // We use a super high number as realistically speaking TG will never increment to this amount of wound series
/// If this wound, when bandaged, will cause a splint overlay to generate rather than a bandage overlay.
#define SPLINT_OVERLAY (1<<200) // we use a big number since tg realistically wouldnt go to it
+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
+1
View File
@@ -541,6 +541,7 @@
SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_ATOM, src, reagents, methods, volume_modifier, show_message)
for(var/datum/reagent/current_reagent as anything in reagents)
. |= current_reagent.expose_atom(src, reagents[current_reagent])
SEND_SIGNAL(src, COMSIG_ATOM_AFTER_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message)
/// Are you allowed to drop this atom
/atom/proc/AllowDrop()
+1 -1
View File
@@ -248,7 +248,7 @@
var/list/arm_zones = shuffle(list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM))
var/obj/item/bodypart/chosen_limb = attached_mob.get_bodypart(arm_zones[1]) || attached_mob.get_bodypart(arm_zones[2]) || attached_mob.get_bodypart(BODY_ZONE_CHEST)
chosen_limb.receive_damage(3)
chosen_limb.force_wound_upwards(/datum/wound/pierce/moderate, wound_source = "IV needle")
chosen_limb.force_wound_upwards(/datum/wound/pierce/bleed/moderate, wound_source = "IV needle")
else
visible_message(span_warning("[attached] is detached from [src]."))
detach_iv()
@@ -286,7 +286,7 @@
holo_cooldown = world.time + 10 SECONDS
return
// see: [/datum/wound/burn/proc/uv()]
// see: [/datum/wound/burn/flesh/proc/uv()]
/obj/item/flashlight/pen/paramedic
name = "paramedic penlight"
desc = "A high-powered UV penlight intended to help stave off infection in the field on serious burned patients. Probably really bad to look into."
+2 -2
View File
@@ -434,9 +434,9 @@
patient.emote("scream")
for(var/i in patient.bodyparts)
var/obj/item/bodypart/bone = i
var/datum/wound/blunt/severe/oof_ouch = new
var/datum/wound/blunt/bone/severe/oof_ouch = new
oof_ouch.apply_wound(bone, wound_source = "bone gel")
var/datum/wound/blunt/critical/oof_OUCH = new
var/datum/wound/blunt/bone/critical/oof_OUCH = new
oof_OUCH.apply_wound(bone, wound_source = "bone gel")
for(var/i in patient.bodyparts)
+2 -1
View File
@@ -465,7 +465,8 @@
new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(mobloc)
new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(emergency_destination)
balloon_alert(user, "emergency teleport triggered!")
make_bloods(mobloc, emergency_destination, user)
if (!HAS_TRAIT(user, TRAIT_NOBLOOD))
make_bloods(mobloc, emergency_destination, user)
playsound(mobloc, SFX_SPARKS, 50, 1, SHORT_RANGE_SOUND_EXTRARANGE)
playsound(emergency_destination, 'sound/effects/phasein.ogg', 25, 1, SHORT_RANGE_SOUND_EXTRARANGE)
playsound(emergency_destination, SFX_SPARKS, 50, 1, SHORT_RANGE_SOUND_EXTRARANGE)
+3 -3
View File
@@ -10,9 +10,9 @@
var/mob/living/carbon/carbon_target = target
for(var/_limb in carbon_target.bodyparts)
var/obj/item/bodypart/limb = _limb
var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate))
var/type_wound = pick(list(/datum/wound/slash/flesh/severe, /datum/wound/slash/flesh/moderate))
limb.force_wound_upwards(type_wound, smited = TRUE)
type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate))
type_wound = pick(list(/datum/wound/slash/flesh/critical, /datum/wound/slash/flesh/severe, /datum/wound/slash/flesh/moderate))
limb.force_wound_upwards(type_wound, smited = TRUE)
type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe))
type_wound = pick(list(/datum/wound/slash/flesh/critical, /datum/wound/slash/flesh/severe))
limb.force_wound_upwards(type_wound, smited = TRUE)
+5 -5
View File
@@ -12,10 +12,10 @@
var/mob/living/carbon/carbon_target = target
for(var/obj/item/bodypart/limb as anything in carbon_target.bodyparts)
var/type_wound = pick(list(
/datum/wound/blunt/critical,
/datum/wound/blunt/severe,
/datum/wound/blunt/critical,
/datum/wound/blunt/severe,
/datum/wound/blunt/moderate,
/datum/wound/blunt/bone/critical,
/datum/wound/blunt/bone/severe,
/datum/wound/blunt/bone/critical,
/datum/wound/blunt/bone/severe,
/datum/wound/blunt/bone/moderate,
))
limb.force_wound_upwards(type_wound, smited = TRUE)
@@ -269,7 +269,7 @@
var/mob/living/carbon/carbon_target = target
var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
var/datum/wound/slash/severe/crit_wound = new()
var/datum/wound/slash/flesh/severe/crit_wound = new()
crit_wound.apply_wound(bodypart, attack_direction = get_dir(source, target))
/datum/heretic_knowledge/summon/stalker
@@ -19,7 +19,7 @@
/// The radius of the cleave effect
var/cleave_radius = 1
/// What type of wound we apply
var/wound_type = /datum/wound/slash/critical/cleave
var/wound_type = /datum/wound/slash/flesh/critical/cleave
/datum/action/cooldown/spell/pointed/cleave/is_valid_target(atom/cast_on)
return ..() && ishuman(cast_on)
@@ -45,7 +45,7 @@
)
var/obj/item/bodypart/bodypart = pick(victim.bodyparts)
var/datum/wound/slash/crit_wound = new wound_type()
var/datum/wound/slash/flesh/crit_wound = new wound_type()
crit_wound.apply_wound(bodypart)
victim.apply_damage(20, BURN, wound_bonus = CANT_WOUND)
@@ -56,7 +56,7 @@
/datum/action/cooldown/spell/pointed/cleave/long
name = "Lesser Cleave"
cooldown_time = 60 SECONDS
wound_type = /datum/wound/slash/severe
wound_type = /datum/wound/slash/flesh/severe
/obj/effect/temp_visual/cleave
icon = 'icons/effects/eldritch.dmi'
@@ -61,7 +61,7 @@
if(ishuman(owner))
var/mob/living/carbon/human/human_owner = owner
var/obj/item/bodypart/bodypart = pick(human_owner.bodyparts)
var/datum/wound/slash/severe/crit_wound = new()
var/datum/wound/slash/flesh/severe/crit_wound = new()
crit_wound.apply_wound(bodypart)
return ..()
@@ -179,8 +179,8 @@
if(!do_after(user, eye_snatch_enthusiasm, target = target, extra_checks = CALLBACK(src, PROC_REF(eyeballs_exist), eyeballies, head, target)))
return
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
target.apply_damage(20, BRUTE, BODY_ZONE_HEAD, wound_bonus = rand(initial(severe_wound_type.threshold_minimum), initial(critical_wound_type.threshold_minimum) + 10), attacking_item = src)
target.visible_message(
span_danger("[src] pierces through [target]'s skull, horribly mutilating their eyes!"),
@@ -13,7 +13,7 @@
/obj/effect/mob_spawn/corpse/human/tigercultist/perforated/special(mob/living/carbon/human/spawned_human)
. = ..()
var/datum/wound/pierce/critical/exit_hole = new()
var/datum/wound/pierce/bleed/critical/exit_hole = new()
exit_hole.apply_wound(spawned_human.get_bodypart(BODY_ZONE_CHEST))
/// A fun drink enjoyed by the tiger cooperative, might corrode your brain if you drink the whole bottle
+10 -5
View File
@@ -1268,12 +1268,17 @@
else
wound_type = forced_type
else
wound_type = pick(GLOB.global_all_wound_types)
for (var/datum/wound/path as anything in shuffle(GLOB.all_wound_pregen_data))
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[path]
if (pregen_data.can_be_applied_to(scar_part, random_roll = TRUE))
wound_type = path
break
var/datum/wound/phantom_wound = new wound_type
scaries.generate(scar_part, phantom_wound)
scaries.fake = TRUE
QDEL_NULL(phantom_wound)
if (wound_type) // can feasibly happen, if its an inorganic limb/cant be wounded/scarred
var/datum/wound/phantom_wound = new wound_type
scaries.generate(scar_part, phantom_wound)
scaries.fake = TRUE
QDEL_NULL(phantom_wound)
/mob/living/carbon/is_face_visible()
return !(wear_mask?.flags_inv & HIDEFACE) && !(head?.flags_inv & HIDEFACE)
@@ -775,7 +775,6 @@
return ..()
var/obj/item/bodypart/grasped_part = get_bodypart(zone_selected)
//SKYRAT EDIT CHANGE BEGIN - MEDICAL
/*
if(!grasped_part?.get_modified_bleed_rate())
return
@@ -795,9 +794,8 @@
QDEL_NULL(grasp)
return
grasp.grasp_limb(grasped_part)
*/
*/ // SKYRAT EDIT REMOVAL - MODULARIZED INTO grasp.dm's self_grasp_bleeding_limb !! IF THIS PROC IS UPDATED, PUT IT IN THERE !!
self_grasp_bleeding_limb(grasped_part, supress_message)
//SKYRAT EDIT CHANGE END
/// an abstract item representing you holding your own limb to staunch the bleeding, see [/mob/living/carbon/proc/grabbedby] will probably need to find somewhere else to put this.
/obj/item/hand_item/self_grasp
@@ -104,6 +104,9 @@
/// All of the scars a carbon has afflicted throughout their limbs
var/list/all_scars
/// Assoc list of BODY_ZONE -> WOUND_TYPE. Set when a limb is dismembered, unset when one is attached. Used for determining what scar to add when it comes time to generate them.
var/list/body_zone_dismembered_by
/// Simple modifier for whether this mob can handle greater or lesser skillchip complexity. See /datum/mutation/human/biotechcompat/ for example.
var/skillchip_complexity_modifier = 0
+1 -1
View File
@@ -154,7 +154,7 @@
SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .)
//SKYRAT EDIT REMOVAL - MOVED - MEDICAL
//SKYRAT EDIT REMOVAL - MOVED - MEDICAL - carbon_examine.dm
/*
/mob/living/carbon/examine_more(mob/user)
. = ..()
@@ -1327,7 +1327,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
if(!(prob(25 + (weapon.force * 2))))
return TRUE
if(IS_ORGANIC_LIMB(affecting))
if(affecting.can_bleed())
weapon.add_mob_blood(human) //Make the weapon bloody, not the person.
if(prob(weapon.force * 2)) //blood spatter!
bloody = TRUE
@@ -1706,19 +1706,19 @@ GLOBAL_LIST_EMPTY(features_by_species)
// Lets pick a random body part and check for an existing burn
var/obj/item/bodypart/bodypart = pick(humi.bodyparts)
var/datum/wound/burn/existing_burn = locate(/datum/wound/burn) in bodypart.wounds
var/datum/wound/burn/flesh/existing_burn = locate(/datum/wound/burn) in bodypart.wounds
// If we have an existing burn try to upgrade it
if(existing_burn)
switch(existing_burn.severity)
if(WOUND_SEVERITY_MODERATE)
if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 400) // 800k
bodypart.force_wound_upwards(/datum/wound/burn/severe, wound_source = "hot temperatures")
bodypart.force_wound_upwards(/datum/wound/burn/flesh/severe, wound_source = "hot temperatures")
if(WOUND_SEVERITY_SEVERE)
if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 2800) // 3200k
bodypart.force_wound_upwards(/datum/wound/burn/critical, wound_source = "hot temperatures")
bodypart.force_wound_upwards(/datum/wound/burn/flesh/critical, wound_source = "hot temperatures")
else // If we have no burn apply the lowest level burn
bodypart.force_wound_upwards(/datum/wound/burn/moderate, wound_source = "hot temperatures")
bodypart.force_wound_upwards(/datum/wound/burn/flesh/moderate, wound_source = "hot temperatures")
// always take some burn damage
var/burn_damage = HEAT_DAMAGE_LEVEL_1
@@ -705,11 +705,7 @@
//SKYRAT EDIT ADDITION BEGIN - MEDICAL
if(body_part.current_gauze)
var/datum/bodypart_aid/current_gauze = body_part.current_gauze
combined_msg += "\t [span_notice("Your [body_part.name] is [current_gauze.desc_prefix] with <a href='?src=[REF(current_gauze)];remove=1'>[current_gauze.get_description()]</a>.")]"
if(body_part.current_splint)
var/datum/bodypart_aid/current_splint = body_part.current_splint
combined_msg += "\t [span_notice("Your [body_part.name] is [current_splint.desc_prefix] with <a href='?src=[REF(current_splint)];remove=1'>[current_splint.get_description()]</a>.")]"
combined_msg += "\t [span_notice("Your [body_part.name] is [body_part.current_gauze.get_gauze_usage_prefix()] with <a href='?src=[REF(body_part.current_gauze)];remove=1'>[body_part.current_gauze.get_gauze_description()]</a>.")]"
//SKYRAT EDIT END
for(var/t in missing)
@@ -169,13 +169,15 @@
if(LAZYLEN(scar_data) != SCAR_SAVE_LENGTH)
return // invalid, should delete
var/version = text2num(scar_data[SCAR_SAVE_VERS])
if(!version || version < SCAR_CURRENT_VERSION) // get rid of old scars
if(!version || version != SCAR_CURRENT_VERSION) // get rid of scars using a incompatable version
return
if(specified_char_index && (mind?.original_character_slot_index != specified_char_index))
return
if (isnull(text2num(scar_data[SCAR_SAVE_BIOLOGY])))
return
var/obj/item/bodypart/the_part = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
var/datum/scar/scaries = new
return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]), text2num(scar_data[SCAR_SAVE_BIOLOGY]), text2num(scar_data[SCAR_SAVE_CHAR_SLOT]))
return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]), text2num(scar_data[SCAR_SAVE_BIOLOGY]), text2num(scar_data[SCAR_SAVE_CHAR_SLOT]), text2num(scar_data[SCAR_SAVE_CHECK_ANY_BIO]))
/// Read all the scars we have for the designated character/scar slots, verify they're good/dump them if they're old/wrong format, create them on the user, and write the scars that passed muster back to the file
/mob/living/carbon/human/proc/load_persistent_scars()
@@ -9,6 +9,8 @@
TRAIT_VIRUSIMMUNE,
TRAIT_NOBLOOD,
TRAIT_CHUNKYFINGERS_IGNORE_BATON,
TRAIT_NODISMEMBER,
TRAIT_NEVER_WOUNDED
)
mutanttongue = /obj/item/organ/internal/tongue/abductor
mutantstomach = null
@@ -7,7 +7,6 @@
TRAIT_GENELESS,
TRAIT_LAVA_IMMUNE,
TRAIT_NOBREATH,
TRAIT_NODISMEMBER,
TRAIT_NOBLOOD,
TRAIT_NOFIRE,
TRAIT_PIERCEIMMUNE,
@@ -15,6 +14,8 @@
TRAIT_NO_DNA_COPY,
TRAIT_NO_TRANSFORMATION_STING,
TRAIT_NO_AUGMENTS,
TRAIT_NODISMEMBER,
TRAIT_NEVER_WOUNDED
)
mutantheart = null
mutantlungs = null
@@ -10,6 +10,8 @@
TRAIT_RADIMMUNE,
TRAIT_VIRUSIMMUNE,
TRAIT_NOBLOOD,
TRAIT_NODISMEMBER,
TRAIT_NEVER_WOUNDED
)
inherent_factions = list(FACTION_FAITHLESS)
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC
+2 -2
View File
@@ -49,8 +49,6 @@
handle_diseases(seconds_per_tick, times_fired)// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not.
handle_wounds(seconds_per_tick, times_fired)
if (QDELETED(src)) // diseases can qdel the mob via transformations
return
@@ -65,6 +63,8 @@
handle_gravity(seconds_per_tick, times_fired)
handle_wounds(seconds_per_tick, times_fired)
if(machine)
machine.check_eye(src)
+1 -1
View File
@@ -171,7 +171,7 @@
to_chat(user, span_userdanger("You neatly cut [stored_paper][clumsy ? "... and your finger in the process!" : "."]"))
if(clumsy)
var/obj/item/bodypart/finger = user.get_active_hand()
var/datum/wound/slash/moderate/papercut = new
var/datum/wound/slash/flesh/moderate/papercut = new
papercut.apply_wound(finger, wound_source = "paper cut")
stored_paper = null
qdel(stored_paper)
@@ -90,7 +90,7 @@
/datum/religion_rites/song_tuner/pain/finish_effect(mob/living/carbon/human/listener, atom/song_source)
var/obj/item/bodypart/sliced_limb = pick(listener.bodyparts)
sliced_limb.force_wound_upwards(/datum/wound/slash/moderate/many_cuts)
sliced_limb.force_wound_upwards(/datum/wound/slash/flesh/moderate/many_cuts)
/datum/religion_rites/song_tuner/lullaby
name = "Spiritual Lullaby"
@@ -216,7 +216,7 @@
var/mob/living/carbon/human/branded = interfering
to_chat(interfering, span_warning("[GLOB.deity] brands your flesh for interfering with [chaplain]'s sparring match!!"))
var/obj/item/bodypart/branded_limb = pick(branded.bodyparts)
branded_limb.force_wound_upwards(/datum/wound/burn/severe/brand, wound_source = "divine intervention")
branded_limb.force_wound_upwards(/datum/wound/burn/flesh/severe/brand, wound_source = "divine intervention")
branded.emote("scream")
flubs--
@@ -21,7 +21,7 @@
span_userdanger("The spell bounces from [victim]'s skin back into your arm!"),
)
var/obj/item/bodypart/to_wound = caster.get_holding_bodypart_of_item(hand)
to_wound.force_wound_upwards(/datum/wound/slash/critical)
to_wound.force_wound_upwards(/datum/wound/slash/flesh/critical)
/datum/action/cooldown/spell/touch/scream_for_me/cast_on_hand_hit(obj/item/melee/touch_attack/hand, mob/living/victim, mob/living/carbon/caster)
if(!ishuman(victim))
@@ -29,7 +29,7 @@
var/mob/living/carbon/human/human_victim = victim
human_victim.emote("scream")
for(var/obj/item/bodypart/to_wound as anything in human_victim.bodyparts)
to_wound.force_wound_upwards(/datum/wound/slash/critical)
to_wound.force_wound_upwards(/datum/wound/slash/flesh/critical)
return TRUE
/obj/item/melee/touch_attack/scream_for_me
+106 -78
View File
@@ -1,3 +1,6 @@
#define AUGGED_LIMB_EMP_BRUTE_DAMAGE 3
#define AUGGED_LIMB_EMP_BURN_DAMAGE 2
/obj/item/bodypart
name = "limb"
desc = "Why is it detached..."
@@ -22,14 +25,15 @@
/// DO NOT MODIFY DIRECTLY. Use set_owner()
var/mob/living/carbon/owner
/// If this limb can be scarred.
var/scarrable = TRUE
/**
* A bitfield of biological states, exclusively used to determine which wounds this limb will get,
* as well as how easily it will happen.
* Set to BIO_FLESH_BONE because most species have both flesh and bone in their limbs.
*
* This currently has absolutely no meaning for robotic limbs.
* Set to BIO_STANDARD because most species have both flesh bone and blood in their limbs.
*/
var/biological_state = BIO_FLESH_BONE
var/biological_state = BIO_STANDARD
///A bitfield of bodytypes for clothing, surgery, and misc information
var/bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC
///Defines when a bodypart should not be changed. Example: BP_BLOCK_CHANGE_SPECIES prevents the limb from being overwritten on species gain
@@ -66,16 +70,14 @@
var/speed_modifier = 0
// Limb disabling variables
///Whether it is possible for the limb to be disabled whatsoever. TRUE means that it is possible.
var/can_be_disabled = FALSE //Defaults to FALSE, as only human limbs can be disabled, and only the appendages.
///Controls if the limb is disabled. TRUE means it is disabled (similar to being removed, but still present for the sake of targeted interactions).
var/bodypart_disabled = FALSE
///Handles limb disabling by damage. If 0 (0%), a limb can't be disabled via damage. If 1 (100%), it is disabled at max limb damage. Anything between is the percentage of damage against maximum limb damage needed to disable the limb.
//var/disabling_threshold_percentage = 0 //ORIGINAL
var/disabling_threshold_percentage = 1 //SKYRAT EDIT CHANGE - COMBAT
///Whether it is possible for the limb to be disabled whatsoever. TRUE means that it is possible.
var/can_be_disabled = FALSE //Defaults to FALSE, as only human limbs can be disabled, and only the appendages.
// Damage state variables
var/disabling_threshold_percentage = 1 //SKYRAT EDIT CHANGE - COMBAT - ORIGINAL : var/disabling_threshold_percentage = 0
// Damage variables
///A mutiplication of the burn and brute damage that the limb's stored damage contributes to its attached mob's overall wellbeing.
var/body_damage_coeff = 1
///The current amount of brute damage the limb has
@@ -152,20 +154,8 @@
var/cached_bleed_rate = 0
/// How much generic bleedstacks we have on this bodypart
var/generic_bleedstacks
//SKYRAT EDIT CHANGE BEGIN - MEDICAL
/*
/// If we have a gauze wrapping currently applied (not including splints)
var/obj/item/stack/current_gauze
*/
/// If we have a gauze wrapping currently applied
var/datum/bodypart_aid/gauze/current_gauze
/// If we have a splint currently applied
var/datum/bodypart_aid/splint/current_splint
/// What icon do we use to render this limb? Ususally used by robotic limb augments.
var/rendered_bp_icon
/// Do we use an organic render for this robotic limb?
var/organic_render = TRUE
//SKYRAT EDIT CHANGE END
/// If something is currently grasping this bodypart and trying to staunch bleeding (see [/obj/item/hand_item/self_grasp])
var/obj/item/hand_item/self_grasp/grasped_by
@@ -200,6 +190,16 @@
/// List of the above datums which have actually been instantiated, managed automatically
var/list/feature_offsets = list()
/// In the case we dont have dismemberable features, or literally cant get wounds, we will use this percent to determine when we can be dismembered.
/// Compared to our ABSOLUTE maximum. Stored in decimal; 0.8 = 80%.
var/hp_percent_to_dismemberable = 0.8
/// If true, we will use [hp_percent_to_dismemberable] even if we are dismemberable via wounds. Useful for things with extreme wound resistance.
var/use_alternate_dismemberment_calc_even_if_mangleable = FALSE
/// If false, no wound that can be applied to us can mangle our flesh. Used for determining if we should use [hp_percent_to_dismemberable] instead of normal dismemberment.
var/any_existing_wound_can_mangle_our_flesh
/// If false, no wound that can be applied to us can mangle our bone. Used for determining if we should use [hp_percent_to_dismemberable] instead of normal dismemberment.
var/any_existing_wound_can_mangle_our_bone
/obj/item/bodypart/apply_fantasy_bonuses(bonus)
. = ..()
unarmed_damage_low = modify_fantasy_variable("unarmed_damage_low", unarmed_damage_low, bonus, minimum = 1)
@@ -241,12 +241,6 @@
if(length(wounds))
stack_trace("[type] qdeleted with [length(wounds)] uncleared wounds")
wounds.Cut()
//SKYRAT EDIT ADDITION BEGIN - MEDICAL
if(current_gauze)
qdel(current_gauze)
if(current_splint)
qdel(current_splint)
//SKYRAT EDIT ADDITION END
if(length(external_organs))
for(var/obj/item/organ/external/external_organ as anything in external_organs)
@@ -415,11 +409,7 @@
var/atom/drop_loc = drop_location()
if(IS_ORGANIC_LIMB(src))
playsound(drop_loc, 'sound/misc/splort.ogg', 50, TRUE, -1)
//seep_gauze(9999) // destroy any existing gauze if any exists
if(current_gauze)
qdel(current_gauze)
if(current_splint)
qdel(current_splint)
seep_gauze(9999) // destroy any existing gauze if any exists
for(var/obj/item/organ/bodypart_organ in get_organs())
bodypart_organ.transfer_to_limb(src, owner)
for(var/obj/item/organ/external/external in external_organs)
@@ -505,40 +495,75 @@
else if (sharpness & SHARP_POINTY)
wounding_type = WOUND_PIERCE
if(owner)
if(owner) // i tried to modularize the below, but the modifications to wounding_dmg and wounding_type cant be extracted to a proc
var/mangled_state = get_mangled_state()
var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
//Handling for bone only/flesh only(none right now)/flesh and bone targets
switch(biological_state)
// if we're bone only, all cutting attacks go straight to the bone
if(BIO_BONE)
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.6)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.75)
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
// note that there's no handling for BIO_FLESH since we don't have any that are that right now (slimepeople maybe someday)
// standard humanoids
if(BIO_FLESH_BONE)
//SKYRAT EDIT ADDITION BEGIN - MEDICAL
//We do a body zone check here because muscles dont have any variants for head or chest, and rolling a muscle wound on them wound end up on a wasted wound roll
if(body_zone != BODY_ZONE_CHEST && body_zone != BODY_ZONE_HEAD && prob(35))
wounding_type = WOUND_MUSCLE
//SKYRAT EDIT ADDITION END
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
if((mangled_state & BODYPART_MANGLED_FLESH) && !(mangled_state & BODYPART_MANGLED_BONE) && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area
if(wounding_type == WOUND_PIERCE && !easy_dismember)
wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
wounding_type = WOUND_BLUNT
else if((mangled_state & BODYPART_MANGLED_FLESH) && (mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
var/has_exterior = FALSE
var/has_interior = FALSE
for (var/state as anything in GLOB.bio_state_states)
var/flag = text2num(state)
if (!(biological_state & flag))
continue
var/value = GLOB.bio_state_states[state]
if (value & BIO_EXTERIOR)
has_exterior = TRUE
if (value & BIO_INTERIOR)
has_interior = TRUE
if (has_exterior && has_interior)
break
// We put this here so we dont increase init time by doing this all at once on initialization
// Effectively, we "lazy load"
if (isnull(any_existing_wound_can_mangle_our_bone) || isnull(any_existing_wound_can_mangle_our_flesh))
any_existing_wound_can_mangle_our_bone = FALSE
any_existing_wound_can_mangle_our_flesh = FALSE
for (var/datum/wound/wound_type as anything in GLOB.all_wound_pregen_data)
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[wound_type]
if (!pregen_data.can_be_applied_to(src, random_roll = TRUE)) // we only consider randoms because non-randoms are usually really specific
continue
if (initial(pregen_data.wound_path_to_generate.wound_flags) & MANGLES_FLESH)
any_existing_wound_can_mangle_our_flesh = TRUE
if (initial(pregen_data.wound_path_to_generate.wound_flags) & MANGLES_BONE)
any_existing_wound_can_mangle_our_bone = TRUE
if (any_existing_wound_can_mangle_our_bone && any_existing_wound_can_mangle_our_flesh)
break
var/can_theoretically_be_dismembered = (any_existing_wound_can_mangle_our_bone || (any_existing_wound_can_mangle_our_flesh && !has_exterior))
var/exterior_ready_to_dismember = (!has_exterior || ((mangled_state & BODYPART_MANGLED_BONE) == BODYPART_MANGLED_BONE))
var/interior_ready_to_dismember = (!has_interior || ((mangled_state & BODYPART_MANGLED_FLESH) == BODYPART_MANGLED_FLESH))
// if we're bone only, all cutting attacks go straight to the bone
if(has_exterior && interior_ready_to_dismember)
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.6)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.75)
if(exterior_ready_to_dismember && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
else
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
if(has_exterior && interior_ready_to_dismember && !(mangled_state & BODYPART_MANGLED_BONE) && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area
if(wounding_type == WOUND_PIERCE && !easy_dismember)
wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
wounding_type = WOUND_BLUNT
else if(interior_ready_to_dismember && exterior_ready_to_dismember && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
if (use_alternate_dismemberment_calc_even_if_mangleable || !can_theoretically_be_dismembered)
var/percent_to_total_max = (get_damage() / max_damage)
if (percent_to_total_max >= hp_percent_to_dismemberable)
if (try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
// now we have our wounding_type and are ready to carry on with wounds and dealing the actual damage
@@ -552,15 +577,14 @@
damaged_percent = DAMAGED_BODYPART_BONUS_WOUNDING_THRESHOLD
wounding_dmg = min(DAMAGED_BODYPART_BONUS_WOUNDING_BONUS, wounding_dmg + (damaged_percent * DAMAGED_BODYPART_BONUS_WOUNDING_COEFF))
if(current_gauze)
current_gauze.take_damage()
if(current_splint)
current_splint.take_damage()
if (istype(current_gauze, /obj/item/stack/medical/gauze))
var/obj/item/stack/medical/gauze/our_gauze = current_gauze
our_gauze.get_hit()
//SKYRAT EDIT ADDITION END - MEDICAL
check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus, attack_direction, damage_source = damage_source)
for(var/datum/wound/iter_wound as anything in wounds)
iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus)
iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus, damage_source)
/*
// END WOUND HANDLING
@@ -1162,7 +1186,7 @@
if(!owner)
return
if(HAS_TRAIT(owner, TRAIT_NOBLOOD) || !IS_ORGANIC_LIMB(src))
if(!can_bleed())
if(cached_bleed_rate != old_bleed_rate)
update_part_wound_overlay()
return
@@ -1203,7 +1227,7 @@
/obj/item/bodypart/proc/update_part_wound_overlay()
if(!owner)
return FALSE
if(HAS_TRAIT(owner, TRAIT_NOBLOOD) || !IS_ORGANIC_LIMB(src))
if(!can_bleed())
if(bleed_overlay_icon)
bleed_overlay_icon = null
owner.update_wound_overlays()
@@ -1236,6 +1260,11 @@
#undef BLEED_OVERLAY_MED
#undef BLEED_OVERLAY_GUSH
/obj/item/bodypart/proc/can_bleed()
SHOULD_BE_PURE(TRUE)
return ((biological_state & BIO_BLOODED) && (!owner || !HAS_TRAIT(owner, TRAIT_NOBLOOD)))
/**
* apply_gauze() is used to- well, apply gauze to a bodypart
*
@@ -1247,7 +1276,6 @@
* Arguments:
* * gauze- Just the gauze stack we're taking a sheet from to apply here
*/
/* SKYRAT EDIT REMOVAL
/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze)
if(!istype(gauze) || !gauze.absorption_capacity)
return
@@ -1259,7 +1287,6 @@
gauze.use(1)
if(newly_gauzed)
SEND_SIGNAL(src, COMSIG_BODYPART_GAUZED, gauze)
*/
/**
* seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity.
@@ -1269,7 +1296,6 @@
* 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?)
*/
/* SKYRAT EDIT REMOVAL
/obj/item/bodypart/proc/seep_gauze(seep_amt = 0)
if(!current_gauze)
return
@@ -1278,7 +1304,6 @@
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)
SEND_SIGNAL(src, COMSIG_BODYPART_GAUZE_DESTROYED)
*/
///Loops through all of the bodypart's external organs and update's their color.
/obj/item/bodypart/proc/recolor_external_organs()
@@ -1328,14 +1353,17 @@
/obj/item/bodypart/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_WIRES || !(bodytype & BODYTYPE_ROBOTIC))
if(. & EMP_PROTECT_WIRES || !IS_ROBOTIC_LIMB(src))
return FALSE
owner.visible_message(span_danger("[owner]'s [src.name] seems to malfunction!"))
// with defines at the time of writing, this is 3 brute and 2 burn
// 3 + 2 = 5, with 6 limbs thats 30, on a heavy 60
// 60 * 0.8 = 48
var/time_needed = 10 SECONDS
var/brute_damage = 2.5 // SKYRAT EDIT : Balances direct EMP damage for Brute - SR's synth values are multiplied 3x 2.5 * 1.3 * 1.3
var/burn_damage = 2 // SKYRAT EDIT : Balances direct EMP damage for Burn - SR's synth values are multiplied 3x 2 * 1.3 * 1.3
var/brute_damage = AUGGED_LIMB_EMP_BRUTE_DAMAGE
var/burn_damage = AUGGED_LIMB_EMP_BURN_DAMAGE
if(severity == EMP_HEAVY)
time_needed *= 2
brute_damage *= 1.3 // SKYRAT EDIT : Balance - Lowers total damage from ~125 Brute to ~30
+35 -17
View File
@@ -1,11 +1,11 @@
/obj/item/bodypart/proc/can_dismember(obj/item/item)
if(bodypart_flags & BODYPART_UNREMOVABLE)
if(bodypart_flags & BODYPART_UNREMOVABLE || (owner && HAS_TRAIT(owner, TRAIT_NODISMEMBER)))
return FALSE
return TRUE
///Remove target limb from it's owner, with side effects.
/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE)
/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE, wound_type)
if(!owner || (bodypart_flags & BODYPART_UNREMOVABLE))
return FALSE
var/mob/living/carbon/limb_owner = owner
@@ -22,11 +22,15 @@
playsound(get_turf(limb_owner), 'sound/effects/dismember.ogg', 80, TRUE)
limb_owner.add_mood_event("dismembered_[body_zone]", /datum/mood_event/dismembered, src)
limb_owner.add_mob_memory(/datum/memory/was_dismembered, lost_limb = src)
if (wound_type)
LAZYSET(limb_owner.body_zone_dismembered_by, body_zone, wound_type)
drop_limb()
limb_owner.update_equipment_speed_mods() // Update in case speed affecting item unequipped by dismemberment
var/turf/owner_location = limb_owner.loc
if(istype(owner_location))
if(wound_type != WOUND_BURN && istype(owner_location) && can_bleed())
limb_owner.add_splatter_floor(owner_location)
if(QDELETED(src)) //Could have dropped into lava/explosion/chasm/whatever
@@ -34,8 +38,9 @@
if(dam_type == BURN)
burn()
return TRUE
add_mob_blood(limb_owner)
limb_owner.bleed(rand(20, 40))
if (can_bleed())
add_mob_blood(limb_owner)
limb_owner.bleed(rand(20, 40))
var/direction = pick(GLOB.cardinals)
var/t_range = rand(2,max(throw_range/2, 2))
var/turf/target_turf = get_turf(src)
@@ -47,10 +52,10 @@
if(new_turf.density)
break
throw_at(target_turf, throw_range, throw_speed)
return TRUE
/obj/item/bodypart/chest/dismember()
/obj/item/bodypart/chest/dismember(dam_type = BRUTE, silent=TRUE, wound_type)
if(!owner)
return FALSE
var/mob/living/carbon/chest_owner = owner
@@ -59,7 +64,7 @@
if(HAS_TRAIT(chest_owner, TRAIT_NODISMEMBER))
return FALSE
. = list()
if(isturf(chest_owner.loc))
if(wound_type != WOUND_BURN && isturf(chest_owner.loc) && can_bleed())
chest_owner.add_splatter_floor(chest_owner.loc)
playsound(get_turf(chest_owner), 'sound/misc/splort.ogg', 80, TRUE)
for(var/obj/item/organ/organ as anything in chest_owner.organs)
@@ -81,8 +86,6 @@
. += cavity_item
cavity_item = null
///limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in.
/obj/item/bodypart/proc/drop_limb(special, dismembered)
if(!owner)
@@ -180,14 +183,17 @@
* * bare_wound_bonus: ditto above
*/
/obj/item/bodypart/proc/try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
if (!can_dismember())
return
if(wounding_dmg < DISMEMBER_MINIMUM_DAMAGE)
return
var/base_chance = wounding_dmg
base_chance += (get_damage() / max_damage * 50) // how much damage we dealt with this blow, + 50% of the damage percentage we already had on this bodypart
if(locate(/datum/wound/blunt/critical) in wounds) // we only require a severe bone break, but if there's a critical bone break, we'll add 15% more
base_chance += 15
for (var/datum/wound/iterated_wound as anything in wounds)
base_chance += iterated_wound.get_dismember_chance_bonus(base_chance)
if(prob(base_chance))
var/datum/wound/loss/dismembering = new
@@ -328,6 +334,8 @@
set_owner(new_limb_owner)
new_limb_owner.add_bodypart(src)
LAZYREMOVE(new_limb_owner.body_zone_dismembered_by, body_zone)
if(special) //non conventional limb attachment
for(var/datum/surgery/attach_surgery as anything in new_limb_owner.surgeries) //if we had an ongoing surgery to attach a new limb, we stop it.
var/surgery_zone = check_zone(attach_surgery.location)
@@ -416,12 +424,15 @@
/mob/living/carbon/proc/regenerate_limbs(list/excluded_zones = list())
SEND_SIGNAL(src, COMSIG_CARBON_REGENERATE_LIMBS, excluded_zones)
var/list/zone_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
var/list/dismembered_by_copy = body_zone_dismembered_by?.Copy()
if(length(excluded_zones))
zone_list -= excluded_zones
for(var/limb_zone in zone_list)
regenerate_limb(limb_zone)
regenerate_limb(limb_zone, dismembered_by_copy)
/mob/living/carbon/proc/regenerate_limb(limb_zone)
/mob/living/carbon/proc/regenerate_limb(limb_zone, list/dismembered_by_copy = body_zone_dismembered_by?.Copy())
var/obj/item/bodypart/limb
if(get_bodypart(limb_zone))
return FALSE
@@ -431,9 +442,16 @@
qdel(limb)
return FALSE
limb.update_limb(is_creating = TRUE)
var/datum/scar/scaries = new
var/datum/wound/loss/phantom_loss = new // stolen valor, really
scaries.generate(limb, phantom_loss)
if (LAZYLEN(dismembered_by_copy))
var/datum/scar/scaries = new
var/datum/wound/loss/phantom_loss = new // stolen valor, really
phantom_loss.loss_wound_type = dismembered_by_copy?[limb_zone]
if (phantom_loss.loss_wound_type)
scaries.generate(limb, phantom_loss)
LAZYREMOVE(dismembered_by_copy, limb_zone) // in case we're using a passed list
else
qdel(scaries)
qdel(phantom_loss)
//Copied from /datum/species/proc/on_species_gain()
for(var/obj/item/organ/external/organ_path as anything in dna.species.external_organs)
+4 -3
View File
@@ -191,9 +191,10 @@
/obj/item/bodypart/head/update_limb(dropping_limb, is_creating)
. = ..()
if(!isnull(owner))
real_name = owner.real_name
if(HAS_TRAIT(owner, TRAIT_HUSK))
real_name = "Unknown"
if(HAS_TRAIT(owner, TRAIT_HUSK))
real_name = "Unknown"
else
real_name = owner.real_name
update_hair_and_lips(dropping_limb, is_creating)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+4
View File
@@ -114,6 +114,8 @@
/// Datum describing how to offset things held in the hands of this arm, the x offset IS functional here
var/datum/worn_feature_offset/held_hand_offset
biological_state = (BIO_STANDARD|BIO_JOINTED)
/obj/item/bodypart/arm/Destroy()
QDEL_NULL(worn_glove_offset)
QDEL_NULL(held_hand_offset)
@@ -344,6 +346,8 @@
/// Datum describing how to offset things worn on the foot of this leg, note that an x offset won't do anything here
var/datum/worn_feature_offset/worn_foot_offset
biological_state = (BIO_STANDARD|BIO_JOINTED)
/obj/item/bodypart/leg/Destroy()
QDEL_NULL(worn_foot_offset)
return ..()
@@ -37,6 +37,8 @@
medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG
heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG
biological_state = (BIO_ROBOTIC|BIO_JOINTED)
damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT)
disabling_threshold_percentage = 1
@@ -58,6 +60,7 @@
brute_modifier = 0.8
burn_modifier = 0.8
disabling_threshold_percentage = 1
light_brute_msg = ROBOTIC_LIGHT_BRUTE_MSG
@@ -68,6 +71,8 @@
medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG
heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG
biological_state = (BIO_ROBOTIC|BIO_JOINTED)
damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT)
/obj/item/bodypart/leg/left/robot
@@ -88,6 +93,7 @@
brute_modifier = 0.8
burn_modifier = 0.8
disabling_threshold_percentage = 1
light_brute_msg = ROBOTIC_LIGHT_BRUTE_MSG
@@ -98,6 +104,8 @@
medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG
heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG
biological_state = (BIO_ROBOTIC|BIO_JOINTED)
damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT)
/obj/item/bodypart/leg/left/robot/emp_act(severity)
@@ -127,6 +135,7 @@
brute_modifier = 0.8
burn_modifier = 0.8
disabling_threshold_percentage = 1
light_brute_msg = ROBOTIC_LIGHT_BRUTE_MSG
@@ -137,6 +146,8 @@
medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG
heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG
biological_state = (BIO_ROBOTIC|BIO_JOINTED)
damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT)
/obj/item/bodypart/leg/right/robot/emp_act(severity)
@@ -174,6 +185,8 @@
medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG
heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG
biological_state = (BIO_ROBOTIC)
damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT)
var/wired = FALSE
@@ -294,6 +307,8 @@
medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG
heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG
biological_state = (BIO_ROBOTIC)
damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT)
head_flags = HEAD_EYESPRITES
@@ -380,6 +395,11 @@
flash2?.forceMove(drop_loc)
return ..()
// Prosthetics - Cheap, mediocre, and worse than organic limbs
// The fact they dont have a internal biotype means theyre a lot weaker defensively,
// since they skip slash and go right to blunt
// They are VERY easy to delimb as a result
// HP is also reduced just in case this isnt enough
/obj/item/bodypart/arm/left/robot/surplus
name = "surplus prosthetic left arm"
@@ -390,6 +410,8 @@
brute_modifier = 1
max_damage = 20
biological_state = (BIO_METAL|BIO_JOINTED)
/obj/item/bodypart/arm/right/robot/surplus
name = "surplus prosthetic right arm"
desc = "A skeletal, robotic limb. Outdated and fragile, but it's still better than nothing."
@@ -399,6 +421,8 @@
brute_modifier = 1
max_damage = 20
biological_state = (BIO_METAL|BIO_JOINTED)
/obj/item/bodypart/leg/left/robot/surplus
name = "surplus prosthetic left leg"
desc = "A skeletal, robotic limb. Outdated and fragile, but it's still better than nothing."
@@ -408,6 +432,8 @@
burn_modifier = 1
max_damage = 20
biological_state = (BIO_METAL|BIO_JOINTED)
/obj/item/bodypart/leg/right/robot/surplus
name = "surplus prosthetic right leg"
desc = "A skeletal, robotic limb. Outdated and fragile, but it's still better than nothing."
@@ -417,6 +443,8 @@
burn_modifier = 1
max_damage = 20
biological_state = (BIO_METAL|BIO_JOINTED)
#undef ROBOTIC_LIGHT_BRUTE_MSG
#undef ROBOTIC_MEDIUM_BRUTE_MSG
#undef ROBOTIC_HEAVY_BRUTE_MSG
@@ -1,19 +1,19 @@
///SNAIL
/obj/item/bodypart/head/snail
biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
limb_id = SPECIES_SNAIL
is_dimorphic = FALSE
burn_modifier = 2
head_flags = HEAD_EYESPRITES|HEAD_DEBRAIN
/obj/item/bodypart/chest/snail
biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
limb_id = SPECIES_SNAIL
is_dimorphic = FALSE
burn_modifier = 2
/obj/item/bodypart/arm/left/snail
biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
limb_id = SPECIES_SNAIL
unarmed_attack_verb = "slap"
unarmed_attack_effect = ATTACK_EFFECT_DISARM
@@ -22,7 +22,7 @@
burn_modifier = 2
/obj/item/bodypart/arm/right/snail
biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
limb_id = SPECIES_SNAIL
unarmed_attack_verb = "slap"
unarmed_attack_effect = ATTACK_EFFECT_DISARM
@@ -31,7 +31,7 @@
burn_modifier = 2
/obj/item/bodypart/leg/left/snail
biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
limb_id = SPECIES_SNAIL
unarmed_damage_low = 1 //SKYRAT EDIT - Roundstart Snails - Lowest possible punch damage. if this is set to 0, punches will always miss.
unarmed_damage_high = 5 //snails are soft and squishy //SKYRAT EDIT - Roundstart Snails - A Bit More Damage. - ORIGINAL: unarmed_damage_high = 0.5 //snails are soft and squishy
@@ -39,7 +39,7 @@
// speed_modifier = 3 //disgustingly slow // SKYRAT EDIT - Moved the movespeed to the shell.
/obj/item/bodypart/leg/right/snail
biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates!
limb_id = SPECIES_SNAIL
unarmed_damage_low = 1 //SKYRAT EDIT - Roundstart Snails - Lowest possible punch damage. if this is set to 0, punches will always miss.
unarmed_damage_high = 5 //snails are soft and squishy //SKYRAT EDIT - Roundstart Snails - A Bit More Damage. - ORIGINAL: unarmed_damage_high = 0.5 //snails are soft and squishy
@@ -48,43 +48,37 @@
///ABDUCTOR
/obj/item/bodypart/head/abductor
biological_state = BIO_INORGANIC //i have no fucking clue why these mfs get no wounds but SURE
limb_id = SPECIES_ABDUCTOR
is_dimorphic = FALSE
should_draw_greyscale = FALSE
head_flags = NONE
/obj/item/bodypart/chest/abductor
biological_state = BIO_INORGANIC
limb_id = SPECIES_ABDUCTOR
is_dimorphic = FALSE
should_draw_greyscale = FALSE
/obj/item/bodypart/arm/left/abductor
biological_state = BIO_INORGANIC
limb_id = SPECIES_ABDUCTOR
should_draw_greyscale = FALSE
bodypart_traits = list(TRAIT_CHUNKYFINGERS)
/obj/item/bodypart/arm/right/abductor
biological_state = BIO_INORGANIC
limb_id = SPECIES_ABDUCTOR
should_draw_greyscale = FALSE
bodypart_traits = list(TRAIT_CHUNKYFINGERS)
/obj/item/bodypart/leg/left/abductor
biological_state = BIO_INORGANIC
limb_id = SPECIES_ABDUCTOR
should_draw_greyscale = FALSE
/obj/item/bodypart/leg/right/abductor
biological_state = BIO_INORGANIC
limb_id = SPECIES_ABDUCTOR
should_draw_greyscale = FALSE
///JELLY
/obj/item/bodypart/head/jelly
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED)
limb_id = SPECIES_JELLYPERSON
is_dimorphic = TRUE
dmg_overlay_type = null
@@ -92,90 +86,90 @@
head_flags = HEAD_ALL_FEATURES
/obj/item/bodypart/chest/jelly
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED)
limb_id = SPECIES_JELLYPERSON
is_dimorphic = TRUE
dmg_overlay_type = null
burn_modifier = 0.5 // = 1/2x generic burn damage
/obj/item/bodypart/arm/left/jelly
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_JELLYPERSON
dmg_overlay_type = null
burn_modifier = 0.5 // = 1/2x generic burn damage
/obj/item/bodypart/arm/right/jelly
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_JELLYPERSON
dmg_overlay_type = null
burn_modifier = 0.5 // = 1/2x generic burn damage
/obj/item/bodypart/leg/left/jelly
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_JELLYPERSON
dmg_overlay_type = null
burn_modifier = 0.5 // = 1/2x generic burn damage
/obj/item/bodypart/leg/right/jelly
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_JELLYPERSON
dmg_overlay_type = null
burn_modifier = 0.5 // = 1/2x generic burn damage
///SLIME
/obj/item/bodypart/head/slime
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED)
limb_id = SPECIES_SLIMEPERSON
is_dimorphic = FALSE
head_flags = HEAD_ALL_FEATURES
/obj/item/bodypart/chest/slime
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED)
limb_id = SPECIES_SLIMEPERSON
is_dimorphic = TRUE
/obj/item/bodypart/arm/left/slime
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_SLIMEPERSON
/obj/item/bodypart/arm/right/slime
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_SLIMEPERSON
/obj/item/bodypart/leg/left/slime
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED)
limb_id = SPECIES_SLIMEPERSON
/obj/item/bodypart/leg/right/slime
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_SLIMEPERSON
///LUMINESCENT
/obj/item/bodypart/head/luminescent
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED)
limb_id = SPECIES_LUMINESCENT
is_dimorphic = TRUE
head_flags = HEAD_ALL_FEATURES
/obj/item/bodypart/chest/luminescent
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED)
limb_id = SPECIES_LUMINESCENT
is_dimorphic = TRUE
/obj/item/bodypart/arm/left/luminescent
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_LUMINESCENT
/obj/item/bodypart/arm/right/luminescent
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_LUMINESCENT
/obj/item/bodypart/leg/left/luminescent
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_LUMINESCENT
/obj/item/bodypart/leg/right/luminescent
biological_state = BIO_INORGANIC
biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED)
limb_id = SPECIES_LUMINESCENT
///ZOMBIE
@@ -282,7 +276,6 @@
///SHADOW
/obj/item/bodypart/head/shadow
biological_state = BIO_INORGANIC
limb_id = SPECIES_SHADOW
is_dimorphic = FALSE
should_draw_greyscale = FALSE
@@ -290,32 +283,27 @@
head_flags = NONE
/obj/item/bodypart/chest/shadow
biological_state = BIO_INORGANIC
limb_id = SPECIES_SHADOW
is_dimorphic = FALSE
should_draw_greyscale = FALSE
burn_modifier = 1.5
/obj/item/bodypart/arm/left/shadow
biological_state = BIO_INORGANIC
limb_id = SPECIES_SHADOW
should_draw_greyscale = FALSE
burn_modifier = 1.5
/obj/item/bodypart/arm/right/shadow
biological_state = BIO_INORGANIC
limb_id = SPECIES_SHADOW
should_draw_greyscale = FALSE
burn_modifier = 1.5
/obj/item/bodypart/leg/left/shadow
biological_state = BIO_INORGANIC
limb_id = SPECIES_SHADOW
should_draw_greyscale = FALSE
burn_modifier = 1.5
/obj/item/bodypart/leg/right/shadow
biological_state = BIO_INORGANIC
limb_id = SPECIES_SHADOW
should_draw_greyscale = FALSE
burn_modifier = 1.5
@@ -343,25 +331,25 @@
dmg_overlay_type = null
/obj/item/bodypart/arm/left/skeleton
biological_state = BIO_BONE
biological_state = (BIO_BONE|BIO_JOINTED)
limb_id = SPECIES_SKELETON
should_draw_greyscale = FALSE
dmg_overlay_type = null
/obj/item/bodypart/arm/right/skeleton
biological_state = BIO_BONE
biological_state = (BIO_BONE|BIO_JOINTED)
limb_id = SPECIES_SKELETON
should_draw_greyscale = FALSE
dmg_overlay_type = null
/obj/item/bodypart/leg/left/skeleton
biological_state = BIO_BONE
biological_state = (BIO_BONE|BIO_JOINTED)
limb_id = SPECIES_SKELETON
should_draw_greyscale = FALSE
dmg_overlay_type = null
/obj/item/bodypart/leg/right/skeleton
biological_state = BIO_BONE
biological_state = (BIO_BONE|BIO_JOINTED)
limb_id = SPECIES_SKELETON
should_draw_greyscale = FALSE
dmg_overlay_type = null
@@ -414,7 +402,7 @@
icon = 'icons/mob/human/species/golems.dmi'
icon_static = 'icons/mob/human/species/golems.dmi'
icon_state = "golem_head"
biological_state = BIO_INORGANIC
biological_state = BIO_BONE
bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC
limb_id = SPECIES_GOLEM
is_dimorphic = FALSE
@@ -451,7 +439,7 @@
icon = 'icons/mob/human/species/golems.dmi'
icon_static = 'icons/mob/human/species/golems.dmi'
icon_state = "golem_chest"
biological_state = BIO_INORGANIC
biological_state = BIO_BONE
acceptable_bodytype = BODYTYPE_GOLEM
bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC
limb_id = SPECIES_GOLEM
@@ -472,7 +460,7 @@
icon = 'icons/mob/human/species/golems.dmi'
icon_static = 'icons/mob/human/species/golems.dmi'
icon_state = "golem_l_arm"
biological_state = BIO_INORGANIC
biological_state = (BIO_BONE|BIO_JOINTED)
bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC
limb_id = SPECIES_GOLEM
should_draw_greyscale = FALSE
@@ -506,7 +494,7 @@
icon = 'icons/mob/human/species/golems.dmi'
icon_static = 'icons/mob/human/species/golems.dmi'
icon_state = "golem_r_arm"
biological_state = BIO_INORGANIC
biological_state = (BIO_BONE|BIO_JOINTED)
bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC
limb_id = SPECIES_GOLEM
should_draw_greyscale = FALSE
@@ -540,7 +528,7 @@
icon = 'icons/mob/human/species/golems.dmi'
icon_static = 'icons/mob/human/species/golems.dmi'
icon_state = "golem_l_leg"
biological_state = BIO_INORGANIC
biological_state = (BIO_BONE|BIO_JOINTED)
bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC
limb_id = SPECIES_GOLEM
should_draw_greyscale = FALSE
@@ -553,7 +541,7 @@
icon = 'icons/mob/human/species/golems.dmi'
icon_static = 'icons/mob/human/species/golems.dmi'
icon_state = "golem_r_leg"
biological_state = BIO_INORGANIC
biological_state = (BIO_BONE|BIO_JOINTED)
bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC
limb_id = SPECIES_GOLEM
should_draw_greyscale = FALSE
@@ -27,7 +27,7 @@
icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi'
icon_state = "plasmaman_l_arm"
icon_static = 'icons/mob/human/species/plasmaman/bodyparts.dmi'
biological_state = BIO_BONE
biological_state = (BIO_BONE|BIO_JOINTED)
limb_id = SPECIES_PLASMAMAN
should_draw_greyscale = FALSE
dmg_overlay_type = null
@@ -38,7 +38,7 @@
icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi'
icon_state = "plasmaman_r_arm"
icon_static = 'icons/mob/human/species/plasmaman/bodyparts.dmi'
biological_state = BIO_BONE
biological_state = (BIO_BONE|BIO_JOINTED)
limb_id = SPECIES_PLASMAMAN
should_draw_greyscale = FALSE
dmg_overlay_type = null
@@ -49,7 +49,7 @@
icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi'
icon_state = "plasmaman_l_leg"
icon_static = 'icons/mob/human/species/plasmaman/bodyparts.dmi'
biological_state = BIO_BONE
biological_state = (BIO_BONE|BIO_JOINTED)
limb_id = SPECIES_PLASMAMAN
should_draw_greyscale = FALSE
dmg_overlay_type = null
@@ -60,7 +60,7 @@
icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi'
icon_state = "plasmaman_r_leg"
icon_static = 'icons/mob/human/species/plasmaman/bodyparts.dmi'
biological_state = BIO_BONE
biological_state = (BIO_BONE|BIO_JOINTED)
limb_id = SPECIES_PLASMAMAN
should_draw_greyscale = FALSE
dmg_overlay_type = null
+76 -38
View File
@@ -8,40 +8,74 @@
var/mangled_state = get_mangled_state()
var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
if(wounding_type == WOUND_BLUNT && sharpness)
if(sharpness & SHARP_EDGED)
wounding_type = WOUND_SLASH
else if (sharpness & SHARP_POINTY)
wounding_type = WOUND_PIERCE
var/has_exterior = FALSE
var/has_interior = FALSE
//Handling for bone only/flesh only(none right now)/flesh and bone targets
switch(biological_state)
// if we're bone only, all cutting attacks go straight to the bone
if(BIO_BONE)
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
phantom_wounding_dmg *= (easy_dismember ? 1 : 0.6)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75)
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
return
// note that there's no handling for BIO_FLESH since we don't have any that are that right now (slimepeople maybe someday)
// standard humanoids
if(BIO_FLESH_BONE)
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
if((mangled_state & BODYPART_MANGLED_FLESH) && !(mangled_state & BODYPART_MANGLED_BONE) && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
phantom_wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area
if(wounding_type == WOUND_PIERCE && !easy_dismember)
phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
wounding_type = WOUND_BLUNT
else if((mangled_state & BODYPART_MANGLED_FLESH) && (mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
for (var/state as anything in GLOB.bio_state_states)
var/flag = text2num(state)
if (!(biological_state & flag))
continue
var/value = GLOB.bio_state_states[state]
if (value & BIO_EXTERIOR)
has_exterior = TRUE
if (value & BIO_INTERIOR)
has_interior = TRUE
if (has_exterior && has_interior)
break
// We put this here so we dont increase init time by doing this all at once on initialization
// Effectively, we "lazy load"
if (isnull(any_existing_wound_can_mangle_our_bone) || isnull(any_existing_wound_can_mangle_our_flesh))
any_existing_wound_can_mangle_our_bone = FALSE
any_existing_wound_can_mangle_our_flesh = FALSE
for (var/datum/wound/wound_type as anything in GLOB.all_wound_pregen_data)
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[wound_type]
if (!pregen_data.can_be_applied_to(src, random_roll = TRUE)) // we only consider randoms because non-randoms are usually really specific
continue
if (initial(pregen_data.wound_path_to_generate.wound_flags) & MANGLES_FLESH)
any_existing_wound_can_mangle_our_flesh = TRUE
if (initial(pregen_data.wound_path_to_generate.wound_flags) & MANGLES_BONE)
any_existing_wound_can_mangle_our_bone = TRUE
if (any_existing_wound_can_mangle_our_bone && any_existing_wound_can_mangle_our_flesh)
break
var/can_theoretically_be_dismembered = (any_existing_wound_can_mangle_our_bone || (any_existing_wound_can_mangle_our_flesh && !has_exterior))
var/exterior_ready_to_dismember = (!has_exterior || ((mangled_state & BODYPART_MANGLED_BONE) == BODYPART_MANGLED_BONE))
var/interior_ready_to_dismember = (!has_interior || ((mangled_state & BODYPART_MANGLED_FLESH) == BODYPART_MANGLED_FLESH))
// if we're bone only, all cutting attacks go straight to the bone
if(has_exterior && interior_ready_to_dismember)
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
phantom_wounding_dmg *= (easy_dismember ? 1 : 0.6)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75)
if(exterior_ready_to_dismember && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
return
else
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
if(has_exterior && interior_ready_to_dismember && !(mangled_state & BODYPART_MANGLED_BONE) && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
phantom_wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area
if(wounding_type == WOUND_PIERCE && !easy_dismember)
phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
wounding_type = WOUND_BLUNT
else if(interior_ready_to_dismember && exterior_ready_to_dismember && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
return
if (use_alternate_dismemberment_calc_even_if_mangleable || !can_theoretically_be_dismembered)
var/percent_to_total_max = (get_damage() / max_damage)
if (percent_to_total_max >= hp_percent_to_dismemberable)
if (try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
return
check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)
return check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)
/**
* check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria
@@ -82,7 +116,11 @@
dismembering.apply_dismember(src, woundtype, outright = TRUE, attack_direction = attack_direction)
return
var/list/wounds_checking = GLOB.global_wound_types[woundtype]
var/list/datum/wound/possible_wounds = list()
for (var/datum/wound/type as anything in GLOB.all_wound_pregen_data)
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[type]
if (pregen_data.can_be_applied_to(src, woundtype, random_roll = TRUE))
possible_wounds += type
// quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow
if(ishuman(owner))
var/mob/living/carbon/human/human_wearer = owner
@@ -94,19 +132,19 @@
break
//cycle through the wounds of the relevant category from the most severe down
for(var/datum/wound/possible_wound as anything in wounds_checking)
for(var/datum/wound/possible_wound as anything in possible_wounds)
var/datum/wound/replaced_wound
for(var/datum/wound/existing_wound as anything in wounds)
if(existing_wound.type in wounds_checking)
if(existing_wound.wound_series == initial(possible_wound.wound_series))
if(existing_wound.severity >= initial(possible_wound.severity))
return
else
replaced_wound = existing_wound
replaced_wound = existing_wound // if we find something we keep iterating untilw e're done or we find we're outclassed by something in our series
if(initial(possible_wound.threshold_minimum) < injury_roll)
var/datum/wound/new_wound
if(replaced_wound)
new_wound = replaced_wound.replace_wound(possible_wound, attack_direction = attack_direction)
new_wound = replaced_wound.replace_wound(new possible_wound, attack_direction = attack_direction)
else
new_wound = new possible_wound
new_wound.apply_wound(src, attack_direction = attack_direction, wound_source = damage_source)
@@ -119,9 +157,9 @@
var/datum/wound/potential_wound = specific_woundtype
for(var/datum/wound/existing_wound as anything in wounds)
if(existing_wound.wound_type == initial(potential_wound.wound_type))
if (existing_wound.wound_series == initial(potential_wound.wound_series))
if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force
existing_wound.replace_wound(potential_wound, smited)
existing_wound.replace_wound(new potential_wound, smited)
return
var/datum/wound/new_wound = new potential_wound
+2 -2
View File
@@ -5,7 +5,7 @@
/datum/surgery/repair_bone_hairline
name = "Repair bone fracture (hairline)"
surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB
targetable_wound = /datum/wound/blunt/severe
targetable_wound = /datum/wound/blunt/bone/severe
possible_locs = list(
BODY_ZONE_R_ARM,
BODY_ZONE_L_ARM,
@@ -31,7 +31,7 @@
/datum/surgery/repair_bone_compound
name = "Repair Compound Fracture"
surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB
targetable_wound = /datum/wound/blunt/critical
targetable_wound = /datum/wound/blunt/bone/critical
possible_locs = list(
BODY_ZONE_R_ARM,
BODY_ZONE_L_ARM,
+8 -8
View File
@@ -5,7 +5,7 @@
/datum/surgery/debride
name = "Debride burnt flesh"
surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB
targetable_wound = /datum/wound/burn
targetable_wound = /datum/wound/burn/flesh
possible_locs = list(
BODY_ZONE_R_ARM,
BODY_ZONE_L_ARM,
@@ -24,7 +24,7 @@
return FALSE
if(..())
var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected)
var/datum/wound/burn/burn_wound = targeted_bodypart.get_wound_type(targetable_wound)
var/datum/wound/burn/flesh/burn_wound = targeted_bodypart.get_wound_type(targetable_wound)
return(burn_wound && burn_wound.infestation > 0)
//SURGERY STEPS
@@ -48,7 +48,7 @@
var/infestation_removed = 4
/// To give the surgeon a heads up how much work they have ahead of them
/datum/surgery_step/debride/proc/get_progress(mob/user, mob/living/carbon/target, datum/wound/burn/burn_wound)
/datum/surgery_step/debride/proc/get_progress(mob/user, mob/living/carbon/target, datum/wound/burn/flesh/burn_wound)
if(!burn_wound?.infestation || !infestation_removed)
return
var/estimated_remaining_steps = burn_wound.infestation / infestation_removed
@@ -68,7 +68,7 @@
/datum/surgery_step/debride/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(surgery.operated_wound)
var/datum/wound/burn/burn_wound = surgery.operated_wound
var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound
if(burn_wound.infestation <= 0)
to_chat(user, span_notice("[target]'s [parse_zone(user.zone_selected)] has no infected flesh to remove!"))
surgery.status++
@@ -86,7 +86,7 @@
user.visible_message(span_notice("[user] looks for [target]'s [parse_zone(user.zone_selected)]."), span_notice("You look for [target]'s [parse_zone(user.zone_selected)]..."))
/datum/surgery_step/debride/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/burn/burn_wound = surgery.operated_wound
var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound
if(burn_wound)
var/progress_text = get_progress(user, target, burn_wound)
display_results(
@@ -120,7 +120,7 @@
/datum/surgery_step/debride/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
if(!..())
return
var/datum/wound/burn/burn_wound = surgery.operated_wound
var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound
while(burn_wound && burn_wound.infestation > 0.25)
if(!..())
break
@@ -139,7 +139,7 @@
/datum/surgery_step/dress/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/datum/wound/burn/burn_wound = surgery.operated_wound
var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound
if(burn_wound)
display_results(
user,
@@ -153,7 +153,7 @@
user.visible_message(span_notice("[user] looks for [target]'s [parse_zone(user.zone_selected)]."), span_notice("You look for [target]'s [parse_zone(user.zone_selected)]..."))
/datum/surgery_step/dress/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/burn/burn_wound = surgery.operated_wound
var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound
if(burn_wound)
display_results(
user,
+6 -6
View File
@@ -9,7 +9,7 @@
/datum/surgery/repair_puncture
name = "Repair puncture"
surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB
targetable_wound = /datum/wound/pierce
targetable_wound = /datum/wound/pierce/bleed
target_mobtypes = list(/mob/living/carbon)
possible_locs = list(
BODY_ZONE_R_ARM,
@@ -32,7 +32,7 @@
. = ..()
if(.)
var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected)
var/datum/wound/burn/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound)
var/datum/wound/burn/flesh/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound)
return(pierce_wound && pierce_wound.blood_flow > 0)
//SURGERY STEPS
@@ -47,7 +47,7 @@
time = 3 SECONDS
/datum/surgery_step/repair_innards/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
var/datum/wound/pierce/bleed/pierce_wound = surgery.operated_wound
if(!pierce_wound)
user.visible_message(span_notice("[user] looks for [target]'s [parse_zone(user.zone_selected)]."), span_notice("You look for [target]'s [parse_zone(user.zone_selected)]..."))
return
@@ -67,7 +67,7 @@
display_pain(target, "You feel a horrible stabbing pain in your [parse_zone(user.zone_selected)]!")
/datum/surgery_step/repair_innards/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
var/datum/wound/pierce/bleed/pierce_wound = surgery.operated_wound
if(!pierce_wound)
to_chat(user, span_warning("[target] has no puncture wound there!"))
return ..()
@@ -112,7 +112,7 @@
return TRUE
/datum/surgery_step/seal_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
var/datum/wound/pierce/bleed/pierce_wound = surgery.operated_wound
if(!pierce_wound)
user.visible_message(span_notice("[user] looks for [target]'s [parse_zone(user.zone_selected)]."), span_notice("You look for [target]'s [parse_zone(user.zone_selected)]..."))
return
@@ -126,7 +126,7 @@
display_pain(target, "You're being burned inside your [parse_zone(user.zone_selected)]!")
/datum/surgery_step/seal_veins/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
var/datum/wound/pierce/bleed/pierce_wound = surgery.operated_wound
if(!pierce_wound)
to_chat(user, span_warning("[target] has no puncture there!"))
return ..()
+12 -10
View File
@@ -12,10 +12,10 @@
var/i = 1
var/list/iter_test_wound_list
for(iter_test_wound_list in list(list(/datum/wound/blunt/moderate, /datum/wound/blunt/severe, /datum/wound/blunt/critical),\
list(/datum/wound/slash/moderate, /datum/wound/slash/severe, /datum/wound/slash/critical),\
list(/datum/wound/pierce/moderate, /datum/wound/pierce/severe, /datum/wound/pierce/critical),\
list(/datum/wound/burn/moderate, /datum/wound/burn/severe, /datum/wound/burn/critical)))
for(iter_test_wound_list in list(list(/datum/wound/blunt/bone/moderate, /datum/wound/blunt/bone/severe, /datum/wound/blunt/bone/critical),\
list(/datum/wound/slash/flesh/moderate, /datum/wound/slash/flesh/severe, /datum/wound/slash/flesh/critical),\
list(/datum/wound/pierce/bleed/moderate, /datum/wound/pierce/bleed/severe, /datum/wound/pierce/bleed/critical),\
list(/datum/wound/burn/flesh/moderate, /datum/wound/burn/flesh/severe, /datum/wound/burn/flesh/critical)))
TEST_ASSERT_EQUAL(length(victim.all_wounds), 0, "Patient is somehow wounded before test")
var/datum/wound/iter_test_wound
@@ -52,10 +52,10 @@
var/list/iter_test_wound_list
tested_part.biological_state &= ~BIO_FLESH // take away the base limb's flesh (ouchie!) ((not actually ouchie, this just affects their wounds and dismemberment handling))
for(iter_test_wound_list in list(list(/datum/wound/blunt/moderate, /datum/wound/blunt/severe, /datum/wound/blunt/critical),\
list(/datum/wound/slash/moderate, /datum/wound/slash/severe, /datum/wound/slash/critical),\
list(/datum/wound/pierce/moderate, /datum/wound/pierce/severe, /datum/wound/pierce/critical),\
list(/datum/wound/burn/moderate, /datum/wound/burn/severe, /datum/wound/burn/critical)))
for(iter_test_wound_list in list(list(/datum/wound/blunt/bone/moderate, /datum/wound/blunt/bone/severe, /datum/wound/blunt/bone/critical),\
list(/datum/wound/slash/flesh/moderate, /datum/wound/slash/flesh/severe, /datum/wound/slash/flesh/critical),\
list(/datum/wound/pierce/bleed/moderate, /datum/wound/pierce/bleed/severe, /datum/wound/pierce/bleed/critical),\
list(/datum/wound/burn/flesh/moderate, /datum/wound/burn/flesh/severe, /datum/wound/burn/flesh/critical)))
TEST_ASSERT_EQUAL(length(victim.all_wounds), 0, "Patient is somehow wounded before test")
var/datum/wound/iter_test_wound
@@ -69,13 +69,15 @@
tested_part.receive_damage(0, WOUND_MINIMUM_DAMAGE, wound_bonus = threshold, sharpness=sharps[i])
// so if we just tried to deal a flesh wound, make sure we didn't actually suffer it. We may have suffered a bone wound instead, but we just want to make sure we don't have a flesh wound
if(initial(iter_test_wound.wound_flags) & FLESH_WOUND)
var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[iter_test_wound]
if (pregen_data.required_limb_biostate & BIO_FLESH)
if(!length(victim.all_wounds)) // not having a wound is good news
continue
else // we have to check that it's actually a bone wound and not the intended wound type
TEST_ASSERT_EQUAL(length(victim.all_wounds), 1, "Patient has more than one wound when only one is expected. Severity: [initial(iter_test_wound.severity)]")
var/datum/wound/actual_wound = victim.all_wounds[1]
TEST_ASSERT((actual_wound.wound_flags & ~FLESH_WOUND), "Limb has flesh wound despite no BIO_FLESH biological_state, expected either no wound or bone wound. Offending wound: [actual_wound]")
var/datum/wound_pregen_data/actual_pregen_data = GLOB.all_wound_pregen_data[actual_wound.type]
TEST_ASSERT((actual_pregen_data.required_limb_biostate & ~BIO_FLESH), "Limb has flesh wound despite no BIO_FLESH biological_state, expected either no wound or bone wound. Offending wound: [actual_wound]")
threshold_penalty = actual_wound.threshold_penalty
else // otherwise if it's a bone wound, check that we have it per usual
TEST_ASSERT(length(victim.all_wounds), "Patient has no wounds when one wound is expected. Severity: [initial(iter_test_wound.severity)]")
+2 -2
View File
@@ -122,8 +122,8 @@
continue
for(var/obj/item/bodypart/head/head_to_wound as anything in carbon_occupant.bodyparts)
var/type_wound = pick(list(
/datum/wound/blunt/moderate,
/datum/wound/blunt/severe,
/datum/wound/blunt/bone/moderate,
/datum/wound/blunt/bone/severe,
))
head_to_wound.force_wound_upwards(type_wound, wound_source = src)
carbon_occupant.playsound_local(src, 'sound/weapons/flash_ring.ogg', 50)
+5 -3
View File
@@ -954,11 +954,13 @@
return FALSE
var/mob/living/carbon/carbon_target = atom_target
for(var/obj/item/bodypart/squish_part in carbon_target.bodyparts)
if(IS_ORGANIC_LIMB(squish_part))
var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
squish_part.force_wound_upwards(type_wound, wound_source = "crushed by [src]")
var/type_wound
if (squish_part.biological_state & BIO_BONE)
type_wound = pick(list(/datum/wound/blunt/bone/critical, /datum/wound/blunt/bone/severe, /datum/wound/blunt/bone/moderate))
else
squish_part.receive_damage(brute=30)
if (type_wound)
squish_part.force_wound_upwards(type_wound, wound_source = "crushed by [src]")
carbon_target.visible_message(span_danger("[carbon_target]'s body is maimed underneath the mass of [src]!"), span_userdanger("Your body is maimed underneath the mass of [src]!"))
return TRUE
if(CRUSH_CRIT_HEADGIB) // skull squish!
@@ -3,25 +3,25 @@
/obj/item/bodypart/head/slime/roundstart
is_dimorphic = TRUE
icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME
biological_state = BIO_FLESH
biological_state = (BIO_FLESH|BIO_BLOODED)
/obj/item/bodypart/chest/slime/roundstart
is_dimorphic = TRUE
icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME
biological_state = BIO_FLESH
biological_state = (BIO_FLESH|BIO_BLOODED)
/obj/item/bodypart/arm/left/slime/roundstart
icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME
biological_state = BIO_FLESH
biological_state = (BIO_FLESH|BIO_BLOODED)
/obj/item/bodypart/arm/right/slime/roundstart
icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME
biological_state = BIO_FLESH
biological_state = (BIO_FLESH|BIO_BLOODED)
/obj/item/bodypart/leg/left/slime/roundstart
icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME
biological_state = BIO_FLESH
biological_state = (BIO_FLESH|BIO_BLOODED)
/obj/item/bodypart/leg/right/slime/roundstart
icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME
biological_state = BIO_FLESH
biological_state = (BIO_FLESH|BIO_BLOODED)
@@ -213,8 +213,8 @@
for(var/i in 1 to 2)
var/obj/item/bodypart/limb = target.get_bodypart(pick_n_take(parts_to_fuck_up))
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
limb.receive_damage(brute = WOUND_MINIMUM_DAMAGE, wound_bonus = rand(initial(severe_wound_type.threshold_minimum), initial(critical_wound_type.threshold_minimum) + 10))
target.update_damage_overlays()
@@ -53,8 +53,6 @@ Re-writes how mutant bodyparts exist and how they're handled. Adds in a per limb
./code/_globalvars/lists/flavor_misc.dm > Removed accessory list defines
.\code\datums\keybindings\living.dm > /datum/keybinding/living/look_up > from L to P
./code/modules/surgery/bodyparts/_bodyparts.dm > var/rendered_bp_icon
./code/__DEFINES/~skyrat_defines/DNA.dm > A TON of defines
./code/__DEFINES/~skyrat_defines/obj_flags.dm > Organ flags
./code/__DEFINES/~skyrat_defines/say.dm > MAX_FLAVOR_LEN
@@ -614,51 +614,30 @@
/obj/item/clothing/suit/space/hev_suit/proc/process_wound(carbon, wound, bodypart)
SIGNAL_HANDLER
var/list/minor_fractures = list(
/datum/wound/blunt,
/datum/wound/blunt/moderate,
/datum/wound/muscle,
/datum/wound/muscle/moderate
)
var/list/major_fractures = list(
/datum/wound/blunt/severe,
/datum/wound/blunt/critical,
/datum/wound/muscle/severe,
/datum/wound/loss
)
var/list/minor_lacerations = list(
/datum/wound/burn,
/datum/wound/burn/moderate,
/datum/wound/pierce,
/datum/wound/pierce/moderate,
/datum/wound/slash,
/datum/wound/slash/moderate
)
var/list/major_lacerations = list(
/datum/wound/burn/severe,
/datum/wound/burn/critical,
/datum/wound/pierce/severe,
/datum/wound/pierce/critical,
/datum/wound/slash/severe,
/datum/wound/slash/critical
)
if (!istype(wound, /datum/wound))
return
if(wound in minor_fractures)
send_hev_sound(minor_fracture_sound)
else if(wound in major_fractures)
send_hev_sound(major_fracture_sound)
else if(wound in minor_lacerations)
send_hev_sound(minor_lacerations_sound)
else if(wound in major_lacerations)
send_hev_sound(major_lacerations_sound)
else
var/sound2play = pick(list(
minor_fracture_sound,
major_fracture_sound,
minor_lacerations_sound,
major_lacerations_sound
))
send_hev_sound(sound2play)
var/datum/wound/new_wound = wound
var/sound_to_play
var/wound_series = new_wound.wound_series
var/wound_type = new_wound.wound_type
var/wound_severity = new_wound.severity
if (wound_type == WOUND_SLASH || wound_type == WOUND_PIERCE)
if (wound_severity >= WOUND_SEVERITY_SEVERE)
sound_to_play = major_lacerations_sound
else
sound_to_play = minor_lacerations_sound
else if (wound_type == WOUND_BLUNT || wound_series == WOUND_SERIES_MUSCLE_DAMAGE)
if (wound_severity >= WOUND_SEVERITY_SEVERE)
sound_to_play = major_fracture_sound
else
sound_to_play = minor_fracture_sound
if (sound_to_play)
send_hev_sound(sound_to_play)
/obj/item/clothing/suit/space/hev_suit/proc/process_acid()
SIGNAL_HANDLER
@@ -1,11 +0,0 @@
/obj/item/bodypart/proc/apply_gauze(obj/item/stack/medical/gauze/new_gauze)
if(!istype(new_gauze) || current_gauze)
return
current_gauze = new new_gauze.gauze_type(src)
new_gauze.use(1)
/obj/item/bodypart/proc/apply_splint(obj/item/stack/medical/gauze/new_splint)
if(!istype(new_splint) || current_splint)
return
current_splint = new new_splint.splint_type(src)
new_splint.use(1)
@@ -1,227 +0,0 @@
#define SELF_AID_REMOVE_DELAY (5 SECONDS)
#define OTHER_AID_REMOVE_DELAY (2 SECONDS)
/datum/bodypart_aid
var/name
/// Keeping track of how damaged our aid is from external things, such as hits, it will break when it reaches 0
var/integrity = 2
/// To which bodypart we're attached to
var/obj/item/bodypart/bodypart
/// Which item do we get when we rip this off, while its in pristine condition
var/stack_to_drop
/// Suffix for our used overlay. The suffix is the bodypart zone, and "_digitigrade" for some legs. If this is null then it wont make an overlay. Gauzes are rendered before splints
var/overlay_prefix
/// Bodypart is [this_prefix] with get_description()
var/desc_prefix
/datum/bodypart_aid/Topic(href, href_list)
. = ..()
if(href_list["remove"])
if(!bodypart.owner)
return
if(!iscarbon(usr))
return
if(!in_range(usr, bodypart.owner))
return
var/mob/living/carbon/C = usr
var/self = (C == bodypart.owner)
C.visible_message(span_notice("[C] begins removing [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]..."), span_notice("You begin to remove [name] from [self ? "your" : "[bodypart.owner]'s"] [bodypart.name]..."))
if(!do_after(C, (self ? SELF_AID_REMOVE_DELAY : OTHER_AID_REMOVE_DELAY), target=bodypart.owner))
return
if(QDELETED(src))
return
C.visible_message(span_notice("[C] removes [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]."), span_notice("You remove [name] from [self ? "your" : "[bodypart.owner]'s" ] [bodypart.name]."))
var/obj/item/gotten = rip_off()
if(gotten && !C.put_in_hands(gotten))
gotten.forceMove(get_turf(C))
/datum/bodypart_aid/New(obj/item/bodypart/BP)
//'bodypart == BP' is set in subtypes to ensure some proper signals and behaviours
if(overlay_prefix && bodypart.owner)
bodypart.owner.update_bandage_overlays()
/datum/bodypart_aid/Destroy()
if(overlay_prefix && bodypart.owner)
bodypart.owner.update_bandage_overlays()
bodypart = null
..()
/**
* take_damage() called when the bandage gets damaged
*
* This proc will subtract integrity and delete the bandage with a to_chat message to whoever was bandaged
*
*/
/datum/bodypart_aid/proc/take_damage()
integrity--
if(integrity <= 0)
if(bodypart.owner)
to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] tears and falls off!"))
qdel(src)
/**
* rip_off() called when someone rips it off
*
* It will return the bandage if it's considered pristine
*
*/
/datum/bodypart_aid/proc/rip_off()
if(is_pristine())
. = new stack_to_drop(null, 1)
qdel(src)
/**
* get_description() called by examine procs
*
* It will returns a description of the bandage
*
*/
/datum/bodypart_aid/proc/get_description()
return "[name]"
/**
* is_pristine() called by rip_off()
*
* Used to determine whether the bandage can be re-used and won't qdel itself
*
*/
/datum/bodypart_aid/proc/is_pristine()
return (integrity == initial(integrity))
/datum/bodypart_aid/splint
name = "splint"
overlay_prefix = "splint"
desc_prefix = "fastened"
stack_to_drop = /obj/item/stack/medical/gauze
/// How effective are we in keeping the bodypart rigid
var/splint_factor = 0.3
/// Whether the splint prevents the limb from being disabled, with a ruptured tendon or a shattered bone
var/helps_disabled = TRUE
/// Total condition of our splint, the more we use it the more it gets looser
var/sling_condition = 5
/datum/bodypart_aid/splint/get_description()
var/desc
switch(sling_condition)
if(0 to 1.25)
desc = "barely holding"
if(1.25 to 2.75)
desc = "loose"
if(2.75 to 4)
desc = "rigid"
if(4 to INFINITY)
desc = "tight"
desc += " [name]"
return desc
/datum/bodypart_aid/splint/Destroy()
SEND_SIGNAL(bodypart, COMSIG_BODYPART_SPLINT_DESTROYED)
bodypart.current_splint = null
return ..()
/datum/bodypart_aid/splint/New(obj/item/bodypart/BP)
bodypart = BP
BP.current_splint = src
SEND_SIGNAL(BP, COMSIG_BODYPART_SPLINTED, src)
..()
/datum/bodypart_aid/splint/improvised
name = "improvised splint"
splint_factor = 0.6
helps_disabled= FALSE
stack_to_drop = /obj/item/stack/medical/gauze/improvised
overlay_prefix = "splint_improv"
/datum/bodypart_aid/gauze
name = "gauze"
stack_to_drop = /obj/item/stack/medical/gauze
overlay_prefix = "gauze"
desc_prefix = "bandaged"
/// How much more can we absorb
var/absorption_capacity = 5
/// How fast do we absorb
var/absorption_rate = 0.12
/// How much does the gauze help with keeping infections clean
var/sanitisation_factor = 0.4
/// How much sanitisation we've got after we become fairly stained and worn
var/sanitisation_factor_stained = 0.8
/// Is it blood stained? For description
var/blood_stained = FALSE
/// Is it pus stained? For description
var/pus_stained = FALSE
/datum/bodypart_aid/gauze/get_description()
var/desc
switch(absorption_capacity)
if(-INFINITY to 0)
desc = "unusable"
if(0 to 1.25)
desc = "nearly ruined"
if(1.25 to 2.75)
desc = "badly worn"
if(2.75 to 4)
desc = "slightly used"
if(4 to INFINITY)
desc = "clean"
if(blood_stained)
desc += ", bloodied"
if(pus_stained)
desc += ", pus stained"
desc += " [name]"
return desc
/datum/bodypart_aid/gauze/New(obj/item/bodypart/BP)
bodypart = BP
BP.current_gauze = src
SEND_SIGNAL(BP, COMSIG_BODYPART_GAUZED, src)
..()
/datum/bodypart_aid/gauze/Destroy()
SEND_SIGNAL(bodypart, COMSIG_BODYPART_GAUZE_DESTROYED)
bodypart.current_gauze = null
return ..()
/datum/bodypart_aid/gauze/is_pristine()
. = ..()
if(.)
return (absorption_capacity == initial(absorption_capacity))
/**
* 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 bandage won't help our wounds.
* When the bandage is left with a low amount of absorption, it'll notify user and act worse as a sanitiser for infections
* Returns TRUE if the bandage absorbed anything, FALSE if it's fully stained.
*
* 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?)
* * type - Is it blood or pus we're being stained with? GAUZE_STAIN_BLOOD, GAUZE_STAIN_PUS defines from wounds.dm
*/
/datum/bodypart_aid/gauze/proc/seep_gauze(amount, type)
if(absorption_capacity > 0)
. = TRUE
absorption_capacity -= amount
else
return FALSE
//If our remaining absorption capacity is low, make so blood and pus stains show
if(absorption_capacity < 2)
sanitisation_factor = sanitisation_factor_stained
if(type == GAUZE_STAIN_BLOOD && !blood_stained)
blood_stained = TRUE
if(bodypart.owner)
to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] [pick(list("pools", "trickles", "seeps"))] with blood."))
else if(type == GAUZE_STAIN_PUS && !pus_stained)
pus_stained = TRUE
if(bodypart.owner)
to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] [pick(list("pools", "trickles", "seeps"))] with pus."))
/datum/bodypart_aid/gauze/improvised
name = "improvised gauze"
stack_to_drop = /obj/item/stack/medical/gauze/improvised
absorption_rate = 0.09
absorption_capacity = 3
@@ -49,11 +49,7 @@
if(WOUND_SEVERITY_CRITICAL)
msg += "\t<span class='warning'><b>[t_His] [LB.name] is suffering [W.a_or_from] [W.get_topic_name(user)]!!</b></span>"
if(LB.current_gauze)
var/datum/bodypart_aid/current_gauze = LB.current_gauze
msg += "\t<span class='notice'><i>[t_His] [LB.name] is [current_gauze.desc_prefix] with <a href='?src=[REF(current_gauze)];remove=1'>[current_gauze.get_description()]</a>.</i></span>"
if(LB.current_splint)
var/datum/bodypart_aid/current_splint = LB.current_splint
msg += "\t<span class='notice'><i>[t_His] [LB.name] is [current_splint.desc_prefix] with a <a href='?src=[REF(current_splint)];remove=1'>[current_splint.get_description()]</a>.</i></span>"
msg += "\t<span class='notice'><i>[t_His] [LB.name] is [LB.current_gauze.get_gauze_usage_prefix()] with <a href='?src=[REF(LB.current_gauze)];remove=1'>[LB.current_gauze.get_gauze_description()]</a>.</i></span>"
if(!any_bodypart_damage)
msg += "\t<span class='smallnotice'><i>[t_He] [t_Has] no significantly damaged bodyparts.</i></span>"
@@ -6,15 +6,9 @@
for(var/b in bodyparts)
var/obj/item/bodypart/BP = b
if(BP.current_gauze && BP.current_gauze.overlay_prefix)
var/bp_suffix = BP.body_zone
if(BP.bodytype & BODYTYPE_DIGITIGRADE)
bp_suffix += "_digitigrade"
overlays.add_overlay("[BP.current_gauze.overlay_prefix]_[bp_suffix]")
if(BP.current_splint && BP.current_splint.overlay_prefix)
var/bp_suffix = BP.body_zone
if(BP.bodytype & BODYTYPE_DIGITIGRADE)
bp_suffix += "_digitigrade"
overlays.add_overlay("[BP.current_splint.overlay_prefix]_[bp_suffix]")
var/obj/item/stack/medical/gauze/our_gauze = BP.current_gauze
if (!our_gauze)
continue
overlays.add_overlay(our_gauze.get_overlay_prefix())
apply_overlay(BANDAGE_LAYER)
@@ -1,65 +0,0 @@
/obj/item/stack/medical/gauze
var/gauze_type = /datum/bodypart_aid/gauze
var/splint_type = /datum/bodypart_aid/splint
/obj/item/stack/medical/gauze/improvised
gauze_type = /datum/bodypart_aid/gauze/improvised
splint_type = /datum/bodypart_aid/splint/improvised
// 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)
var/treatment_delay = (user == patient ? self_delay : other_delay)
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/splintable_wound = FALSE
var/datum/wound/woundies
for(var/i in limb.wounds)
woundies = i
if(woundies.wound_flags & (ACCEPTS_GAUZE | ACCEPTS_SPLINT))
if(woundies.wound_flags & ACCEPTS_GAUZE)
gauzeable_wound = TRUE
continue
if(woundies.wound_flags & ACCEPTS_SPLINT)
splintable_wound = TRUE
continue
if(!gauzeable_wound && !splintable_wound)
patient.balloon_alert(user, "can't heal those!")
return
if(limb.current_gauze && gauzeable_wound)
gauzeable_wound = FALSE
if(limb.current_splint && splintable_wound)
splintable_wound = FALSE
if(!gauzeable_wound && !splintable_wound)
balloon_alert(user, "already bandaged!")
return
if(HAS_TRAIT(woundies, TRAIT_WOUND_SCANNED))
treatment_delay *= 0.5
if(user == patient)
user.visible_message(span_warning("[user] begins expertly [gauzeable_wound ? "wrapping the wounds on their [limb.plaintext_zone]" : "splinting their [limb.plaintext_zone]"] with [src]..."), span_notice("You keep in mind the indications from the holo-image about your injury, and expertly begin [gauzeable_wound ? "wrapping your wounds" : "splinting your [limb.plaintext_zone]"] with [src]."))
else
user.visible_message(span_warning("[user] begins expertly [gauzeable_wound ? "wrapping the wounds on [patient]'s [limb.plaintext_zone]" : "splinting [patient]'s [limb.plaintext_zone]"] with [src]..."), span_warning("You begin quickly [gauzeable_wound ? "wrapping the wounds on [patient]'s [limb.plaintext_zone]" : "splinting [patient]'s [limb.plaintext_zone]"] with [src], keeping the holo-image indications in mind..."))
else
user.visible_message(span_warning("[user] begins [gauzeable_wound ? "wrapping the wounds on [patient]'s [limb.plaintext_zone]" : "splinting [patient]'s [limb.plaintext_zone]"] with [src]..."), span_warning("You begin [gauzeable_wound ? "wrapping the wounds on" : "splinting"] [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]..."))
if(!do_after(user, treatment_delay, target = patient))
return
user.visible_message("<span class='infoplain'><span class='green'>[user] [gauzeable_wound ? "wraps the wounds on" : "splints"] [user == patient ? "[user.p_their()]" : "[patient]'s"] [limb.plaintext_zone] with [src].</span></span>", "<span class='infoplain'><span class='green'>You [gauzeable_wound ? "wrap the wounds on" : "splint"] [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone].</span></span>")
if(gauzeable_wound)
limb.apply_gauze(src)
return
if(splintable_wound)
limb.apply_splint(src)
return
@@ -0,0 +1,19 @@
/datum/wound/slash/flesh/show_wound_topic(mob/user)
return (user == victim && blood_flow)
/datum/wound/slash/flesh/Topic(href, href_list)
. = ..()
if(href_list["wound_topic"])
if(!usr == victim)
return
victim.self_grasp_bleeding_limb(limb)
/datum/wound/pierce/bleed/show_wound_topic(mob/user)
return (user == victim && blood_flow)
/datum/wound/slash/bleed/Topic(href, href_list)
. = ..()
if(href_list["wound_topic"])
if(!usr == victim)
return
victim.self_grasp_bleeding_limb(limb)
@@ -1,455 +0,0 @@
/*
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
name = "Blunt (Bone) Wound"
sound_effect = 'sound/effects/wounds/crack1.ogg'
wound_type = WOUND_BLUNT
wound_flags = (BONE_WOUND | ACCEPTS_SPLINT)
/// Have we been taped?
var/taped
/// Have we been bone gel'd?
var/gelled
/// If we did the gel + surgical tape healing method for fractures, how many ticks does it take to heal by default
var/regen_ticks_needed
/// Our current counter for gel + surgical tape regeneration
var/regen_ticks_current
/// If we suffer severe head booboos, we can get brain traumas tied to them
var/datum/brain_trauma/active_trauma
/// What brain trauma group, if any, we can draw from for head wounds
var/brain_trauma_group
/// If we deal brain traumas, when is the next one due?
var/next_trauma_cycle
/// How long do we wait +/- 20% for the next trauma?
var/trauma_cycle_cooldown
/// 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
/*
Overwriting of base procs
*/
/datum/wound/blunt/wound_injury(datum/wound/old_wound = null, attack_direction)
// 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_SPLINTED, COMSIG_BODYPART_SPLINT_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/held_item = victim.get_item_for_held_index(limb.held_index)
if(istype(held_item, /obj/item/offhand))
held_item = victim.get_inactive_held_item()
if(held_item && victim.dropItemToGround(held_item))
victim.visible_message(span_danger("[victim] drops [held_item] in shock!"), span_warning("<b>The force on your [parse_zone(limb.body_zone)] causes you to drop [held_item]!</b>"), vision_distance=COMBAT_MESSAGE_RANGE)
update_inefficiencies()
/datum/wound/blunt/remove_wound(ignore_limb, replaced)
limp_slowdown = 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()
. = ..()
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle)
if(active_trauma)
QDEL_NULL(active_trauma)
else
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)
if(!gelled || !taped)
return
regen_ticks_current++
if(victim.body_position == LYING_DOWN)
if(prob(50))
regen_ticks_current += 0.5
if(victim.IsSleeping() && prob(50))
regen_ticks_current += 0.5
if(prob(severity * 3))
victim.take_bodypart_damage(rand(1, severity * 2), wound_bonus = CANT_WOUND)
victim.adjustStaminaLoss(rand(2, severity * 2.5))
if(prob(33))
to_chat(victim, span_danger("You feel a sharp pain in your body as your bones are reforming!"))
if(regen_ticks_current > regen_ticks_needed)
if(!victim || !limb)
qdel(src)
return
to_chat(victim, span_green("Your [parse_zone(limb.body_zone)] has recovered from your fracture!"))
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)
SIGNAL_HANDLER
if(victim.get_active_hand() != limb || !victim.combat_mode || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE)
return
// With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit
if(prob((severity - 1) * 15))
// And you have a 70% or 50% chance to actually land the blow, respectively
if(prob(70 - 20 * (severity - 1)))
to_chat(victim, span_userdanger("The fracture in your [parse_zone(limb.body_zone)] shoots with pain as you strike [target]!"))
limb.receive_damage(brute=rand(1,5))
else
victim.visible_message(span_danger("[victim] weakly strikes [target] with [victim.p_their()] broken [parse_zone(limb.body_zone)], recoiling from pain!"), \
span_userdanger("You fail to strike [target] as the fracture in your [parse_zone(limb.body_zone)] lights up in unbearable pain!"), vision_distance=COMBAT_MESSAGE_RANGE)
INVOKE_ASYNC(victim, TYPE_PROC_REF(/mob, emote), "scream")
victim.Stun(0.5 SECONDS)
limb.receive_damage(brute=rand(3,7))
return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/wound/blunt/receive_damage(wounding_type, wounding_dmg, wound_bonus)
if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE)
return
if(ishuman(victim))
var/mob/living/carbon/human/human_victim = victim
if(HAS_TRAIT(human_victim, TRAIT_NOBLOOD))
return
if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg))
var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound
switch(blood_bled)
if(1 to 6)
victim.bleed(blood_bled, TRUE)
if(7 to 13)
victim.visible_message(span_smalldanger("A thin stream of blood drips from [victim]'s mouth from the blow to [victim.p_their()] chest."), span_danger("You cough up a bit of blood from the blow to your chest."), vision_distance=COMBAT_MESSAGE_RANGE)
victim.bleed(blood_bled, TRUE)
if(14 to 19)
victim.visible_message(span_smalldanger("Blood spews out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), span_danger("You spit out a string of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.bleed(blood_bled)
if(20 to INFINITY)
victim.visible_message(span_danger("Blood spurts out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), span_danger("<b>You choke up on a spray of blood from the blow to your chest!</b>"), vision_distance=COMBAT_MESSAGE_RANGE)
victim.bleed(blood_bled)
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/get_examine_description(mob/user)
if(!limb.current_splint && !gelled && !taped)
return ..()
var/list/msg = list()
if(!limb.current_splint)
msg += "[victim.p_their(TRUE)] [parse_zone(limb.body_zone)] [examine_desc]"
else
var/sling_condition = ""
// how much life we have left in these bandages
switch(limb.current_splint.sling_condition)
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(TRUE)] [parse_zone(limb.body_zone)] is [sling_condition] fastened with a [limb.current_splint.name]"
if(taped)
msg += ", <span class='notice'>and appears to be reforming itself under some surgical tape!</span>"
else if(gelled)
msg += ", <span class='notice'>with fizzing flecks of blue bone gel sparking off the bone!</span>"
else
msg += "!"
return "<B>[msg.Join()]</B>"
/*
New common procs for /datum/wound/blunt/
*/
/datum/wound/blunt/proc/update_inefficiencies()
SIGNAL_HANDLER
if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
if(limb.current_splint)
limp_slowdown = initial(limp_slowdown) * limb.current_splint.splint_factor
else
limp_slowdown = initial(limp_slowdown)
victim.apply_status_effect(/datum/status_effect/limp)
else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
if(limb.current_splint)
interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * limb.current_splint.splint_factor)
else
interaction_efficiency_penalty = interaction_efficiency_penalty
if(initial(disabling))
set_disabling(!(limb.current_splint && limb.current_splint.helps_disabled))
limb.update_wounds()
/// Joint Dislocation (Moderate Blunt)
/datum/wound/blunt/moderate
name = "Joint Dislocation"
desc = "Patient's bone 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 jammed out of place"
occur_text = "jerks 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.5
limp_slowdown = 3
threshold_minimum = 35
threshold_penalty = 15
treatable_tool = TOOL_BONESET
wound_flags = (BONE_WOUND)
status_effect_type = /datum/status_effect/wound/blunt/moderate
scar_keyword = "bluntmoderate"
/datum/wound/blunt/moderate/Destroy()
if(victim)
UnregisterSignal(victim, COMSIG_LIVING_DOORCRUSHED)
return ..()
/datum/wound/blunt/moderate/wound_injury(datum/wound/old_wound, attack_direction)
. = ..()
RegisterSignal(victim, COMSIG_LIVING_DOORCRUSHED, PROC_REF(door_crush))
/// Getting smushed in an airlock/firelock is a last-ditch attempt to try relocating your limb
/datum/wound/blunt/moderate/proc/door_crush()
SIGNAL_HANDLER
if(prob(33))
victim.visible_message(span_danger("[victim]'s dislocated [parse_zone(limb.body_zone)] pops back into place!"), span_userdanger("Your dislocated [parse_zone(limb.body_zone)] pops back into place! Ow!"))
remove_wound()
/datum/wound/blunt/moderate/try_handling(mob/living/carbon/human/user)
if(user.pulling != victim || user.zone_selected != limb.body_zone)
return FALSE
if(user.grab_state == GRAB_PASSIVE)
to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!"))
return TRUE
if(user.grab_state >= GRAB_AGGRESSIVE)
user.visible_message(span_danger("[user] begins twisting and straining [victim]'s dislocated [parse_zone(limb.body_zone)]!"), span_notice("You begin twisting and straining [victim]'s dislocated [parse_zone(limb.body_zone)]..."), ignored_mobs=victim)
to_chat(victim, span_userdanger("[user] begins twisting and straining your dislocated [parse_zone(limb.body_zone)]!"))
if(!user.combat_mode)
chiropractice(user)
else
malpractice(user)
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)
var/time = base_treat_time
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
if(prob(65))
user.visible_message(span_danger("[user] snaps [victim]'s dislocated [parse_zone(limb.body_zone)] back into place!"), span_notice("You snap [victim]'s dislocated [parse_zone(limb.body_zone)] back into place!"), ignored_mobs=victim)
to_chat(victim, span_userdanger("[user] snaps your dislocated [parse_zone(limb.body_zone)] back into place!"))
victim.emote("scream")
limb.receive_damage(brute=20, wound_bonus=CANT_WOUND)
qdel(src)
else
user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), span_danger("You wrench [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), ignored_mobs=victim)
to_chat(victim, span_userdanger("[user] wrenches your dislocated [parse_zone(limb.body_zone)] around painfully!"))
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
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)
var/time = base_treat_time
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
if(prob(65))
user.visible_message(span_danger("[user] snaps [victim]'s dislocated [parse_zone(limb.body_zone)] with a sickening crack!"), span_danger("You snap [victim]'s dislocated [parse_zone(limb.body_zone)] with a sickening crack!"), ignored_mobs=victim)
to_chat(victim, span_userdanger("[user] snaps your dislocated [parse_zone(limb.body_zone)] with a sickening crack!"))
victim.emote("scream")
limb.receive_damage(brute=25, wound_bonus=30)
else
user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), span_danger("You wrench [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), ignored_mobs=victim)
to_chat(victim, span_userdanger("[user] wrenches your dislocated [parse_zone(limb.body_zone)] around painfully!"))
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
malpractice(user)
/datum/wound/blunt/moderate/treat(obj/item/I, mob/user)
if(victim == user)
victim.visible_message(span_danger("[user] begins resetting [victim.p_their()] [parse_zone(limb.body_zone)] with [I]."), span_warning("You begin resetting your [parse_zone(limb.body_zone)] with [I]..."))
else
user.visible_message(span_danger("[user] begins resetting [victim]'s [parse_zone(limb.body_zone)] with [I]."), span_notice("You begin resetting [victim]'s [parse_zone(limb.body_zone)] with [I]..."))
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists))))
return
if(victim == user)
limb.receive_damage(brute=15, wound_bonus=CANT_WOUND)
victim.visible_message(span_danger("[user] finishes resetting [victim.p_their()] [parse_zone(limb.body_zone)]!"), span_userdanger("You reset your [parse_zone(limb.body_zone)]!"))
else
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
user.visible_message(span_danger("[user] finishes resetting [victim]'s [parse_zone(limb.body_zone)]!"), span_nicegreen("You finish resetting [victim]'s [parse_zone(limb.body_zone)]!"), victim)
to_chat(victim, span_userdanger("[user] resets your [parse_zone(limb.body_zone)]!"))
victim.emote("scream")
qdel(src)
/*
Severe (Hairline Fracture)
*/
/datum/wound/blunt/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."
examine_desc = "appears grotesquely swollen, its attachment weakened"
occur_text = "sprays chips of bone and develops a nasty looking bruise"
severity = WOUND_SEVERITY_SEVERE
interaction_efficiency_penalty = 2
limp_slowdown = 6
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
scar_keyword = "bluntsevere"
brain_trauma_group = BRAIN_TRAUMA_MILD
trauma_cycle_cooldown = 1.5 MINUTES
internal_bleeding_chance = 40
wound_flags = (BONE_WOUND | ACCEPTS_SPLINT | MANGLES_BONE)
regen_ticks_needed = 120 // ticks every 2 seconds, 240 seconds, so roughly 4 minutes default
/// Compound Fracture (Critical Blunt)
/datum/wound/blunt/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."
examine_desc = "is mangled and pulped, seemingly held together by tissue alone"
occur_text = "cracks apart, exposing broken bones to open air"
severity = WOUND_SEVERITY_CRITICAL
interaction_efficiency_penalty = 4
limp_slowdown = 9
sound_effect = 'sound/effects/wounds/crack2.ogg'
threshold_minimum = 115
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
scar_keyword = "bluntcritical"
brain_trauma_group = BRAIN_TRAUMA_SEVERE
trauma_cycle_cooldown = 2.5 MINUTES
internal_bleeding_chance = 60
wound_flags = (BONE_WOUND | ACCEPTS_SPLINT | MANGLES_BONE)
regen_ticks_needed = 240 // ticks every 2 seconds, 480 seconds, so roughly 8 minutes default
// 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")
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/gel, mob/user)
if(gelled)
to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] is already coated with bone gel!"))
return
user.visible_message(span_danger("[user] begins hastily applying [gel] to [victim]'s' [parse_zone(limb.body_zone)]..."), span_warning("You begin hastily applying [gel] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_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
gel.use(1)
victim.emote("scream")
if(user != victim)
user.visible_message(span_notice("[user] finishes applying [gel] to [victim]'s [parse_zone(limb.body_zone)], emitting a fizzing noise!"), span_notice("You finish applying [gel] to [victim]'s [parse_zone(limb.body_zone)]!"), ignored_mobs=victim)
to_chat(victim, span_userdanger("[user] finishes applying [gel] to your [parse_zone(limb.body_zone)], and you can feel the bones exploding with pain as they begin melting and reforming!"))
else
var/painkiller_bonus = 0
if(victim.get_drunk_amount() > 10)
painkiller_bonus += 10
if(victim.reagents.has_reagent(/datum/reagent/medicine/morphine))
painkiller_bonus += 20
if(victim.reagents.has_reagent(/datum/reagent/determination))
painkiller_bonus += 10
if(victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/painkiller))
painkiller_bonus += 5
if(victim.reagents.has_reagent(/datum/reagent/medicine/mine_salve))
painkiller_bonus += 20
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 [gel] to [victim.p_their()] [parse_zone(limb.body_zone)], passing out from the pain!"), span_notice("You pass out from the pain of applying [gel] to your [parse_zone(limb.body_zone)] before you can finish!"))
victim.AdjustUnconscious(5 SECONDS)
return
victim.visible_message(span_notice("[victim] finishes applying [gel] to [victim.p_their()] [parse_zone(limb.body_zone)], grimacing from the pain!"), span_notice("You finish applying [gel] to your [parse_zone(limb.body_zone)], and your bones explode in pain!"))
limb.receive_damage(25, wound_bonus=CANT_WOUND)
victim.adjustStaminaLoss(100)
if(!gelled)
gelled = TRUE
/// if someone is using surgical tape on our wound
/datum/wound/blunt/proc/tape(obj/item/stack/sticky_tape/surgical/tape, mob/user)
if(!gelled)
to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] must be coated with bone gel to perform this emergency operation!"))
return
if(taped)
to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] is already wrapped in [tape.name] and reforming!"))
return
user.visible_message(span_danger("[user] begins applying [tape] to [victim]'s' [parse_zone(limb.body_zone)]..."), span_warning("You begin applying [tape] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]..."))
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists))))
return
if(victim == user)
regen_ticks_needed *= 1.5
tape.use(1)
if(user != victim)
user.visible_message(span_notice("[user] finishes applying [tape] to [victim]'s [parse_zone(limb.body_zone)], emitting a fizzing noise!"), span_notice("You finish applying [tape] to [victim]'s [parse_zone(limb.body_zone)]!"), ignored_mobs=victim)
to_chat(victim, span_green("[user] finishes applying [tape] to your [parse_zone(limb.body_zone)], you immediately begin to feel your bones start to reform!"))
else
victim.visible_message(span_notice("[victim] finishes applying [tape] to [victim.p_their()] [parse_zone(limb.body_zone)], !"), span_green("You finish applying [tape] to your [parse_zone(limb.body_zone)], and you immediately begin to feel your bones start to reform!"))
taped = TRUE
processes = TRUE
/datum/wound/blunt/treat(obj/item/used_item, mob/user)
if(istype(used_item, /obj/item/stack/medical/bone_gel))
gel(used_item, user)
else if(istype(used_item, /obj/item/stack/sticky_tape/surgical))
tape(used_item, user)
/datum/wound/blunt/get_scanner_description(mob/user)
. = ..()
. += "<div class='ml-3'>"
if(!gelled)
. += "Alternative Treatment: Apply bone gel directly to injured limb, then apply surgical tape to begin bone regeneration. This is both excruciatingly painful and slow, and only recommended in dire circumstances.\n"
else if(!taped)
. += span_notice("Continue Alternative Treatment: Apply surgical tape directly to injured limb to begin bone regeneration. Note, this is both excruciatingly painful and slow, though sleep or laying down will speed recovery.\n")
else
. += span_notice("Note: Bone regeneration in effect. Bone is [round(regen_ticks_current*100/regen_ticks_needed)]% regenerated.\n")
if(limb.body_zone == BODY_ZONE_HEAD)
. += "Cranial Trauma Detected: Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired."
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>"
/datum/wound/blunt/get_limb_examine_description()
return span_warning("The bones in this limb appear badly cracked.")
@@ -1,311 +0,0 @@
/*
Burn wounds
*/
// TODO: well, a lot really, but specifically I want to add potential fusing of clothing/equipment on the affected area, and limb infections, though those may go in body part code
/datum/wound/burn
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)
treatable_by = list(/obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon
// Flesh damage vars
/// How much damage to our flesh we currently have. Once both this and infestation reach 0, the wound is considered healed
var/flesh_damage = 5
/// Our current counter for how much flesh regeneration we have stacked from regenerative mesh/synthflesh/whatever, decrements each tick and lowers flesh_damage
var/flesh_healing = 0
// Infestation vars (only for severe and critical)
/// How quickly infection breeds on this burn if we don't have disinfectant
var/infestation_rate = 0
/// Our current level of infection
var/infestation = 0
/// Our current level of sanitization/anti-infection, from disinfectants/alcohol/UV lights. While positive, totally pauses and slowly reverses infestation effects each tick
var/sanitization = 0
/// 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/handle_process()
. = ..()
if(strikes_to_lose_limb == 0) // we've already hit sepsis, nothing more to do
victim.adjustToxLoss(0.5)
if(prob(1))
victim.visible_message(span_danger("The infection on the remnants of [victim]'s [parse_zone(limb.body_zone)] shift and bubble nauseatingly!"), span_warning("You can feel the infection on the remnants of your [parse_zone(limb.body_zone)] coursing through your veins!"), vision_distance = COMBAT_MESSAGE_RANGE)
return
if(victim.reagents)
if(victim.reagents.has_reagent(/datum/reagent/medicine/spaceacillin))
sanitization += 0.9
if(victim.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine))
sanitization += 0.9
if(victim.reagents.has_reagent(/datum/reagent/medicine/mine_salve))
sanitization += 0.3
flesh_healing += 0.5
var/bandage_factor = 1 // good bandages multiply the length of flesh healing
if(limb.current_gauze && limb.current_gauze.seep_gauze(WOUND_BURN_SANITIZATION_RATE, GAUZE_STAIN_PUS))
bandage_factor = limb.current_gauze.sanitisation_factor
// if we have little/no infection, the limb doesn't have much burn damage, and our nutrition is good, heal some flesh
if(infestation <= WOUND_INFECTION_MODERATE && (limb.burn_dam < 5) && (victim.nutrition >= NUTRITION_LEVEL_FED))
flesh_healing += 0.2
if(flesh_healing > 0)
flesh_damage = max(0, flesh_damage - 0.5)
flesh_healing = max(0, flesh_healing - (0.5 * bandage_factor)) // good bandages multiply the length of flesh healing
// here's the check to see if we're cleared up
if((flesh_damage <= 0) && (infestation <= 1))
to_chat(victim, span_green("The burns on your [parse_zone(limb.body_zone)] have cleared up!"))
qdel(src)
return
// sanitization is checked after the clearing check but before the actual ill-effects, because we freeze the effects of infection while we have sanitization
if(sanitization > 0)
infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE)
sanitization = max(0, sanitization - (WOUND_BURN_SANITIZATION_RATE * bandage_factor))
return
infestation += infestation_rate
switch(infestation)
if(0 to WOUND_INFECTION_MODERATE)
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
if(prob(30))
victim.adjustToxLoss(0.2)
if(prob(6))
to_chat(victim, span_warning("The blisters on your [parse_zone(limb.body_zone)] ooze a strange pus..."))
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
if(!disabling && prob(2))
to_chat(victim, span_warning("<b>Your [parse_zone(limb.body_zone)] completely locks up, as you struggle for control against the infection!</b>"))
set_disabling(TRUE)
else if(disabling && prob(8))
to_chat(victim, span_notice("You regain sensation in your [parse_zone(limb.body_zone)], but it's still in terrible shape!"))
set_disabling(FALSE)
else if(prob(20))
victim.adjustToxLoss(0.5)
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
if(!disabling && prob(3))
to_chat(victim, span_warning("<b>You suddenly lose all sensation of the festering infection in your [parse_zone(limb.body_zone)]!</b>"))
set_disabling(TRUE)
else if(disabling && prob(3))
to_chat(victim, span_notice("You can barely feel your [parse_zone(limb.body_zone)] again, and you have to strain to retain motor control!"))
set_disabling(FALSE)
else if(prob(1))
to_chat(victim, span_warning("You contemplate life without your [parse_zone(limb.body_zone)]..."))
victim.adjustToxLoss(0.75)
else if(prob(4))
victim.adjustToxLoss(1)
if(WOUND_INFECTION_SEPTIC to INFINITY)
if(prob(infestation))
switch(strikes_to_lose_limb)
if(3 to INFINITY)
to_chat(victim, span_deadsay("The skin on your [parse_zone(limb.body_zone)] is literally dripping off, you feel awful!"))
if(2)
to_chat(victim, span_deadsay("<b>The infection in your [parse_zone(limb.body_zone)] is literally dripping off, you feel horrible!</b>"))
if(1)
to_chat(victim, span_deadsay("<b>Infection has just about completely claimed your [parse_zone(limb.body_zone)]!</b>"))
if(0)
to_chat(victim, span_deadsay("<b>The last of the nerve endings in your [parse_zone(limb.body_zone)] wither away, as the infection completely paralyzes your joint connector.</b>"))
threshold_penalty = 120 // piss easy to destroy
var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone)
victim.gain_trauma(sepsis)
strikes_to_lose_limb--
/datum/wound/burn/get_examine_description(mob/user)
if(strikes_to_lose_limb <= 0)
return span_deadsay("<B>[victim.p_Their()] [parse_zone(limb.body_zone)] has locked up completely and is non-functional. Amputate or augment limb immediately, or place the patient in a cryotube.</B>")
var/list/condition = list("[victim.p_Their()] [parse_zone(limb.body_zone)] [examine_desc]")
if(limb.current_gauze)
var/bandage_condition
switch(limb.current_gauze.absorption_capacity)
if(0 to 1.25)
bandage_condition = "nearly ruined"
if(1.25 to 2.75)
bandage_condition = "badly worn"
if(2.75 to 4)
bandage_condition = "slightly pus-stained"
if(4 to INFINITY)
bandage_condition = "clean"
condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]"
else
switch(infestation)
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
condition += ", <span class='deadsay'>with small spots of discoloration along the nearby veins!</span>"
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
condition += ", <span class='deadsay'>with growing clouds of infection.</span>"
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
condition += ", <span class='deadsay'>with streaks of rotten, pulsating infection!</span>"
if(WOUND_INFECTION_SEPTIC to INFINITY)
return span_deadsay("<B>[victim.p_Their()] [parse_zone(limb.body_zone)] is a mess of charred skin and infected rot!</B>")
else
condition += "!"
return "<B>[condition.Join()]</B>"
/datum/wound/burn/get_scanner_description(mob/user)
if(strikes_to_lose_limb == 0)
var/oopsie = "Type: [name]\nSeverity: [severity_text()]"
oopsie += "<div class='ml-3'>Infection Level: <span class='deadsay'>The bodypart has suffered complete sepsis and must be removed. Amputate or augment limb immediately.</span></div>"
return oopsie
. = ..()
. += "<div class='ml-3'>"
if(infestation <= sanitization && flesh_damage <= flesh_healing)
. += "No further treatment required: Burns will heal shortly."
else
switch(infestation)
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
. += "Infection Level: Moderate\n"
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
. += "Infection Level: Severe\n"
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
. += "Infection Level: <span class='deadsay'>CRITICAL</span>\n"
if(WOUND_INFECTION_SEPTIC to INFINITY)
. += "Infection Level: <span class='deadsay'>LOSS IMMINENT</span>\n"
if(infestation > sanitization)
. += "\tSurgical debridement, antibiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n"
if(flesh_damage > 0)
. += "Flesh damage detected: Application of ointment, regenerative mesh, Synthflesh, or ingestion of \"Miner's Salve\" will repair damaged flesh. Good nutrition, rest, and keeping the wound clean can also slowly repair flesh.\n"
. += "</div>"
/datum/wound/burn/get_limb_examine_description()
return span_warning("The flesh on this limb appears badly cooked.")
/*
new burn common procs
*/
/// if someone is using ointment or mesh on our burns
/datum/wound/burn/proc/ointmentmesh(obj/item/stack/medical/treatment_item, mob/user)
user.visible_message(span_notice("[user] begins applying [treatment_item] to [victim]'s [parse_zone(limb.body_zone)]..."), span_notice("You begin applying [treatment_item] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]..."))
if(!do_after(user, (user == victim ? treatment_item.self_delay : treatment_item.other_delay), extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
limb.heal_damage(treatment_item.heal_brute, treatment_item.heal_burn)
user.visible_message(span_green("[user] applies [treatment_item] to [victim]."), span_green("You apply [treatment_item] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]."))
treatment_item.use(1)
sanitization += treatment_item.sanitization
flesh_healing += treatment_item.flesh_regeneration
if((infestation <= 0 || sanitization >= infestation) && (flesh_damage <= 0 || flesh_healing > flesh_damage))
to_chat(user, span_notice("You've done all you can with [treatment_item], now you must wait for the flesh on [victim]'s [parse_zone(limb.body_zone)] to recover."))
else
try_treating(treatment_item, user)
/// Paramedic UV penlights
/datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/penlight_used, mob/user)
if(!COOLDOWN_FINISHED(penlight_used, uv_cooldown))
to_chat(user, span_notice("[penlight_used] is still recharging!"))
return
if(infestation <= 0 || infestation < sanitization)
to_chat(user, span_notice("There's no infection to treat on [victim]'s [parse_zone(limb.body_zone)]!"))
return
user.visible_message(span_notice("[user] flashes the burns on [victim]'s [limb] with [penlight_used]."), span_notice("You flash the burns on [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [penlight_used]."), vision_distance=COMBAT_MESSAGE_RANGE)
sanitization += penlight_used.uv_power
COOLDOWN_START(penlight_used, uv_cooldown, penlight_used.uv_cooldown_length)
/datum/wound/burn/treat(obj/item/treatment_item, mob/user)
if(istype(treatment_item, /obj/item/stack/medical/ointment))
ointmentmesh(treatment_item, user)
else if(istype(treatment_item, /obj/item/stack/medical/mesh))
var/obj/item/stack/medical/mesh/mesh_check = treatment_item
if(!mesh_check.is_open)
to_chat(user, span_warning("You need to open [mesh_check] first."))
return
ointmentmesh(mesh_check, user)
else if(istype(treatment_item, /obj/item/flashlight/pen/paramedic))
uv(treatment_item, 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()
. = ..()
if(flesh_healing > 0)
flesh_damage = max(0, flesh_damage - 0.2)
if((flesh_damage <= 0) && (infestation <= WOUND_INFECTION_MODERATE))
to_chat(victim, span_green("The burns on your [parse_zone(limb.body_zone)] have cleared up!"))
qdel(src)
return
if(sanitization > 0)
infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE * 0.2)
/datum/wound/burn/on_synthflesh(amount)
flesh_healing += amount * 0.5 // 20u patch will heal 10 flesh standard
// we don't even care about first degree burns, straight to second
/datum/wound/burn/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."
examine_desc = "is badly burned and breaking out in blisters"
occur_text = "breaks out with violent red burns"
severity = WOUND_SEVERITY_MODERATE
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
flesh_damage = 5
scar_keyword = "burnmoderate"
/datum/wound/burn/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."
examine_desc = "appears seriously charred, with aggressive red splotches"
occur_text = "chars rapidly, exposing ruined tissue and spreading angry red burns"
severity = WOUND_SEVERITY_SEVERE
damage_mulitplier_penalty = 1.2
threshold_minimum = 80
threshold_penalty = 40
status_effect_type = /datum/status_effect/wound/burn/severe
treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
infestation_rate = 0.05 // appx 13 minutes to reach sepsis without any treatment
flesh_damage = 12.5
scar_keyword = "burnsevere"
/datum/wound/burn/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."
examine_desc = "is a ruined mess of blanched bone, melted fat, and charred tissue"
occur_text = "vaporizes as flesh, bone, and fat melt together in a horrifying mess"
severity = WOUND_SEVERITY_CRITICAL
damage_mulitplier_penalty = 1.3
sound_effect = 'sound/effects/wounds/sizzle2.ogg'
threshold_minimum = 140
threshold_penalty = 80
status_effect_type = /datum/status_effect/wound/burn/critical
treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
infestation_rate = 0.15 // appx 4.33 minutes to reach sepsis without any treatment
flesh_damage = 20
scar_keyword = "burncritical"
///special severe wound caused by sparring interference or other god related punishments.
/datum/wound/burn/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."
/// special severe wound caused by the cursed slot machine.
/datum/wound/burn/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."
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()
return span_warning("The flesh on this limb has several ornate symbols burned into it, with pitting throughout.")
@@ -0,0 +1,147 @@
#define SELF_AID_REMOVE_DELAY 5 SECONDS
#define OTHER_AID_REMOVE_DELAY 2 SECONDS
/obj/item/stack/medical/gauze
/// The amount of direct hits our limb can take before we fall off.
var/integrity = 2
/// The bodypart we are attached to. Nullable if we aren't applied to anything.
var/obj/item/bodypart/bodypart
/// If we are splinting a limb, this is the overlay prefix we will use.
var/splint_prefix = "splint"
/// If we are bandaging a limb, this is the overlay prefix we will use.
var/gauze_prefix = "gauze"
/// If it is at all possible for us to splint a limb.
var/can_splint = TRUE
/obj/item/bodypart/apply_gauze(obj/item/stack/gauze)
RegisterSignal(src, COMSIG_BODYPART_GAUZED, PROC_REF(got_gauzed))
. = ..()
UnregisterSignal(src, COMSIG_BODYPART_GAUZED)
/// Signal handler that allows us to modularly detect if we were applied to a limb or not.
/obj/item/bodypart/proc/got_gauzed(datum/signal_source, obj/item/stack/medical/gauze/new_gauze)
SIGNAL_HANDLER
if (istype(current_gauze, /obj/item/stack/medical/gauze))
var/obj/item/stack/medical/gauze/applied_gauze = current_gauze
applied_gauze.set_limb(src) // new_gauze isnt actually the gauze that was applied weirdly
/obj/item/stack/medical/gauze/Destroy()
bodypart?.current_gauze = null
bodypart?.owner?.update_bandage_overlays()
set_limb(null)
return ..()
/**
* rip_off() called when someone rips it off
*
* It will return the bandage if it's considered pristine
*
*/
/obj/item/stack/medical/gauze/proc/rip_off()
if (is_pristine())
. = new src.type(null, 1)
bodypart?.owner?.update_bandage_overlays()
qdel(src)
/// Returns either [splint_prefix] or [gauze_prefix] depending on if we are splinting or not. Suffixes it with a digitigrade flag if applicable for the limb.
/obj/item/stack/medical/gauze/proc/get_overlay_prefix()
var/splinting = is_splinting()
var/prefix
if (splinting)
prefix = splint_prefix
else
prefix = gauze_prefix
var/suffix = bodypart.body_zone
if(bodypart.bodytype & BODYTYPE_DIGITIGRADE)
suffix += "_digitigrade"
return "[prefix]_[suffix]"
/// Returns if we can splint, and if any wound on our bodypart gives a splint overlay.
/obj/item/stack/medical/gauze/proc/is_splinting()
SHOULD_BE_PURE(TRUE)
if (!can_splint)
return FALSE
for (var/datum/wound/iterated_wound as anything in bodypart.wounds)
if (iterated_wound.wound_flags & SPLINT_OVERLAY)
return TRUE
return FALSE
/**
* is_pristine() called by rip_off()
*
* Used to determine whether the bandage can be re-used and won't qdel itself
*
*/
/obj/item/stack/medical/gauze/proc/is_pristine()
return (integrity == initial(integrity))
/**
* get_hit() called when the bandage gets damaged
*
* This proc will subtract integrity and delete the bandage with a to_chat message to whoever was bandaged
*
*/
/obj/item/stack/medical/gauze/proc/get_hit()
integrity--
if(integrity <= 0)
if(bodypart.owner)
to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] tears and falls off!"))
qdel(src)
/obj/item/stack/medical/gauze/Topic(href, href_list)
. = ..()
if(href_list["remove"])
if(!bodypart.owner)
return
if(!iscarbon(usr))
return
if(!in_range(usr, bodypart.owner))
return
var/mob/living/carbon/C = usr
var/self = (C == bodypart.owner)
C.visible_message(span_notice("[C] begins removing [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]..."), span_notice("You begin to remove [name] from [self ? "your" : "[bodypart.owner]'s"] [bodypart.name]..."))
if(!do_after(C, (self ? SELF_AID_REMOVE_DELAY : OTHER_AID_REMOVE_DELAY), target=bodypart.owner))
return
if(QDELETED(src))
return
C.visible_message(span_notice("[C] removes [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]."), span_notice("You remove [name] from [self ? "your" : "[bodypart.owner]'s" ] [bodypart.name]."))
var/obj/item/gotten = rip_off()
if(gotten && !C.put_in_hands(gotten))
gotten.forceMove(get_turf(C))
/// Sets bodypart to limb, and then updates owner's bandage overlays. Limb is nullable.
/obj/item/stack/medical/gauze/proc/set_limb(limb)
bodypart = limb
bodypart?.owner?.update_bandage_overlays()
/// Returns the name of ourself when used in a "owner is [usage_prefix] by [name]" examine_more situation/
/obj/item/stack/proc/get_gauze_description()
return "[name]"
/// Returns the usage prefix of ourself when used in a "owner is [usage_prefix] by [name]" examine_more situation/
/obj/item/stack/proc/get_gauze_usage_prefix()
return "bandaged"
/obj/item/stack/medical/gauze/get_gauze_usage_prefix()
if (is_splinting())
return "fastened"
else
return ..()
/// Returns TRUE if we can generate an overlay, false otherwise.
/obj/item/stack/medical/gauze/proc/has_overlay()
return (!isnull(gauze_prefix) && !isnull(splint_prefix))
/obj/item/stack/medical/gauze/improvised
splint_prefix = "splint_improv"
@@ -6,15 +6,58 @@
/datum/wound/muscle
name = "Muscle Wound"
sound_effect = 'sound/effects/wounds/blood1.ogg'
wound_type = WOUND_MUSCLE
wound_flags = (FLESH_WOUND | ACCEPTS_SPLINT)
viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
wound_type = WOUND_BLUNT
wound_flags = (ACCEPTS_GAUZE | SPLINT_OVERLAY)
wound_series = WOUND_SERIES_MUSCLE_DAMAGE
processes = TRUE
/// How much do we need to regen. Will regen faster if we're splinted and or laying down
var/regen_ticks_needed
/// Our current counter for healing
var/regen_ticks_current = 0
/datum/wound_pregen_data/muscle
abstract = TRUE
viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
required_limb_biostate = BIO_FLESH
/datum/wound_pregen_data/muscle/can_be_applied_to(obj/item/bodypart/limb, wound_type, datum/wound/old_wound, random_roll)
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
// THIS IS HIGHLY TEMPORARY A PROC WILL COME FROM UPSTREAM THAT SHOULD REPLACE THIS!! REPLACE IT!!!!!!!!!!!! REMOVE THE OVERRIDE 8/31/23 ~Niko
if (wound_type != (WOUND_BLUNT) && wound_type != (WOUND_SLASH) && wound_type != (WOUND_PIERCE))
return FALSE
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
/*
Overwriting of base procs
*/
@@ -51,8 +94,8 @@
if(victim.IsSleeping())
regen_ticks_current += 0.5
if(limb.current_splint)
regen_ticks_current += (1-limb.current_splint.splint_factor)
if(limb.current_gauze)
regen_ticks_current += (1-limb.current_gauze.splint_factor)
if(regen_ticks_current > regen_ticks_needed)
if(!victim || !limb)
@@ -83,26 +126,26 @@
return COMPONENT_CANCEL_ATTACK_CHAIN
/datum/wound/muscle/get_examine_description(mob/user)
if(!limb.current_splint)
if(!limb.current_gauze)
return ..()
var/list/msg = list()
if(!limb.current_splint)
if(!limb.current_gauze)
msg += "[victim.p_Their()] [parse_zone(limb.body_zone)] [examine_desc]"
else
var/sling_condition = ""
var/absorption_capacity = ""
// how much life we have left in these bandages
switch(limb.current_splint.sling_condition)
switch(limb.current_gauze.absorption_capacity)
if(0 to 1.25)
sling_condition = "just barely"
absorption_capacity = "just barely"
if(1.25 to 2.75)
sling_condition = "loosely"
absorption_capacity = "loosely"
if(2.75 to 4)
sling_condition = "mostly"
absorption_capacity = "mostly"
if(4 to INFINITY)
sling_condition = "tightly"
absorption_capacity = "tightly"
msg += "[victim.p_Their()] [parse_zone(limb.body_zone)] is [sling_condition] fastened with a [limb.current_splint.name]!"
msg += "[victim.p_Their()] [parse_zone(limb.body_zone)] is [absorption_capacity] fastened with a [limb.current_gauze.name]!"
return "<B>[msg.Join()]</B>"
@@ -113,19 +156,19 @@
/datum/wound/muscle/proc/update_inefficiencies()
SIGNAL_HANDLER
if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
if(limb.current_splint)
limp_slowdown = initial(limp_slowdown) * limb.current_splint.splint_factor
if(limb.current_gauze)
limp_slowdown = initial(limp_slowdown) * limb.current_gauze.splint_factor
else
limp_slowdown = initial(limp_slowdown)
victim.apply_status_effect(/datum/status_effect/limp)
else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
if(limb.current_splint)
interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * limb.current_splint.splint_factor)
if(limb.current_gauze)
interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * limb.current_gauze.splint_factor)
else
interaction_efficiency_penalty = interaction_efficiency_penalty
if(initial(disabling))
if(limb.current_splint && limb.current_splint.helps_disabled)
if(limb.current_gauze)
set_disabling(FALSE)
else
set_disabling(TRUE)
@@ -147,6 +190,11 @@
status_effect_type = /datum/status_effect/wound/muscle/moderate
regen_ticks_needed = 90
/datum/wound_pregen_data/muscle/tear
abstract = FALSE
wound_path_to_generate = /datum/wound/muscle/moderate
/*
Severe (Ruptured Tendon)
*/
@@ -167,6 +215,11 @@
status_effect_type = /datum/status_effect/wound/muscle/severe
regen_ticks_needed = 150
/datum/wound_pregen_data/muscle/tendon
abstract = FALSE
wound_path_to_generate = /datum/wound/muscle/severe
/datum/status_effect/wound/muscle
/datum/status_effect/wound/muscle/on_apply()
@@ -1,198 +0,0 @@
/*
Piercing wounds
*/
/datum/wound/pierce
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)
/// How much blood we start losing when this wound is first applied
var/initial_flow
/// If gauzed, what percent of the internal bleeding actually clots of the total absorption rate
var/gauzed_clot_rate
/// When hit on this bodypart, we have this chance of losing some blood + the incoming damage
var/internal_bleeding_chance
/// If we let off blood when hit, the max blood lost is this * the incoming damage
var/internal_bleeding_coefficient
/datum/wound/slash/show_wound_topic(mob/user)
return (user == victim && blood_flow)
/datum/wound/slash/Topic(href, href_list)
. = ..()
if(href_list["wound_topic"])
if(!usr == victim)
return
victim.self_grasp_bleeding_limb(limb)
/datum/wound/pierce/wound_injury(datum/wound/old_wound, attack_direction)
set_blood_flow(initial_flow)
/datum/wound/pierce/receive_damage(wounding_type, wounding_dmg, wound_bonus)
if(victim.stat == DEAD || wounding_dmg < 5)
return
if(victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg))
if(limb.current_splint && limb.current_splint.splint_factor)
wounding_dmg *= (1 - limb.current_splint.splint_factor)
var/blood_bled = rand(1, wounding_dmg * internal_bleeding_coefficient) // 12 brute toolbox can cause up to 15/18/21 bloodloss on mod/sev/crit
switch(blood_bled)
if(1 to 6)
victim.bleed(blood_bled, TRUE)
if(7 to 13)
victim.visible_message(span_smalldanger("Blood droplets fly from the hole in [victim]'s [parse_zone(limb.body_zone)]."), span_danger("You cough up a bit of blood from the blow to your [parse_zone(limb.body_zone)]."), vision_distance=COMBAT_MESSAGE_RANGE)
victim.bleed(blood_bled, TRUE)
if(14 to 19)
victim.visible_message(span_smalldanger("A small stream of blood spurts from the hole in [victim]'s [parse_zone(limb.body_zone)]!"), span_danger("You spit out a string of blood from the blow to your [parse_zone(limb.body_zone)]!"), vision_distance=COMBAT_MESSAGE_RANGE)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.bleed(blood_bled)
if(20 to INFINITY)
victim.visible_message(span_danger("A spray of blood streams from the gash in [victim]'s [parse_zone(limb.body_zone)]!"), span_danger("<b>You choke up on a spray of blood from the blow to your [parse_zone(limb.body_zone)]!</b>"), vision_distance=COMBAT_MESSAGE_RANGE)
victim.bleed(blood_bled)
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()
if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS))
return BLOOD_FLOW_INCREASING
if(limb.current_gauze)
return BLOOD_FLOW_DECREASING
return BLOOD_FLOW_STEADY
/datum/wound/pierce/handle_process()
set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW))
if(victim.bodytemperature < (BODYTEMP_NORMAL - 10))
adjust_blood_flow(-0.2)
if(prob(5))
to_chat(victim, span_notice("You feel the [lowertext(name)] in your [parse_zone(limb.body_zone)] firming up from the cold!"))
if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS))
adjust_blood_flow(0.5) // 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 && limb.current_gauze.seep_gauze(limb.current_gauze.absorption_rate, GAUZE_STAIN_BLOOD))
adjust_blood_flow(-(limb.current_gauze.absorption_rate * gauzed_clot_rate))
if(blood_flow <= 0)
qdel(src)
/datum/wound/pierce/on_stasis()
. = ..()
if(blood_flow <= 0)
qdel(src)
/datum/wound/pierce/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/treatment_item, mob/user)
if(istype(treatment_item, /obj/item/stack/medical/suture))
suture(treatment_item, user)
else if(treatment_item.tool_behaviour == TOOL_CAUTERY || treatment_item.get_temperature())
tool_cauterize(treatment_item, user)
/datum/wound/pierce/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)
. = ..()
adjust_blood_flow(-(0.05 * 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/used_suture, mob/user)
var/self_penalty_mult = (user == victim ? 1.4 : 1)
user.visible_message(span_notice("[user] begins stitching [victim]'s [parse_zone(limb.body_zone)] with [used_suture]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [used_suture]..."))
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
user.visible_message(span_green("[user] stitches up some of the bleeding on [victim]."), span_green("You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"]."))
var/blood_sutured = used_suture.stop_bleeding / self_penalty_mult
adjust_blood_flow(-blood_sutured)
limb.heal_damage(used_suture.heal_brute, used_suture.heal_burn)
used_suture.use(1)
if(blood_flow > 0)
try_treating(used_suture, user)
else
to_chat(user, span_green("You successfully close the hole in [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]."))
/// If someone is using either a cautery tool or something with heat to cauterize this pierce
/datum/wound/pierce/proc/tool_cauterize(obj/item/used_cautery, mob/user)
var/improv_penalty_mult = (used_cautery.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
user.visible_message(span_danger("[user] begins cauterizing [victim]'s [parse_zone(limb.body_zone)] with [used_cautery]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [used_cautery]..."))
if(!do_after(user, base_treat_time * self_penalty_mult * improv_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
user.visible_message(span_green("[user] cauterizes some of the bleeding on [victim]."), span_green("You cauterize some of the bleeding on [victim]."))
limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND)
if(prob(30))
victim.emote("scream")
var/blood_cauterized = (0.6 / (self_penalty_mult * improv_penalty_mult))
adjust_blood_flow(-blood_cauterized)
if(blood_flow > 0)
try_treating(used_cautery, user)
/datum/wound/pierce/moderate
name = "Minor 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"
occur_text = "spurts out a thin stream of blood"
sound_effect = 'sound/effects/wounds/pierce1.ogg'
severity = WOUND_SEVERITY_MODERATE
initial_flow = 1.5
gauzed_clot_rate = 0.8
internal_bleeding_chance = 30
internal_bleeding_coefficient = 1.25
threshold_minimum = 30
threshold_penalty = 20
status_effect_type = /datum/status_effect/wound/pierce/moderate
scar_keyword = "piercemoderate"
/datum/wound/pierce/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."
examine_desc = "is pierced clear through, with bits of tissue obscuring the open hole"
occur_text = "looses a violent spray of blood, revealing a pierced wound"
sound_effect = 'sound/effects/wounds/pierce2.ogg'
severity = WOUND_SEVERITY_SEVERE
initial_flow = 2.25
gauzed_clot_rate = 0.6
internal_bleeding_chance = 60
internal_bleeding_coefficient = 1.5
threshold_minimum = 50
threshold_penalty = 35
status_effect_type = /datum/status_effect/wound/pierce/severe
scar_keyword = "piercesevere"
/datum/wound/pierce/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."
examine_desc = "is ripped clear through, barely held together by exposed bone"
occur_text = "blasts apart, sending chunks of viscera flying in all directions"
sound_effect = 'sound/effects/wounds/pierce3.ogg'
severity = WOUND_SEVERITY_CRITICAL
initial_flow = 3
gauzed_clot_rate = 0.4
internal_bleeding_chance = 80
internal_bleeding_coefficient = 1.75
threshold_minimum = 100
threshold_penalty = 50
status_effect_type = /datum/status_effect/wound/pierce/critical
scar_keyword = "piercecritical"
wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH)
/datum/wound/pierce/get_limb_examine_description()
return span_warning("The flesh on this limb appears badly perforated.")
@@ -1,324 +0,0 @@
/*
Slashing wounds
*/
/datum/wound/slash
name = "Slashing (Cut) Wound"
sound_effect = 'sound/weapons/slice.ogg'
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)
/// How much blood we start losing when this wound is first applied
var/initial_flow
/// When we have less than this amount of flow, either from treatment or clotting, we demote to a lower cut or are healed of the wound
var/minimum_flow
/// How much our blood_flow will naturally decrease per second, not only do larger cuts bleed more blood faster, they clot slower (higher number = clot quicker, negative = opening up)
var/clot_rate
/// Once the blood flow drops below minimum_flow, we demote it to this type of wound. If there's none, we're all better
var/demotes_to
/// The maximum flow we've had so far
var/highest_flow
/// 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/show_wound_topic(mob/user)
return (user == victim && blood_flow)
/datum/wound/slash/Topic(href, href_list)
. = ..()
if(href_list["wound_topic"])
if(!usr == victim)
return
victim.self_grasp_bleeding_limb(limb)
/datum/wound/slash/wound_injury(datum/wound/slash/old_wound = null, attack_direction)
if(old_wound)
set_blood_flow(max(old_wound.blood_flow, initial_flow))
if(old_wound.severity > severity && old_wound.highest_scar)
highest_scar = old_wound.highest_scar
old_wound.highest_scar = null
else
set_blood_flow(initial_flow)
if(attack_direction && victim.blood_volume > BLOOD_VOLUME_OKAY)
victim.spray_blood(attack_direction, severity)
if(!highest_scar)
highest_scar = new
highest_scar.generate(limb, src, add_to_scars=FALSE)
/datum/wound/slash/remove_wound(ignore_limb, replaced)
if(!replaced && highest_scar)
already_scarred = TRUE
highest_scar.lazy_attach(limb)
return ..()
/datum/wound/slash/get_examine_description(mob/user)
if(!limb.current_gauze)
return ..()
var/list/msg = list("The cuts on [victim.p_their()] [parse_zone(limb.body_zone)] are wrapped with ")
// how much life we have left in these bandages
switch(limb.current_gauze.absorption_capacity)
if(0 to 1.25)
msg += "nearly ruined"
if(1.25 to 2.75)
msg += "badly worn"
if(2.75 to 4)
msg += "slightly bloodied"
if(4 to INFINITY)
msg += "clean"
msg += " [limb.current_gauze.name]!"
return "<B>[msg.Join()]</B>"
/datum/wound/slash/receive_damage(wounding_type, wounding_dmg, wound_bonus)
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()
// 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.
if(limb.current_gauze && limb.current_gauze.seep_gauze(bleed_amt * 0.33, GAUZE_STAIN_BLOOD)) // gauze stops all bleeding from dragging on this limb, but wears the gauze out quicker
return 0
return bleed_amt
/datum/wound/slash/get_bleed_rate_of_change()
if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS))
return BLOOD_FLOW_INCREASING
if(limb.current_gauze || clot_rate > 0)
return BLOOD_FLOW_DECREASING
if(clot_rate < 0)
return BLOOD_FLOW_INCREASING
/datum/wound/slash/handle_process()
set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW))
if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS))
adjust_blood_flow(0.5) // 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)
if(clot_rate > 0)
adjust_blood_flow(-clot_rate)
if(limb.current_gauze && limb.current_gauze.seep_gauze(limb.current_gauze.absorption_rate, GAUZE_STAIN_BLOOD))
adjust_blood_flow(-limb.current_gauze.absorption_rate)
else
adjust_blood_flow(-clot_rate)
if(blood_flow > highest_flow)
highest_flow = blood_flow
if(blood_flow < minimum_flow)
if(demotes_to)
replace_wound(demotes_to)
else
to_chat(victim, span_green("The cut on your [parse_zone(limb.body_zone)] has stopped bleeding!"))
qdel(src)
/datum/wound/slash/on_stasis()
if(blood_flow >= minimum_flow)
return
if(demotes_to)
replace_wound(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/treatment_item, mob/user)
if(istype(treatment_item, /obj/item/gun/energy/laser))
return TRUE
if(treatment_item.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/treatment_item, mob/user)
if(istype(treatment_item, /obj/item/gun/energy/laser))
las_cauterize(treatment_item, user)
else if(treatment_item.tool_behaviour == TOOL_CAUTERY || treatment_item.get_temperature())
tool_cauterize(treatment_item, user)
else if(istype(treatment_item, /obj/item/stack/medical/suture))
suture(treatment_item, user)
/datum/wound/slash/try_handling(mob/living/carbon/human/user)
if(user.pulling != victim || user.zone_selected != limb.body_zone || !user.combat_mode || !isfelinid(user) || !victim.can_inject(user, TRUE))
return FALSE
if(DOING_INTERACTION_WITH_TARGET(user, victim))
to_chat(user, span_warning("You're already interacting with [victim]!"))
return
if(user.is_mouth_covered())
to_chat(user, span_warning("Your mouth is covered, you can't lick [victim]'s wounds!"))
return
if(!user.get_organ_slot(ORGAN_SLOT_TONGUE))
to_chat(user, span_warning("You can't lick wounds without a tongue!")) // f in chat
return
lick_wounds(user)
return TRUE
/// if a felinid is licking this cut to reduce bleeding
/datum/wound/slash/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
if(iter_disease.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS))
continue
user.ForceContractDisease(iter_disease)
user.visible_message(span_notice("[user] begins licking the wounds on [victim]'s [parse_zone(limb.body_zone)]."), span_notice("You begin licking the wounds on [victim]'s [parse_zone(limb.body_zone)]..."), ignored_mobs=victim)
to_chat(victim, span_notice("[user] begins to lick the wounds on your [parse_zone(limb.body_zone)]."))
if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
user.visible_message(span_notice("[user] licks the wounds on [victim]'s [parse_zone(limb.body_zone)]."), span_notice("You lick some of the wounds on [victim]'s [parse_zone(limb.body_zone)]"), ignored_mobs=victim)
to_chat(victim, span_green("[user] licks the wounds on your [parse_zone(limb.body_zone)]!"))
adjust_blood_flow(-0.5)
if(blood_flow > minimum_flow)
try_handling(user)
else if(demotes_to)
to_chat(user, span_green("You successfully lower the severity of [victim]'s cuts."))
/datum/wound/slash/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)
. = ..()
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)
var/self_penalty_mult = (user == victim ? 1.25 : 1)
user.visible_message(span_warning("[user] begins aiming [lasgun] directly at [victim]'s [parse_zone(limb.body_zone)]..."), span_userdanger("You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]..."))
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
var/damage = lasgun.chambered.loaded_projectile.damage
lasgun.chambered.loaded_projectile.wound_bonus -= 30
lasgun.chambered.loaded_projectile.damage *= self_penalty_mult
if(!lasgun.process_fire(victim, victim, TRUE, null, limb.body_zone))
return
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 [parse_zone(limb.body_zone)] scar over!"))
/// If someone is using either a cautery tool or something with heat to cauterize this cut
/datum/wound/slash/proc/tool_cauterize(obj/item/used_cautery, mob/user)
var/improv_penalty_mult = (used_cautery.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
user.visible_message(span_danger("[user] begins cauterizing [victim]'s [parse_zone(limb.body_zone)] with [used_cautery]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [used_cautery]..."))
if(!do_after(user, base_treat_time * self_penalty_mult * improv_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
user.visible_message(span_green("[user] cauterizes some of the bleeding on [victim]."), span_green("You cauterize some of the bleeding on [victim]."))
limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND)
if(prob(30))
victim.emote("scream")
var/blood_cauterized = (0.6 / (self_penalty_mult * improv_penalty_mult))
adjust_blood_flow(-blood_cauterized)
if(blood_flow > minimum_flow)
try_treating(used_cautery, user)
else if(demotes_to)
to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts."))
/// If someone is using a suture to close this cut
/datum/wound/slash/proc/suture(obj/item/stack/medical/suture/used_suture, mob/user)
var/self_penalty_mult = (user == victim ? 1.4 : 1)
user.visible_message(span_notice("[user] begins stitching [victim]'s [parse_zone(limb.body_zone)] with [used_suture]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [used_suture]..."))
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists))))
return
user.visible_message(span_green("[user] stitches up some of the bleeding on [victim]."), span_green("You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"]."))
var/blood_sutured = used_suture.stop_bleeding / self_penalty_mult
adjust_blood_flow(-blood_sutured)
limb.heal_damage(used_suture.heal_brute, used_suture.heal_burn)
used_suture.use(1)
if(blood_flow > minimum_flow)
try_treating(used_suture, user)
else if(demotes_to)
to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts."))
/datum/wound/slash/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."
examine_desc = "has an open cut"
occur_text = "is cut open, slowly leaking blood"
sound_effect = 'sound/effects/wounds/blood1.ogg'
severity = WOUND_SEVERITY_MODERATE
initial_flow = 2
minimum_flow = 0.5
clot_rate = 0.05
threshold_minimum = 20
threshold_penalty = 10
status_effect_type = /datum/status_effect/wound/slash/moderate
scar_keyword = "slashmoderate"
/datum/wound/slash/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."
examine_desc = "has a severe cut"
occur_text = "is ripped open, veins spurting blood"
sound_effect = 'sound/effects/wounds/blood2.ogg'
severity = WOUND_SEVERITY_SEVERE
initial_flow = 3.25
minimum_flow = 2.75
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
scar_keyword = "slashsevere"
/datum/wound/slash/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"
occur_text = "is torn open, spraying blood wildly"
sound_effect = 'sound/effects/wounds/blood3.ogg'
severity = WOUND_SEVERITY_CRITICAL
initial_flow = 4
minimum_flow = 3.85
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
scar_keyword = "slashcritical"
wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH)
/datum/wound/slash/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."
// Subtype for cleave (heretic spell)
/datum/wound/slash/critical/cleave
name = "Burning Avulsion"
examine_desc = "is ruptured, spraying blood wildly"
clot_rate = 0.01
/datum/wound/slash/critical/cleave/update_descriptions()
if(no_bleeding)
occur_text = "is ruptured"
/datum/wound/slash/get_limb_examine_description()
return span_warning("The flesh on this limb appears badly lacerated.")
@@ -100,7 +100,7 @@
if(SPT_PROB(10, seconds_per_tick))
var/obj/item/bodypart/wound_area = host.get_bodypart(BODY_ZONE_CHEST)
if(wound_area)
var/datum/wound/slash/moderate/rotting_wound = new
var/datum/wound/slash/flesh/moderate/rotting_wound = new
rotting_wound.apply_wound(wound_area)
host.emote(pick(list("cough", "sneeze", "scream")))
if(timer_id)
@@ -91,4 +91,3 @@
/obj/item/autosurgeon/bodypart/r_arm_robotic/Initialize(mapload)
. = ..()
storedbodypart.icon = 'modular_skyrat/master_files/icons/mob/augmentation/hi2ipc.dmi'
storedbodypart.organic_render = FALSE
-1
View File
@@ -88,7 +88,6 @@ https://freesound.org/people/squareal/sounds/237375/
ding_short.ogg is from Natty23 (CC 4)
https://freesound.org/people/Natty23/sounds/411747/
jingle.ogg is from Zapsplat (https://www.zapsplat.com/license-type/standard-license/)
https://www.zapsplat.com/sound-effect-category/sleigh-bells/
+7 -8
View File
@@ -432,6 +432,7 @@
#include "code\__DEFINES\~skyrat_defines\turfs.dm"
#include "code\__DEFINES\~skyrat_defines\vox_defines.dm"
#include "code\__DEFINES\~skyrat_defines\vv.dm"
#include "code\__DEFINES\~skyrat_defines\wounds.dm"
#include "code\__DEFINES\~skyrat_defines\_globalvars\bitfields.dm"
#include "code\__DEFINES\~skyrat_defines\_globalvars\logging.dm"
#include "code\__DEFINES\~skyrat_defines\_globalvars\lists\mapping.dm"
@@ -1701,13 +1702,16 @@
#include "code\datums\wires\syndicatebomb.dm"
#include "code\datums\wires\tesla_coil.dm"
#include "code\datums\wires\vending.dm"
#include "code\datums\wounds\_wound_static_data.dm"
#include "code\datums\wounds\_wounds.dm"
#include "code\datums\wounds\blunt.dm"
#include "code\datums\wounds\bones.dm"
#include "code\datums\wounds\burns.dm"
#include "code\datums\wounds\loss.dm"
#include "code\datums\wounds\pierce.dm"
#include "code\datums\wounds\slash.dm"
#include "code\datums\wounds\scars\_scars.dm"
#include "code\datums\wounds\scars\_static_scar_data.dm"
#include "code\game\alternate_appearance.dm"
#include "code\game\atom_defense.dm"
#include "code\game\atoms.dm"
@@ -6885,19 +6889,14 @@
#include "modular_skyrat\modules\marines\code\modsuit_modules.dm"
#include "modular_skyrat\modules\marines\code\smartgun.dm"
#include "modular_skyrat\modules\medical\code\anesthetic_machine.dm"
#include "modular_skyrat\modules\medical\code\bodypart.dm"
#include "modular_skyrat\modules\medical\code\bodypart_aid.dm"
#include "modular_skyrat\modules\medical\code\carbon_defense.dm"
#include "modular_skyrat\modules\medical\code\carbon_examine.dm"
#include "modular_skyrat\modules\medical\code\carbon_update_icons.dm"
#include "modular_skyrat\modules\medical\code\medical_stacks.dm"
#include "modular_skyrat\modules\medical\code\grasp.dm"
#include "modular_skyrat\modules\medical\code\smartdarts.dm"
#include "modular_skyrat\modules\medical\code\wounds\_wounds.dm"
#include "modular_skyrat\modules\medical\code\wounds\bones.dm"
#include "modular_skyrat\modules\medical\code\wounds\burns.dm"
#include "modular_skyrat\modules\medical\code\wounds\bleed.dm"
#include "modular_skyrat\modules\medical\code\wounds\medical.dm"
#include "modular_skyrat\modules\medical\code\wounds\muscle.dm"
#include "modular_skyrat\modules\medical\code\wounds\pierce.dm"
#include "modular_skyrat\modules\medical\code\wounds\slash.dm"
#include "modular_skyrat\modules\medical_designs\medical_designs.dm"
#include "modular_skyrat\modules\medievalcrate_skyrat\code\vintageitems.dm"
#include "modular_skyrat\modules\mentor\code\_globalvars.dm"
File diff suppressed because it is too large Load Diff