mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-15 10:04:30 +01:00
[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:
@@ -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)
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/datum/wound/blunt
|
||||
name = "Blunt Wound"
|
||||
sound_effect = 'sound/effects/wounds/crack1.ogg'
|
||||
wound_type = WOUND_BLUNT
|
||||
+112
-87
@@ -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
@@ -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
@@ -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 ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user