diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index 6610e463163..85ede44936d 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -126,8 +126,13 @@
#define AGENDER 16
/// Do not draw eyes or eyeless overlay
#define NOEYESPRITES 17
-/// If this species can be scarred (fleshy)
-#define CAN_SCAR 18
+
+/// Used for determining which wounds are applicable to this species.
+/// if we have flesh (can suffer slash/piercing/burn wounds, requires they don't have NOBLOOD)
+#define HAS_FLESH 18
+/// if we have bones (can suffer bone wounds)
+#define HAS_BONE 19
+
//organ slots
#define ORGAN_SLOT_BRAIN "brain"
@@ -166,6 +171,7 @@
#define CHROMOSOME_NONE 1
#define CHROMOSOME_USED 2
+//used for mob's genetic gender (mainly just for pronouns, members of sexed species with plural gender refer to their body_type for the actual sprites, which is not genetic)
#define G_MALE 1
#define G_FEMALE 2
#define G_PLURAL 3
diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index a0e8a1f9420..cd8b8bff570 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -100,6 +100,7 @@
#define ADMIN_PUNISHMENT_NUGGET "Nugget"
#define ADMIN_PUNISHMENT_CRACK ":B:oneless"
#define ADMIN_PUNISHMENT_BLEED ":B:loodless"
+#define ADMIN_PUNISHMENT_PERFORATE ":B:erforate"
#define ADMIN_PUNISHMENT_SCARIFY "Scarify"
#define ADMIN_PUNISHMENT_SHOES "Knot Shoes"
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 8965715cbb7..db9007686da 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -189,9 +189,9 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
#define REFLECT_FAKEPROJECTILE (1<<1)
//Object/Item sharpness
-#define IS_BLUNT 0
-#define IS_SHARP 1
-#define IS_SHARP_ACCURATE 2
+#define SHARP_NONE 0
+#define SHARP_EDGED 1
+#define SHARP_POINTY 2
//His Grace.
#define HIS_GRACE_SATIATED 0 //He hungers not. If bloodthirst is set to this, His Grace is asleep.
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 14f13439d00..11b2655f2df 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -556,7 +556,7 @@
// /obj/projectile signals (sent to the firer)
-///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
+///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb)
#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit"
///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit"
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 7deeda4c140..76c120a3373 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -180,14 +180,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define iscash(A) (istype(A, /obj/item/coin) || istype(A, /obj/item/stack/spacecash) || istype(A, /obj/item/holochip))
-GLOBAL_LIST_INIT(pointed_types, typecacheof(list(
- /obj/item/pen,
- /obj/item/screwdriver,
- /obj/item/reagent_containers/syringe,
- /obj/item/kitchen/fork)))
-
-#define is_pointed(W) (is_type_in_typecache(W, GLOB.pointed_types))
-
#define isbodypart(A) (istype(A, /obj/item/bodypart))
#define isprojectile(A) (istype(A, /obj/projectile))
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 3ac969e4cd4..c0049150a49 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -411,6 +411,9 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE)))
#define LOCATIONS_FILE "locations.json"
#define WANTED_FILE "wanted_message.json"
#define VISTA_FILE "steve.json"
+#define FLESH_SCAR_FILE "wounds/flesh_scar_desc.json"
+#define BONE_SCAR_FILE "wounds/bone_scar_desc.json"
+#define SCAR_LOC_FILE "wounds/scar_loc.json"
//Fullscreen overlay resolution in tiles.
#define FULLSCREEN_OVERLAY_RESOLUTION_X 15
diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm
index b993429961d..5618439ae8b 100644
--- a/code/__DEFINES/wounds.dm
+++ b/code/__DEFINES/wounds.dm
@@ -1,43 +1,120 @@
+
#define WOUND_DAMAGE_EXPONENT 1.4
+/// an attack must do this much damage after armor in order to roll for being a wound (incremental pressure damage need not apply)
+#define WOUND_MINIMUM_DAMAGE 5
+/// an attack must do this much damage after armor in order to be eliigible to dismember a suitably mushed bodypart
+#define DISMEMBER_MINIMUM_DAMAGE 10
+/// any damage dealt over this is ignored for damage rolls unless the target has the frail quirk (35^1.4=145)
+#define WOUND_MAX_CONSIDERED_DAMAGE 35
+
+
#define WOUND_SEVERITY_TRIVIAL 0 // for jokey/meme wounds like stubbed toe, no standard messages/sounds or second winds
#define WOUND_SEVERITY_MODERATE 1
#define WOUND_SEVERITY_SEVERE 2
#define WOUND_SEVERITY_CRITICAL 3
#define WOUND_SEVERITY_LOSS 4 // theoretical total limb loss, like dismemberment for cuts
-#define WOUND_BRUTE 0
-#define WOUND_SHARP 1
-#define WOUND_BURN 2
+/// any brute weapon/attack that doesn't have sharpness. rolls for blunt bone wounds
+#define WOUND_BLUNT 1
+/// any brute weapon/attack with sharpness = SHARP_EDGED. rolls for slash wounds
+#define WOUND_SLASH 2
+/// any brute weapon/attack with sharpness = SHARP_POINTY. rolls for piercing wounds
+#define WOUND_PIERCE 3
+/// any concentrated burn attack (lasers really). rolls for burning wounds
+#define WOUND_BURN 4
// How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind()]
#define WOUND_DETERMINATION_MODERATE 1
#define WOUND_DETERMINATION_SEVERE 2.5
#define WOUND_DETERMINATION_CRITICAL 5
+#define WOUND_DETERMINATION_LOSS 7.5
+/// the max amount of determination you can have
#define WOUND_DETERMINATION_MAX 10
-// set wound_bonus on an item or attack to this to disable checking wounding for the attack
+/// set wound_bonus on an item or attack to this to disable checking wounding for the attack
#define CANT_WOUND -100
// list in order of highest severity to lowest
-#define WOUND_LIST_BONE list(/datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/moderate)
-#define WOUND_LIST_CUT list(/datum/wound/brute/cut/loss, /datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate)
-#define WOUND_LIST_BURN list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate)
+GLOBAL_LIST_INIT(global_wound_types, list(WOUND_BLUNT = list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate),
+ WOUND_SLASH = list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate),
+ WOUND_PIERCE = list(/datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate),
+ WOUND_BURN = list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate)
+ ))
+
+GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate,
+ /datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate,
+ /datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate,
+ /datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate))
// Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse
-#define WOUND_INFECTION_MODERATE 4 // below this has no ill effects from infection
-#define WOUND_INFECTION_SEVERE 8 // then below here, you ooze some pus and suffer minor tox damage, but nothing serious
-#define WOUND_INFECTION_CRITICAL 12 // then below here, your limb occasionally locks up from damage and infection and briefly becomes disabled. Things are getting really bad
-#define WOUND_INFECTION_SEPTIC 20 // below here, your skin is almost entirely falling off and your limb locks up more frequently. You are within a stone's throw of septic paralysis and losing the limb
+/// below this has no ill effects from infection
+#define WOUND_INFECTION_MODERATE 4
+/// then below here, you ooze some pus and suffer minor tox damage, but nothing serious
+#define WOUND_INFECTION_SEVERE 8
+/// then below here, your limb occasionally locks up from damage and infection and briefly becomes disabled. Things are getting really bad
+#define WOUND_INFECTION_CRITICAL 12
+/// below here, your skin is almost entirely falling off and your limb locks up more frequently. You are within a stone's throw of septic paralysis and losing the limb
+#define WOUND_INFECTION_SEPTIC 20
// above WOUND_INFECTION_SEPTIC, your limb is completely putrid and you start rolling to lose the entire limb by way of paralyzation. After 3 failed rolls (~4-5% each probably), the limb is paralyzed
-#define WOUND_BURN_SANITIZATION_RATE 0.15 // how quickly sanitization removes infestation and decays per tick
-#define WOUND_CUT_MAX_BLOODFLOW 8 // how much blood you can lose per tick per cut max. 8 is a LOT of blood for one cut so don't worry about hitting it easily
-#define WOUND_BONE_HEAD_TIME_VARIANCE 20 // if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100)
+
+/// how quickly sanitization removes infestation and decays per tick
+#define WOUND_BURN_SANITIZATION_RATE 0.15
+/// how much blood you can lose per tick per slash max. 8 is a LOT of blood for one cut so don't worry about hitting it easily
+#define WOUND_SLASH_MAX_BLOODFLOW 8
+/// dead people don't bleed, but they can clot! this is the minimum amount of clotting per tick on dead people, so even critical cuts will slowly clot in dead people
+#define WOUND_SLASH_DEAD_CLOT_MIN 0.05
+/// if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100)
+#define WOUND_BONE_HEAD_TIME_VARIANCE 20
// The following are for persistent scar save formats
-#define SCAR_SAVE_ZONE 1 // The body_zone we're applying to on granting
-#define SCAR_SAVE_DESC 2 // The description we're loading
-#define SCAR_SAVE_PRECISE_LOCATION 3 // The precise location we're loading
-#define SCAR_SAVE_SEVERITY 4 // The severity the scar had
+/// The version number of the scar we're saving
+#define SCAR_SAVE_VERS 1
+/// The body_zone we're applying to on granting
+#define SCAR_SAVE_ZONE 2
+/// The description we're loading
+#define SCAR_SAVE_DESC 3
+/// The precise location we're loading
+#define SCAR_SAVE_PRECISE_LOCATION 4
+/// The severity the scar had
+#define SCAR_SAVE_SEVERITY 5
+///how many fields there are above (NOT INCLUDING THIS OBVIOUSLY)
+#define SCAR_SAVE_LENGTH 5
+
+// increment this number when you update the persistent scarring format in a way that invalidates previous saved scars (new fields, reordering, etc)
+/// saved scars with a version lower than this will be discarded
+#define SCAR_CURRENT_VERSION 1
+
+
+// With the wounds pt. 2 update, general dismemberment now requires 2 things for a limb to be dismemberable (bone only creatures just need the second):
+// 1. Skin is mangled: A critical slash or pierce wound on that limb
+// 2. Bone is mangled: At least a severe bone wound on that limb
+// see [/obj/item/bodypart/proc/get_mangled_state] for more information
+#define BODYPART_MANGLED_NONE 0
+#define BODYPART_MANGLED_BONE 1
+#define BODYPART_MANGLED_FLESH 2
+#define BODYPART_MANGLED_BOTH 3
+
+// What kind of biology we have, and what wounds we can suffer, mostly relies on the HAS_FLESH and HAS_BONE species traits on human species
+/// golems and androids, cannot suffer any wounds
+#define BIO_INORGANIC 0
+/// skeletons and plasmemes, can only suffer bone wounds, only needs mangled bone to be able to dismember
+#define BIO_JUST_BONE 1
+/// nothing right now, maybe slimepeople in the future, can only suffer slashing, piercing, and burn wounds
+#define BIO_JUST_FLESH 2
+/// standard humanoids, can suffer all wounds, needs mangled bone and flesh to dismember
+#define BIO_FLESH_BONE 3
+
+/// If this wound requires having the HAS_FLESH flag for humanoids
+#define FLESH_WOUND (1<<0)
+/// If this wound requires having the HAS_BONE flag for humanaoids
+#define BONE_WOUND (1<<1)
+/// If having this wound counts as mangled flesh for dismemberment
+#define MANGLES_FLESH (1<<2)
+/// If having this wound counts as mangled bone for dismemberment
+#define MANGLES_BONE (1<<3)
+/// If this wound marks the limb as being allowed to have gauze applied
+#define ACCEPTS_GAUZE (1<<4)
+
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index e02fd415b0d..64851ffbd7a 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -171,9 +171,9 @@
else
return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
-/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
+/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, obj/item/bodypart/hit_bodypart)
var/message_verb = "attacked"
- if(I.attack_verb && I.attack_verb.len)
+ if(length(I.attack_verb))
message_verb = "[pick(I.attack_verb)]"
else if(!I.force)
return
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index 2e2ba59e9c5..c464d45a6ce 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -402,8 +402,8 @@ SUBSYSTEM_DEF(persistence)
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ""
else
for(var/k in ending_human.all_wounds)
- var/datum/wound/W = k
- W.remove_wound() // so we can get the scars for open wounds
+ var/datum/wound/iter_wound = k
+ iter_wound.remove_wound() // so we can get the scars for open wounds
if(!ending_human.client)
return
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ending_human.format_scars()
diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm
index c34cd5bcd2f..f49a35c1124 100644
--- a/code/datums/components/butchering.dm
+++ b/code/datums/components/butchering.dm
@@ -71,7 +71,7 @@
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/brute/cut/critical/screaming_through_a_slit_throat = new
+ var/datum/wound/slash/critical/screaming_through_a_slit_throat = new
screaming_through_a_slit_throat.apply_wound(slit_throat)
H.apply_status_effect(/datum/status_effect/neck_slice)
diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm
index 06dcc0bfd1a..3f8a995e8f0 100644
--- a/code/datums/components/embedded.dm
+++ b/code/datums/components/embedded.dm
@@ -23,7 +23,6 @@
*/
-
/datum/component/embedded
dupe_mode = COMPONENT_DUPE_ALLOWED
var/obj/item/bodypart/limb
@@ -90,14 +89,18 @@
RegisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING), .proc/weaponDeleted)
victim.visible_message("[weapon] [harmful ? "embeds" : "sticks"] itself [harmful ? "in" : "to"] [victim]'s [limb.name]!", "[weapon] [harmful ? "embeds" : "sticks"] itself [harmful ? "in" : "to"] your [limb.name]!")
+ var/damage = weapon.throwforce
if(harmful)
victim.throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
playsound(victim,'sound/weapons/bladeslice.ogg', 40)
weapon.add_mob_blood(victim)//it embedded itself in you, of course it's bloody!
- var/damage = weapon.w_class * impact_pain_mult
- limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
+ damage += weapon.w_class * impact_pain_mult
SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
+ if(damage > 0)
+ var/armor = victim.run_armor_check(limb.body_zone, "melee", "Your armor has protected your [limb.name].", "Your armor has softened a hit to your [limb.name].",I.armour_penetration)
+ limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, blocked=armor, sharpness = I.get_sharpness())
+
/datum/component/embedded/Destroy()
var/mob/living/carbon/victim = parent
if(victim && !victim.has_embedded_objects())
@@ -129,16 +132,22 @@
return
var/damage = weapon.w_class * pain_mult
- var/chance = pain_chance
+ var/pain_chance_current = pain_chance
if(pain_stam_pct && victim.stam_paralyzed) //if it's a less-lethal embed, give them a break if they're already stamcritted
- chance *= 0.2
+ pain_chance_current *= 0.2
damage *= 0.5
+ else if(victim.mobility_flags & ~MOBILITY_STAND)
+ pain_chance_current *= 0.2
- if(harmful && prob(chance))
+ if(harmful && prob(pain_chance_current))
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, sharpness=TRUE, wound_bonus = CANT_WOUND)
to_chat(victim, "[weapon] embedded in your [limb.name] hurts!")
- if(prob(fall_chance))
+ var/fall_chance_current = fall_chance
+ if(victim.mobility_flags & ~MOBILITY_STAND)
+ fall_chance_current *= 0.2
+
+ if(prob(fall_chance_current))
fallOut()
////////////////////////////////////////
@@ -155,7 +164,7 @@
if(harmful && prob(chance))
var/damage = weapon.w_class * jostle_pain_mult
- limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, sharpness=TRUE, wound_bonus = CANT_WOUND)
+ limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
to_chat(victim, "[weapon] embedded in your [limb.name] jostles and stings!")
@@ -165,29 +174,27 @@
if(harmful)
var/damage = weapon.w_class * remove_pain_mult
- limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, sharpness=TRUE, wound_bonus = CANT_WOUND)
+ limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, sharpness=SHARP_EDGED) // can wound
victim.visible_message("[weapon] falls [harmful ? "out" : "off"] of [victim.name]'s [limb.name]!", "[weapon] falls [harmful ? "out" : "off"] of your [limb.name]!")
safeRemove()
+
/// Called when a carbon with an object embedded/stuck to them inspects themselves and clicks the appropriate link to begin ripping the item out. This handles the ripping attempt, descriptors, and dealing damage, then calls safe_remove()
/datum/component/embedded/proc/ripOut(datum/source, obj/item/I, obj/item/bodypart/limb)
if(I != weapon || src.limb != limb)
return
-
var/mob/living/carbon/victim = parent
var/time_taken = rip_time * weapon.w_class
victim.visible_message("[victim] attempts to remove [weapon] from [victim.p_their()] [limb.name].","You attempt to remove [weapon] from your [limb.name]... (It will take [DisplayTimeText(time_taken)].)")
-
if(!do_after(victim, time_taken, target = victim))
return
if(!weapon || !limb || weapon.loc != victim || !(weapon in limb.embedded_objects))
qdel(src)
return
-
if(harmful)
var/damage = weapon.w_class * remove_pain_mult
- limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, sharpness=TRUE) //It hurts to rip it out, get surgery you dingus.
+ limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, sharpness=SHARP_EDGED) //It hurts to rip it out, get surgery you dingus.
victim.emote("scream")
victim.visible_message("[victim] successfully rips [weapon] [harmful ? "out" : "off"] of [victim.p_their()] [limb.name]!", "You successfully remove [weapon] from your [limb.name].")
diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm
index c817252ef69..30e880a693f 100644
--- a/code/datums/components/pellet_cloud.dm
+++ b/code/datums/components/pellet_cloud.dm
@@ -1,3 +1,8 @@
+// the following defines are used for [/datum/component/pellet_cloud/var/list/wound_info_by_part] to store the damage, wound_bonus, and bw_bonus for each bodypart hit
+#define CLOUD_POSITION_DAMAGE 1
+#define CLOUD_POSITION_W_BONUS 2
+#define CLOUD_POSITION_BW_BONUS 3
+
/*
* This component is used when you want to create a bunch of shrapnel or projectiles (say, shrapnel from a fragmentation grenade, or buckshot from a shotgun) from a central point,
* without necessarily printing a separate message for every single impact. This component should be instantiated right when you need it (like the moment of firing), then activated
@@ -29,9 +34,11 @@
var/list/pellets = list()
/// An associated list with the atom hit as the key and how many pellets they've eaten for the value, for printing aggregate messages
var/list/targets_hit = list()
- /// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs()]
+ /// Another associated list for hit bodyparts on carbons so we can track how much wounding potential we have for each bodypart
+ var/list/wound_info_by_part = list()
+ /// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs]
var/list/bodies
- /// For grenades, tracking people who die covering a grenade for achievement purposes, see [/datum/component/pellet_cloud/proc/handle_martyrs()]
+ /// For grenades, tracking people who die covering a grenade for achievement purposes, see [/datum/component/pellet_cloud/proc/handle_martyrs]
var/list/purple_hearts
/// For grenades, tracking how many pellets are removed due to martyrs and how many pellets are added due to the last person to touch it being on top of it
@@ -65,6 +72,7 @@
purple_hearts = null
pellets = null
targets_hit = null
+ wound_info_by_part = null
bodies = null
return ..()
@@ -86,7 +94,7 @@
/**
* create_casing_pellets() is for directed pellet clouds for ammo casings that have multiple pellets (buckshot and scatter lasers for instance)
*
- * Honestly this is mostly just a rehash of [/obj/item/ammo_casing/proc/fire_casing()] for pellet counts > 1, except this lets us tamper with the pellets and hook onto them for tracking purposes.
+ * Honestly this is mostly just a rehash of [/obj/item/ammo_casing/proc/fire_casing] for pellet counts > 1, except this lets us tamper with the pellets and hook onto them for tracking purposes.
* The arguments really don't matter, this proc is triggered by COMSIG_PELLET_CLOUD_INIT which is only for this really, it's just a big mess of the state vars we need for doing the stuff over here.
*/
/datum/component/pellet_cloud/proc/create_casing_pellets(obj/item/ammo_casing/shell, atom/target, mob/living/user, fired_from, randomspread, spread, zone_override, params, distro)
@@ -114,7 +122,7 @@
/**
* create_blast_pellets() is for when we have a central point we want to shred the surroundings of with a ring of shrapnel, namely frag grenades and landmines.
*
- * Note that grenades have extra handling for someone throwing themselves/being thrown on top of it, while landmines do not (obviously, it's a landmine!). See [/datum/component/pellet_cloud/proc/handle_martyrs()]
+ * Note that grenades have extra handling for someone throwing themselves/being thrown on top of it, while landmines do not (obviously, it's a landmine!). See [/datum/component/pellet_cloud/proc/handle_martyrs]
*/
/datum/component/pellet_cloud/proc/create_blast_pellets(obj/O, mob/living/lanced_by)
var/atom/A = parent
@@ -189,10 +197,26 @@
break
///One of our pellets hit something, record what it was and check if we're done (terminated == num_pellets)
-/datum/component/pellet_cloud/proc/pellet_hit(obj/projectile/P, atom/movable/firer, atom/target, Angle)
+/datum/component/pellet_cloud/proc/pellet_hit(obj/projectile/P, atom/movable/firer, atom/target, Angle, hit_zone)
pellets -= P
terminated++
hits++
+ var/obj/item/bodypart/hit_part
+ if(iscarbon(target) && hit_zone)
+ var/mob/living/carbon/hit_carbon = target
+ hit_part = hit_carbon.get_bodypart(hit_zone)
+ if(hit_part)
+ target = hit_part
+ if(P.wound_bonus != CANT_WOUND) // handle wounding
+ // unfortunately, due to how pellet clouds handle finalizing only after every pellet is accounted for, that also means there might be a short delay in dealing wounds if one pellet goes wide
+ // while buckshot may reach a target or miss it all in one tick, we also have to account for possible ricochets that may take a bit longer to hit the target
+ if(isnull(wound_info_by_part[hit_part]))
+ wound_info_by_part[hit_part] = list(0, 0, 0)
+ wound_info_by_part[hit_part][CLOUD_POSITION_DAMAGE] += P.damage // these account for decay
+ wound_info_by_part[hit_part][CLOUD_POSITION_W_BONUS] += P.wound_bonus
+ wound_info_by_part[hit_part][CLOUD_POSITION_BW_BONUS] += P.bare_wound_bonus
+ P.wound_bonus = CANT_WOUND // actual wounding will be handled aggregate
+
targets_hit[target]++
if(targets_hit[target] == 1)
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/on_target_qdel, override=TRUE)
@@ -233,12 +257,23 @@
for(var/atom/target in targets_hit)
var/num_hits = targets_hit[target]
UnregisterSignal(target, COMSIG_PARENT_QDELETING)
+ var/obj/item/bodypart/hit_part
+ if(isbodypart(target))
+ hit_part = target
+ target = hit_part.owner
+ var/damage_dealt = wound_info_by_part[hit_part][CLOUD_POSITION_DAMAGE]
+ var/w_bonus = wound_info_by_part[hit_part][CLOUD_POSITION_W_BONUS]
+ var/bw_bonus = wound_info_by_part[hit_part][CLOUD_POSITION_BW_BONUS]
+ var/wound_type = (initial(P.damage_type) == BRUTE) ? WOUND_BLUNT : WOUND_BURN // sharpness is handled in the wound rolling
+ wound_info_by_part[hit_part] = null
+ hit_part.painless_wound_roll(wound_type, damage_dealt, w_bonus, bw_bonus, initial(P.sharpness))
+
if(num_hits > 1)
- target.visible_message("[target] is hit by [num_hits] [proj_name]s!", null, null, COMBAT_MESSAGE_RANGE, target)
- to_chat(target, "You're hit by [num_hits] [proj_name]s!")
+ target.visible_message("[target] is hit by [num_hits] [proj_name]s[hit_part ? " in the [hit_part.name]" : ""]!", null, null, COMBAT_MESSAGE_RANGE, target)
+ to_chat(target, "You're hit by [num_hits] [proj_name]s[hit_part ? " in the [hit_part.name]" : ""]!")
else
- target.visible_message("[target] is hit by a [proj_name]!", null, null, COMBAT_MESSAGE_RANGE, target)
- to_chat(target, "You're hit by a [proj_name]!")
+ target.visible_message("[target] is hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!", null, null, COMBAT_MESSAGE_RANGE, target)
+ to_chat(target, "You're hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!")
for(var/M in purple_hearts)
var/mob/living/martyr = M
@@ -287,3 +322,8 @@
targets_hit -= target
LAZYREMOVE(bodies, target)
LAZYREMOVE(purple_hearts, target)
+
+
+#undef CLOUD_POSITION_DAMAGE
+#undef CLOUD_POSITION_W_BONUS
+#undef CLOUD_POSITION_BW_BONUS
diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm
index cc35c1f78af..84124c9878c 100644
--- a/code/datums/components/tackle.dm
+++ b/code/datums/components/tackle.dm
@@ -366,7 +366,7 @@
user.adjustBruteLoss(30)
playsound(user, 'sound/effects/blobattack.ogg', 60, TRUE)
playsound(user, 'sound/effects/splat.ogg', 70, TRUE)
- playsound(user, 'sound/effects/crack2.ogg', 70, TRUE)
+ playsound(user, 'sound/effects/wounds/crack2.ogg', 70, TRUE)
user.emote("scream")
user.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic) // oopsie indeed!
shake_camera(user, 7, 7)
diff --git a/code/datums/elements/embed.dm b/code/datums/elements/embed.dm
index 301799316d3..24965d435f8 100644
--- a/code/datums/elements/embed.dm
+++ b/code/datums/elements/embed.dm
@@ -34,9 +34,9 @@
if(!isitem(target) && !isprojectile(target))
return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_ELEMENT_ATTACH, .proc/severancePackage)
if(isitem(target))
RegisterSignal(target, COMSIG_MOVABLE_IMPACT_ZONE, .proc/checkEmbed)
- RegisterSignal(target, COMSIG_ELEMENT_ATTACH, .proc/severancePackage)
RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/examined)
RegisterSignal(target, COMSIG_EMBED_TRY_FORCE, .proc/tryForceEmbed)
RegisterSignal(target, COMSIG_ITEM_DISABLE_EMBED, .proc/detachFromWeapon)
@@ -63,7 +63,7 @@
if(isitem(target))
UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT_ZONE, COMSIG_ELEMENT_ATTACH, COMSIG_MOVABLE_IMPACT, COMSIG_PARENT_EXAMINE, COMSIG_EMBED_TRY_FORCE, COMSIG_ITEM_DISABLE_EMBED))
else
- UnregisterSignal(target, list(COMSIG_PROJECTILE_SELF_ON_HIT))
+ UnregisterSignal(target, list(COMSIG_PROJECTILE_SELF_ON_HIT, COMSIG_ELEMENT_ATTACH))
/// Checking to see if we're gonna embed into a human
@@ -74,13 +74,13 @@
var/actual_chance = embed_chance
if(!weapon.isEmbedHarmless()) // all the armor in the world won't save you from a kick me sign
- var/armor = max(victim.run_armor_check(hit_zone, "bullet", silent=TRUE), victim.run_armor_check(hit_zone, "bomb", silent=TRUE)) // we'll be nice and take the better of bullet and bomb armor
+ var/armor = max(victim.run_armor_check(hit_zone, "bullet", silent=TRUE), victim.run_armor_check(hit_zone, "bomb", silent=TRUE)) * 0.5 // we'll be nice and take the better of bullet and bomb armor, halved
if(armor) // we only care about armor penetration if there's actually armor to penetrate
var/pen_mod = -armor + weapon.armour_penetration // even a little bit of armor can make a big difference for shrapnel with large negative armor pen
actual_chance += pen_mod // doing the armor pen as a separate calc just in case this ever gets expanded on
if(actual_chance <= 0)
- victim.visible_message("[weapon] bounces off [victim]'s armor!", "[weapon] bounces off your armor!", vision_distance = COMBAT_MESSAGE_RANGE)
+ victim.visible_message("[weapon] bounces off [victim]'s armor, unable to embed!", "[weapon] bounces off your armor, unable to embed!", vision_distance = COMBAT_MESSAGE_RANGE)
return
var/roll_embed = prob(actual_chance)
@@ -107,7 +107,7 @@
return TRUE
///A different embed element has been attached, so we'll detach and let them handle things
-/datum/element/embed/proc/severancePackage(obj/item/weapon, datum/element/E)
+/datum/element/embed/proc/severancePackage(obj/weapon, datum/element/E)
if(istype(E, /datum/element/embed))
Detach(weapon)
@@ -134,13 +134,16 @@
return // we don't care
var/obj/item/payload = new payload_type(get_turf(hit))
+ if(istype(payload, /obj/item/shrapnel/bullet))
+ payload.name = P.name
+ payload.embedding = P.embedding
+ payload.updateEmbedding()
var/mob/living/carbon/C = hit
var/obj/item/bodypart/limb = C.get_bodypart(hit_zone)
if(!limb)
limb = C.get_bodypart()
- if(!payload.tryEmbed(limb))
- payload.failedEmbed()
+ payload.tryEmbed(limb)
Detach(P)
/**
@@ -172,4 +175,5 @@
hit_zone = limb.body_zone
C = limb.owner
- return checkEmbed(I, C, hit_zone, forced=TRUE)
+ checkEmbed(I, C, hit_zone, forced=TRUE)
+ return TRUE
diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm
index 4dcb91e660b..9c4b4ff25f5 100644
--- a/code/datums/mutations/actions.dm
+++ b/code/datums/mutations/actions.dm
@@ -284,7 +284,7 @@
throw_speed = 4
embedding = list("embedded_pain_multiplier" = 4, "embed_chance" = 100, "embedded_fall_chance" = 0, "embedded_ignore_throwspeed_threshold" = TRUE)
w_class = WEIGHT_CLASS_SMALL
- sharpness = IS_SHARP
+ sharpness = SHARP_POINTY
custom_materials = list(/datum/material/biomass = 500)
var/mob/living/carbon/human/fired_by
/// if we missed our target
diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm
index b80b64b66ec..63d87ea4728 100644
--- a/code/datums/mutations/hulk.dm
+++ b/code/datums/mutations/hulk.dm
@@ -54,11 +54,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/brute/bone/critical)
+ arm.force_wound_upwards(/datum/wound/blunt/critical)
if(41 to 45)
- arm.force_wound_upwards(/datum/wound/brute/bone/severe)
+ arm.force_wound_upwards(/datum/wound/blunt/severe)
if(35 to 41)
- arm.force_wound_upwards(/datum/wound/brute/bone/moderate)
+ arm.force_wound_upwards(/datum/wound/blunt/moderate)
/datum/mutation/human/hulk/on_life()
if(owner.health < 0)
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 1f6cfa5e3c6..40b1f40f05c 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -350,7 +350,7 @@
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
var/obj/item/bodypart/bodypart = pick(H.bodyparts)
- var/datum/wound/brute/cut/severe/crit_wound = new
+ var/datum/wound/slash/severe/crit_wound = new
crit_wound.apply_wound(bodypart)
return ..()
@@ -434,7 +434,7 @@
var/still_bleeding = FALSE
for(var/thing in throat.wounds)
var/datum/wound/W = thing
- if(W.wound_type == WOUND_LIST_CUT && W.severity > WOUND_SEVERITY_MODERATE)
+ if(W.wound_type == WOUND_SLASH && W.severity > WOUND_SEVERITY_MODERATE)
still_bleeding = TRUE
break
if(!still_bleeding)
diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm
index 751a3508a38..775b72699ab 100644
--- a/code/datums/status_effects/wound_effects.dm
+++ b/code/datums/status_effects/wound_effects.dm
@@ -116,8 +116,7 @@
/datum/status_effect/wound/on_creation(mob/living/new_owner, incoming_wound)
. = ..()
- var/datum/wound/W = incoming_wound
- linked_wound = W
+ linked_wound = incoming_wound
linked_limb = linked_wound.limb
/datum/status_effect/wound/on_remove()
@@ -138,9 +137,9 @@
// bones
-/datum/status_effect/wound/bone
+/datum/status_effect/wound/blunt
-/datum/status_effect/wound/bone/interact_speed_modifier()
+/datum/status_effect/wound/blunt/interact_speed_modifier()
var/mob/living/carbon/C = owner
if(C.get_active_hand() == linked_limb)
@@ -149,7 +148,7 @@
return 1
-/datum/status_effect/wound/bone/nextmove_modifier()
+/datum/status_effect/wound/blunt/nextmove_modifier()
var/mob/living/carbon/C = owner
if(C.get_active_hand() == linked_limb)
@@ -157,30 +156,31 @@
return 1
-/datum/status_effect/wound/bone/moderate
+// blunt
+/datum/status_effect/wound/blunt/moderate
id = "disjoint"
-/datum/status_effect/wound/bone/severe
+/datum/status_effect/wound/blunt/severe
id = "hairline"
-
-/datum/status_effect/wound/bone/critical
+/datum/status_effect/wound/blunt/critical
id = "compound"
-
-// cuts
-/datum/status_effect/wound/cut/moderate
+// slash
+/datum/status_effect/wound/slash/moderate
id = "abrasion"
-
-/datum/status_effect/wound/cut/severe
+/datum/status_effect/wound/slash/severe
id = "laceration"
-
-/datum/status_effect/wound/cut/critical
+/datum/status_effect/wound/slash/critical
id = "avulsion"
-
+// pierce
+/datum/status_effect/wound/pierce/moderate
+ id = "breakage"
+/datum/status_effect/wound/pierce/severe
+ id = "puncture"
+/datum/status_effect/wound/pierce/critical
+ id = "rupture"
// burns
/datum/status_effect/wound/burn/moderate
id = "seconddeg"
-
/datum/status_effect/wound/burn/severe
id = "thirddeg"
-
/datum/status_effect/wound/burn/critical
id = "fourthdeg"
diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm
index d70a4ebdb2d..29c87b32d4e 100644
--- a/code/datums/wounds/_wounds.dm
+++ b/code/datums/wounds/_wounds.dm
@@ -33,15 +33,13 @@
/// 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_BONE, WOUND_LIST_CUT, or WOUND_LIST_BURN
+ /// The list of wounds it belongs in, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN
var/wound_type
/// 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
- /// If we only work on organics (everything right now)
- var/organic_only = TRUE
/// The bodypart we're parented to
var/obj/item/bodypart/limb = null
@@ -51,8 +49,6 @@
var/list/treatable_by_grabbed
/// Tools with the specified tool flag will also be able to try directly treating this wound
var/treatable_tool
- /// Set to TRUE if we don't give a shit about the patient's comfort and are allowed to just use any random sharp thing on this wound. Will require an aggressive grab or more to perform
- var/treatable_sharp
/// How long it will take to treat this wound with a standard effective tool, assuming it doesn't need surgery
var/base_treat_time = 5 SECONDS
@@ -65,17 +61,13 @@
/// How much we're contributing to this limb's bleed_rate
var/blood_flow
- /// The minimum we need to roll on [/obj/item/bodypart/proc/check_wounding()] to begin suffering this wound, see check_wounding_mods() for more
+ /// The minimum we need to roll on [/obj/item/bodypart/proc/check_wounding] to begin suffering this wound, see check_wounding_mods() for more
var/threshold_minimum
/// How much having this wound will add to all future check_wounding() rolls on this limb, to allow progression to worse injuries with repeated damage
var/threshold_penalty
/// If we need to process each life tick
var/processes = FALSE
- /// If TRUE and an item that can treat multiple different types of coexisting wounds (gauze can be used to splint broken bones, staunch bleeding, and cover burns), we get first dibs if we come up first for it, then become nonpriority.
- /// Otherwise, if no untreated wound claims the item, we cycle through the non priority wounds and pick a random one who can use that item.
- var/treat_priority = FALSE
-
/// If having this wound makes currently makes the parent bodypart unusable
var/disabling
@@ -89,12 +81,15 @@
var/cryo_progress
/// What kind of scars this wound will create description wise once healed
- var/list/scarring_descriptions = list("general disfigurement")
+ var/scar_keyword = "generic"
/// If we've already tried scarring while removing (since remove_wound calls qdel, and qdel calls remove wound, .....) TODO: make this cleaner
var/already_scarred = FALSE
/// If we forced this wound through badmin smite, we won't count it towards the round totals
var/from_smite
+ /// What flags apply to this wound
+ var/wound_flags = (FLESH_WOUND | BONE_WOUND | ACCEPTS_GAUZE)
+
/datum/wound/Destroy()
if(attached_surgery)
QDEL_NULL(attached_surgery)
@@ -115,13 +110,13 @@
* * smited- If this is a smite, we don't care about this wound for stat tracking purposes (not yet implemented)
*/
/datum/wound/proc/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE)
- if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || isalien(L.owner))
+ if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || isalien(L.owner) || !L.is_organic_limb())
qdel(src)
return
if(ishuman(L.owner))
var/mob/living/carbon/human/H = L.owner
- if(organic_only && ((NOBLOOD in H.dna.species.species_traits) || !L.is_organic_limb()))
+ if(((wound_flags & BONE_WOUND) && !(HAS_BONE in H.dna.species.species_traits)) || ((wound_flags & FLESH_WOUND) && !(HAS_FLESH in H.dna.species.species_traits)))
qdel(src)
return
@@ -161,7 +156,7 @@
victim.visible_message(msg, "Your [limb.name] [occur_text]!", vision_distance = vis_dist)
if(sound_effect)
- playsound(L.owner, sound_effect, 60 + 20 * severity, TRUE)
+ playsound(L.owner, sound_effect, 70 + 20 * severity, TRUE)
if(!demoted)
wound_injury(old_wound)
@@ -181,7 +176,7 @@
SEND_SIGNAL(victim, COMSIG_CARBON_LOSE_WOUND, src, limb)
if(limb && !ignore_limb)
LAZYREMOVE(limb.wounds, src)
- limb.update_wounds()
+ limb.update_wounds(replaced)
/**
* 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)
@@ -189,7 +184,7 @@
* 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/brute/cut/severe
+ * * new_type- The TYPE PATH of the wound you want to replace this, like /datum/wound/slash/severe
* * 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)
@@ -206,9 +201,6 @@
/// Additional beneficial effects when the wound is gained, in case you want to give a temporary boost to allow the victim to try an escape or last stand
/datum/wound/proc/second_wind()
- if(HAS_TRAIT(victim, TRAIT_NOMETABOLISM))
- return
-
switch(severity)
if(WOUND_SEVERITY_MODERATE)
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_MODERATE)
@@ -216,11 +208,13 @@
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_SEVERE)
if(WOUND_SEVERITY_CRITICAL)
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_CRITICAL)
+ if(WOUND_SEVERITY_LOSS)
+ victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_LOSS)
/**
- * try_treating() is an intercept run from [/mob/living/carbon/attackby()] right after surgeries but before anything else. Return TRUE here if the item is something that is relevant to treatment to take over the interaction.
+ * try_treating() is an intercept run from [/mob/living/carbon/proc/attackby] right after surgeries but before anything else. Return TRUE here if the item is something that is relevant to treatment to take over the interaction.
*
- * This proc leads into [/datum/wound/proc/treat()] and probably shouldn't be added onto in children types. You can specify what items or tools you want to be intercepted
+ * This proc leads into [/datum/wound/proc/treat] and probably shouldn't be added onto in children types. You can specify what items or tools you want to be intercepted
* with var/list/treatable_by and var/treatable_tool, then if an item fulfills one of those requirements and our wound claims it first, it goes over to treat() and treat_self().
*
* Arguments:
@@ -260,7 +254,7 @@
treat(I, user)
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()]
+/// 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)
return FALSE
@@ -290,10 +284,22 @@
if(cryo_progress > 33 * severity)
qdel(src)
+/// When synthflesh is applied to the victim, we call this. No sense in setting up an entire chem reaction system for wounds when we only care for a few chems. Probably will change in the future
+/datum/wound/proc/on_synthflesh(power)
+ return
+
+/// Called when the patient is undergoing stasis, so that having fully treated a wound doesn't make you sit there helplessly until you think to unbuckle them
+/datum/wound/proc/on_stasis()
+ return
+
/// Called when we're crushed in an airlock or firedoor, for one of the improvised joint dislocation fixes
/datum/wound/proc/crush()
return
+/// Used when we're being dragged while bleeding, the value we return is how much bloodloss this wound causes from being dragged. Since it's a proc, you can let bandages soak some of the blood
+/datum/wound/proc/drag_bleed_amount()
+ return
+
/**
* get_examine_description() is used in carbon/examine and human/examine to show the status of this wound. Useful if you need to show some status like the wound being splinted or bandaged.
*
@@ -303,7 +309,8 @@
* * mob/user: The user examining the wound's owner, if that matters
*/
/datum/wound/proc/get_examine_description(mob/user)
- return "[victim.p_their(TRUE)] [limb.name] [examine_desc]!"
+ . = "[victim.p_their(TRUE)] [limb.name] [examine_desc]"
+ . = severity <= WOUND_SEVERITY_MODERATE ? "[.]." : "[.]!"
/datum/wound/proc/get_scanner_description(mob/user)
return "Type: [name]\nSeverity: [severity_text()]\nDescription: [desc]\nRecommended Treatment: [treat_text]"
diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm
index 93ca9c5b671..4d1c27b42e0 100644
--- a/code/datums/wounds/bones.dm
+++ b/code/datums/wounds/bones.dm
@@ -7,12 +7,10 @@
/*
Base definition
*/
-/datum/wound/brute/bone
- sound_effect = 'sound/effects/crack1.ogg'
- wound_type = WOUND_LIST_BONE
-
- /// The item we're currently splinted with, if there is one
- var/obj/item/stack/splinted
+/datum/wound/blunt
+ sound_effect = 'sound/effects/wounds/crack1.ogg'
+ wound_type = WOUND_BLUNT
+ wound_flags = (BONE_WOUND | ACCEPTS_GAUZE)
/// Have we been taped?
var/taped
@@ -31,12 +29,12 @@
/// How long do we wait +/- 20% for the next trauma?
var/trauma_cycle_cooldown
/// If this is a chest wound and this is set, we have this chance to cough up blood when hit in the chest
- var/chance_internal_bleeding = 0
+ var/internal_bleeding_chance = 0
/*
Overwriting of base procs
*/
-/datum/wound/brute/bone/wound_injury(datum/wound/old_wound = null)
+/datum/wound/blunt/wound_injury(datum/wound/old_wound = null)
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group)
processes = TRUE
active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND)
@@ -53,14 +51,14 @@
update_inefficiencies()
-/datum/wound/brute/bone/remove_wound(ignore_limb, replaced)
+/datum/wound/blunt/remove_wound(ignore_limb, replaced)
limp_slowdown = 0
QDEL_NULL(active_trauma)
if(victim)
UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK)
return ..()
-/datum/wound/brute/bone/handle_process()
+/datum/wound/blunt/handle_process()
. = ..()
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle)
if(active_trauma)
@@ -86,7 +84,7 @@
remove_wound()
/// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so
-/datum/wound/brute/bone/proc/attack_with_hurt_hand(mob/M, atom/target, proximity)
+/datum/wound/blunt/proc/attack_with_hurt_hand(mob/M, atom/target, proximity)
if(victim.get_active_hand() != limb || victim.a_intent == INTENT_HELP || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE)
return
@@ -104,61 +102,54 @@
limb.receive_damage(brute=rand(3,7))
return COMPONENT_NO_ATTACK_HAND
-/datum/wound/brute/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus)
- if(!victim)
+/datum/wound/blunt/receive_damage(wounding_type, wounding_dmg, wound_bonus)
+ if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE)
return
+ if(ishuman(victim))
+ var/mob/living/carbon/human/human_victim = victim
+ if(NOBLOOD in human_victim.dna?.species.species_traits)
+ return
- if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(chance_internal_bleeding + wounding_dmg))
+ if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg))
var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound
switch(blood_bled)
if(1 to 6)
victim.bleed(blood_bled, TRUE)
if(7 to 13)
- victim.visible_message("[victim] coughs up a bit of blood from the blow to [victim.p_their()] chest.", "You cough up a bit of blood from the blow to your chest.")
+ victim.visible_message("[victim] coughs up a bit of blood from the blow to [victim.p_their()] chest.", "You cough up a bit of blood from the blow to your chest.", vision_distance=COMBAT_MESSAGE_RANGE)
victim.bleed(blood_bled, TRUE)
if(14 to 19)
- victim.visible_message("[victim] spits out a string of blood from the blow to [victim.p_their()] chest!", "You spit out a string of blood from the blow to your chest!")
+ victim.visible_message("[victim] spits out a string of blood from the blow to [victim.p_their()] chest!", "You spit out a string of blood from the blow to your chest!", vision_distance=COMBAT_MESSAGE_RANGE)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.bleed(blood_bled)
if(20 to INFINITY)
- victim.visible_message("[victim] chokes up a spray of blood from the blow to [victim.p_their()] chest!", "You choke up on a spray of blood from the blow to your chest!")
+ victim.visible_message("[victim] chokes up a spray of blood from the blow to [victim.p_their()] chest!", "You choke up on a spray of blood from the blow to your chest!", vision_distance=COMBAT_MESSAGE_RANGE)
victim.bleed(blood_bled)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.add_splatter_floor(get_step(victim.loc, victim.dir))
- if(!(wounding_type in list(WOUND_SHARP, WOUND_BURN)) || !splinted || wound_bonus == CANT_WOUND)
- return
- splinted.take_damage(wounding_dmg, damage_type = (wounding_type == WOUND_SHARP ? BRUTE : BURN), sound_effect = FALSE)
- if(QDELETED(splinted))
- var/destroyed_verb = (wounding_type == WOUND_SHARP ? "torn" : "burned")
- victim.visible_message("The splint securing [victim]'s [limb.name] is [destroyed_verb] away!", "The splint securing your [limb.name] is [destroyed_verb] away!", vision_distance=COMBAT_MESSAGE_RANGE)
- splinted = null
- treat_priority = TRUE
- update_inefficiencies()
-
-
-/datum/wound/brute/bone/get_examine_description(mob/user)
- if(!splinted && !gelled && !taped)
+/datum/wound/blunt/get_examine_description(mob/user)
+ if(!limb.current_gauze && !gelled && !taped)
return ..()
- var/msg = ""
- if(!splinted)
- msg = "[victim.p_their(TRUE)] [limb.name] [examine_desc]"
+ var/list/msg = list()
+ if(!limb.current_gauze)
+ msg += "[victim.p_their(TRUE)] [limb.name] [examine_desc]"
else
- var/splint_condition = ""
+ var/sling_condition = ""
// how much life we have left in these bandages
- switch(splinted.obj_integrity / splinted.max_integrity * 100)
+ switch(limb.current_gauze.obj_integrity / limb.current_gauze.max_integrity * 100)
if(0 to 25)
- splint_condition = "just barely "
+ sling_condition = "just barely "
if(25 to 50)
- splint_condition = "loosely "
+ sling_condition = "loosely "
if(50 to 75)
- splint_condition = "mostly "
+ sling_condition = "mostly "
if(75 to INFINITY)
- splint_condition = "tightly "
+ sling_condition = "tightly "
- msg = "[victim.p_their(TRUE)] [limb.name] is [splint_condition] fastened in a splint of [splinted.name]"
+ msg += "[victim.p_their(TRUE)] [limb.name] is [sling_condition] fastened in a sling of [limb.current_gauze.name]"
if(taped)
msg += ", and appears to be reforming itself under some surgical tape!"
@@ -166,58 +157,35 @@
msg += ", with fizzing flecks of blue bone gel sparking off the bone!"
else
msg += "!"
- return "[msg]"
+ return "[msg.Join()]"
/*
- New common procs for /datum/wound/brute/bone/
+ New common procs for /datum/wound/blunt/
*/
-/datum/wound/brute/bone/proc/update_inefficiencies()
+/datum/wound/blunt/proc/update_inefficiencies()
if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
- if(splinted)
- limp_slowdown = initial(limp_slowdown) * splinted.splint_factor
+ if(limb.current_gauze)
+ limp_slowdown = initial(limp_slowdown) * limb.current_gauze.splint_factor
else
limp_slowdown = initial(limp_slowdown)
victim.apply_status_effect(STATUS_EFFECT_LIMP)
else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
- if(splinted)
- interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * splinted.splint_factor)
+ if(limb.current_gauze)
+ interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * limb.current_gauze.splint_factor)
else
interaction_efficiency_penalty = interaction_efficiency_penalty
- if(initial(disabling) && splinted)
- disabling = FALSE
- else if(initial(disabling))
- disabling = TRUE
+ if(initial(disabling))
+ disabling = !limb.current_gauze
limb.update_wounds()
-/*
- BEWARE OF REDUNDANCY AHEAD THAT I MUST PARE DOWN
-*/
-
-/datum/wound/brute/bone/proc/splint(obj/item/stack/I, mob/user)
- if(splinted && splinted.splint_factor >= I.splint_factor)
- to_chat(user, "The splint already on [user == victim ? "your" : "[victim]'s"] [limb.name] is better than you can do with [I].")
- return
-
- user.visible_message("[user] begins splinting [victim]'s [limb.name] with [I].", "You begin splinting [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
-
- if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
- return
-
- user.visible_message("[user] finishes splinting [victim]'s [limb.name]!", "You finish splinting [user == victim ? "your" : "[victim]'s"] [limb.name]!")
- treat_priority = FALSE
- splinted = new I.type(limb)
- splinted.amount = 1
- I.use(1)
- update_inefficiencies()
-
/*
Moderate (Joint Dislocation)
*/
-/datum/wound/brute/bone/moderate
+/datum/wound/blunt/moderate
name = "Joint Dislocation"
desc = "Patient's bone has been unset from socket, causing pain and reduced motor function."
treat_text = "Recommended application of bonesetter to affected limb, though manual relocation by applying an aggressive grab to the patient and helpfully interacting with afflicted limb may suffice."
@@ -230,15 +198,16 @@
threshold_minimum = 35
threshold_penalty = 15
treatable_tool = TOOL_BONESET
- status_effect_type = /datum/status_effect/wound/bone/moderate
- scarring_descriptions = list("light discoloring", "a slight blue tint")
+ wound_flags = (BONE_WOUND)
+ status_effect_type = /datum/status_effect/wound/blunt/moderate
+ scar_keyword = "bluntmoderate"
-/datum/wound/brute/bone/moderate/crush()
+/datum/wound/blunt/moderate/crush()
if(prob(33))
victim.visible_message("[victim]'s dislocated [limb.name] pops back into place!", "Your dislocated [limb.name] pops back into place! Ow!")
remove_wound()
-/datum/wound/brute/bone/moderate/try_handling(mob/living/carbon/human/user)
+/datum/wound/blunt/moderate/try_handling(mob/living/carbon/human/user)
if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB)
return FALSE
@@ -256,7 +225,7 @@
return TRUE
/// If someone is snapping our dislocated joint back into place by hand with an aggro grab and help intent
-/datum/wound/brute/bone/moderate/proc/chiropractice(mob/living/carbon/human/user)
+/datum/wound/blunt/moderate/proc/chiropractice(mob/living/carbon/human/user)
var/time = base_treat_time
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
@@ -275,7 +244,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/brute/bone/moderate/proc/malpractice(mob/living/carbon/human/user)
+/datum/wound/blunt/moderate/proc/malpractice(mob/living/carbon/human/user)
var/time = base_treat_time
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
@@ -293,7 +262,7 @@
malpractice(user)
-/datum/wound/brute/bone/moderate/treat(obj/item/I, mob/user)
+/datum/wound/blunt/moderate/treat(obj/item/I, mob/user)
if(victim == user)
victim.visible_message("[user] begins resetting [victim.p_their()] [limb.name] with [I].", "You begin resetting your [limb.name] with [I]...")
else
@@ -317,56 +286,57 @@
Severe (Hairline Fracture)
*/
-/datum/wound/brute/bone/severe
+/datum/wound/blunt/severe
name = "Hairline Fracture"
desc = "Patient's bone has suffered a crack in the foundation, causing serious pain and reduced limb functionality."
- treat_text = "Recommended light surgical application of bone gel, though splinting will prevent worsening situation."
- examine_desc = "appears bruised and grotesquely swollen"
-
+ treat_text = "Recommended light surgical application of bone gel, though a sling of medical gauze will prevent worsening situation."
+ examine_desc = "appears grotesquely swollen, its attachment weakened"
occur_text = "sprays chips of bone and develops a nasty looking bruise"
+
severity = WOUND_SEVERITY_SEVERE
interaction_efficiency_penalty = 2
limp_slowdown = 6
threshold_minimum = 60
threshold_penalty = 30
- treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/gauze, /obj/item/stack/medical/bone_gel)
- status_effect_type = /datum/status_effect/wound/bone/severe
- treat_priority = TRUE
- scarring_descriptions = list("a faded, fist-sized bruise", "a vaguely triangular peel scar")
+ treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel)
+ status_effect_type = /datum/status_effect/wound/blunt/severe
+ scar_keyword = "bluntsevere"
brain_trauma_group = BRAIN_TRAUMA_MILD
trauma_cycle_cooldown = 1.5 MINUTES
- chance_internal_bleeding = 40
+ internal_bleeding_chance = 40
+ wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE)
-/datum/wound/brute/bone/critical
+/datum/wound/blunt/critical
name = "Compound Fracture"
desc = "Patient's bones have suffered multiple gruesome fractures, causing significant pain and near uselessness of limb."
treat_text = "Immediate binding of affected limb, followed by surgical intervention ASAP."
- examine_desc = "has a cracked bone sticking out of it"
+ examine_desc = "is mangled and pulped, seemingly held together by tissue alone"
occur_text = "cracks apart, exposing broken bones to open air"
+
severity = WOUND_SEVERITY_CRITICAL
interaction_efficiency_penalty = 4
limp_slowdown = 9
- sound_effect = 'sound/effects/crack2.ogg'
+ sound_effect = 'sound/effects/wounds/crack2.ogg'
threshold_minimum = 115
threshold_penalty = 50
disabling = TRUE
- treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/gauze, /obj/item/stack/medical/bone_gel)
- status_effect_type = /datum/status_effect/wound/bone/critical
- treat_priority = TRUE
- scarring_descriptions = list("a section of janky skin lines and badly healed scars", "a large patch of uneven skin tone", "a cluster of calluses")
+ treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel)
+ status_effect_type = /datum/status_effect/wound/blunt/critical
+ scar_keyword = "bluntcritical"
brain_trauma_group = BRAIN_TRAUMA_SEVERE
trauma_cycle_cooldown = 2.5 MINUTES
- chance_internal_bleeding = 60
+ internal_bleeding_chance = 60
+ wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE)
// doesn't make much sense for "a" bone to stick out of your head
-/datum/wound/brute/bone/critical/apply_wound(obj/item/bodypart/L, silent, datum/wound/old_wound, smited)
+/datum/wound/blunt/critical/apply_wound(obj/item/bodypart/L, silent, datum/wound/old_wound, smited)
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/brute/bone/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user)
+/datum/wound/blunt/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user)
if(gelled)
to_chat(user, "[user == victim ? "Your" : "[victim]'s"] [limb.name] is already coated with bone gel!")
return
@@ -385,9 +355,9 @@
var/painkiller_bonus = 0
if(victim.drunkenness)
painkiller_bonus += 5
- if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/medicine/morphine))
+ if(victim.reagents?.has_reagent(/datum/reagent/medicine/morphine))
painkiller_bonus += 10
- if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/determination))
+ if(victim.reagents?.has_reagent(/datum/reagent/determination))
painkiller_bonus += 5
if(prob(25 + (20 * severity - 2) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers
@@ -401,7 +371,7 @@
gelled = TRUE
/// if someone is using surgical tape on our wound
-/datum/wound/brute/bone/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user)
+/datum/wound/blunt/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user)
if(!gelled)
to_chat(user, "[user == victim ? "Your" : "[victim]'s"] [limb.name] must be coated with bone gel to perform this emergency operation!")
return
@@ -426,15 +396,13 @@
taped = TRUE
processes = TRUE
-/datum/wound/brute/bone/treat(obj/item/I, mob/user)
+/datum/wound/blunt/treat(obj/item/I, mob/user)
if(istype(I, /obj/item/stack/medical/bone_gel))
gel(I, user)
else if(istype(I, /obj/item/stack/sticky_tape/surgical))
tape(I, user)
- else if(istype(I, /obj/item/stack/medical/gauze))
- splint(I, user)
-/datum/wound/brute/bone/get_scanner_description(mob/user)
+/datum/wound/blunt/get_scanner_description(mob/user)
. = ..()
. += "
"
@@ -444,7 +412,7 @@
else if(!taped)
. += "
Continue Alternative Treatment: Apply surgical tape directly to injured limb to begin bone regeneration. Note, this is both excruciatingly painful and slow.\n"
else
- . += "
Note: Bone regeneration in effect. Bone is [round(regen_points_current/regen_points_needed)]% regenerated.\n"
+ . += "
Note: Bone regeneration in effect. Bone is [round(regen_points_current*100/regen_points_needed)]% regenerated.\n"
if(limb.body_zone == BODY_ZONE_HEAD)
. += "Cranial Trauma Detected: Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired."
diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm
index a09cf2fb7b0..e403ac2850a 100644
--- a/code/datums/wounds/burns.dm
+++ b/code/datums/wounds/burns.dm
@@ -4,11 +4,12 @@
// TODO: well, a lot really, but specifically I want to add potential fusing of clothing/equipment on the affected area, and limb infections, though those may go in body part code
/datum/wound/burn
a_or_from = "from"
- wound_type = WOUND_LIST_BURN
+ wound_type = WOUND_BURN
processes = TRUE
- sound_effect = 'sound/effects/sizzle1.ogg'
+ sound_effect = 'sound/effects/wounds/sizzle1.ogg'
+ wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE)
- treatable_by = list(/obj/item/stack/medical/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon
+ treatable_by = list(/obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon
// Flesh damage vars
/// How much damage to our flesh we currently have. Once both this and infestation reach 0, the wound is considered healed
@@ -27,8 +28,6 @@
/// 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
- /// The current bandage we have for this wound (maybe move bandages to the limb?)
- var/obj/item/stack/current_bandage
/datum/wound/burn/handle_process()
. = ..()
@@ -47,15 +46,11 @@
sanitization += 0.3
flesh_healing += 0.5
- if(current_bandage)
- current_bandage.absorption_capacity -= WOUND_BURN_SANITIZATION_RATE
- if(current_bandage.absorption_capacity <= 0)
- victim.visible_message("
Pus soaks through \the [current_bandage] on [victim]'s [limb.name].", "
Pus soaks through \the [current_bandage] on your [limb.name].", vision_distance=COMBAT_MESSAGE_RANGE)
- QDEL_NULL(current_bandage)
- treat_priority = TRUE
+ if(limb.current_gauze)
+ limb.seep_gauze(WOUND_BURN_SANITIZATION_RATE)
if(flesh_healing > 0)
- var/bandage_factor = (current_bandage ? current_bandage.splint_factor : 1)
+ var/bandage_factor = (limb.current_gauze ? limb.current_gauze.splint_factor : 1)
flesh_damage = max(0, flesh_damage - 1)
flesh_healing = max(0, flesh_healing - bandage_factor) // good bandages multiply the length of flesh healing
@@ -67,7 +62,7 @@
// sanitization is checked after the clearing check but before the rest, because we freeze the effects of infection while we have sanitization
if(sanitization > 0)
- var/bandage_factor = (current_bandage ? current_bandage.splint_factor : 1)
+ var/bandage_factor = (limb.current_gauze ? limb.current_gauze.splint_factor : 1)
infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE)
sanitization = max(0, sanitization - (WOUND_BURN_SANITIZATION_RATE * bandage_factor))
return
@@ -122,10 +117,10 @@
if(strikes_to_lose_limb <= 0)
return "
[victim.p_their(TRUE)] [limb.name] is completely dead and unrecognizable as organic."
- var/condition = ""
- if(current_bandage)
+ var/list/condition = list("[victim.p_their(TRUE)] [limb.name] [examine_desc]")
+ if(limb.current_gauze)
var/bandage_condition
- switch(current_bandage.absorption_capacity)
+ switch(limb.current_gauze.absorption_capacity)
if(0 to 1.25)
bandage_condition = "nearly ruined "
if(1.25 to 2.75)
@@ -135,7 +130,7 @@
if(4 to INFINITY)
bandage_condition = "clean "
- condition += " underneath a dressing of [bandage_condition] [current_bandage.name]"
+ condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]"
else
switch(infestation)
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
@@ -149,7 +144,7 @@
else
condition += "!"
- return "
[victim.p_their(TRUE)] [limb.name] [examine_desc][condition]"
+ return "
[condition.Join()]"
/datum/wound/burn/get_scanner_description(mob/user)
if(strikes_to_lose_limb == 0)
@@ -200,36 +195,6 @@
else
try_treating(I, user)
-/// for use in the burn dressing surgery since we don't want to make them do another do_after obviously
-/datum/wound/burn/proc/force_bandage(obj/item/stack/medical/gauze/I, mob/user)
- QDEL_NULL(current_bandage)
- current_bandage = new I.type(limb)
- current_bandage.amount = 1
- treat_priority = FALSE
- sanitization += I.sanitization
- I.use(1)
-
-/// if someone is wrapping gauze on our burns
-/datum/wound/burn/proc/bandage(obj/item/stack/medical/gauze/I, mob/user)
- if(current_bandage)
- if(current_bandage.absorption_capacity > I.absorption_capacity + 1)
- to_chat(user, "
The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!")
- return
- user.visible_message("
[user] begins to redress the burns on [victim]'s [limb.name] with [I]...", "
You begin redressing the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
- else
- user.visible_message("
[user] begins to dress the burns on [victim]'s [limb.name] with [I]...", "
You begin dressing the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
-
- if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
- return
-
- user.visible_message("
[user] applies [I] to [victim].", "
You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].")
- QDEL_NULL(current_bandage)
- current_bandage = new I.type(limb)
- current_bandage.amount = 1
- treat_priority = FALSE
- sanitization += I.sanitization
- I.use(1)
-
/// if someone is using mesh on our burns
/datum/wound/burn/proc/mesh(obj/item/stack/medical/mesh/I, mob/user)
user.visible_message("
[user] begins wrapping [victim]'s [limb.name] with [I]...", "
You begin wrapping [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
@@ -261,17 +226,26 @@
COOLDOWN_START(I, uv_cooldown, I.uv_cooldown_length)
/datum/wound/burn/treat(obj/item/I, mob/user)
- if(istype(I, /obj/item/stack/medical/gauze))
- bandage(I, user)
- else if(istype(I, /obj/item/stack/medical/ointment))
+ if(istype(I, /obj/item/stack/medical/ointment))
ointment(I, user)
else if(istype(I, /obj/item/stack/medical/mesh))
mesh(I, user)
else if(istype(I, /obj/item/flashlight/pen/paramedic))
uv(I, user)
-/// basic support for instabitaluri/synthflesh healing flesh damage, more chem support in the future
-/datum/wound/burn/proc/regenerate_flesh(amount)
+// people complained about burns not healing on stasis beds, so in addition to checking if it's cured, they also get the special ability to very slowly heal on stasis beds if they have the healing effects stored
+/datum/wound/burn/on_stasis()
+ . = ..()
+ if(flesh_healing > 0)
+ flesh_damage = max(0, flesh_damage - 0.2)
+ if((flesh_damage <= 0) && (infestation <= 1))
+ to_chat(victim, "
The burns on your [limb.name] have cleared up!")
+ qdel(src)
+ return
+ if(sanitization > 0)
+ infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE * 0.2)
+
+/datum/wound/burn/on_synthflesh(amount)
flesh_healing += amount * 0.5 // 20u patch will heal 10 flesh standard
// we don't even care about first degree burns, straight to second
@@ -287,7 +261,7 @@
threshold_penalty = 30 // burns cause significant decrease in limb integrity compared to other wounds
status_effect_type = /datum/status_effect/wound/burn/moderate
flesh_damage = 5
- scarring_descriptions = list("small amoeba-shaped skinmarks", "a faded streak of depressed skin")
+ scar_keyword = "burnmoderate"
/datum/wound/burn/severe
name = "Third Degree Burns"
@@ -300,10 +274,10 @@
threshold_minimum = 80
threshold_penalty = 40
status_effect_type = /datum/status_effect/wound/burn/severe
- treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
+ treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
infestation_rate = 0.05 // appx 13 minutes to reach sepsis without any treatment
flesh_damage = 12.5
- scarring_descriptions = list("a large, jagged patch of faded skin", "random spots of shiny, smooth skin", "spots of taut, leathery skin")
+ scar_keyword = "burnsevere"
/datum/wound/burn/critical
name = "Catastrophic Burns"
@@ -313,11 +287,11 @@
occur_text = "vaporizes as flesh, bone, and fat melt together in a horrifying mess"
severity = WOUND_SEVERITY_CRITICAL
damage_mulitplier_penalty = 1.3
- sound_effect = 'sound/effects/sizzle2.ogg'
+ sound_effect = 'sound/effects/wounds/sizzle2.ogg'
threshold_minimum = 140
threshold_penalty = 80
status_effect_type = /datum/status_effect/wound/burn/critical
- treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
+ treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
infestation_rate = 0.15 // appx 4.33 minutes to reach sepsis without any treatment
flesh_damage = 20
- scarring_descriptions = list("massive, disfiguring keloid scars", "several long streaks of badly discolored and malformed skin", "unmistakeable splotches of dead tissue from serious burns")
+ scar_keyword = "burncritical"
diff --git a/code/datums/wounds/loss.dm b/code/datums/wounds/loss.dm
new file mode 100644
index 00000000000..bc7e18a1831
--- /dev/null
+++ b/code/datums/wounds/loss.dm
@@ -0,0 +1,42 @@
+
+/datum/wound/loss
+ name = "Dismembered"
+ desc = "oof ouch!!"
+
+ sound_effect = 'sound/effects/dismember.ogg'
+ severity = WOUND_SEVERITY_LOSS
+ threshold_minimum = 180
+ status_effect_type = null
+ scar_keyword = "dismember"
+ wound_flags = null
+
+/// 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)
+ if(!istype(dismembered_part) || !dismembered_part.owner || !(dismembered_part.body_zone in viable_zones) || isalien(dismembered_part.owner) || !dismembered_part.can_dismember())
+ qdel(src)
+ return
+
+ already_scarred = TRUE // so we don't scar a limb we don't have. If I add different levels of amputation desc, do it here
+
+ switch(wounding_type)
+ if(WOUND_BLUNT)
+ occur_text = "is shattered through the last bone holding it together, severing it completely!"
+ if(WOUND_SLASH)
+ occur_text = "is slashed through the last tissue holding it together, severing it completely!"
+ if(WOUND_PIERCE)
+ occur_text = "is pierced through the last tissue holding it together, severing it completely!"
+ if(WOUND_BURN)
+ occur_text = "is completely incinerated, falling to dust!"
+
+ victim = dismembered_part.owner
+
+ var/msg = "
[victim]'s [dismembered_part.name] [occur_text]!"
+
+ victim.visible_message(msg, "
Your [dismembered_part.name] [occur_text]!")
+
+ limb = dismembered_part
+ severity = WOUND_SEVERITY_LOSS
+ second_wind()
+ log_wound(victim, src)
+ dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE)
+ qdel(src)
diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm
new file mode 100644
index 00000000000..c307f9582de
--- /dev/null
+++ b/code/datums/wounds/pierce.dm
@@ -0,0 +1,171 @@
+
+/*
+ Pierce
+*/
+
+/datum/wound/pierce
+ sound_effect = 'sound/weapons/slice.ogg'
+ processes = TRUE
+ wound_type = WOUND_PIERCE
+ treatable_by = list(/obj/item/stack/medical/suture)
+ treatable_tool = TOOL_CAUTERY
+ base_treat_time = 3 SECONDS
+ wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE)
+
+ /// How much blood we start losing when this wound is first applied
+ var/initial_flow
+ /// If gauzed, what percent of the internal bleeding actually clots of the total absorption rate
+ var/gauzed_clot_rate
+
+ /// When hit on this bodypart, we have this chance of losing some blood + the incoming damage
+ var/internal_bleeding_chance
+ /// If we let off blood when hit, the max blood lost is this * the incoming damage
+ var/internal_bleeding_coefficient
+
+/datum/wound/pierce/wound_injury(datum/wound/old_wound)
+ blood_flow = initial_flow
+
+/datum/wound/pierce/receive_damage(wounding_type, wounding_dmg, wound_bonus)
+ if(victim.stat == DEAD || wounding_dmg < 5)
+ return
+ if(victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg))
+ if(limb.current_gauze && limb.current_gauze.splint_factor)
+ wounding_dmg *= (1 - limb.current_gauze.splint_factor)
+ var/blood_bled = rand(1, wounding_dmg * internal_bleeding_coefficient) // 12 brute toolbox can cause up to 15/18/21 bloodloss on mod/sev/crit
+ switch(blood_bled)
+ if(1 to 6)
+ victim.bleed(blood_bled, TRUE)
+ if(7 to 13)
+ victim.visible_message("
Blood droplets fly from the hole in [victim]'s [limb.name].", "
You cough up a bit of blood from the blow to your [limb.name].", vision_distance=COMBAT_MESSAGE_RANGE)
+ victim.bleed(blood_bled, TRUE)
+ if(14 to 19)
+ victim.visible_message("
A small stream of blood spurts from the hole in [victim]'s [limb.name]!", "
You spit out a string of blood from the blow to your [limb.name]!", vision_distance=COMBAT_MESSAGE_RANGE)
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
+ victim.bleed(blood_bled)
+ if(20 to INFINITY)
+ victim.visible_message("
A spray of blood streams from the gash in [victim]'s [limb.name]!", "
You choke up on a spray of blood from the blow to your [limb.name]!", vision_distance=COMBAT_MESSAGE_RANGE)
+ victim.bleed(blood_bled)
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
+ victim.add_splatter_floor(get_step(victim.loc, victim.dir))
+
+/datum/wound/pierce/handle_process()
+ blood_flow = min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW)
+
+ if(victim.bodytemperature < (BODYTEMP_NORMAL - 10))
+ blood_flow -= 0.2
+ if(prob(5))
+ to_chat(victim, "
You feel the [lowertext(name)] in your [limb.name] firming up from the cold!")
+
+ if(victim.reagents?.has_reagent(/datum/reagent/toxin/heparin))
+ blood_flow += 0.5 // old herapin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first
+
+ if(limb.current_gauze)
+ blood_flow -= limb.current_gauze.absorption_rate * gauzed_clot_rate
+ limb.current_gauze.absorption_capacity -= limb.current_gauze.absorption_rate
+
+ if(blood_flow <= 0)
+ qdel(src)
+
+/datum/wound/pierce/on_stasis()
+ . = ..()
+ if(blood_flow <= 0)
+ qdel(src)
+
+/datum/wound/pierce/treat(obj/item/I, mob/user)
+ if(istype(I, /obj/item/stack/medical/suture))
+ suture(I, user)
+ else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature() > 300)
+ tool_cauterize(I, user)
+
+/datum/wound/pierce/on_xadone(power)
+ . = ..()
+ 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)
+ . = ..()
+ blood_flow -= 0.05 * power // 20u * 0.05 = -1 blood flow, less than with slashes but still good considering smaller bleed rates
+
+/// If someone is using a suture to close this cut
+/datum/wound/pierce/proc/suture(obj/item/stack/medical/suture/I, mob/user)
+ var/self_penalty_mult = (user == victim ? 1.4 : 1)
+ user.visible_message("
[user] begins stitching [victim]'s [limb.name] with [I]...", "
You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
+ if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
+ return
+ user.visible_message("
[user] stitches up some of the bleeding on [victim].", "
You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].")
+ var/blood_sutured = I.stop_bleeding / self_penalty_mult * 0.5
+ blood_flow -= blood_sutured
+ limb.heal_damage(I.heal_brute, I.heal_burn)
+
+ if(blood_flow > 0)
+ try_treating(I, user)
+ else
+ to_chat(user, "
You successfully close the hole in [user == victim ? "your" : "[victim]'s"] [limb.name].")
+
+/// 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)
+ var/self_penalty_mult = (user == victim ? 1.5 : 1)
+ user.visible_message("
[user] begins cauterizing [victim]'s [limb.name] with [I]...", "
You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
+ if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
+ return
+
+ user.visible_message("
[user] cauterizes some of the bleeding on [victim].", "
You cauterize some of the bleeding on [victim].")
+ limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND)
+ if(prob(30))
+ victim.emote("scream")
+ var/blood_cauterized = (0.6 / self_penalty_mult) * 0.5
+ blood_flow -= blood_cauterized
+
+ if(blood_flow > 0)
+ try_treating(I, user)
+
+/datum/wound/pierce/moderate
+ name = "Minor Breakage"
+ desc = "Patient's skin has been broken open, causing severe bruising and minor internal bleeding in affected area."
+ treat_text = "Treat affected site with bandaging or exposure to extreme cold. In dire cases, brief exposure to vacuum may suffice." // space is cold in ss13, so it's like an ice pack!
+ examine_desc = "has a small, circular hole, gently bleeding"
+ occur_text = "spurts out a thin stream of blood"
+ sound_effect = 'sound/effects/wounds/pierce1.ogg'
+ severity = WOUND_SEVERITY_MODERATE
+ initial_flow = 1.5
+ gauzed_clot_rate = 0.8
+ internal_bleeding_chance = 30
+ internal_bleeding_coefficient = 1.25
+ threshold_minimum = 30
+ threshold_penalty = 15
+ status_effect_type = /datum/status_effect/wound/pierce/moderate
+ scar_keyword = "piercemoderate"
+
+/datum/wound/pierce/severe
+ name = "Open Puncture"
+ desc = "Patient's internal tissue is penetrated, causing sizeable internal bleeding and reduced limb stability."
+ treat_text = "Repair punctures in skin by suture or cautery, extreme cold may also work."
+ examine_desc = "is pierced clear through, with bits of tissue obscuring the open hole"
+ occur_text = "looses a violent spray of blood, revealing a pierced wound"
+ sound_effect = 'sound/effects/wounds/pierce2.ogg'
+ severity = WOUND_SEVERITY_SEVERE
+ initial_flow = 2.25
+ gauzed_clot_rate = 0.6
+ internal_bleeding_chance = 60
+ internal_bleeding_coefficient = 1.5
+ threshold_minimum = 50
+ threshold_penalty = 25
+ status_effect_type = /datum/status_effect/wound/pierce/severe
+ scar_keyword = "piercesevere"
+
+/datum/wound/pierce/critical
+ name = "Ruptured Cavity"
+ desc = "Patient's internal tissue and circulatory system is shredded, causing significant internal bleeding and damage to internal organs."
+ treat_text = "Surgical repair of puncture wound, followed by supervised resanguination."
+ examine_desc = "is ripped clear through, barely held together by exposed bone"
+ occur_text = "blasts apart, sending chunks of viscera flying in all directions"
+ sound_effect = 'sound/effects/wounds/pierce3.ogg'
+ severity = WOUND_SEVERITY_CRITICAL
+ initial_flow = 3
+ gauzed_clot_rate = 0.4
+ internal_bleeding_chance = 80
+ internal_bleeding_coefficient = 1.75
+ threshold_minimum = 100
+ threshold_penalty = 40
+ status_effect_type = /datum/status_effect/wound/pierce/critical
+ scar_keyword = "piercecritical"
+ wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH)
diff --git a/code/datums/wounds/scars/_scars.dm b/code/datums/wounds/scars/_scars.dm
index bfbaab835e6..3365fc359d9 100644
--- a/code/datums/wounds/scars/_scars.dm
+++ b/code/datums/wounds/scars/_scars.dm
@@ -53,8 +53,12 @@
if(victim)
LAZYADD(victim.all_scars, src)
- description = pick(W.scarring_descriptions)
- precise_location = pick(limb.specific_locations)
+ if(victim && victim.get_biological_state() == BIO_JUST_BONE)
+ description = pick(strings(BONE_SCAR_FILE, W.scar_keyword)) || "general disfigurement"
+ else
+ description = pick(strings(FLESH_SCAR_FILE, W.scar_keyword)) || "general disfigurement"
+
+ precise_location = pick(strings(SCAR_LOC_FILE, limb.body_zone))
switch(W.severity)
if(WOUND_SEVERITY_MODERATE)
visibility = 2
@@ -62,6 +66,9 @@
visibility = 3
if(WOUND_SEVERITY_CRITICAL)
visibility = 5
+ if(WOUND_SEVERITY_LOSS)
+ visibility = 7
+ precise_location = "amputation"
/// Used when we finalize a scar from a healing cut
/datum/scar/proc/lazy_attach(obj/item/bodypart/BP, datum/wound/W)
@@ -71,10 +78,11 @@
LAZYADD(victim.all_scars, src)
/// Used to "load" a persistent scar
-/datum/scar/proc/load(obj/item/bodypart/BP, description, specific_location, severity=WOUND_SEVERITY_SEVERE)
- if(!(BP.body_zone in applicable_zones))
+/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity=WOUND_SEVERITY_SEVERE)
+ if(!(BP.body_zone in applicable_zones) || !BP.is_organic_limb())
qdel(src)
return
+
limb = BP
src.severity = severity
LAZYADD(limb.scars, src)
@@ -90,6 +98,8 @@
visibility = 3
if(WOUND_SEVERITY_CRITICAL)
visibility = 5
+ if(WOUND_SEVERITY_LOSS)
+ visibility = 7
return TRUE
/// What will show up in examine_more() if this scar is visible
@@ -102,9 +112,12 @@
if(WOUND_SEVERITY_MODERATE)
msg = "
[msg]"
if(WOUND_SEVERITY_SEVERE)
- msg = "
[msg]"
+ msg = "
[msg]"
if(WOUND_SEVERITY_CRITICAL)
- msg = "
[msg]"
+ msg = "
[msg]"
+ if(WOUND_SEVERITY_LOSS)
+ msg = "[victim.p_their(TRUE)] [limb.name] [description]." // different format
+ msg = "
[msg]"
return "\t[msg]"
/// Whether a scar can currently be seen by the viewer
@@ -117,12 +130,12 @@
if(!ishuman(victim) || isobserver(viewer) || victim == viewer)
return TRUE
- var/mob/living/carbon/human/H = victim
+ var/mob/living/carbon/human/human_victim = victim
if(istype(limb, /obj/item/bodypart/head))
- if((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) || (H.head && (H.head.flags_inv & HIDEFACE)))
+ if((human_victim.wear_mask && (human_victim.wear_mask.flags_inv & HIDEFACE)) || (human_victim.head && (human_victim.head.flags_inv & HIDEFACE)))
return FALSE
else if(limb.scars_covered_by_clothes)
- var/num_covers = LAZYLEN(H.clothingonpart(limb))
+ var/num_covers = LAZYLEN(human_victim.clothingonpart(limb))
if(num_covers + get_dist(viewer, victim) >= visibility)
return FALSE
@@ -131,4 +144,9 @@
/// Used to format a scar to safe in preferences for persistent scars
/datum/scar/proc/format()
if(!fake)
- return "[limb.body_zone]|[description]|[precise_location]|[severity]"
+ return "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]"
+
+/// Used to format a scar to safe in preferences for persistent scars
+/datum/scar/proc/format_amputated(body_zone)
+ description = pick(list("is several skintone shades paler than the rest of the body", "is a gruesome patchwork of artificial flesh", "has a large series of attachment scars at the articulation points"))
+ return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]"
diff --git a/code/datums/wounds/cuts.dm b/code/datums/wounds/slash.dm
similarity index 60%
rename from code/datums/wounds/cuts.dm
rename to code/datums/wounds/slash.dm
index 5f9d7542386..6b1ded05ed1 100644
--- a/code/datums/wounds/cuts.dm
+++ b/code/datums/wounds/slash.dm
@@ -3,15 +3,15 @@
Cuts
*/
-/datum/wound/brute/cut
+/datum/wound/slash
sound_effect = 'sound/weapons/slice.ogg'
processes = TRUE
- wound_type = WOUND_LIST_CUT
- treatable_by = list(/obj/item/stack/medical/suture, /obj/item/stack/medical/gauze)
+ 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
- treat_priority = TRUE
base_treat_time = 3 SECONDS
+ wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE)
/// How much blood we start losing when this wound is first applied
var/initial_flow
@@ -27,75 +27,82 @@
var/max_per_type
/// The maximum flow we've had so far
var/highest_flow
- /// How much flow we've already cauterized
- var/cauterized
- /// How much flow we've already sutured
- var/sutured
- /// The current bandage we have for this wound (maybe move bandages to the limb?)
- var/obj/item/stack/current_bandage
/// 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/brute/cut/wound_injury(datum/wound/brute/cut/old_wound = null)
+/datum/wound/slash/wound_injury(datum/wound/slash/old_wound = null)
blood_flow = initial_flow
if(old_wound)
blood_flow = max(old_wound.blood_flow, initial_flow)
if(old_wound.severity > severity && old_wound.highest_scar)
highest_scar = old_wound.highest_scar
old_wound.highest_scar = null
- if(old_wound.current_bandage)
- current_bandage = old_wound.current_bandage
- old_wound.current_bandage = null
if(!highest_scar)
highest_scar = new
highest_scar.generate(limb, src, add_to_scars=FALSE)
-/datum/wound/brute/cut/remove_wound(ignore_limb, replaced)
+/datum/wound/slash/remove_wound(ignore_limb, replaced)
if(!replaced && highest_scar)
already_scarred = TRUE
highest_scar.lazy_attach(limb)
return ..()
-/datum/wound/brute/cut/get_examine_description(mob/user)
- if(!current_bandage)
+/datum/wound/slash/get_examine_description(mob/user)
+ if(!limb.current_gauze)
return ..()
- var/bandage_condition = ""
+ var/list/msg = list("The cuts on [victim.p_their()] [limb.name] are wrapped with")
// how much life we have left in these bandages
- switch(current_bandage.absorption_capacity)
+ switch(limb.current_gauze.absorption_capacity)
if(0 to 1.25)
- bandage_condition = "nearly ruined "
+ msg += "nearly ruined "
if(1.25 to 2.75)
- bandage_condition = "badly worn "
+ msg += "badly worn "
if(2.75 to 4)
- bandage_condition = "slightly bloodied "
+ msg += "slightly bloodied "
if(4 to INFINITY)
- bandage_condition = "clean "
- return "
The cuts on [victim.p_their()] [limb.name] are wrapped with [bandage_condition] [current_bandage.name]!"
+ msg += "clean "
+ msg += "[limb.current_gauze.name]!"
-/datum/wound/brute/cut/receive_damage(wounding_type, wounding_dmg, wound_bonus)
- if(victim.stat != DEAD && wounding_type == WOUND_SHARP) // can't stab dead bodies to make it bleed faster this way
+ return "
[msg.Join()]"
+
+/datum/wound/slash/receive_damage(wounding_type, wounding_dmg, wound_bonus)
+ if(victim.stat != DEAD && wounding_type == WOUND_SLASH) // can't stab dead bodies to make it bleed faster this way
blood_flow += 0.05 * wounding_dmg
-/datum/wound/brute/cut/handle_process()
- blood_flow = min(blood_flow, WOUND_CUT_MAX_BLOODFLOW)
+/datum/wound/slash/drag_bleed_amount()
+ // say we have 3 severe cuts with 3 blood flow each, pretty reasonable
+ // compare with being at 100 brute damage before, where you bled (brute/100 * 2), = 2 blood per tile
+ var/bleed_amt = min(blood_flow * 0.1, 1) // 3 * 3 * 0.1 = 0.9 blood total, less than before! the share here is .3 blood of course.
- if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/toxin/heparin))
+ if(limb.current_gauze) // gauze stops all bleeding from dragging on this limb, but wears the gauze out quicker
+ limb.seep_gauze(bleed_amt * 0.33)
+ return
+
+ return bleed_amt
+
+/datum/wound/slash/handle_process()
+ if(victim.stat == DEAD)
+ blood_flow -= max(clot_rate, WOUND_SLASH_DEAD_CLOT_MIN)
+ if(blood_flow < minimum_flow)
+ if(demotes_to)
+ replace_wound(demotes_to)
+ return
+ qdel(src)
+ return
+
+ blood_flow = min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW)
+
+ if(victim.reagents?.has_reagent(/datum/reagent/toxin/heparin))
blood_flow += 0.5 // old herapin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first
- else if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/medicine/coagulant))
- blood_flow -= 0.25
- if(current_bandage)
+ if(limb.current_gauze)
if(clot_rate > 0)
blood_flow -= clot_rate
- blood_flow -= current_bandage.absorption_rate
- current_bandage.absorption_capacity -= current_bandage.absorption_rate
- if(current_bandage.absorption_capacity < 0)
- victim.visible_message("
Blood soaks through \the [current_bandage] on [victim]'s [limb.name].", "
Blood soaks through \the [current_bandage] on your [limb.name].", vision_distance=COMBAT_MESSAGE_RANGE)
- QDEL_NULL(current_bandage)
- treat_priority = TRUE
+ blood_flow -= limb.current_gauze.absorption_rate
+ limb.seep_gauze(limb.current_gauze.absorption_rate)
else
blood_flow -= clot_rate
@@ -109,23 +116,30 @@
to_chat(victim, "
The cut on your [limb.name] has stopped bleeding!")
qdel(src)
+
+/datum/wound/slash/on_stasis()
+ if(blood_flow >= minimum_flow)
+ return
+ if(demotes_to)
+ replace_wound(demotes_to)
+ return
+ qdel(src)
+
/* BEWARE, THE BELOW NONSENSE IS MADNESS. bones.dm looks more like what I have in mind and is sufficiently clean, don't pay attention to this messiness */
-/datum/wound/brute/cut/check_grab_treatments(obj/item/I, mob/user)
+/datum/wound/slash/check_grab_treatments(obj/item/I, mob/user)
if(istype(I, /obj/item/gun/energy/laser))
return TRUE
-/datum/wound/brute/cut/treat(obj/item/I, mob/user)
+/datum/wound/slash/treat(obj/item/I, mob/user)
if(istype(I, /obj/item/gun/energy/laser))
las_cauterize(I, user)
else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature() > 300)
tool_cauterize(I, user)
- else if(istype(I, /obj/item/stack/medical/gauze))
- bandage(I, user)
else if(istype(I, /obj/item/stack/medical/suture))
suture(I, user)
-/datum/wound/brute/cut/try_handling(mob/living/carbon/human/user)
+/datum/wound/slash/try_handling(mob/living/carbon/human/user)
if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB)
return FALSE
@@ -136,7 +150,7 @@
return TRUE
/// if a felinid is licking this cut to reduce bleeding
-/datum/wound/brute/cut/proc/lick_wounds(mob/living/carbon/human/user)
+/datum/wound/slash/proc/lick_wounds(mob/living/carbon/human/user)
if(INTERACTING_WITH(user, victim))
to_chat(user, "
You're already interacting with [victim]!")
return
@@ -155,12 +169,16 @@
else if(demotes_to)
to_chat(user, "
You successfully lower the severity of [victim]'s cuts.")
-/datum/wound/brute/cut/on_xadone(power)
+/datum/wound/slash/on_xadone(power)
. = ..()
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)
+ . = ..()
+ 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/brute/cut/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user)
+/datum/wound/slash/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user)
var/self_penalty_mult = (user == victim ? 1.25 : 1)
user.visible_message("
[user] begins aiming [lasgun] directly at [victim]'s [limb.name]...", "
You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [limb.name]...")
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
@@ -172,11 +190,10 @@
return
victim.emote("scream")
blood_flow -= damage / (5 * self_penalty_mult) // 20 / 5 = 4 bloodflow removed, p good
- cauterized += damage / (5 * self_penalty_mult)
victim.visible_message("
The cuts on [victim]'s [limb.name] scar over!")
/// If someone is using either a cautery tool or something with heat to cauterize this cut
-/datum/wound/brute/cut/proc/tool_cauterize(obj/item/I, mob/user)
+/datum/wound/slash/proc/tool_cauterize(obj/item/I, mob/user)
var/self_penalty_mult = (user == victim ? 1.5 : 1)
user.visible_message("
[user] begins cauterizing [victim]'s [limb.name] with [I]...", "
You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
@@ -188,7 +205,6 @@
victim.emote("scream")
var/blood_cauterized = (0.6 / self_penalty_mult)
blood_flow -= blood_cauterized
- cauterized += blood_cauterized
if(blood_flow > minimum_flow)
try_treating(I, user)
@@ -196,15 +212,15 @@
to_chat(user, "
You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.")
/// If someone is using a suture to close this cut
-/datum/wound/brute/cut/proc/suture(obj/item/stack/medical/suture/I, mob/user)
+/datum/wound/slash/proc/suture(obj/item/stack/medical/suture/I, mob/user)
var/self_penalty_mult = (user == victim ? 1.4 : 1)
user.visible_message("
[user] begins stitching [victim]'s [limb.name] with [I]...", "
You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
+
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
user.visible_message("
[user] stitches up some of the bleeding on [victim].", "
You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].")
var/blood_sutured = I.stop_bleeding / self_penalty_mult
blood_flow -= blood_sutured
- sutured += blood_sutured
limb.heal_damage(I.heal_brute, I.heal_burn)
if(blood_flow > minimum_flow)
@@ -212,51 +228,31 @@
else if(demotes_to)
to_chat(user, "
You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.")
-/// If someone is using gauze on this cut
-/datum/wound/brute/cut/proc/bandage(obj/item/stack/I, mob/user)
- if(current_bandage)
- if(current_bandage.absorption_capacity > I.absorption_capacity + 1)
- to_chat(user, "
The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!")
- return
- else
- user.visible_message("
[user] begins rewrapping the cuts on [victim]'s [limb.name] with [I]...", "
You begin rewrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
- else
- user.visible_message("
[user] begins wrapping the cuts on [victim]'s [limb.name] with [I]...", "
You begin wrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...")
- if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
- return
- user.visible_message("
[user] applies [I] to [victim]'s [limb.name].", "
You bandage some of the bleeding on [user == victim ? "yourself" : "[victim]"].")
- QDEL_NULL(current_bandage)
- current_bandage = new I.type(limb)
- current_bandage.amount = 1
- treat_priority = FALSE
- I.use(1)
-
-
-/datum/wound/brute/cut/moderate
+/datum/wound/slash/moderate
name = "Rough Abrasion"
desc = "Patient's skin has been badly scraped, generating moderate blood loss."
treat_text = "Application of clean bandages or first-aid grade sutures, followed by food and rest."
examine_desc = "has an open cut"
occur_text = "is cut open, slowly leaking blood"
- sound_effect = 'sound/effects/blood1.ogg'
+ sound_effect = 'sound/effects/wounds/blood1.ogg'
severity = WOUND_SEVERITY_MODERATE
initial_flow = 2
minimum_flow = 0.5
max_per_type = 3
- clot_rate = 0.15
+ clot_rate = 0.12
threshold_minimum = 20
threshold_penalty = 10
- status_effect_type = /datum/status_effect/wound/cut/moderate
- scarring_descriptions = list("light, faded lines", "minor cut marks", "a small faded slit", "a series of small scars")
+ status_effect_type = /datum/status_effect/wound/slash/moderate
+ scar_keyword = "slashmoderate"
-/datum/wound/brute/cut/severe
+/datum/wound/slash/severe
name = "Open Laceration"
desc = "Patient's skin is ripped clean open, allowing significant blood loss."
treat_text = "Speedy application of first-aid grade sutures and clean bandages, followed by vitals monitoring to ensure recovery."
examine_desc = "has a severe cut"
occur_text = "is ripped open, veins spurting blood"
- sound_effect = 'sound/effects/blood2.ogg'
+ sound_effect = 'sound/effects/wounds/blood2.ogg'
severity = WOUND_SEVERITY_SEVERE
initial_flow = 3.25
minimum_flow = 2.75
@@ -264,17 +260,17 @@
max_per_type = 4
threshold_minimum = 50
threshold_penalty = 25
- demotes_to = /datum/wound/brute/cut/moderate
- status_effect_type = /datum/status_effect/wound/cut/severe
- scarring_descriptions = list("a twisted line of faded gashes", "a gnarled sickle-shaped slice scar", "a long-faded puncture wound")
+ demotes_to = /datum/wound/slash/moderate
+ status_effect_type = /datum/status_effect/wound/slash/severe
+ scar_keyword = "slashsevere"
-/datum/wound/brute/cut/critical
+/datum/wound/slash/critical
name = "Weeping Avulsion"
desc = "Patient's skin is completely torn open, along with significant loss of tissue. Extreme blood loss will lead to quick death without intervention."
treat_text = "Immediate bandaging and either suturing or cauterization, followed by supervised resanguination."
- examine_desc = "is spurting blood at an alarming rate"
+ examine_desc = "is carved down to the bone, spraying blood wildly"
occur_text = "is torn open, spraying blood wildly"
- sound_effect = 'sound/effects/blood3.ogg'
+ sound_effect = 'sound/effects/wounds/blood3.ogg'
severity = WOUND_SEVERITY_CRITICAL
initial_flow = 4.25
minimum_flow = 4
@@ -282,25 +278,7 @@
max_per_type = 5
threshold_minimum = 80
threshold_penalty = 40
- demotes_to = /datum/wound/brute/cut/severe
- status_effect_type = /datum/status_effect/wound/cut/critical
- scarring_descriptions = list("a winding path of very badly healed scar tissue", "a series of peaks and valleys along a gruesome line of cut scar tissue", "a grotesque snake of indentations and stitching scars")
-
-// TODO: see about moving dismemberment over to this, i'll have to add judging dismembering power/wound potential wrt item size i guess
-/datum/wound/brute/cut/loss
- name = "Dismembered"
- desc = "oof ouch!!"
- occur_text = "is violently dismembered!"
- sound_effect = 'sound/effects/dismember.ogg'
- viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
- severity = WOUND_SEVERITY_LOSS
- threshold_minimum = 180
- status_effect_type = null
-
-/datum/wound/brute/cut/loss/apply_wound(obj/item/bodypart/L, silent, datum/wound/brute/cut/old_wound, smited = FALSE)
- if(!L.dismemberable)
- qdel(src)
- return
-
- L.dismember()
- qdel(src)
+ demotes_to = /datum/wound/slash/severe
+ status_effect_type = /datum/status_effect/wound/slash/critical
+ scar_keyword = "slashcritical"
+ wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH)
diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm
index 8a821edffb8..ae55a648b30 100644
--- a/code/game/gamemodes/clown_ops/clown_weapons.dm
+++ b/code/game/gamemodes/clown_ops/clown_weapons.dm
@@ -64,7 +64,7 @@
hitsound = null
attack_verb_on = list("slipped")
clumsy_check = FALSE
- sharpness = IS_BLUNT
+ sharpness = SHARP_NONE
sword_color = "yellow"
heat = 0
light_color = "#ffff00"
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index c3a7e06586b..505aec3eac2 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -351,7 +351,8 @@
L.visible_message("
[src] closes on [L], crushing [L.p_them()]!", "
[src] closes on you and crushes you!")
if(iscarbon(L))
var/mob/living/carbon/C = L
- for(var/datum/wound/W in C.all_wounds)
+ for(var/i in C.all_wounds) // should probably replace with signal
+ var/datum/wound/W = i
W.crush(DOOR_CRUSH_DAMAGE)
if(isalien(L)) //For xenos
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 996ab78ea54..808f08d281d 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -139,13 +139,13 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
///Does it embed and if yes, what kind of embed
- var/list/embedding = NONE
+ var/list/embedding
///for flags such as [GLASSESCOVERSEYES]
var/flags_cover = 0
var/heat = 0
- ///All items with sharpness of IS_SHARP or higher will automatically get the butchering component.
- var/sharpness = IS_BLUNT
+ ///All items with sharpness of SHARP_EDGED or higher will automatically get the butchering component.
+ var/sharpness = SHARP_NONE
///How a tool acts when you use it on something, such as wirecutters cutting wires while multitools measure power
var/tool_behaviour = NONE
@@ -241,7 +241,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
if(GLOB.rpg_loot_items)
AddComponent(/datum/component/fantasy)
- if(sharpness) //give sharp objects butchering functionality, for consistency
+ if(sharpness && force > 5) //give sharp objects butchering functionality, for consistency
AddComponent(/datum/component/butchering, 80 * toolspeed)
/**Makes cool stuff happen when you suicide with an item
@@ -720,11 +720,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
/obj/item/proc/get_sharpness()
return sharpness
-/obj/item/proc/get_dismemberment_chance(obj/item/bodypart/affecting)
- if(affecting.can_dismember(src))
- if((sharpness || damtype == BURN) && w_class >= WEIGHT_CLASS_NORMAL && force >= 10)
- . = force * (affecting.get_damage() / affecting.max_damage)
-
/obj/item/proc/get_dismember_sound()
if(damtype == BURN)
. = 'sound/weapons/sear.ogg'
@@ -995,7 +990,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
///For when you want to add/update the embedding on an item. Uses the vars in [/obj/item/embedding], and defaults to config values for values that aren't set. Will automatically detach previous embed elements on this item.
/obj/item/proc/updateEmbedding()
- if(!islist(embedding) || !LAZYLEN(embedding))
+ if(!LAZYLEN(embedding))
return
AddElement(/datum/element/embed,\
diff --git a/code/game/objects/items/chainsaw.dm b/code/game/objects/items/chainsaw.dm
index 6c597000545..42986bef5fb 100644
--- a/code/game/objects/items/chainsaw.dm
+++ b/code/game/objects/items/chainsaw.dm
@@ -16,7 +16,7 @@
custom_materials = list(/datum/material/iron=13000)
attack_verb = list("sawed", "tore", "lacerated", "cut", "chopped", "diced")
hitsound = "swing_hit"
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
actions_types = list(/datum/action/item_action/startchainsaw)
tool_behaviour = TOOL_SAW
toolspeed = 0.5
@@ -73,10 +73,6 @@
var/datum/action/A = X
A.UpdateButtonIcon()
-/obj/item/chainsaw/get_dismemberment_chance()
- if(wielded)
- . = ..()
-
/obj/item/chainsaw/doomslayer
name = "THE GREAT COMMUNICATOR"
desc = "
VRRRRRRR!!!"
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 69bc7154e3b..797168179e3 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -186,8 +186,20 @@ GENE SCANNER
render_list += "
Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.\n"
if(advanced)
render_list += "
Cellular Damage Level: [M.getCloneLoss()].\n"
- if (!M.getorgan(/obj/item/organ/brain))
+ if (!M.getorganslot(ORGAN_SLOT_BRAIN)) // brain not added to carbon/human check because it's funny to get to bully simple mobs
render_list += "
Subject lacks a brain.\n"
+ if(ishuman(M))
+ var/mob/living/carbon/human/the_dude = M
+ var/datum/species/the_dudes_species = the_dude.dna.species
+ if (!(NOBLOOD in the_dudes_species.species_traits) && !the_dude.getorganslot(ORGAN_SLOT_HEART))
+ render_list += "
Subject lacks a heart.\n"
+ if (!(TRAIT_NOBREATH in the_dudes_species.species_traits) && !the_dude.getorganslot(ORGAN_SLOT_LUNGS))
+ render_list += "
Subject lacks lungs.\n"
+ if (!(TRAIT_NOMETABOLISM in the_dudes_species.species_traits) && !the_dude.getorganslot(ORGAN_SLOT_LIVER))
+ render_list += "
Subject lacks a liver.\n"
+ if (!(NOSTOMACH in the_dudes_species.species_traits) && !the_dude.getorganslot(ORGAN_SLOT_STOMACH))
+ render_list += "
Subject lacks a stomach.\n"
+
if(iscarbon(M))
var/mob/living/carbon/C = M
if(LAZYLEN(C.get_traumas()))
diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm
index b8689c2faca..5e5b2f31af3 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -43,7 +43,7 @@
to_chat(user, "
You lack the grace to wield this!")
return COMPONENT_TWOHANDED_BLOCK_WIELD
wielded = TRUE
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
w_class = w_class_on
hitsound = 'sound/weapons/blade1.ogg'
START_PROCESSING(SSobj, src)
diff --git a/code/game/objects/items/fireaxe.dm b/code/game/objects/items/fireaxe.dm
index 792568bc9ec..ba47631e118 100644
--- a/code/game/objects/items/fireaxe.dm
+++ b/code/game/objects/items/fireaxe.dm
@@ -13,11 +13,12 @@
slot_flags = ITEM_SLOT_BACK
attack_verb = list("attacked", "chopped", "cleaved", "tore", "lacerated", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
- wound_bonus = -20
+ wound_bonus = -15
+ bare_wound_bonus = 20
var/wielded = FALSE // track wielded status on item
/obj/item/fireaxe/Initialize()
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 19857ce675d..7485239e71f 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -316,7 +316,7 @@
w_class = WEIGHT_CLASS_HUGE
slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_BELT
block_chance = 30
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
@@ -418,7 +418,7 @@
w_class = WEIGHT_CLASS_BULKY
armour_penetration = 35
slot_flags = ITEM_SLOT_BACK
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
attack_verb = list("chopped", "sliced", "cut", "reaped")
/obj/item/nullrod/scythe/Initialize()
@@ -526,7 +526,7 @@
righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi'
w_class = WEIGHT_CLASS_HUGE
item_flags = ABSTRACT
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
attack_verb = list("sawed", "tore", "lacerated", "cut", "chopped", "diced")
hitsound = 'sound/weapons/chainsawhit.ogg'
tool_behaviour = TOOL_SAW
@@ -544,7 +544,7 @@
name = "clown dagger"
desc = "Used for absolutely hilarious sacrifices."
hitsound = 'sound/items/bikehorn.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
/obj/item/nullrod/pride_hammer
@@ -590,7 +590,7 @@
throw_speed = 4
throw_range = 7
throwforce = 30
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
attack_verb = list("enlightened", "redpilled")
/obj/item/nullrod/armblade
@@ -603,7 +603,7 @@
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
item_flags = ABSTRACT
w_class = WEIGHT_CLASS_HUGE
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
wound_bonus = -20
bare_wound_bonus = 25
@@ -644,7 +644,7 @@
force = 15
block_chance = 40
slot_flags = ITEM_SLOT_BACK
- sharpness = IS_BLUNT
+ sharpness = SHARP_NONE
hitsound = "swing_hit"
attack_verb = list("smashed", "slammed", "whacked", "thwacked")
icon = 'icons/obj/items_and_weapons.dmi'
@@ -662,7 +662,7 @@
name = "arrhythmic knife"
w_class = WEIGHT_CLASS_HUGE
desc = "They say fear is the true mind killer, but stabbing them in the head works too. Honour compels you to not sheathe it once drawn."
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
slot_flags = null
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
@@ -693,7 +693,7 @@
desc = "Holding this makes you look absolutely devilish."
attack_verb = list("poked", "impaled", "pierced", "jabbed")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/nullrod/egyptian
name = "egyptian staff"
@@ -730,7 +730,7 @@
icon = 'icons/obj/clockwork_objects.dmi'
slot_flags = ITEM_SLOT_BELT
armour_penetration = 10
- sharpness = IS_SHARP_ACCURATE
+ sharpness = SHARP_POINTY
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("stabbed", "poked", "slashed", "clocked")
hitsound = 'sound/weapons/bladeslice.ogg'
diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm
index 1d849b6c887..598576a208f 100644
--- a/code/game/objects/items/kitchen.dm
+++ b/code/game/objects/items/kitchen.dm
@@ -19,7 +19,7 @@
name = "fork"
desc = "Pointy."
icon_state = "fork"
- force = 5
+ force = 4
w_class = WEIGHT_CLASS_TINY
throwforce = 0
throw_speed = 3
@@ -30,6 +30,7 @@
hitsound = 'sound/weapons/bladeslice.ogg'
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
item_flags = EYE_STAB
+ sharpness = SHARP_POINTY
var/datum/reagent/forkload //used to eat omelette
/obj/item/kitchen/fork/suicide_act(mob/living/carbon/user)
@@ -84,7 +85,7 @@
throw_range = 6
custom_materials = list(/datum/material/iron=12000)
attack_verb = list("slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
- sharpness = IS_SHARP_ACCURATE
+ sharpness = SHARP_EDGED
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
item_flags = EYE_STAB
var/bayonet = FALSE //Can this be attached to a gun?
@@ -117,7 +118,7 @@
throw_range = 5
custom_materials = list(/datum/material/plastic = 100)
attack_verb = list("prodded", "whiffed","scratched", "poked")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
custom_price = 50
var/break_chance = 25
diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm
index 4951712547d..91c9677ff29 100644
--- a/code/game/objects/items/latexballoon.dm
+++ b/code/game/objects/items/latexballoon.dm
@@ -54,5 +54,5 @@
var/obj/item/tank/T = W
blow(T, user)
return
- if (W.get_sharpness() || W.get_temperature() || is_pointed(W))
+ if (W.get_sharpness() || W.get_temperature())
burst()
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index a25a7d607b1..bbdccc18ba1 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -98,7 +98,7 @@
attack_verb_off = list("tapped", "poked")
throw_speed = 3
throw_range = 5
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
embedding = list("embed_chance" = 75, "impact_pain_mult" = 10)
armour_penetration = 35
block_chance = 50
@@ -138,7 +138,7 @@
sword_color = null //stops icon from breaking when turned on.
hitcost = 75 //Costs more than a standard cyborg esword
w_class = WEIGHT_CLASS_NORMAL
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
light_color = "#40ceff"
tool_behaviour = TOOL_SAW
toolspeed = 0.7 //faster as a saw
@@ -219,7 +219,7 @@
throw_range = 1
w_class = WEIGHT_CLASS_BULKY//So you can't hide it in your pocket or some such.
var/datum/effect_system/spark_spread/spark_system
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
//Most of the other special functions are handled in their own files. aka special snowflake code so kewl
/obj/item/melee/transforming/energy/blade/Initialize()
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index d3dc42f8935..0e7486c705f 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -44,7 +44,7 @@
throwforce = 10
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/melee/synthetic_arm_blade/Initialize()
. = ..()
@@ -64,10 +64,12 @@
w_class = WEIGHT_CLASS_BULKY
block_chance = 50
armour_penetration = 75
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
attack_verb = list("slashed", "cut")
hitsound = 'sound/weapons/rapierhit.ogg'
custom_materials = list(/datum/material/iron = 1000)
+ wound_bonus = 10
+ bare_wound_bonus = 25
/obj/item/melee/sabre/Initialize()
. = ..()
@@ -143,7 +145,7 @@
slot_flags = ITEM_SLOT_BELT
force = 5
w_class = WEIGHT_CLASS_BULKY
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
throwforce = 10
block_chance = 20
armour_penetration = 65
diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm
index bfed019f671..c6fe6c4eda4 100644
--- a/code/game/objects/items/melee/transforming.dm
+++ b/code/game/objects/items/melee/transforming.dm
@@ -1,5 +1,5 @@
/obj/item/melee/transforming
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
var/active = FALSE
var/force_on = 30 //force when active
var/faction_bonus_force = 0 //Bonus force dealt against certain factions
diff --git a/code/game/objects/items/pitchfork.dm b/code/game/objects/items/pitchfork.dm
index d006fa7cab2..2a56df47fe4 100644
--- a/code/game/objects/items/pitchfork.dm
+++ b/code/game/objects/items/pitchfork.dm
@@ -9,7 +9,7 @@
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("attacked", "impaled", "pierced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
diff --git a/code/game/objects/items/sharpener.dm b/code/game/objects/items/sharpener.dm
index 62bc2a0b4b7..01593f81589 100644
--- a/code/game/objects/items/sharpener.dm
+++ b/code/game/objects/items/sharpener.dm
@@ -39,7 +39,7 @@
I.force = clamp(I.force + increment, 0, max)
user.visible_message("
[user] sharpens [I] with [src]!", "
You sharpen [I], making it much more deadly than before.")
playsound(src, 'sound/items/unsheath.ogg', 25, TRUE)
- I.sharpness = IS_SHARP_ACCURATE
+ I.sharpness = SHARP_POINTY
I.throwforce = clamp(I.throwforce + increment, 0, max)
I.name = "[prefix] [I.name]"
name = "worn out [name]"
diff --git a/code/game/objects/items/shrapnel.dm b/code/game/objects/items/shrapnel.dm
index 91df52a6ea5..2b1adaab6dd 100644
--- a/code/game/objects/items/shrapnel.dm
+++ b/code/game/objects/items/shrapnel.dm
@@ -7,47 +7,41 @@
icon_state = "large"
w_class = WEIGHT_CLASS_TINY
item_flags = DROPDEL
- sharpness = TRUE
+ sharpness = SHARP_EDGED
/obj/item/shrapnel/stingball // stingbang grenades
name = "stingball"
embedding = list(embed_chance=90, fall_chance=3, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=5, jostle_pain_mult=6, rip_time=15)
icon_state = "tiny"
- sharpness = FALSE
+ sharpness = SHARP_NONE
/obj/item/shrapnel/bullet // bullets
name = "bullet"
icon = 'icons/obj/ammo.dmi'
icon_state = "s-casing"
- item_flags = NONE
-
-/obj/item/shrapnel/bullet/c38 // .38 round
- name = "\improper .38 bullet"
-
-/obj/item/shrapnel/bullet/c38/dumdum // .38 DumDum round
- name = "\improper .38 DumDum bullet"
- embedding = list(embed_chance=70, fall_chance=7, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
+ embedding = null // embedding vars are taken from the projectile itself
/obj/projectile/bullet/shrapnel
name = "flying shrapnel shard"
- damage = 8
- range = 10
+ damage = 14
+ range = 20
armour_penetration = -30
dismemberment = 5
ricochets_max = 2
- ricochet_chance = 40
+ ricochet_chance = 70
shrapnel_type = /obj/item/shrapnel
ricochet_incidence_leeway = 60
hit_stunned_targets = TRUE
- sharpness = TRUE
- wound_bonus = 30
+ sharpness = SHARP_EDGED
+ wound_bonus = 40
/obj/projectile/bullet/shrapnel/mega
name = "flying shrapnel hunk"
- range = 25
- dismemberment = 10
- ricochets_max = 4
- ricochet_chance = 90
+ range = 45
+ dismemberment = 15
+ ricochets_max = 6
+ ricochet_chance = 130
+ ricochet_incidence_leeway = 0
ricochet_decay_chance = 0.9
/obj/projectile/bullet/pellet/stingball
@@ -72,13 +66,13 @@
name = "breakbang pellet"
damage = 10
wound_bonus = 40
- sharpness = FALSE
+ sharpness = SHARP_NONE
/obj/projectile/bullet/pellet/stingball/shred
name = "shredbang pellet"
damage = 10
wound_bonus = 30
- sharpness = TRUE
+ sharpness = SHARP_EDGED
/obj/projectile/bullet/pellet/stingball/on_ricochet(atom/A)
hit_stunned_targets = TRUE // ducking will save you from the first wave, but not the rebounds
diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm
index 0c54185ae40..cf1ed2fa6dc 100644
--- a/code/game/objects/items/spear.dm
+++ b/code/game/objects/items/spear.dm
@@ -15,12 +15,12 @@
custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075)
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "poked", "jabbed", "tore", "lacerated", "gored")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED // i know the whole point of spears is that they're pointy, but edged is more devastating at the moment so
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
var/war_cry = "AAAAARGH!!!"
var/icon_prefix = "spearglass"
- wound_bonus = -25
+ wound_bonus = -15
bare_wound_bonus = 15
/obj/item/spear/ComponentInitialize()
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index dadb5ada594..ebfd5b8b3a7 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -124,11 +124,34 @@
// gauze is only relevant for wounds, which are handled in the wounds themselves
/obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent)
var/obj/item/bodypart/limb = M.get_bodypart(check_zone(user.zone_selected))
- if(limb)
- if(limb.brute_dam > 40)
- to_chat(user, "
The bleeding on [user==M ? "your" : "[M]'s"] [limb.name] is from bruising, and cannot be treated with [src]!")
- else
- to_chat(user, "
There's no bleeding on [user==M ? "your" : "[M]'s"] [limb.name]")
+ if(!limb)
+ to_chat(user, "
There's nothing there to bandage!")
+ return
+ if(!LAZYLEN(limb.wounds))
+ to_chat(user, "
There's no wounds that require bandaging on [user==M ? "your" : "[M]'s"] [limb.name]!") // good problem to have imo
+ return
+
+ var/gauzeable_wound = FALSE
+ for(var/i in limb.wounds)
+ var/datum/wound/woundies = i
+ if(woundies.wound_flags & ACCEPTS_GAUZE)
+ gauzeable_wound = TRUE
+ break
+ if(!gauzeable_wound)
+ to_chat(user, "
There's no wounds that require bandaging on [user==M ? "your" : "[M]'s"] [limb.name]!") // good problem to have imo
+ return
+
+ if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 0.8 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row
+ to_chat(user, "
The bandage currently on [user==M ? "your" : "[M]'s"] [limb.name] is still in good condition!")
+ return
+
+ user.visible_message("
[user] begins wrapping the wounds on [M]'s [limb.name] with [src]...", "
You begin wrapping the wounds on [user == M ? "your" : "[M]'s"] [limb.name] with [src]...")
+
+ if(!do_after(user, (user == M ? self_delay : other_delay), target=M))
+ return
+
+ user.visible_message("
[user] applies [src] to [M]'s [limb.name].", "
You bandage the wounds on [user == M ? "yourself" : "[M]'s"] [limb.name].")
+ limb.apply_gauze(src)
/obj/item/stack/medical/gauze/twelve
amount = 12
@@ -399,9 +422,9 @@
C.emote("scream")
for(var/i in C.bodyparts)
var/obj/item/bodypart/bone = i
- var/datum/wound/brute/bone/severe/oof_ouch = new
+ var/datum/wound/blunt/severe/oof_ouch = new
oof_ouch.apply_wound(bone)
- var/datum/wound/brute/bone/critical/oof_OUCH = new
+ var/datum/wound/blunt/critical/oof_OUCH = new
oof_OUCH.apply_wound(bone)
for(var/i in C.bodyparts)
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index facca0f589a..16419573993 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -250,7 +250,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
resistance_flags = ACID_PROOF
armor = list("melee" = 100, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 100)
max_integrity = 40
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
var/icon_prefix
var/obj/item/stack/sheet/weld_material = /obj/item/stack/sheet/glass
embedding = list("embed_chance" = 65)
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index a5f39ce3522..5cbbb748f42 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -195,7 +195,7 @@
new /obj/item/reagent_containers/syringe(src)
new /obj/item/stack/medical/bone_gel(src)
new /obj/item/stack/sticky_tape/surgical(src)
- new /obj/item/reagent_containers/glass/bottle/calomel(src)
+ new /obj/item/reagent_containers/glass/bottle/formaldehyde(src)
update_icon()
/obj/item/storage/belt/security
diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm
index 59108d05c6e..b306cd229aa 100644
--- a/code/game/objects/items/tools/screwdriver.dm
+++ b/code/game/objects/items/tools/screwdriver.dm
@@ -24,6 +24,7 @@
drop_sound = 'sound/items/handling/screwdriver_drop.ogg'
pickup_sound = 'sound/items/handling/screwdriver_pickup.ogg'
item_flags = EYE_STAB
+ sharpness = SHARP_POINTY
var/random_color = TRUE //if the screwdriver uses random coloring
var/static/list/screwdriver_colors = list(
"blue" = rgb(24, 97, 213),
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 2c7d2664c94..623c1caacc9 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -35,6 +35,8 @@
heat = 3800
tool_behaviour = TOOL_WELDER
toolspeed = 1
+ wound_bonus = 10
+ bare_wound_bonus = 15
/obj/item/weldingtool/Initialize()
. = ..()
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index cfb86786baf..ada02101cfa 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -65,7 +65,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
block_chance = 50
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
@@ -219,7 +219,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
block_chance = 50
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
@@ -290,13 +290,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
force = 2
- throwforce = 20 //20 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 28 damage on hit due to guaranteed embedding
+ throwforce = 10 //10 + 2 (WEIGHT_CLASS_SMALL) * 9 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 28 damage on hit due to guaranteed embedding
throw_speed = 4
embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0)
armour_penetration = 40
w_class = WEIGHT_CLASS_SMALL
- sharpness = IS_SHARP
+ sharpness = SHARP_POINTY
custom_materials = list(/datum/material/iron=500, /datum/material/glass=500)
resistance_flags = FIRE_PROOF
@@ -309,7 +309,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/throwing_star/toy
name = "toy throwing star"
desc = "An aerodynamic disc strapped with adhesive for sticking to people, good for playing pranks and getting yourself killed by security."
- sharpness = IS_BLUNT
+ sharpness = SHARP_NONE
force = 0
throwforce = 0
embedding = list("pain_mult" = 0, "jostle_pain_mult" = 0, "embed_chance" = 100, "fall_chance" = 0)
@@ -353,7 +353,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = "switchblade_ext"
attack_verb = list("slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
else
force = 3
w_class = WEIGHT_CLASS_SMALL
@@ -361,7 +361,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
icon_state = "switchblade"
attack_verb = list("stubbed", "poked")
hitsound = 'sound/weapons/genhit.ogg'
- sharpness = IS_BLUNT
+ sharpness = SHARP_NONE
/obj/item/switchblade/suicide_act(mob/user)
user.visible_message("
[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -466,7 +466,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
throwforce = 0
throw_range = 0
throw_speed = 0
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
attack_verb = list("sawed", "tore", "lacerated", "cut", "chopped", "diced")
hitsound = 'sound/weapons/chainsawhit.ogg'
tool_behaviour = TOOL_SAW
@@ -855,7 +855,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
force = 20
throwforce = 20
throw_speed = 4
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
attack_verb = list("cut", "sliced", "diced")
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index ef628ba299d..05953a5b959 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1069,6 +1069,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
ADMIN_PUNISHMENT_NUGGET,
ADMIN_PUNISHMENT_CRACK,
ADMIN_PUNISHMENT_BLEED,
+ ADMIN_PUNISHMENT_PERFORATE,
ADMIN_PUNISHMENT_SCARIFY,
ADMIN_PUNISHMENT_SHOES
)
@@ -1159,41 +1160,112 @@ Traitors and the like can also be revived with the previous role mostly intact.
to_chat(usr,"
This must be used on a carbon mob.", confidential = TRUE)
return
var/mob/living/carbon/C = target
- for(var/obj/item/bodypart/squish_part in C.bodyparts)
- var/type_wound = pick(list(/datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/moderate))
+ for(var/i in C.bodyparts)
+ var/obj/item/bodypart/squish_part = i
+ var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
squish_part.force_wound_upwards(type_wound, smited=TRUE)
if(ADMIN_PUNISHMENT_BLEED)
if(!iscarbon(target))
to_chat(usr,"
This must be used on a carbon mob.", confidential = TRUE)
return
var/mob/living/carbon/C = target
- for(var/obj/item/bodypart/slice_part in C.bodyparts)
- var/type_wound = pick(list(/datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate))
+ for(var/i in C.bodyparts)
+ var/obj/item/bodypart/slice_part = i
+ var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate))
slice_part.force_wound_upwards(type_wound, smited=TRUE)
- type_wound = pick(list(/datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate))
+ type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate))
slice_part.force_wound_upwards(type_wound, smited=TRUE)
- type_wound = pick(list(/datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe))
+ type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe))
slice_part.force_wound_upwards(type_wound, smited=TRUE)
+ if(ADMIN_PUNISHMENT_PERFORATE)
+ if(!iscarbon(target))
+ to_chat(usr,"
This must be used on a carbon mob.", confidential = TRUE)
+ return
+
+ var/list/how_fucked_is_this_dude = list("A little", "A lot", "So fucking much", "FUCK THIS DUDE")
+ var/hatred = input("How much do you hate this guy?") in how_fucked_is_this_dude
+ var/repetitions
+ var/shots_per_limb_per_rep = 2
+ var/damage
+ switch(hatred)
+ if("A little")
+ repetitions = 1
+ damage = 5
+ if("A lot")
+ repetitions = 2
+ damage = 8
+ if("So fucking much")
+ repetitions = 3
+ damage = 10
+ if("FUCK THIS DUDE")
+ repetitions = 4
+ damage = 10
+
+ var/mob/living/carbon/dude = target
+ var/list/open_adj_turfs = get_adjacent_open_turfs(dude)
+ var/list/wound_bonuses = list(15, 70, 110, 250)
+
+ var/delay_per_shot = 1
+ var/delay_counter = 1
+
+ dude.Immobilize(5 SECONDS)
+ for(var/wound_bonus_rep in 1 to repetitions)
+ for(var/i in dude.bodyparts)
+ var/obj/item/bodypart/slice_part = i
+ var/shots_this_limb = 0
+ for(var/t in shuffle(open_adj_turfs))
+ var/turf/iter_turf = t
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/firing_squad, dude, iter_turf, slice_part.body_zone, wound_bonuses[wound_bonus_rep], damage), delay_counter)
+ delay_counter += delay_per_shot
+ shots_this_limb++
+ if(shots_this_limb > shots_per_limb_per_rep)
+ break
+
if(ADMIN_PUNISHMENT_SCARIFY)
if(!iscarbon(target))
to_chat(usr,"
This must be used on a carbon mob.", confidential = TRUE)
return
- var/mob/living/carbon/C = target
- C.generate_fake_scars(rand(1, 4))
- to_chat(C, "
You feel your body grow jaded and torn...")
+ var/mob/living/carbon/dude = target
+ dude.generate_fake_scars(rand(1, 4))
+ to_chat(dude, "
You feel your body grow jaded and torn...")
if(ADMIN_PUNISHMENT_SHOES)
if(!iscarbon(target))
to_chat(usr,"
This must be used on a carbon mob.", confidential = TRUE)
return
- var/mob/living/carbon/C = target
- var/obj/item/clothing/shoes/sick_kicks = C.shoes
+ var/mob/living/carbon/dude = target
+ var/obj/item/clothing/shoes/sick_kicks = dude.shoes
if(!sick_kicks?.can_be_tied)
- to_chat(usr,"
[C] does not have knottable shoes!", confidential = TRUE)
+ to_chat(usr,"
[dude] does not have knottable shoes!", confidential = TRUE)
return
sick_kicks.adjust_laces(SHOES_KNOTTED)
punish_log(target, punishment)
+/**
+ * firing_squad is a proc for the :B:erforate smite to shoot each individual bullet at them, so that we can add actual delays without sleep() nonsense
+ *
+ * Hilariously, if you drag someone away mid smite, the bullets will still chase after them from the original spot, possibly hitting other people. Too funny to fix imo
+ *
+ * Arguments:
+ * * target- guy we're shooting obviously
+ * * source_turf- where the bullet begins, preferably on a turf next to the target
+ * * body_zone- which bodypart we're aiming for, if there is one there
+ * * wound_bonus- the wounding power we're assigning to the bullet, since we don't care about the base one
+ * * damage- the damage we're assigning to the bullet, since we don't care about the base one
+ */
+/proc/firing_squad(mob/living/carbon/target, turf/source_turf, body_zone, wound_bonus, damage)
+ if(!target.get_bodypart(body_zone))
+ return
+ playsound(target, 'sound/weapons/gun/revolver/shot.ogg', 100)
+ var/obj/projectile/bullet/smite/divine_wrath = new(source_turf)
+ divine_wrath.damage = damage
+ divine_wrath.wound_bonus = wound_bonus
+ divine_wrath.original = target
+ divine_wrath.def_zone = body_zone
+ divine_wrath.spread = 0
+ divine_wrath.preparePixelProjectile(target, source_turf)
+ divine_wrath.fire()
+
/client/proc/punish_log(whom, punishment)
var/msg = "[key_name_admin(usr)] punished [key_name_admin(whom)] with [punishment]."
message_admins(msg)
diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm
index 93a8dec8d6c..290660e08d1 100644
--- a/code/modules/antagonists/changeling/powers/mutations.dm
+++ b/code/modules/antagonists/changeling/powers/mutations.dm
@@ -161,7 +161,7 @@
throw_speed = 0
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
wound_bonus = -60
bare_wound_bonus = 20
var/can_drop = FALSE
diff --git a/code/modules/antagonists/changeling/powers/regenerate.dm b/code/modules/antagonists/changeling/powers/regenerate.dm
index d65d1181bed..a060cda7f8e 100644
--- a/code/modules/antagonists/changeling/powers/regenerate.dm
+++ b/code/modules/antagonists/changeling/powers/regenerate.dm
@@ -35,8 +35,8 @@
B.Insert(C)
C.regenerate_organs()
for(var/i in C.all_wounds)
- var/datum/wound/W = i
- W.remove_wound()
+ var/datum/wound/iter_wound = i
+ iter_wound.remove_wound()
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.restore_blood()
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index af7a7493e28..7919fd125bd 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -39,7 +39,7 @@
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
flags_1 = CONDUCT_1
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
w_class = WEIGHT_CLASS_BULKY
force = 30 // whoever balanced this got beat in the head by a bible too many times good lord
throwforce = 10
@@ -91,7 +91,7 @@
armour_penetration = 45
throw_speed = 1
throw_range = 3
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
light_color = "#ff0000"
attack_verb = list("cleaved", "slashed", "tore", "lacerated", "hacked", "ripped", "diced", "carved")
icon_state = "cultbastard"
@@ -627,7 +627,7 @@
armour_penetration = 30
block_chance = 30
attack_verb = list("attacked", "impaled", "stabbed", "tore", "lacerated", "gored")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
hitsound = 'sound/weapons/bladeslice.ogg'
var/datum/action/innate/cult/spear/spear_act
var/wielded = FALSE // track wielded status on item
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index d2383d7d7e0..1a725daba5b 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -123,7 +123,7 @@
var/weakness = check_weakness(I, user)
apply_damage(I.force * weakness, I.damtype, def_zone)
var/message_verb = ""
- if(I.attack_verb && I.attack_verb.len)
+ if(I.attack_verb && length(I.attack_verb))
message_verb = "[pick(I.attack_verb)]"
else if(I.force)
message_verb = "attacked"
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_items.dm b/code/modules/antagonists/eldritch_cult/eldritch_items.dm
index f450d9d6a90..fba5de445a1 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_items.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_items.dm
@@ -41,7 +41,7 @@
inhand_x_dimension = 64
inhand_y_dimension = 64
flags_1 = CONDUCT_1
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
w_class = WEIGHT_CLASS_NORMAL
force = 17
throwforce = 10
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
index b8b48028620..20224b39e65 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
@@ -140,14 +140,15 @@
if(iscarbon(target))
var/mob/living/carbon/C1 = target
for(var/obj/item/bodypart/bodypart in C2.bodyparts)
- for(var/datum/wound/wound in bodypart.wounds)
+ for(var/i in bodypart.wounds)
+ var/datum/wound/iter_wound = i
if(prob(50))
continue
var/obj/item/bodypart/target_bodypart = locate(bodypart.type) in C1.bodyparts
if(!target_bodypart)
continue
- wound.remove_wound()
- wound.apply_wound(target_bodypart)
+ iter_wound.remove_wound()
+ iter_wound.apply_wound(target_bodypart)
C1.blood_volume -= 20
if(C2.blood_volume < BLOOD_VOLUME_MAXIMUM) //we dont want to explode after all
@@ -241,7 +242,7 @@
target.visible_message("
[target]'s veins are shredded from within as an unholy blaze erupts from their blood!", \
"
Your veins burst from within and unholy flame erupts from your blood!")
var/obj/item/bodypart/bodypart = pick(target.bodyparts)
- var/datum/wound/brute/cut/critical/crit_wound = new
+ var/datum/wound/slash/critical/crit_wound = new
crit_wound.apply_wound(bodypart)
target.adjustFireLoss(20)
new /obj/effect/temp_visual/cleave(target.drop_location())
diff --git a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
index 3d579853ba9..597054c4adc 100644
--- a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
+++ b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
@@ -86,7 +86,7 @@
if(iscarbon(target))
var/mob/living/carbon/carbon_target = target
var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
- var/datum/wound/brute/cut/severe/crit_wound = new
+ var/datum/wound/slash/severe/crit_wound = new
crit_wound.apply_wound(bodypart)
if(QDELETED(human_target) || human_target.stat != DEAD)
@@ -157,7 +157,7 @@
if(iscarbon(target))
var/mob/living/carbon/carbon_target = target
var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
- var/datum/wound/brute/cut/severe/crit_wound = new
+ var/datum/wound/slash/severe/crit_wound = new
crit_wound.apply_wound(bodypart)
/datum/eldritch_knowledge/summon/raw_prophet
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index 13fa3793cde..b140c343c50 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -38,7 +38,7 @@
melee_damage_upper = 15
wound_bonus = -10
bare_wound_bonus = 0
- sharpness = TRUE
+ sharpness = SHARP_EDGED
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
var/playstyle_string = "
You are a slaughter demon, a terrible creature from another realm. You have a single desire: To kill. \
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 585ec34c4a9..d2979a59c91 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -293,7 +293,7 @@
to_chat(target, "You suddenly feel very hot!")
target.adjust_bodytemperature(50)
GiveHint(target)
- else if(is_pointed(I))
+ else if(I.get_sharpness() == SHARP_POINTY)
to_chat(target, "You feel a stabbing pain in [parse_zone(user.zone_selected)]!")
target.Paralyze(40)
GiveHint(target)
diff --git a/code/modules/cargo/goodies.dm b/code/modules/cargo/goodies.dm
index a942d20db69..c071cbb4753 100644
--- a/code/modules/cargo/goodies.dm
+++ b/code/modules/cargo/goodies.dm
@@ -129,3 +129,9 @@
desc = "The simple beach ball is one of Nanotrasen's most popular products. 'Why do we make beach balls? Because we can! (TM)' - Nanotrasen"
cost = 200
contains = list(/obj/item/toy/beach_ball)
+
+/datum/supply_pack/goody/medipen_twopak
+ name = "Medipen Two-Pak"
+ desc = "Contains one standard epinephrine medipen and one standard emergency first-aid kit medipen. For when you want to prepare for the worst."
+ cost = 500
+ contains = list(/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/hypospray/medipen/ekit)
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 20140de0723..37a42049891 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -1160,6 +1160,21 @@
crate_name = "blood freezer"
crate_type = /obj/structure/closet/crate/freezer
+/datum/supply_pack/medical/medipen_variety
+ name = "Medipen Variety-Pak"
+ desc = "Contains eight different medipens in three different varieties, to assist in quickly treating seriously injured patients."
+ cost = 2000
+ contains = list(/obj/item/reagent_containers/hypospray/medipen/,
+ /obj/item/reagent_containers/hypospray/medipen/,
+ /obj/item/reagent_containers/hypospray/medipen/ekit,
+ /obj/item/reagent_containers/hypospray/medipen/ekit,
+ /obj/item/reagent_containers/hypospray/medipen/ekit,
+ /obj/item/reagent_containers/hypospray/medipen/blood_loss,
+ /obj/item/reagent_containers/hypospray/medipen/blood_loss,
+ /obj/item/reagent_containers/hypospray/medipen/blood_loss
+)
+ crate_name = "medipen crate"
+
/datum/supply_pack/medical/chemical
name = "Chemical Starter Kit Crate"
desc = "Contains thirteen different chemicals, for all the fun experiments you can make."
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index d1c3866bae2..6e71c8a2ec6 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -301,7 +301,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "
Backpack:
[backpack]"
dat += "[(randomise[RANDOM_BACKPACK]) ? "Lock" : "Unlock"]"
- if(CAN_SCAR in pref_species.species_traits)
+ if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits))
dat += "
Temporal Scarring:
[(persistent_scars) ? "Enabled" : "Disabled"]"
dat += "Clear scar slots"
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 6b8f78f823c..5d76d91f57c 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -354,8 +354,8 @@
to_chat(M, "[src] start[p_s()] to fall apart!")
//This mostly exists so subtypes can call appriopriate update icon calls on the wearer.
-/obj/item/clothing/proc/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED)
- damaged_clothes = damaged_state
+/obj/item/clothing/proc/update_clothes_damaged_state()
+ return
/obj/item/clothing/update_overlays()
. = ..()
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 32a8d00c748..912a8b6f331 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -88,7 +88,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/clothing/glasses/science
name = "science goggles"
@@ -156,7 +156,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
glass_colour_type = /datum/client_colour/glass_colour/lightgreen
/obj/item/clothing/glasses/regular
@@ -228,7 +228,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/clothing/glasses/sunglasses/garb/supergarb
name = "black giga gar glasses"
@@ -248,7 +248,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
glass_colour_type = /datum/client_colour/glass_colour/orange
/obj/item/clothing/glasses/sunglasses/gar/supergar
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index 6a86dd4aafe..316d29cdc02 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -159,7 +159,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/clothing/glasses/hud/security/sunglasses/gars/supergars
name = "giga HUD gar glasses"
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 78514228098..35fb84a5745 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -9,7 +9,7 @@
equip_delay_other = 40
max_integrity = 250
resistance_flags = NONE
- armor = list("melee" = 35, "bullet" = 30, "laser" = 30, "energy" = 40, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 15)
+ armor = list("melee" = 35, "bullet" = 30, "laser" = 30, "energy" = 40, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 10)
/obj/item/clothing/suit/armor/Initialize()
. = ..()
@@ -49,7 +49,7 @@
icon_state = "hos"
inhand_icon_state = "greatcoat"
body_parts_covered = CHEST|GROIN|ARMS|LEGS
- armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 40, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 90, "wound" = 20)
+ armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 40, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 90, "wound" = 10)
cold_protection = CHEST|GROIN|LEGS|ARMS
heat_protection = CHEST|GROIN|LEGS|ARMS
strip_delay = 80
@@ -118,7 +118,7 @@
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80, "wound" = 30)
+ armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80, "wound" = 20)
clothing_flags = BLOCKS_SHOVE_KNOCKDOWN
strip_delay = 80
equip_delay_other = 60
diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
index 8f2c39a4754..bbd45f01074 100644
--- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
@@ -146,7 +146,7 @@
inhand_icon_state = "beer"
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("stabbed", "slashed", "attacked")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
var/static/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken")
/obj/item/broken_bottle/Initialize()
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index cf47992834e..f9de7318480 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -230,21 +230,10 @@ All foods are distributed among various categories. Use common sense.
to_chat(user, "You cannot slice [src] here! You need a table or at least a tray.")
return FALSE
- var/slices_lost = 0
- if (accuracy >= IS_SHARP_ACCURATE)
- user.visible_message( \
- "[user] slices [src].", \
- "You slice [src]." \
- )
- else
- user.visible_message( \
- "[user] inaccurately slices [src] with [W]!", \
- "You inaccurately slice [src] with your [W]!" \
- )
- slices_lost = rand(1,min(1,round(slices_num/2)))
+ user.visible_message("[user] slices [src].", "You slice [src].")
var/reagents_per_slice = reagents.total_volume/slices_num
- for(var/i=1 to (slices_num-slices_lost))
+ for(var/i in 1 to slices_num)
var/obj/item/reagent_containers/food/snacks/slice = new slice_path (loc)
initialize_slice(slice, reagents_per_slice)
qdel(src)
diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css
index 1a990391dec..135ef6ea1e5 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput.css
@@ -298,7 +298,10 @@ em {font-style: normal; font-weight: bold;}
.emote { font-style: italic;}
.userdanger {color: #c51e1e; font-weight: bold; font-size: 185%;}
+.bolddanger {color: #c51e1e;font-weight: bold;}
.danger {color: #c51e1e;}
+.tinydanger {color: #c51e1e; font-size: 85%;}
+.smalldanger {color: #c51e1e; font-size: 90%;}
.warning {color: #c51e1e; font-style: italic;}
.alertwarning {color: #FF0000; font-weight: bold}
.boldwarning {color: #c51e1e; font-style: italic; font-weight: bold}
@@ -308,8 +311,9 @@ em {font-style: normal; font-weight: bold;}
.rose {color: #ff5050;}
.info {color: #9ab0ff;}
.notice {color: #6685f5;}
-.tinynotice {color: #6685f5; font-style: italic; font-size: 85%;}
-.smallnotice {color: #6685f5; font-style: italic; font-size: 90%;}
+.tinynotice {color: #6685f5; font-style: italic; font-size: 85%;}
+.smallnotice {color: #6685f5; font-size: 90%;}
+.smallnoticeital {color: #6685f5; font-style: italic; font-size: 90%;}
.boldnotice {color: #6685f5; font-weight: bold;}
.hear {color: #6685f5; font-style: italic;}
.adminnotice {color: #6685f5;}
diff --git a/code/modules/goonchat/browserassets/css/browserOutput_white.css b/code/modules/goonchat/browserassets/css/browserOutput_white.css
index 0bddfb761af..1c9d0cdfb29 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput_white.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput_white.css
@@ -296,7 +296,10 @@ h1.alert, h2.alert {color: #000000;}
.emote { font-style: italic;}
.userdanger {color: #ff0000; font-weight: bold; font-size: 185%;}
+.bolddanger {color: #ff0000; font-weight: bold;}
.danger {color: #ff0000;}
+.tinydanger {color: #ff0000; font-size: 85%;}
+.smalldanger {color: #ff0000; font-size: 90%;}
.warning {color: #ff0000; font-style: italic;}
.alertwarning {color: #FF0000; font-weight: bold}
.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
@@ -307,7 +310,8 @@ h1.alert, h2.alert {color: #000000;}
.info {color: #0000CC;}
.notice {color: #000099;}
.tinynotice {color: #000099; font-style: italic; font-size: 85%;}
-.smallnotice {color: #000099; font-style: italic; font-size: 90%;}
+.smallnotice {color: #000099; font-size: 90%;}
+.smallnoticeital {color: #000099; font-style: italic; font-size: 90%;}
.boldnotice {color: #000099; font-weight: bold;}
.hear {color: #000099; font-style: italic;}
.adminnotice {color: #0000ff;}
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index 1837e37cb0e..c0998045425 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -29,6 +29,12 @@
juice_results = list(/datum/reagent/consumable/banana = 0)
distill_reagent = /datum/reagent/consumable/ethanol/bananahonk
+/obj/item/reagent_containers/food/snacks/grown/banana/generate_trash(atom/location)
+ . = ..()
+ var/obj/item/grown/bananapeel/peel = .
+ if(istype(peel))
+ peel.grind_results = list(/datum/reagent/consumable/banana_peel = seed.potency * 0.2)
+
/obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user)
user.visible_message("[user] is aiming [src] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/items/bikehorn.ogg', 50, TRUE, -1)
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 056f9aa163a..137a49b8ded 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -127,7 +127,7 @@
custom_materials = list(/datum/material/iron = 15000)
attack_verb = list("chopped", "tore", "lacerated", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/hatchet/Initialize()
. = ..()
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index 2553edeb394..d74088f09b0 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -17,7 +17,7 @@
custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075)
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
actions_types = list(/datum/action/item_action/toggle_light)
obj_flags = UNIQUE_RENAME
var/list/trophies = list()
diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm
index a2c004a09dc..cf292e4a82d 100644
--- a/code/modules/mining/equipment/mining_tools.dm
+++ b/code/modules/mining/equipment/mining_tools.dm
@@ -133,7 +133,7 @@
w_class = WEIGHT_CLASS_NORMAL
custom_materials = list(/datum/material/iron=50)
attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/shovel/Initialize()
. = ..()
@@ -169,4 +169,4 @@
w_class = WEIGHT_CLASS_NORMAL
toolspeed = 0.7
attack_verb = list("slashed", "impaled", "stabbed", "sliced")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 809796c8e3c..e1d2c332730 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -711,7 +711,7 @@
hitsound = 'sound/weapons/bladeslice.ogg'
hitsound_on = 'sound/weapons/bladeslice.ogg'
w_class = WEIGHT_CLASS_BULKY
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
faction_bonus_force = 30
nemesis_factions = list("mining", "boss")
var/transform_cooldown
@@ -817,7 +817,7 @@
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
flags_1 = CONDUCT_1
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
w_class = WEIGHT_CLASS_BULKY
force = 1
throwforce = 1
diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm
index 75ee9c53c25..ae9ad1a560b 100644
--- a/code/modules/mob/living/bloodcrawl.dm
+++ b/code/modules/mob/living/bloodcrawl.dm
@@ -74,7 +74,7 @@
if(victim.stat == CONSCIOUS)
visible_message("[victim] kicks free of the blood pool just before entering it!", null, "You hear splashing and struggling.")
- else if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/demonsblood, needs_metabolizing = TRUE))
+ else if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/demonsblood, needs_metabolizing = TRUE))
visible_message("Something prevents [victim] from entering the pool!", "A strange force is blocking [victim] from entering!", "You hear a splash and a thud.")
else
victim.forceMove(src)
@@ -107,7 +107,7 @@
if(!victim)
return FALSE
- if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/devilskiss, needs_metabolizing = TRUE))
+ if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/devilskiss, needs_metabolizing = TRUE))
to_chat(src, "AAH! THEIR FLESH! IT BURNS!")
adjustBruteLoss(25) //I can't use adjustHealth() here because bloodcrawl affects /mob/living and adjustHealth() only affects simple mobs
var/found_bloodpool = FALSE
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 6b7c183c7af..fec1ae9deef 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -65,17 +65,8 @@
if(!all_wounds || !(user.a_intent == INTENT_HELP || user == src))
return ..()
- // The following priority/nonpriority searching is so that if we have two wounds on a limb that use the same item for treatment (gauze can bandage cuts AND splint broken bones),
- // we prefer whichever wound is not already treated (ignore the splinted broken bone for the open cut). If there's no priority wounds that this can treat, go through the
- // non-priority ones randomly.
- var/list/nonpriority_wounds = list()
- for(var/datum/wound/W in shuffle(all_wounds))
- if(!W.treat_priority)
- nonpriority_wounds += W
- else if(W.treat_priority && W.try_treating(I, user))
- return 1
-
- for(var/datum/wound/W in shuffle(nonpriority_wounds))
+ for(var/i in shuffle(all_wounds))
+ var/datum/wound/W = i
if(W.try_treating(I, user))
return 1
@@ -1164,16 +1155,16 @@
/**
* generate_fake_scars()- for when you want to scar someone, but you don't want to hurt them first. These scars don't count for temporal scarring (hence, fake)
*
- * If you want a specific wound scar, pass that wound type as the second arg, otherwise you can pass a list like WOUND_LIST_CUT to generate a random cut scar.
+ * If you want a specific wound scar, pass that wound type as the second arg, otherwise you can pass a list like WOUND_LIST_SLASH to generate a random cut scar.
*
* Arguments:
* * num_scars- A number for how many scars you want to add
- * * forced_type- Which wound or category of wounds you want to choose from, WOUND_LIST_BONE, WOUND_LIST_CUT, or WOUND_LIST_BURN (or some combination). If passed a list, picks randomly from the listed wounds. Defaults to all 3 types
+ * * forced_type- Which wound or category of wounds you want to choose from, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN (or some combination). If passed a list, picks randomly from the listed wounds. Defaults to all 3 types
*/
/mob/living/carbon/proc/generate_fake_scars(num_scars, forced_type)
for(var/i in 1 to num_scars)
- var/datum/scar/S = new
- var/obj/item/bodypart/BP = pick(bodyparts)
+ var/datum/scar/scaries = new
+ var/obj/item/bodypart/scar_part = pick(bodyparts)
var/wound_type
if(forced_type)
@@ -1182,12 +1173,20 @@
else
wound_type = forced_type
else
- wound_type = pick(WOUND_LIST_BONE + WOUND_LIST_CUT + WOUND_LIST_BURN)
+ wound_type = pick(GLOB.global_all_wound_types)
- var/datum/wound/W = new wound_type
- S.generate(BP, W)
- S.fake = TRUE
- QDEL_NULL(W)
+ var/datum/wound/phantom_wound = new wound_type
+ scaries.generate(scar_part, phantom_wound)
+ scaries.fake = TRUE
+ QDEL_NULL(phantom_wound)
/mob/living/carbon/is_face_visible()
return !(wear_mask?.flags_inv & HIDEFACE) && !(head?.flags_inv & HIDEFACE)
+
+/**
+ * get_biological_state is a helper used to see what kind of wounds we roll for. By default we just assume carbons (read:monkeys) are flesh and bone, but humans rely on their species datums
+ *
+ * go look at the species def for more info [/datum/species/proc/get_biological_state]
+ */
+/mob/living/carbon/proc/get_biological_state()
+ return BIO_FLESH_BONE
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 6d332704428..473415f8de8 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -75,7 +75,7 @@
if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest)
affecting = bodyparts[1]
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
- send_item_attack_message(I, user, affecting.name)
+ send_item_attack_message(I, user, affecting.name, affecting)
if(I.force)
apply_damage(I.force, I.damtype, affecting, wound_bonus = I.wound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness())
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
@@ -96,14 +96,41 @@
head.add_mob_blood(src)
update_inv_head()
- //dismemberment
- var/probability = I.get_dismemberment_chance(affecting)
- if(prob(probability))
- if(affecting.dismember(I.damtype))
- I.add_mob_blood(src)
- playsound(get_turf(src), I.get_dismember_sound(), 80, TRUE)
return TRUE //successful attack
+/mob/living/carbon/send_item_attack_message(obj/item/I, mob/living/user, hit_area, obj/item/bodypart/hit_bodypart)
+ var/message_verb = "attacked"
+ if(length(I.attack_verb))
+ message_verb = "[pick(I.attack_verb)]"
+ else if(!I.force)
+ return
+
+ var/extra_wound_details = ""
+ if(I.damtype == BRUTE && hit_bodypart.can_dismember())
+ var/mangled_state = hit_bodypart.get_mangled_state()
+ var/bio_state = get_biological_state()
+ if(mangled_state == BODYPART_MANGLED_BOTH)
+ extra_wound_details = ", threatening to sever it entirely"
+ else if((mangled_state == BODYPART_MANGLED_FLESH && I.get_sharpness()) || (mangled_state & BODYPART_MANGLED_BONE && bio_state == BIO_JUST_BONE))
+ extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] through to the bone"
+ else if((mangled_state == BODYPART_MANGLED_BONE && I.get_sharpness()) || (mangled_state & BODYPART_MANGLED_FLESH && bio_state == BIO_JUST_FLESH))
+ extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] at the remaining tissue"
+
+ var/message_hit_area = ""
+ if(hit_area)
+ message_hit_area = " in the [hit_area]"
+ var/attack_message = "[src] is [message_verb][message_hit_area] with [I][extra_wound_details]!"
+ var/attack_message_local = "You're [message_verb][message_hit_area] with [I][extra_wound_details]!"
+ if(user in viewers(src, null))
+ attack_message = "[user] [message_verb] [src][message_hit_area] with [I][extra_wound_details]!"
+ attack_message_local = "[user] [message_verb] you[message_hit_area] with [I][extra_wound_details]!"
+ if(user == src)
+ attack_message_local = "You [message_verb] yourself[message_hit_area] with [I][extra_wound_details]"
+ visible_message("[attack_message]",\
+ "[attack_message_local]", null, COMBAT_MESSAGE_RANGE)
+ return TRUE
+
+
/mob/living/carbon/attack_drone(mob/living/simple_animal/drone/user)
return //so we don't call the carbon's attack_hand().
@@ -124,13 +151,14 @@
if(!(mobility_flags & MOBILITY_STAND) || !S.lying_required)
if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)
if(S.next_step(user, user.a_intent))
- return 1
+ return TRUE
- for(var/datum/wound/W in all_wounds)
+ for(var/i in all_wounds)
+ var/datum/wound/W = i
if(W.try_handling(user))
- return 1
+ return TRUE
- return 0
+ return FALSE
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
@@ -148,13 +176,13 @@
if(M.a_intent == INTENT_HELP)
help_shake_act(M)
- return 0
+ return FALSE
if(..()) //successful monkey bite.
for(var/thing in M.diseases)
var/datum/disease/D = thing
ForceContractDisease(D)
- return 1
+ return TRUE
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm
index c64dd449cfc..df5067da7d0 100644
--- a/code/modules/mob/living/carbon/damage_procs.dm
+++ b/code/modules/mob/living/carbon/damage_procs.dm
@@ -1,6 +1,6 @@
-/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
var/hit_percent = (100-blocked)/100
if(!damage || (!forced && hit_percent <= 0))
@@ -209,7 +209,7 @@
*
* It automatically updates health status
*/
-/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
var/list/obj/item/bodypart/parts = get_damageable_bodyparts(required_status)
if(!parts.len)
return
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 0040bed767f..12ecaffcd3f 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -45,7 +45,8 @@
msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!\n"
else
msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n"
- for(var/datum/wound/W in BP.wounds)
+ for(var/i in BP.wounds)
+ var/datum/wound/W = i
msg += "[W.get_examine_description(user)]\n"
for(var/X in disabled)
@@ -111,7 +112,7 @@
switch(scar_severity)
if(1 to 2)
- msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n"
+ msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n"
if(3 to 4)
msg += "[t_He] [t_has] several bad scars, you can look again to take a closer look...\n"
if(5 to 6)
diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm
index 231f85097b0..0947cfe49db 100644
--- a/code/modules/mob/living/carbon/human/damage_procs.dm
+++ b/code/modules/mob/living/carbon/human/damage_procs.dm
@@ -1,4 +1,4 @@
/// depending on the species, it will run the corresponding apply_damage code there
-/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index b6e484e4a32..1a17d1d0603 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -151,8 +151,9 @@
else
msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n"
- for(var/datum/wound/W in BP.wounds)
- msg += "[W.get_examine_description(user)]\n"
+ for(var/i in BP.wounds)
+ var/datum/wound/iter_wound = i
+ msg += "[iter_wound.get_examine_description(user)]\n"
for(var/X in disabled)
var/obj/item/bodypart/BP = X
@@ -259,7 +260,13 @@
bleeding_limbs += BP
var/num_bleeds = LAZYLEN(bleeding_limbs)
- var/bleed_text = "[t_He] [t_is] bleeding from [t_his]"
+
+ var/list/bleed_text
+ if(appears_dead)
+ bleed_text = list("Blood is visible in [t_his] open")
+ else
+ bleed_text = list("[t_He] [t_is] bleeding from [t_his]")
+
switch(num_bleeds)
if(1 to 2)
bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]"
@@ -268,11 +275,15 @@
var/obj/item/bodypart/BP = bleeding_limbs[i]
bleed_text += " [BP.name],"
bleed_text += " and [bleeding_limbs[num_bleeds].name]"
- if(reagents.has_reagent(/datum/reagent/toxin/heparin, needs_metabolizing = TRUE))
- bleed_text += " incredibly quickly"
- bleed_text += "!\n"
- msg += bleed_text
+ if(appears_dead)
+ bleed_text += ", but it has pooled and is not flowing.\n"
+ else
+ if(reagents.has_reagent(/datum/reagent/toxin/heparin, needs_metabolizing = TRUE))
+ bleed_text += " incredibly quickly"
+
+ bleed_text += "!\n"
+ msg += bleed_text.Join()
if(reagents.has_reagent(/datum/reagent/teslium, needs_metabolizing = TRUE))
msg += "[t_He] [t_is] emitting a gentle blue glow!\n"
@@ -349,7 +360,7 @@
switch(scar_severity)
if(1 to 2)
- msg += "
[t_He] [t_has] visible scarring, you can look again to take a closer look...\n"
+ msg += "
[t_He] [t_has] visible scarring, you can look again to take a closer look...\n"
if(3 to 4)
msg += "
[t_He] [t_has] several bad scars, you can look again to take a closer look...\n"
if(5 to 6)
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index cb13e795c63..6bf01049be9 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -178,19 +178,29 @@
/// For use formatting all of the scars this human has for saving for persistent scarring
/mob/living/carbon/human/proc/format_scars()
- if(!all_scars)
+ var/list/missing_bodyparts = get_missing_limbs()
+ if(!all_scars && !length(missing_bodyparts))
return
var/scars = ""
+ for(var/i in missing_bodyparts)
+ var/datum/scar/scaries = new
+ scars += "[scaries.format_amputated(i)]"
for(var/i in all_scars)
- var/datum/scar/S = i
- scars += "[S.format()];"
+ var/datum/scar/scaries = i
+ scars += "[scaries.format()];"
return scars
/// Takes a single scar from the persistent scar loader and recreates it from the saved data
/mob/living/carbon/human/proc/load_scar(scar_line)
var/list/scar_data = splittext(scar_line, "|")
- if(LAZYLEN(scar_data) != 4)
+ if(LAZYLEN(scar_data) != SCAR_SAVE_LENGTH)
return // invalid, should delete
- var/obj/item/bodypart/BP = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
- var/datum/scar/S = new
- return S.load(BP, scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]))
+ var/version = text2num(scar_data[SCAR_SAVE_VERS])
+ if(!version || version < SCAR_CURRENT_VERSION) // get rid of old scars
+ return
+ var/obj/item/bodypart/the_part = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
+ var/datum/scar/scaries = new
+ return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]))
+
+/mob/living/carbon/human/get_biological_state()
+ return dna.species.get_biological_state()
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 454eaea180f..70bf9cce8fa 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -40,6 +40,10 @@
handle_liver()
dna.species.spec_life(src) // for mutantraces
+ else
+ for(var/i in all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_stasis()
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 8469bd8a219..dc2013bfd45 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1565,18 +1565,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/weakness = H.check_weakness(I, user)
apply_damage(I.force * weakness, I.damtype, def_zone, armor_block, H, wound_bonus = Iwound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness())
- H.send_item_attack_message(I, user, hit_area)
+ H.send_item_attack_message(I, user, hit_area, affecting)
if(!I.force)
return 0 //item force is zero
- //dismemberment
- var/probability = I.get_dismemberment_chance(affecting)
- if(prob(probability) || (HAS_TRAIT(H, TRAIT_EASYDISMEMBER) && prob(probability))) //try twice
- if(affecting.dismember(I.damtype))
- I.add_mob_blood(H)
- playsound(get_turf(H), I.get_dismember_sound(), 80, TRUE)
-
var/bloody = 0
if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2))))
if(affecting.status == BODYPART_ORGANIC)
@@ -1637,7 +1630,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
return TRUE
-/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness) // make sure putting wound_bonus here doesn't screw up other signals or uses for this signal
var/hit_percent = (100-(blocked+armor))/100
hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100
@@ -2111,3 +2104,13 @@ GLOBAL_LIST_EMPTY(roundstart_races)
else
to_chat(H, "
You beat your wings and begin to hover gently above the ground...")
H.set_resting(FALSE, TRUE)
+
+/**
+ * The human species version of [/mob/living/carbon/proc/get_biological_state]. Depends on the HAS_FLESH and HAS_BONE species traits, having bones lets you have bone wounds, having flesh lets you have burn, slash, and piercing wounds
+ */
+/datum/species/proc/get_biological_state(mob/living/carbon/human/H)
+ . = BIO_INORGANIC
+ if(HAS_FLESH in species_traits)
+ . |= BIO_JUST_FLESH
+ if(HAS_BONE in species_traits)
+ . |= BIO_JUST_BONE
diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
index 9935717ba80..f977dd0c4aa 100644
--- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
@@ -2,7 +2,7 @@
name = "Dullahan"
id = "dullahan"
default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS, HAS_FLESH, HAS_BONE)
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None")
use_skintones = TRUE
diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
index 7153cacfdcb..3db33a17cb6 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -15,7 +15,7 @@
payday_modifier = 0.75
attack_type = BURN //burn bish
damage_overlay_type = "" //We are too cool for regular damage overlays
- species_traits = list(DYNCOLORS, AGENDER, NO_UNDERWEAR, HAIR)
+ species_traits = list(DYNCOLORS, AGENDER, NO_UNDERWEAR, HAIR, HAS_FLESH, HAS_BONE) // i mean i guess they have blood so they can have wounds too
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
species_language_holder = /datum/language_holder/ethereal
inherent_traits = list(TRAIT_NOHUNGER)
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 3cb9bc4237d..8c59ab07567 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -914,7 +914,7 @@
special_names = list("Head", "Broth", "Fracture", "Rattler", "Appetit")
liked_food = GROSS | MEAT | RAW
toxic_food = null
- species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES)
+ species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYESPRITES,HAS_BONE)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutanttongue = /obj/item/organ/tongue/bone
sexes = FALSE
@@ -942,8 +942,10 @@
H.reagents.remove_reagent(chem.type, chem.volume - 10)
to_chat(H, "
The excess milk is dripping off your bones!")
H.heal_bodypart_damage(1.5,0, 0)
+ for(var/i in H.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(2)
H.reagents.remove_reagent(chem.type, chem.metabolization_rate)
- return TRUE
if(chem.type == /datum/reagent/toxin/bonehurtingjuice)
H.adjustStaminaLoss(7.5, 0)
H.adjustBruteLoss(0.5, 0)
diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm
index 2c61d6a5e61..2c80700c589 100644
--- a/code/modules/mob/living/carbon/human/species_types/humans.dm
+++ b/code/modules/mob/living/carbon/human/species_types/humans.dm
@@ -2,7 +2,7 @@
name = "Human"
id = "human"
default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,CAN_SCAR)
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
default_features = list("mcolor" = "FFF", "wings" = "None")
use_skintones = 1
skinned_type = /obj/item/stack/sheet/animalhide/human
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index 3e8654bf684..ed7f3df50d3 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -4,7 +4,7 @@
id = "lizard"
say_mod = "hisses"
default_color = "00FF00"
- species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
+ species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs")
mutanttongue = /obj/item/organ/tongue/lizard
@@ -84,6 +84,6 @@
name = "Ash Walker"
id = "ashlizard"
limbs_id = "lizard"
- species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE,CAN_SCAR)
+ species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_CHUNKYFINGERS,TRAIT_NOBREATH)
species_language_holder = /datum/language_holder/lizard/ash
diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm
index c28fa0768e0..c6704cef159 100644
--- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm
@@ -3,7 +3,7 @@
id = "moth"
say_mod = "flutters"
default_color = "00FF00"
- species_traits = list(LIPS, NOEYESPRITES, CAN_SCAR)
+ species_traits = list(LIPS, NOEYESPRITES, HAS_FLESH, HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
mutant_bodyparts = list("moth_wings", "moth_markings")
default_features = list("moth_wings" = "Plain", "moth_markings" = "None")
diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
index 8e302abbb29..ca20e5e6aa7 100644
--- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
@@ -10,7 +10,7 @@
nojumpsuit = TRUE
say_mod = "poofs" //what does a mushroom sound like
- species_traits = list(MUTCOLORS, NOEYESPRITES, NO_UNDERWEAR)
+ species_traits = list(MUTCOLORS, NOEYESPRITES, NO_UNDERWEAR, HAS_FLESH, HAS_BONE)
inherent_traits = list(TRAIT_NOBREATH, TRAIT_NOFLASH)
inherent_factions = list("mushroom")
speedmod = 1.5 //faster than golems but not by much
diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
index 6e6a1b7ba4f..51327257ed5 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -4,7 +4,7 @@
say_mod = "rattles"
sexes = 0
meat = /obj/item/stack/sheet/mineral/plasma
- species_traits = list(NOBLOOD,NOTRANSSTING)
+ species_traits = list(NOBLOOD,NOTRANSSTING, HAS_BONE)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_NOHUNGER,TRAIT_ALWAYS_CLEAN)
inherent_biotypes = MOB_HUMANOID|MOB_MINERAL
mutantlungs = /obj/item/organ/lungs/plasmaman
@@ -150,14 +150,23 @@
/datum/species/plasmaman/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
. = ..()
- if(chem.type == /datum/reagent/consumable/milk)
+ if(istype(chem, /datum/reagent/consumable/milk))
if(chem.volume > 10)
H.reagents.remove_reagent(chem.type, chem.volume - 10)
to_chat(H, "
The excess milk is dripping off your bones!")
H.heal_bodypart_damage(1.5,0, 0)
H.reagents.remove_reagent(chem.type, chem.metabolization_rate)
+ for(var/i in H.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(2)
return TRUE
- if(chem.type == /datum/reagent/toxin/bonehurtingjuice)
+ if(istype(chem, /datum/reagent/toxin/plasma))
+ H.reagents.remove_reagent(chem.type, chem.metabolization_rate)
+ for(var/i in H.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(4) // plasmamen use plasma to reform their bones or whatever
+ return TRUE
+ if(istype(chem, /datum/reagent/toxin/bonehurtingjuice))
H.adjustStaminaLoss(7.5, 0)
H.adjustBruteLoss(0.5, 0)
if(prob(20))
diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index 4d9f557f02d..742ca01cd67 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -3,7 +3,7 @@
name = "Podperson"
id = "pod"
default_color = "59CE00"
- species_traits = list(MUTCOLORS,EYECOLOR)
+ species_traits = list(MUTCOLORS,EYECOLOR, HAS_FLESH, HAS_BONE)
inherent_traits = list(TRAIT_ALWAYS_CLEAN)
inherent_factions = list("plants", "vines")
attack_verb = "slash"
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index 3c4b1428f81..b3102eab051 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -172,7 +172,7 @@
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
item_flags = ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_HUGE
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
wound_bonus = -60
bare_wound_bonus = 20
diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
index 3ea96e01468..7443224e7f6 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -5,7 +5,7 @@
say_mod = "rattles"
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
- species_traits = list(NOBLOOD)
+ species_traits = list(NOBLOOD, HAS_BONE)
inherent_traits = list(TRAIT_NOMETABOLISM,TRAIT_TOXIMMUNE,TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_GENELESS,\
TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH,TRAIT_XENO_IMMUNE,TRAIT_NOCLONELOSS)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
@@ -29,6 +29,9 @@
if(chem.volume > 10)
H.reagents.remove_reagent(chem.type, chem.volume - 10)
to_chat(H, "
The excess milk is dripping off your bones!")
+ for(var/i in H.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(2)
H.heal_bodypart_damage(1,1, 0)
H.reagents.remove_reagent(chem.type, chem.metabolization_rate)
return TRUE
diff --git a/code/modules/mob/living/carbon/human/species_types/snail.dm b/code/modules/mob/living/carbon/human/species_types/snail.dm
index 73b133f46f3..0b4c9537089 100644
--- a/code/modules/mob/living/carbon/human/species_types/snail.dm
+++ b/code/modules/mob/living/carbon/human/species_types/snail.dm
@@ -3,7 +3,7 @@
id = "snail"
offset_features = list(OFFSET_UNIFORM = list(0,0), OFFSET_ID = list(0,0), OFFSET_GLOVES = list(0,0), OFFSET_GLASSES = list(0,4), OFFSET_EARS = list(0,0), OFFSET_SHOES = list(0,0), OFFSET_S_STORE = list(0,0), OFFSET_FACEMASK = list(0,0), OFFSET_HEAD = list(0,0), OFFSET_FACE = list(0,0), OFFSET_BELT = list(0,0), OFFSET_BACK = list(0,0), OFFSET_SUIT = list(0,0), OFFSET_NECK = list(0,0))
default_color = "336600" //vomit green
- species_traits = list(MUTCOLORS, NO_UNDERWEAR)
+ species_traits = list(MUTCOLORS, NO_UNDERWEAR, HAS_FLESH, HAS_BONE)
inherent_traits = list(TRAIT_ALWAYS_CLEAN, TRAIT_NOSLIPALL)
attack_verb = "slap"
say_mod = "slurs"
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index 1bd65fc01ab..e1ece348605 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -2,7 +2,7 @@
name = "Vampire"
id = "vampire"
default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD)
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD, HAS_FLESH, HAS_BONE)
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None")
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index 31f2b715a18..2ebf0c5f729 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -7,7 +7,7 @@
say_mod = "moans"
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
- species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING)
+ species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING, HAS_FLESH, HAS_BONE)
inherent_traits = list(TRAIT_NOMETABOLISM,TRAIT_TOXIMMUNE,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH,TRAIT_NOCLONELOSS)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutanttongue = /obj/item/organ/tongue/zombie
@@ -46,7 +46,7 @@
/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount)
. = min(20, amount)
-/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
. = ..()
if(.)
regen_cooldown = world.time + REGENERATION_DELAY
@@ -64,9 +64,9 @@
C.heal_overall_damage(heal_amt,heal_amt)
C.adjustToxLoss(-heal_amt)
for(var/i in C.all_wounds)
- var/datum/wound/W = i
- if(prob(4-W.severity))
- W.remove_wound()
+ var/datum/wound/iter_wound = i
+ if(prob(4-iter_wound.severity))
+ iter_wound.remove_wound()
if(!C.InCritical() && prob(4))
playsound(C, pick(spooks), 50, TRUE, 10)
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index 55cf8d56a1a..18cb1c5b236 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -14,7 +14,7 @@
*
* Returns TRUE if damage applied
*/
-/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
var/hit_percent = (100-blocked)/100
if(!damage || (!forced && hit_percent <= 0))
@@ -263,7 +263,7 @@
update_stamina()
/// damage ONE external organ, organ gets randomly selected from damaged ones.
-/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
adjustBruteLoss(brute, FALSE) //zero as argument for no instant health update
adjustFireLoss(burn, FALSE)
adjustStaminaLoss(stamina, FALSE)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 0bb380b7b76..df378b0f410 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -677,41 +677,56 @@
return
/mob/living/proc/makeTrail(turf/target_turf, turf/start, direction)
- if(!has_gravity())
+ if(!has_gravity() || !isturf(start) || !blood_volume)
return
- var/blood_exists = FALSE
- for(var/obj/effect/decal/cleanable/trail_holder/C in start) //checks for blood splatter already on the floor
- blood_exists = TRUE
- if(isturf(start))
- var/trail_type = getTrail()
- if(trail_type)
- var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1)
- if(blood_volume && blood_volume > max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold
- blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage.
- var/newdir = get_dir(target_turf, start)
- if(newdir != direction)
- newdir = newdir | direction
- if(newdir == 3) //N + S
- newdir = NORTH
- else if(newdir == 12) //E + W
- newdir = EAST
- if((newdir in GLOB.cardinals) && (prob(50)))
- newdir = turn(get_dir(target_turf, start), 180)
- if(!blood_exists)
- new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses())
+ var/blood_exists = locate(/obj/effect/decal/cleanable/trail_holder) in start
- for(var/obj/effect/decal/cleanable/trail_holder/TH in start)
- if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled)
- TH.existing_dirs += newdir
- TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir))
- TH.transfer_mob_blood_dna(src)
+ var/trail_type = getTrail()
+ if(!trail_type)
+ return
+
+ var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1)
+ if(blood_volume < max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold
+ return
+
+ var/bleed_amount = bleedDragAmount()
+ blood_volume = max(blood_volume - bleed_amount, 0) //that depends on our brute damage.
+ var/newdir = get_dir(target_turf, start)
+ if(newdir != direction)
+ newdir = newdir | direction
+ if(newdir == (NORTH|SOUTH))
+ newdir = NORTH
+ else if(newdir == (EAST|WEST))
+ newdir = EAST
+ if((newdir in GLOB.cardinals) && (prob(50)))
+ newdir = turn(get_dir(target_turf, start), 180)
+ if(!blood_exists)
+ new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses())
+
+ for(var/obj/effect/decal/cleanable/trail_holder/TH in start)
+ if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled)
+ TH.existing_dirs += newdir
+ TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir))
+ TH.transfer_mob_blood_dna(src)
/mob/living/carbon/human/makeTrail(turf/T)
if((NOBLOOD in dna.species.species_traits) || !is_bleeding() || bleedsuppress)
return
..()
+///Returns how much blood we're losing from being dragged a tile, from [mob/living/proc/makeTrail]
+/mob/living/proc/bleedDragAmount()
+ var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1)
+ return max(1, brute_ratio * 2)
+
+/mob/living/carbon/bleedDragAmount()
+ var/bleed_amount = 0
+ for(var/i in all_wounds)
+ var/datum/wound/iter_wound = i
+ bleed_amount += iter_wound.drag_bleed_amount()
+ return bleed_amount
+
/mob/living/proc/getTrail()
if(getBruteLoss() < 300)
return pick("ltrails_1", "ltrails_2")
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index b634bd42822..4748489e0c8 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -51,7 +51,7 @@
var/armor = run_armor_check(def_zone, P.flag, "","",P.armour_penetration)
var/on_hit_state = P.on_hit(src, armor)
if(!P.nodamage && on_hit_state != BULLET_ACT_BLOCK)
- apply_damage(P.damage, P.damage_type, def_zone, armor, wound_bonus=P.wound_bonus, bare_wound_bonus=P.bare_wound_bonus, sharpness=P.sharpness)
+ apply_damage(P.damage, P.damage_type, def_zone, armor, wound_bonus=P.wound_bonus, bare_wound_bonus=P.bare_wound_bonus, sharpness = P.sharpness)
apply_effects(P.stun, P.knockdown, P.unconscious, P.irradiate, P.slur, P.stutter, P.eyeblur, P.drowsy, armor, P.stamina, P.jitter, P.paralyze, P.immobilize)
if(P.dismemberment)
check_projectile_dismemberment(P, def_zone)
@@ -80,14 +80,16 @@
dtype = I.damtype
if(!blocked)
- visible_message("
[src] is hit by [I]!", \
- "
You're hit by [I]!")
- if(!I.throwforce)
- return
- var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
- apply_damage(I.throwforce, dtype, zone, armor, sharpness=I.sharpness)
if(I.thrownby)
log_combat(I.thrownby, src, "threw and hit", I)
+ if(!nosell_hit)
+ visible_message("
[src] is hit by [I]!", \
+ "
You're hit by [I]!")
+ if(!I.throwforce)
+ return
+ var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
+ apply_damage(I.throwforce, dtype, zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND))
+
else
return 1
else
diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm
index 3f0ce34d971..1a6e3e16492 100644
--- a/code/modules/mob/living/silicon/damage_procs.dm
+++ b/code/modules/mob/living/silicon/damage_procs.dm
@@ -1,5 +1,5 @@
-/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
var/hit_percent = (100-blocked)/100
if((!damage || (!forced && hit_percent <= 0)))
return 0
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index 7f3056ec998..8fad5c4f8cb 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -29,7 +29,7 @@
melee_damage_upper = 15
wound_bonus = -5
bare_wound_bonus = 10 // BEAR wound bonus am i right
- sharpness = TRUE
+ sharpness = SHARP_EDGED
attack_verb_continuous = "claws"
attack_verb_simple = "claw"
attack_sound = 'sound/weapons/bladeslice.ogg'
diff --git a/code/modules/mob/living/simple_animal/hostile/cockroach.dm b/code/modules/mob/living/simple_animal/hostile/cockroach.dm
index 8008858a8bd..f50d8fd9724 100644
--- a/code/modules/mob/living/simple_animal/hostile/cockroach.dm
+++ b/code/modules/mob/living/simple_animal/hostile/cockroach.dm
@@ -96,7 +96,7 @@
gold_core_spawnable = HOSTILE_SPAWN
attack_sound = 'sound/weapons/bladeslice.ogg'
faction = list("hostile")
- sharpness = IS_SHARP
+ sharpness = SHARP_POINTY
squish_chance = 0 // manual squish if relevant
/mob/living/simple_animal/hostile/cockroach/hauberoach/ComponentInitialize()
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 4804bb09e59..3deed6857b1 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -296,7 +296,7 @@
melee_damage_upper = 15
wound_bonus = -10
bare_wound_bonus = 20
- sharpness = TRUE
+ sharpness = SHARP_EDGED
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
attack_verb_continuous = "cuts"
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 4f3f481226a..a7625a7b6ef 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -150,7 +150,7 @@
///How much bare wounding power it has
var/bare_wound_bonus = 0
///If the attacks from this are sharp
- var/sharpness = FALSE
+ var/sharpness = SHARP_NONE
///Generic flags
var/simple_mob_flags = NONE
diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm
index 151952097fe..e21894eb0cc 100644
--- a/code/modules/ninja/energy_katana.dm
+++ b/code/modules/ninja/energy_katana.dm
@@ -14,7 +14,7 @@
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_BELT
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
max_integrity = 200
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/datum/effect_system/spark_spread/spark_system
diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm
index ccce6c3af2b..a0c6073281a 100644
--- a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm
+++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm
@@ -14,5 +14,5 @@
/obj/item/throwing_star/ninja
name = "ninja throwing star"
- throwforce = 30
+ throwforce = 20
embedding = list("pain_mult" = 6, "embed_chance" = 100, "fall_chance" = 0)
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 013a025391b..898c133a8a9 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -29,6 +29,7 @@
var/degrees = 0
var/font = PEN_FONT
embedding = list()
+ sharpness = SHARP_POINTY
/obj/item/pen/suicide_act(mob/user)
user.visible_message("
[user] is scribbling numbers all over [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit sudoku...")
@@ -101,7 +102,7 @@
throw_speed = 4
colour = "crimson"
custom_materials = list(/datum/material/gold = 750)
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
resistance_flags = FIRE_PROOF
unique_reskin = list("Oak" = "pen-fountain-o",
"Gold" = "pen-fountain-g",
@@ -196,7 +197,7 @@
*/
/obj/item/pen/edagger
attack_verb = list("slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut") //these won't show up if the pen is off
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
var/on = FALSE
/obj/item/pen/edagger/ComponentInitialize()
diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
index cc5122052db..8ffa5b51a7a 100644
--- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
+++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
@@ -38,7 +38,7 @@
/obj/item/ammo_box/c38/dumdum
name = "speed loader (.38 DumDum)"
- desc = "Designed to quickly reload revolvers. DumDum bullets shatter on impact and shred the target's innards, likely getting caught inside."
+ desc = "Designed to quickly reload revolvers. These rounds expand on impact, allowing them to shred the target and cause massive bleeding. Very weak against armor and distant targets."
ammo_type = /obj/item/ammo_casing/c38/dumdum
/obj/item/ammo_box/c38/hotshot
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 8b3860edab4..fc0e58659df 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -198,7 +198,8 @@
return
if(iscarbon(target))
var/mob/living/carbon/C = target
- for(var/datum/wound/W in C.all_wounds)
+ for(var/i in C.all_wounds)
+ var/datum/wound/W = i
if(W.try_treating(src, user))
return // another coward cured!
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index d279ef9cf6c..c08bd8e6afa 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -128,7 +128,7 @@
flags_1 = CONDUCT_1
attack_verb = list("attacked", "slashed", "cut", "sliced")
force = 12
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
can_charge = FALSE
heat = 3800
diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm
index b5135d66bd4..2046ecf1d22 100644
--- a/code/modules/projectiles/guns/magic/staff.dm
+++ b/code/modules/projectiles/guns/magic/staff.dm
@@ -87,7 +87,7 @@
force = 20
armour_penetration = 75
block_chance = 50
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
max_charges = 4
/obj/item/gun/magic/staff/spellblade/Initialize()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index d18be3b119e..ea5fdbde6b6 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -11,6 +11,7 @@
pass_flags = PASSTABLE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
movement_type = FLYING
+ wound_bonus = CANT_WOUND // can't wound by default
//The sound this plays on impact.
var/hitsound = 'sound/weapons/pierce.ogg'
var/hitsound_wall = ""
@@ -124,23 +125,36 @@
var/temporary_unstoppable_movement = FALSE
- ///If defined, on hit we create an item of this type then call hitby() on the hit target with this
+ ///If defined, on hit we create an item of this type then call hitby() on the hit target with this, mainly used for embedding items (bullets) in targets
var/shrapnel_type
+ ///If we have a shrapnel_type defined, these embedding stats will be passed to the spawned shrapnel type, which will roll for embedding on the target
+ var/list/embedding
+
///If TRUE, hit mobs even if they're on the floor and not our target
var/hit_stunned_targets = FALSE
- wound_bonus = CANT_WOUND
- /// For telling whether we want to roll for bone breaking or lacerations if we're bothering with wounds
- var/sharpness = FALSE
+ ///For what kind of brute wounds we're rolling for, if we're doing such a thing. Lasers obviously don't care since they do burn instead.
+ var/sharpness = SHARP_NONE
+ ///How much we want to drop both wound_bonus and bare_wound_bonus (to a minimum of 0 for the latter) per tile, for falloff purposes
+ var/wound_falloff_tile
+ ///How much we want to drop the embed_chance value, if we can embed, per tile, for falloff purposes
+ var/embed_falloff_tile
/obj/projectile/Initialize()
. = ..()
permutated = list()
decayedRange = range
+ if(embedding)
+ updateEmbedding()
/obj/projectile/proc/Range()
range--
+ if(wound_bonus != CANT_WOUND)
+ wound_bonus += wound_falloff_tile
+ bare_wound_bonus = max(0, bare_wound_bonus + wound_falloff_tile)
+ if(embedding)
+ embedding["embed_chance"] += embed_falloff_tile
if(range <= 0 && loc)
on_range()
@@ -743,3 +757,23 @@
/obj/projectile/experience_pressure_difference()
return
+
+///Like [/obj/item/proc/updateEmbedding] but for projectiles instead, call this when you want to add embedding or update the stats on the embedding element
+/obj/projectile/proc/updateEmbedding()
+ if(!shrapnel_type || !LAZYLEN(embedding))
+ return
+
+ AddElement(/datum/element/embed,\
+ embed_chance = (!isnull(embedding["embed_chance"]) ? embedding["embed_chance"] : EMBED_CHANCE),\
+ fall_chance = (!isnull(embedding["fall_chance"]) ? embedding["fall_chance"] : EMBEDDED_ITEM_FALLOUT),\
+ pain_chance = (!isnull(embedding["pain_chance"]) ? embedding["pain_chance"] : EMBEDDED_PAIN_CHANCE),\
+ pain_mult = (!isnull(embedding["pain_mult"]) ? embedding["pain_mult"] : EMBEDDED_PAIN_MULTIPLIER),\
+ remove_pain_mult = (!isnull(embedding["remove_pain_mult"]) ? embedding["remove_pain_mult"] : EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER),\
+ rip_time = (!isnull(embedding["rip_time"]) ? embedding["rip_time"] : EMBEDDED_UNSAFE_REMOVAL_TIME),\
+ ignore_throwspeed_threshold = (!isnull(embedding["ignore_throwspeed_threshold"]) ? embedding["ignore_throwspeed_threshold"] : FALSE),\
+ impact_pain_mult = (!isnull(embedding["impact_pain_mult"]) ? embedding["impact_pain_mult"] : EMBEDDED_IMPACT_PAIN_MULTIPLIER),\
+ jostle_chance = (!isnull(embedding["jostle_chance"]) ? embedding["jostle_chance"] : EMBEDDED_JOSTLE_CHANCE),\
+ jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\
+ pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\
+ projectile_payload = shrapnel_type)
+ return TRUE
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index b76ff677c56..8dac813f8e5 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -6,5 +6,13 @@
nodamage = FALSE
flag = "bullet"
hitsound_wall = "ricochet"
- sharpness = TRUE
+ sharpness = SHARP_POINTY
impact_effect_type = /obj/effect/temp_visual/impact_effect
+ shrapnel_type = /obj/item/shrapnel/bullet
+ embedding = list(embed_chance=15, fall_chance=2, jostle_chance=0, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.5, pain_mult=3, rip_time=10)
+ wound_falloff_tile = -5
+ embed_falloff_tile = -5
+
+/obj/projectile/bullet/smite
+ name = "divine retribution"
+ damage = 10
diff --git a/code/modules/projectiles/projectile/bullets/lmg.dm b/code/modules/projectiles/projectile/bullets/lmg.dm
index a6e2f3386d0..e05240a7369 100644
--- a/code/modules/projectiles/projectile/bullets/lmg.dm
+++ b/code/modules/projectiles/projectile/bullets/lmg.dm
@@ -25,8 +25,10 @@
/obj/projectile/bullet/mm712x82
name = "7.12x82mm bullet"
- damage = 45
+ damage = 40
armour_penetration = 5
+ wound_bonus = -50
+ wound_falloff_tile = 0
/obj/projectile/bullet/mm712x82_ap
name = "7.12x82mm armor-piercing bullet"
@@ -35,8 +37,12 @@
/obj/projectile/bullet/mm712x82_hp
name = "7.12x82mm hollow-point bullet"
- damage = 60
+ damage = 50
armour_penetration = -60
+ sharpness = SHARP_EDGED
+ wound_bonus = -40
+ bare_wound_bonus = 30
+ wound_falloff_tile = -8
/obj/projectile/bullet/incendiary/mm712x82
name = "7.12x82mm incendiary bullet"
@@ -50,4 +56,4 @@
ricochet_chance = 60
ricochet_auto_aim_range = 4
ricochet_incidence_leeway = 35
-
+ wound_bonus = -50
diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm
index 1e53db3cdbd..0752c0f8533 100644
--- a/code/modules/projectiles/projectile/bullets/pistol.dm
+++ b/code/modules/projectiles/projectile/bullets/pistol.dm
@@ -3,11 +3,13 @@
/obj/projectile/bullet/c9mm
name = "9mm bullet"
damage = 30
+ embedding = list(embed_chance=15, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
/obj/projectile/bullet/c9mm_ap
name = "9mm armor-piercing bullet"
damage = 27
armour_penetration = 40
+ embedding = null
/obj/projectile/bullet/c9mm_hp
name = "9mm hollow-point bullet"
diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm
index 0c713426365..dc7b56d77ae 100644
--- a/code/modules/projectiles/projectile/bullets/revolver.dm
+++ b/code/modules/projectiles/projectile/bullets/revolver.dm
@@ -19,8 +19,9 @@
ricochet_chance = 50
ricochet_auto_aim_angle = 10
ricochet_auto_aim_range = 3
- wound_bonus = -35
- sharpness = TRUE
+ wound_bonus = -20
+ bare_wound_bonus = 10
+ embedding = list(embed_chance=15, fall_chance=2, jostle_chance=2, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=5, rip_time=10)
/obj/projectile/bullet/c38/match
name = ".38 Match bullet"
@@ -42,14 +43,21 @@
ricochet_chance = 130
ricochet_decay_damage = 0.8
shrapnel_type = NONE
+ sharpness = SHARP_NONE
+ embedding = null
+// premium .38 ammo from cargo, weak against armor, lower base damage, but excellent at embedding and causing slice wounds at close range
/obj/projectile/bullet/c38/dumdum
name = ".38 DumDum bullet"
damage = 15
armour_penetration = -30
ricochets_max = 0
- wound_bonus = 0
- shrapnel_type = /obj/item/shrapnel/bullet/c38/dumdum
+ sharpness = SHARP_EDGED
+ wound_bonus = 20
+ bare_wound_bonus = 20
+ embedding = list(embed_chance=75, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
+ wound_falloff_tile = -5
+ embed_falloff_tile = -15
/obj/projectile/bullet/c38/trac
name = ".38 TRAC bullet"
@@ -98,6 +106,7 @@
/obj/projectile/bullet/a357
name = ".357 bullet"
damage = 60
+ wound_bonus = -70
// admin only really, for ocelot memes
/obj/projectile/bullet/a357/match
diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm
index 1f596e75f29..d1794ef3036 100644
--- a/code/modules/projectiles/projectile/bullets/rifle.dm
+++ b/code/modules/projectiles/projectile/bullets/rifle.dm
@@ -4,6 +4,7 @@
name = "5.56mm bullet"
damage = 35
armour_penetration = 30
+ wound_bonus = -40
/obj/projectile/bullet/a556/phasic
name = "5.56mm phasic bullet"
@@ -17,6 +18,8 @@
/obj/projectile/bullet/a762
name = "7.62 bullet"
damage = 60
+ wound_bonus = -35
+ wound_falloff_tile = 0
/obj/projectile/bullet/a762_enchanted
name = "enchanted 7.62 bullet"
diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm
index 70ab3dd7aa3..4128eb39d22 100644
--- a/code/modules/projectiles/projectile/bullets/shotgun.dm
+++ b/code/modules/projectiles/projectile/bullets/shotgun.dm
@@ -1,23 +1,26 @@
/obj/projectile/bullet/shotgun_slug
name = "12g shotgun slug"
- damage = 60
+ damage = 50
+ sharpness = SHARP_POINTY
+ wound_bonus = 0
/obj/projectile/bullet/shotgun_slug/executioner
name = "executioner slug" // admin only, can dismember limbs
- sharpness = TRUE
- wound_bonus = 0
+ sharpness = SHARP_EDGED
+ wound_bonus = 80
/obj/projectile/bullet/shotgun_slug/pulverizer
name = "pulverizer slug" // admin only, can crush bones
- sharpness = FALSE
- wound_bonus = 0
+ sharpness = SHARP_NONE
+ wound_bonus = 80
/obj/projectile/bullet/shotgun_beanbag
name = "beanbag slug"
damage = 10
stamina = 55
wound_bonus = 20
- sharpness = FALSE
+ sharpness = SHARP_NONE
+ embedding = null
/obj/projectile/bullet/incendiary/shotgun
name = "incendiary slug"
@@ -68,18 +71,22 @@
return BULLET_ACT_HIT
/obj/projectile/bullet/pellet
- var/tile_dropoff = 0.75
+ var/tile_dropoff = 0.45
var/tile_dropoff_s = 0.5
/obj/projectile/bullet/pellet/shotgun_buckshot
name = "buckshot pellet"
- damage = 12.5
- wound_bonus = -10
+ damage = 7.5
+ wound_bonus = 5
+ bare_wound_bonus = 5
+ wound_falloff_tile = -2.5 // low damage + additional dropoff will already curb wounding potential anything past point blank
/obj/projectile/bullet/pellet/shotgun_rubbershot
name = "rubbershot pellet"
damage = 3
stamina = 11
+ sharpness = SHARP_NONE
+ embedding = null
/obj/projectile/bullet/pellet/shotgun_incapacitate
name = "incapacitating pellet"
@@ -96,8 +103,10 @@
qdel(src)
/obj/projectile/bullet/pellet/shotgun_improvised
- tile_dropoff = 0.55 //Come on it does 6 damage don't be like that.
+ tile_dropoff = 0.35 //Come on it does 6 damage don't be like that.
damage = 6
+ wound_bonus = 0
+ bare_wound_bonus = 7.5
/obj/projectile/bullet/pellet/shotgun_improvised/Initialize()
. = ..()
diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm
index faa0fd98ca2..3cdf3de789e 100644
--- a/code/modules/projectiles/projectile/bullets/smg.dm
+++ b/code/modules/projectiles/projectile/bullets/smg.dm
@@ -2,7 +2,9 @@
/obj/projectile/bullet/c45
name = ".45 bullet"
- damage = 35
+ damage = 30
+ wound_bonus = -10
+ wound_falloff_tile = -10
/obj/projectile/bullet/c45_ap
name = ".45 armor-piercing bullet"
@@ -19,11 +21,15 @@
/obj/projectile/bullet/c46x30mm
name = "4.6x30mm bullet"
damage = 20
+ wound_bonus = -5
+ bare_wound_bonus = 5
+ embed_falloff_tile = -4
/obj/projectile/bullet/c46x30mm_ap
name = "4.6x30mm armor-piercing bullet"
damage = 15
armour_penetration = 40
+ embedding = null
/obj/projectile/bullet/incendiary/c46x30mm
name = "4.6x30mm incendiary bullet"
diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
index b655ae30568..b263b1f8f82 100644
--- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
@@ -420,8 +420,9 @@
if(method in list(PATCH, TOUCH, VAPOR))
var/harmies = min(carbies.getBruteLoss(),carbies.adjustBruteLoss(-1.25 * reac_volume)*-1)
var/burnies = min(carbies.getFireLoss(),carbies.adjustFireLoss(-1.25 * reac_volume)*-1)
- for(var/datum/wound/burn/burn_wound in carbies.all_wounds)
- burn_wound.regenerate_flesh(reac_volume)
+ for(var/i in carbies.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_synthflesh(reac_volume)
carbies.adjustToxLoss((harmies+burnies)*0.66)
if(show_message)
to_chat(carbies, "
You feel your burns and bruises healing! It stings like hell!")
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index 19aa060636a..acbc59c3df3 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -132,6 +132,25 @@
. = 1
..()
+// i googled "natural coagulant" and a couple of results came up for banana peels, so after precisely 30 more seconds of research, i now dub grinding banana peels good for your blood
+/datum/reagent/consumable/banana_peel
+ name = "Pulped Banana Peel"
+ description = "Okay, so you put a banana peel in a grinder... Why, exactly?"
+ color = "#863333" // rgb: 175, 175, 0
+ reagent_state = SOLID
+ taste_description = "stringy, bitter pulp"
+ glass_name = "glass of banana peel pulp"
+ glass_desc = "Okay, so you put a banana peel in a grinder... Why, exactly?"
+
+/datum/reagent/consumable/baked_banana_peel
+ name = "Baked Banana Peel Powder"
+ description = "You took a banana peel... pulped it... baked it... Where are you going with this?"
+ color = "#863333" // rgb: 175, 175, 0
+ reagent_state = SOLID
+ taste_description = "bitter powder"
+ glass_name = "glass of banana peel powder"
+ description = "You took a banana peel... pulped it... baked it... Where are you going with this?"
+
/datum/reagent/consumable/nothing
name = "Nothing"
description = "Absolutely nothing."
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 592924afaea..e6b3c864593 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -151,8 +151,8 @@
M.adjustToxLoss(-power, 0, TRUE) //heals TOXINLOVERs
M.adjustCloneLoss(-power, 0)
for(var/i in M.all_wounds)
- var/datum/wound/W = i
- W.on_xadone(power)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(power)
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) //fixes common causes for disfiguration
. = 1
metabolization_rate = REAGENTS_METABOLISM * (0.00001 * (M.bodytemperature ** 2) + 0.5)
@@ -204,8 +204,8 @@
M.adjustToxLoss(-power, 0, TRUE)
M.adjustCloneLoss(-power, 0)
for(var/i in M.all_wounds)
- var/datum/wound/W = i
- W.on_xadone(power)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(power)
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC)
. = 1
..()
@@ -272,7 +272,7 @@
/datum/reagent/medicine/salglu_solution
name = "Saline-Glucose Solution"
- description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute."
+ description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute, as well as slowly speeding blood regeneration."
reagent_state = LIQUID
color = "#DCDCDC"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
@@ -280,6 +280,7 @@
taste_description = "sweetness and salt"
var/last_added = 0
var/maximum_reachable = BLOOD_VOLUME_NORMAL - 10 //So that normal blood regeneration can continue with salglu active
+ var/extra_regen = 0.25 // in addition to acting as temporary blood, also add this much to their actual blood per tick
/datum/reagent/medicine/salglu_solution/on_mob_life(mob/living/carbon/M)
if(last_added)
@@ -289,7 +290,7 @@
var/amount_to_add = min(M.blood_volume, volume*5)
var/new_blood_level = min(M.blood_volume + amount_to_add, maximum_reachable)
last_added = new_blood_level - M.blood_volume
- M.blood_volume = new_blood_level
+ M.blood_volume = new_blood_level + extra_regen
if(prob(33))
M.adjustBruteLoss(-0.5*REM, 0)
M.adjustFireLoss(-0.5*REM, 0)
@@ -1337,10 +1338,57 @@
L.Dizzy(0)
L.Jitter(0)
-// handled in cut wounds process
+// helps bleeding wounds clot faster
/datum/reagent/medicine/coagulant
name = "Sanguirite"
- description = "A coagulant used to help open cuts clot faster."
+ description = "A proprietary coagulant used to help bleeding wounds clot faster."
reagent_state = LIQUID
color = "#bb2424"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
+ overdose_threshold = 20
+ /// How much base clotting we do per bleeding wound, multiplied by the below number for each bleeding wound
+ var/clot_rate = 0.25
+ /// If we have multiple bleeding wounds, we count the number of bleeding wounds, then multiply the clot rate by this^(n) before applying it to each cut, so more cuts = less clotting per cut (though still more total clotting)
+ var/clot_coeff_per_wound = 0.9
+
+/datum/reagent/medicine/coagulant/on_mob_life(mob/living/carbon/M)
+ . = ..()
+ if(!M.blood_volume || !M.all_wounds)
+ return
+
+ var/effective_clot_rate = clot_rate
+
+ for(var/i in M.all_wounds)
+ var/datum/wound/iter_wound = i
+ if(iter_wound.blood_flow)
+ effective_clot_rate *= clot_coeff_per_wound
+
+ for(var/i in M.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.blood_flow = max(0, iter_wound.blood_flow - effective_clot_rate)
+
+/datum/reagent/medicine/coagulant/overdose_process(mob/living/M)
+ . = ..()
+ if(!M.blood_volume)
+ return
+
+ if(prob(15))
+ M.losebreath += rand(2,4)
+ M.adjustOxyLoss(rand(1,3))
+ if(prob(30))
+ to_chat(M, "
You can feel your blood clotting up in your veins!")
+ else if(prob(10))
+ to_chat(M, "
You feel like your blood has stopped moving!")
+
+ if(prob(50))
+ var/obj/item/organ/lungs/our_lungs = M.getorganslot(ORGAN_SLOT_LUNGS)
+ our_lungs.applyOrganDamage(1)
+ else
+ var/obj/item/organ/heart/our_heart = M.getorganslot(ORGAN_SLOT_HEART)
+ our_heart.applyOrganDamage(1)
+
+// can be synthesized on station rather than bought. made by grinding a banana peel, heating it up, then mixing the banana peel powder with salglu
+/datum/reagent/medicine/coagulant/weak
+ name = "Synthi-Sanguirite"
+ description = "A synthetic coagulant used to help bleeding wounds clot faster. Not quite as effective as name brand Sanguirite, especially on patients with lots of cuts."
+ clot_coeff_per_wound = 0.8
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 1f973772c40..9f46d5ec43f 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -201,6 +201,11 @@
M.ExtinguishMob()
..()
+/datum/reagent/water/on_mob_life(mob/living/carbon/M)
+ . = ..()
+ if(M.blood_volume)
+ M.blood_volume += 0.1 // water is good for you!
+
/datum/reagent/water/holywater
name = "Holy Water"
description = "Water blessed by some deity."
@@ -233,6 +238,8 @@
..()
/datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M)
+ if(M.blood_volume)
+ M.blood_volume += 0.1 // water is good for you!
if(!data)
data = list("misc" = 1)
data["misc"]++
@@ -2285,6 +2292,7 @@
reagent_state = LIQUID
color = "#D2FFFA"
metabolization_rate = 0.75 * REAGENTS_METABOLISM // 5u (WOUND_DETERMINATION_CRITICAL) will last for ~17 ticks
+ self_consuming = TRUE
/// Whether we've had at least WOUND_DETERMINATION_SEVERE (2.5u) of determination at any given time. No damage slowdown immunity or indication we're having a second wind if it's just a single moderate wound
var/significant = FALSE
diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index 3165fe9f4a8..95322debcd0 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -30,6 +30,18 @@
results = list(/datum/reagent/medicine/salglu_solution = 3)
required_reagents = list(/datum/reagent/consumable/sodiumchloride = 1, /datum/reagent/water = 1, /datum/reagent/consumable/sugar = 1)
+/datum/chemical_reaction/baked_banana_peel
+ results = list(/datum/reagent/consumable/baked_banana_peel = 1)
+ required_temp = 413.15 // if it's good enough for caramel it's good enough for this
+ required_reagents = list(/datum/reagent/consumable/banana_peel = 1)
+ mix_message = "The pulp dries up and takes on a powdery state!"
+ mob_react = FALSE
+
+/datum/chemical_reaction/coagulant_weak
+ results = list(/datum/reagent/medicine/coagulant/weak = 3)
+ required_reagents = list(/datum/reagent/medicine/salglu_solution = 2, /datum/reagent/consumable/baked_banana_peel = 1)
+ mob_react = FALSE
+
/datum/chemical_reaction/mine_salve
results = list(/datum/reagent/medicine/mine_salve = 3)
required_reagents = list(/datum/reagent/fuel/oil = 1, /datum/reagent/water = 1, /datum/reagent/iron = 1)
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 6226e681e66..6711be55a1e 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -277,7 +277,14 @@
/obj/item/reagent_containers/hypospray/medipen/ekit
name = "emergency first-aid autoinjector"
- desc = "An epinephrine medipen with trace amounts of coagulants and antibiotics to help stabilize bad cuts and burns."
+ desc = "An epinephrine medipen with extra coagulant and antibiotics to help stabilize bad cuts and burns."
volume = 15
amount_per_transfer_from_this = 15
list_reagents = list(/datum/reagent/medicine/epinephrine = 12, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/medicine/spaceacillin = 0.5)
+
+/obj/item/reagent_containers/hypospray/medipen/blood_loss
+ name = "hypovolemic-response autoinjector"
+ desc = "A medipen designed to stabilize and rapidly reverse severe bloodloss."
+ volume = 15
+ amount_per_transfer_from_this = 15
+ list_reagents = list(/datum/reagent/medicine/epinephrine = 5, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/iron = 3.5, /datum/reagent/medicine/salglu_solution = 4)
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 38bddb8e3b8..0aa074a33cd 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -15,6 +15,7 @@
custom_materials = list(/datum/material/iron=10, /datum/material/glass=20)
reagent_flags = TRANSPARENT
custom_price = 150
+ sharpness = SHARP_POINTY
/obj/item/reagent_containers/syringe/Initialize()
. = ..()
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 55ca39ec0a6..0adebde80d8 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -81,12 +81,12 @@
/// A hat won't cover your face, but a shirt covering your chest will cover your... you know, chest
var/scars_covered_by_clothes = TRUE
- /// Descriptions for the locations on the limb for scars to be assigned, just cosmetic
- var/list/specific_locations = list("general area")
/// So we know if we need to scream if this limb hits max damage
var/last_maxed
/// How much generic bleedstacks we have on this bodypart
var/generic_bleedstacks
+ /// If we have a gauze wrapping currently applied (not including splints)
+ var/obj/item/stack/current_gauze
/obj/item/bodypart/examine(mob/user)
@@ -149,9 +149,23 @@
var/turf/T = get_turf(src)
if(status != BODYPART_ROBOTIC)
playsound(T, 'sound/misc/splort.ogg', 50, TRUE, -1)
+ if(current_gauze)
+ QDEL_NULL(current_gauze)
+ for(var/obj/item/organ/drop_organ in get_organs())
+ drop_organ.transfer_to_limb(src, owner)
for(var/obj/item/I in src)
I.forceMove(T)
+///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have
+/obj/item/bodypart/proc/get_organs()
+ if(!owner)
+ return
+ . = list()
+ for(var/i in owner.internal_organs) //internal organs inside the dismembered limb are dropped.
+ var/obj/item/organ/organ_check = i
+ if(check_zone(organ_check.zone) == body_zone)
+ . += organ_check
+
/obj/item/bodypart/proc/consider_processing()
if(stamina_dam > DAMAGE_PRECISION)
. = TRUE
@@ -169,7 +183,7 @@
//Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all.
//Damage will not exceed max_damage using this proc
//Cannot apply negative damage
-/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) // maybe separate BRUTE_SHARP and BRUTE_OTHER eventually somehow hmm
+/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) // maybe separate BRUTE_SHARP and BRUTE_OTHER eventually somehow hmm
var/hit_percent = (100-blocked)/100
if((!brute && !burn && !stamina) || hit_percent <= 0)
return FALSE
@@ -197,16 +211,64 @@
if(ALIEN_BODYPART,LARVA_BODYPART) //aliens take double burn //nothing can burn with so much snowflake code around
burn *= 2
- var/wounding_type = (brute > burn ? WOUND_BRUTE : WOUND_BURN)
+ /*
+ // START WOUND HANDLING
+ */
+
+ // what kind of wounds we're gonna roll for, take the greater between brute and burn, then if it's brute, we subdivide based on sharpness
+ var/wounding_type = (brute > burn ? WOUND_BLUNT : WOUND_BURN)
var/wounding_dmg = max(brute, burn)
- if(wounding_type == WOUND_BRUTE && sharpness)
- wounding_type = WOUND_SHARP
- // i know this is effectively the same check as above but i don't know if those can null the damage by rounding and want to be safe
- if(owner && wounding_dmg > 4 && wound_bonus != CANT_WOUND)
- // if you want to make tox wounds or some other type, this will need to be expanded and made more modular
- // handle all our wounding stuff
+
+ var/mangled_state = get_mangled_state()
+ var/bio_state = owner.get_biological_state()
+ var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
+
+ if(wounding_type == WOUND_BLUNT)
+ if(sharpness == SHARP_EDGED)
+ wounding_type = WOUND_SLASH
+ else if(sharpness == SHARP_POINTY)
+ wounding_type = WOUND_PIERCE
+
+ //Handling for bone only/flesh only(none right now)/flesh and bone targets
+ switch(bio_state)
+ // if we're bone only, all cutting attacks go straight to the bone
+ if(BIO_JUST_BONE)
+ if(wounding_type == WOUND_SLASH)
+ wounding_type = WOUND_BLUNT
+ wounding_dmg *= (easy_dismember ? 1 : 0.5)
+ else if(wounding_type == WOUND_PIERCE)
+ wounding_type = WOUND_BLUNT
+ wounding_dmg *= (easy_dismember ? 1 : 0.75)
+ if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+ // note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
+ // standard humanoids
+ if(BIO_FLESH_BONE)
+ // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
+ // So a big sharp weapon is still all you need to destroy a limb
+ if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
+ playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
+ if(wounding_type == WOUND_SLASH && !easy_dismember)
+ wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area
+ if(wounding_type == WOUND_PIERCE && !easy_dismember)
+ wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
+ wounding_type = WOUND_BLUNT
+ else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+
+ // now we have our wounding_type and are ready to carry on with wounds and dealing the actual damage
+ if(owner && wounding_dmg >= WOUND_MINIMUM_DAMAGE && wound_bonus != CANT_WOUND)
check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
+ for(var/i in wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus)
+
+ /*
+ // END WOUND HANDLING
+ */
+
+ //back to our regularly scheduled program, we now actually apply damage if there's room below limb damage cap
var/can_inflict = max_damage - get_damage()
var/total_damage = brute + burn
if(total_damage > can_inflict && total_damage > 0) // TODO: the second part of this check should be removed once disabling is all done
@@ -219,10 +281,6 @@
brute_dam += brute
burn_dam += burn
- for(var/i in wounds)
- var/datum/wound/W = i
- W.receive_damage(wounding_type, wounding_dmg, wound_bonus)
-
//We've dealt the physical damages, if there's room lets apply the stamina damage.
stamina_dam += round(clamp(stamina, 0, max_stamina_damage - stamina_dam), DAMAGE_PRECISION)
@@ -236,14 +294,58 @@
update_disabled()
return update_bodypart_damage_state() || .
+/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds
+/obj/item/bodypart/proc/painless_wound_roll(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus, sharpness=SHARP_NONE)
+ if(!owner || phantom_wounding_dmg <= WOUND_MINIMUM_DAMAGE || wound_bonus == CANT_WOUND)
+ return
+
+ var/mangled_state = get_mangled_state()
+ var/bio_state = owner.get_biological_state()
+ var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
+
+ if(wounding_type == WOUND_BLUNT)
+ if(sharpness == SHARP_EDGED)
+ wounding_type = WOUND_SLASH
+ else if(sharpness == SHARP_POINTY)
+ wounding_type = WOUND_PIERCE
+
+ //Handling for bone only/flesh only(none right now)/flesh and bone targets
+ switch(bio_state)
+ // if we're bone only, all cutting attacks go straight to the bone
+ if(BIO_JUST_BONE)
+ if(wounding_type == WOUND_SLASH)
+ wounding_type = WOUND_BLUNT
+ phantom_wounding_dmg *= (easy_dismember ? 1 : 0.5)
+ else if(wounding_type == WOUND_PIERCE)
+ wounding_type = WOUND_BLUNT
+ phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75)
+ if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+ // note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
+ // standard humanoids
+ if(BIO_FLESH_BONE)
+ // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
+ // So a big sharp weapon is still all you need to destroy a limb
+ if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
+ playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
+ if(wounding_type == WOUND_SLASH && !easy_dismember)
+ phantom_wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area
+ if(wounding_type == WOUND_PIERCE && !easy_dismember)
+ phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
+ wounding_type = WOUND_BLUNT
+ else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+
+ check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)
+
/**
* check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria
*
- * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [check_wounding_mods()], then go down the list from most severe to least severe wounds in that category.
+ * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [/obj/item/bodypart/proc/check_wounding_mods], then go down the list from most severe to least severe wounds in that category.
* We can promote a wound from a lesser to a higher severity this way, but we give up if we have a wound of the given type and fail to roll a higher severity, so no sidegrades/downgrades
*
* Arguments:
- * * woundtype- Either WOUND_SHARP, WOUND_BRUTE, or WOUND_BURN based on the attack type.
+ * * woundtype- Either WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE, or WOUND_BURN based on the attack type.
* * damage- How much damage is tied to this attack, since wounding potential scales with damage in an attack (see: WOUND_DAMAGE_EXPONENT)
* * wound_bonus- The wound_bonus of an attack
* * bare_wound_bonus- The bare_wound_bonus of an attack
@@ -252,21 +354,29 @@
// actually roll wounds if applicable
if(HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE))
damage *= 1.5
+ else
+ damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE)
if(HAS_TRAIT(owner,TRAIT_HARDLIMBDISABLE))
- damage *= 0.5
+ damage *= 0.8
+
+ if(HAS_TRAIT(owner, TRAIT_EASYDISMEMBER))
+ damage *= 1.25
var/base_roll = rand(1, round(damage ** WOUND_DAMAGE_EXPONENT))
var/injury_roll = base_roll
injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus)
- var/list/wounds_checking
+ var/list/wounds_checking = GLOB.global_wound_types[woundtype]
- switch(woundtype)
- if(WOUND_SHARP)
- wounds_checking = WOUND_LIST_CUT
- if(WOUND_BRUTE)
- wounds_checking = WOUND_LIST_BONE
- if(WOUND_BURN)
- wounds_checking = WOUND_LIST_BURN
+ // quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow
+ if(ishuman(owner))
+ var/mob/living/carbon/human/human_wearer = owner
+ var/list/clothing = human_wearer.clothingonpart(src)
+ for(var/i in clothing)
+ var/obj/item/clothing/clothes_check = i
+ // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
+ if(clothes_check.armor.getRating("wound"))
+ bare_wound_bonus = 0
+ break
//cycle through the wounds of the relevant category from the most severe down
for(var/PW in wounds_checking)
@@ -281,21 +391,22 @@
replaced_wound = existing_wound
if(initial(possible_wound.threshold_minimum) < injury_roll)
+ var/datum/wound/new_wound
if(replaced_wound)
- var/datum/wound/new_wound = replaced_wound.replace_wound(possible_wound)
- log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll)
+ new_wound = replaced_wound.replace_wound(possible_wound)
+ log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) // dismembering wounds are logged in the apply_wound() for loss wounds since they delete themselves immediately, these will be immediately returned
else
- var/datum/wound/new_wound = new possible_wound
+ new_wound = new possible_wound
new_wound.apply_wound(src)
log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll)
- return
+ return new_wound
// try forcing a specific wound, but only if there isn't already a wound of that severity or greater for that type on this bodypart
/obj/item/bodypart/proc/force_wound_upwards(specific_woundtype, smited = FALSE)
var/datum/wound/potential_wound = specific_woundtype
for(var/i in wounds)
var/datum/wound/existing_wound = i
- if(existing_wound.type in (initial(potential_wound.wound_type)))
+ if(existing_wound.wound_type == initial(potential_wound.wound_type))
if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force
existing_wound.replace_wound(potential_wound, smited)
return
@@ -303,12 +414,20 @@
var/datum/wound/new_wound = new potential_wound
new_wound.apply_wound(src, smited = smited)
+/**
+ * check_wounding_mods() is where we handle the various modifiers of a wound roll
+ *
+ * A short list of things we consider: any armor a human target may be wearing, and if they have no wound armor on the limb, if we have a bare_wound_bonus to apply, plus the plain wound_bonus
+ * We also flick through all of the wounds we currently have on this limb and add their threshold penalties, so that having lots of bad wounds makes you more liable to get hurt worse
+ * Lastly, we add the inherent wound_resistance variable the bodypart has (heads and chests are slightly harder to wound), and a small bonus if the limb is already disabled
+ *
+ * Arguments:
+ * * It's the same ones on [receive_damage]
+ */
/obj/item/bodypart/proc/check_woundings_mods(wounding_type, damage, wound_bonus, bare_wound_bonus)
var/armor_ablation = 0
var/injury_mod = 0
- //var/bwb = 0
-
if(owner && ishuman(owner))
var/mob/living/carbon/human/H = owner
var/list/clothing = H.clothingonpart(src)
@@ -316,7 +435,7 @@
var/obj/item/clothing/C = c
// unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
armor_ablation += C.armor.getRating("wound")
- if(wounding_type == WOUND_SHARP)
+ if(wounding_type == WOUND_SLASH)
C.take_damage_zone(body_zone, damage, BRUTE, armour_penetration)
else if(wounding_type == WOUND_BURN && damage >= 10) // lazy way to block freezing from shredding clothes without adding another var onto apply_damage()
C.take_damage_zone(body_zone, damage, BURN, armour_penetration)
@@ -332,7 +451,7 @@
injury_mod += W.threshold_penalty
var/part_mod = -wound_resistance
- if(is_disabled())
+ if(get_damage(TRUE) >= max_damage)
part_mod += disabled_wound_penalty
injury_mod += part_mod
@@ -382,12 +501,11 @@
if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE))
. = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
- // TODO: figure if i'm keeping disabling to broken bones only
- if((get_damage(TRUE) >= max_damage) || (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) && (get_damage(TRUE) >= (max_damage * 0.6)))) //Easy limb disable disables the limb at 40% health instead of 0%
+ if(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0%
if(!last_maxed)
owner.emote("scream")
last_maxed = TRUE
- if(!is_organic_limb())
+ if(!is_organic_limb() || stamina_dam >= max_damage)
return BODYPART_DISABLED_DAMAGE
else if(disabled && (get_damage(TRUE) <= (max_damage * 0.8))) // reenabled at 80% now instead of 50% as of wounds update
last_maxed = FALSE
@@ -603,18 +721,29 @@
if(isnull(wounds))
return
- for(var/thing in wounds)
- var/datum/wound/W = thing
- if(istype(W, checking_type))
- return W
+ for(var/i in wounds)
+ if(istype(i, checking_type))
+ return i
-/// very rough start for updating efficiency and other stats on a body part whenever a wound is gained/lost
-/obj/item/bodypart/proc/update_wounds()
+/**
+ * update_wounds() is called whenever a wound is gained or lost on this bodypart, as well as if there's a change of some kind on a bone wound possibly changing disabled status
+ *
+ * Covers tabulating the damage multipliers we have from wounds (burn specifically), as well as deleting our gauze wrapping if we don't have any wounds that can use bandaging
+ *
+ * Arguments:
+ * * replaced- If true, this is being called from the remove_wound() of a wound that's being replaced, so the bandage that already existed is still relevant, but the new wound hasn't been added yet
+ */
+/obj/item/bodypart/proc/update_wounds(replaced = FALSE)
var/dam_mul = 1 //initial(wound_damage_multiplier)
- // we can only have one wound per type, but remember there's multiple types
- for(var/datum/wound/W in wounds)
- dam_mul *= W.damage_mulitplier_penalty
+ // we can (normally) only have one wound per type, but remember there's multiple types (smites like :B:loodless can generate multiple cuts on a limb)
+ for(var/i in wounds)
+ var/datum/wound/iter_wound = i
+ dam_mul *= iter_wound.damage_mulitplier_penalty
+
+ if(!LAZYLEN(wounds) && current_gauze && !replaced)
+ owner.visible_message("
\The [current_gauze] on [owner]'s [name] fall away.", "
The [current_gauze] on your [name] fall away.")
+ QDEL_NULL(current_gauze)
wound_damage_multiplier = dam_mul
update_disabled()
@@ -627,9 +756,6 @@
if(generic_bleedstacks > 0)
bleed_rate++
- if(brute_dam >= 40)
- bleed_rate += (brute_dam * 0.008)
-
//We want an accurate reading of .len
listclearnulls(embedded_objects)
for(var/obj/item/embeddies in embedded_objects)
@@ -640,4 +766,40 @@
var/datum/wound/W = thing
bleed_rate += W.blood_flow
+ if(owner.mobility_flags & ~MOBILITY_STAND)
+ bleed_rate *= 0.75
return bleed_rate
+
+/**
+ * apply_gauze() is used to- well, apply gauze to a bodypart
+ *
+ * As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons).
+ * The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze
+ * applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared,
+ * the gauze falls off.
+ *
+ * Arguments:
+ * * gauze- Just the gauze stack we're taking a sheet from to apply here
+ */
+/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze)
+ if(!istype(gauze) || !gauze.absorption_capacity)
+ return
+ QDEL_NULL(current_gauze)
+ current_gauze = new gauze.type(src, 1)
+ gauze.use(1)
+
+/**
+ * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity.
+ *
+ * The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandages fall off and we're left with nothing.
+ *
+ * Arguments:
+ * * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?)
+ */
+/obj/item/bodypart/proc/seep_gauze(seep_amt = 0)
+ if(!current_gauze)
+ return
+ current_gauze.absorption_capacity -= seep_amt
+ if(current_gauze.absorption_capacity < 0)
+ owner.visible_message("
\The [current_gauze] on [owner]'s [name] fall away in rags.", "
\The [current_gauze] on your [name] fall away in rags.", vision_distance=COMBAT_MESSAGE_RANGE)
+ QDEL_NULL(current_gauze)
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 48312107dad..f02c7a86a36 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -4,7 +4,7 @@
return TRUE
//Dismember a limb
-/obj/item/bodypart/proc/dismember(dam_type = BRUTE)
+/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE)
if(!owner)
return FALSE
var/mob/living/carbon/C = owner
@@ -17,7 +17,8 @@
var/obj/item/bodypart/affecting = C.get_bodypart(BODY_ZONE_CHEST)
affecting.receive_damage(clamp(brute_dam/2 * affecting.body_damage_coeff, 15, 50), clamp(burn_dam/2 * affecting.body_damage_coeff, 0, 50), wound_bonus=CANT_WOUND) //Damage the chest based on limb's existing damage
- C.visible_message("
[C]'s [src.name] is violently dismembered!")
+ if(!silent)
+ C.visible_message("
[C]'s [name] is violently dismembered!")
C.emote("scream")
playsound(get_turf(C), 'sound/effects/dismember.ogg', 80, TRUE)
SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "dismembered", /datum/mood_event/dismembered)
@@ -34,6 +35,7 @@
burn()
return TRUE
add_mob_blood(C)
+ C.bleed(rand(20, 40))
var/direction = pick(GLOB.cardinals)
var/t_range = rand(2,max(throw_range/2, 2))
var/turf/target_turf = get_turf(src)
@@ -154,7 +156,52 @@
forceMove(Tsec)
+/**
+ * get_mangled_state() is relevant for flesh and bone bodyparts, and returns whether this bodypart has mangled skin, mangled bone, or both (or neither i guess)
+ *
+ * Dismemberment for flesh and bone requires the victim to have the skin on their bodypart destroyed (either a critical cut or piercing wound), and at least a hairline fracture
+ * (severe bone), at which point we can start rolling for dismembering. The attack must also deal at least 10 damage, and must be a brute attack of some kind (sorry for now, cakehat, maybe later)
+ *
+ * Returns: BODYPART_MANGLED_NONE if we're fine, BODYPART_MANGLED_FLESH if our skin is broken, BODYPART_MANGLED_BONE if our bone is broken, or BODYPART_MANGLED_BOTH if both are broken and we're up for dismembering
+ */
+/obj/item/bodypart/proc/get_mangled_state()
+ . = BODYPART_MANGLED_NONE
+ for(var/i in wounds)
+ var/datum/wound/iter_wound = i
+ if((iter_wound.wound_flags & MANGLES_BONE))
+ . |= BODYPART_MANGLED_BONE
+ if((iter_wound.wound_flags & MANGLES_FLESH))
+ . |= BODYPART_MANGLED_FLESH
+
+/**
+ * try_dismember() is used, once we've confirmed that a flesh and bone bodypart has both the skin and bone mangled, to actually roll for it
+ *
+ * Mangling is described in the above proc, [/obj/item/bodypart/proc/get_mangled_state()]. This simply makes the roll for whether we actually dismember or not
+ * using how damaged the limb already is, and how much damage this blow was for. If we have a critical bone wound instead of just a severe, we add +10% to the roll.
+ * Lastly, we choose which kind of dismember we want based on the wounding type we hit with. Note we don't care about all the normal mods or armor for this
+ *
+ * Arguments:
+ * * wounding_type: Either WOUND_BLUNT, WOUND_SLASH, or WOUND_PIERCE, basically only matters for the dismember message
+ * * wounding_dmg: The damage of the strike that prompted this roll, higher damage = higher chance
+ * * wound_bonus: Not actually used right now, but maybe someday
+ * * bare_wound_bonus: ditto above
+ */
+/obj/item/bodypart/proc/try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
+ if(wounding_dmg < DISMEMBER_MINIMUM_DAMAGE)
+ return
+
+ var/base_chance = wounding_dmg + (get_damage() / max_damage * 50) // how much damage we dealt with this blow, + 50% of the damage percentage we already had on this bodypart
+ if(locate(/datum/wound/blunt/critical) in wounds) // we only require a severe bone break, but if there's a critical bone break, we'll add 10% more
+ base_chance += 10
+
+ if(!prob(base_chance))
+ return
+
+ var/datum/wound/loss/dismembering = new
+ dismembering.apply_dismember(src, wounding_type)
+
+ return TRUE
//when a limb is dropped, the internal organs are removed from the mob and put into the limb
/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C)
@@ -414,4 +461,7 @@
if(!L.attach_limb(src, 1))
qdel(L)
return FALSE
+ var/datum/scar/scaries = new
+ var/datum/wound/loss/phantom_loss = new // stolen valor, really
+ scaries.generate(L, phantom_loss)
return TRUE
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index 9abbf3441b6..61ddecefb1f 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -14,7 +14,6 @@
stam_damage_coeff = 1
max_stamina_damage = 100
wound_resistance = 10
- specific_locations = list("left eyebrow", "cheekbone", "neck", "throat", "jawline", "entire face")
scars_covered_by_clothes = FALSE
var/mob/living/brain/brainmob = null //The current occupant.
@@ -94,7 +93,7 @@
/obj/item/bodypart/head/can_dismember(obj/item/I)
- if(!((owner.stat == DEAD) || owner.InFullCritical()))
+ if(owner && !((owner.stat == DEAD) || owner.InFullCritical()))
return FALSE
return ..()
diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm
index bd4abaa7650..3dea81eff1d 100644
--- a/code/modules/surgery/bodyparts/parts.dm
+++ b/code/modules/surgery/bodyparts/parts.dm
@@ -11,11 +11,10 @@
stam_damage_coeff = 1
max_stamina_damage = 120
var/obj/item/cavity_item
- specific_locations = list("upper chest", "lower abdomen", "midsection", "collarbone", "lower back")
wound_resistance = 10
/obj/item/bodypart/chest/can_dismember(obj/item/I)
- if(!((owner.stat == DEAD) || owner.InFullCritical()))
+ if(!((owner.stat == DEAD) || owner.InFullCritical()) || !get_organs())
return FALSE
return ..()
@@ -72,7 +71,6 @@
held_index = 1
px_x = -6
px_y = 0
- specific_locations = list("outer left forearm", "inner left wrist", "left elbow", "left bicep", "left shoulder")
/obj/item/bodypart/l_arm/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM))
@@ -138,7 +136,6 @@
px_x = 6
px_y = 0
max_stamina_damage = 50
- specific_locations = list("outer right forearm", "inner right wrist", "right elbow", "right bicep", "right shoulder")
/obj/item/bodypart/r_arm/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM))
@@ -201,7 +198,6 @@
px_x = -2
px_y = 12
max_stamina_damage = 50
- specific_locations = list("inner left thigh", "outer left calf", "outer left hip", " left kneecap", "lower left shin")
/obj/item/bodypart/l_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
@@ -261,7 +257,6 @@
px_x = 2
px_y = 12
max_stamina_damage = 50
- specific_locations = list("inner right thigh", "outer right calf", "outer right hip", "right kneecap", "lower right shin")
/obj/item/bodypart/r_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
diff --git a/code/modules/surgery/bone_mending.dm b/code/modules/surgery/bone_mending.dm
index 81d9fa8d97d..0c0083575bb 100644
--- a/code/modules/surgery/bone_mending.dm
+++ b/code/modules/surgery/bone_mending.dm
@@ -8,7 +8,7 @@
target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
- targetable_wound = /datum/wound/brute/bone/severe
+ targetable_wound = /datum/wound/blunt/severe
/datum/surgery/repair_bone_hairline/can_start(mob/living/user, mob/living/carbon/target)
if(..())
@@ -23,7 +23,7 @@
target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
- targetable_wound = /datum/wound/brute/bone/critical
+ targetable_wound = /datum/wound/blunt/critical
/datum/surgery/repair_bone_compound/can_start(mob/living/user, mob/living/carbon/target)
if(..())
diff --git a/code/modules/surgery/burn_dressing.dm b/code/modules/surgery/burn_dressing.dm
index 1688f7b5d17..8bfa52d2454 100644
--- a/code/modules/surgery/burn_dressing.dm
+++ b/code/modules/surgery/burn_dressing.dm
@@ -94,7 +94,8 @@
log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]")
burn_wound.sanitization += 3
burn_wound.flesh_healing += 5
- burn_wound.force_bandage(tool)
+ var/obj/item/bodypart/the_part = target.get_bodypart(target_zone)
+ the_part.apply_gauze(tool)
else
to_chat(user, "
[target] has no burns there!")
return ..()
diff --git a/code/modules/surgery/repair_puncture.dm b/code/modules/surgery/repair_puncture.dm
new file mode 100644
index 00000000000..12aefefc822
--- /dev/null
+++ b/code/modules/surgery/repair_puncture.dm
@@ -0,0 +1,108 @@
+
+/////BURN FIXING SURGERIES//////
+
+//the step numbers of each of these two, we only currently use the first to switch back and forth due to advancing after finishing steps anyway
+#define REALIGN_INNARDS 1
+#define WELD_VEINS 2
+
+///// Repair puncture wounds
+/datum/surgery/repair_puncture
+ name = "Repair puncture"
+ steps = list(/datum/surgery_step/incise, /datum/surgery_step/repair_innards, /datum/surgery_step/seal_veins, /datum/surgery_step/close) // repeat between steps 2 and 3 until healed
+ target_mobtypes = list(/mob/living/carbon)
+ possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
+ requires_real_bodypart = TRUE
+ targetable_wound = /datum/wound/pierce
+
+/datum/surgery/repair_puncture/can_start(mob/living/user, mob/living/carbon/target)
+ . = ..()
+ if(.)
+ var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected)
+ var/datum/wound/burn/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound)
+ return(pierce_wound && pierce_wound.blood_flow > 0)
+
+//SURGERY STEPS
+
+///// realign the blood vessels so we can reweld them
+/datum/surgery_step/repair_innards
+ name = "realign blood vessels"
+ implements = list(TOOL_HEMOSTAT = 100, TOOL_SCALPEL = 85, TOOL_WIRECUTTER = 40)
+ time = 3 SECONDS
+
+/datum/surgery_step/repair_innards/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/datum/wound/pierce/pierce_wound = surgery.operated_wound
+ if(!pierce_wound)
+ user.visible_message("
[user] looks for [target]'s [parse_zone(user.zone_selected)].", "
You look for [target]'s [parse_zone(user.zone_selected)]...")
+ return
+
+ if(pierce_wound.blood_flow <= 0)
+ to_chat(user, "
[target]'s [parse_zone(user.zone_selected)] has no puncture to repair!")
+ surgery.status++
+ return
+
+ display_results(user, target, "
You begin to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)]...",
+ "
[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].",
+ "
[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)].")
+
+/datum/surgery_step/repair_innards/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
+ var/datum/wound/pierce/pierce_wound = surgery.operated_wound
+ if(!pierce_wound)
+ to_chat(user, "
[target] has no puncture wound there!")
+ return ..()
+
+ display_results(user, target, "
You successfully realign some of the blood vessels in [target]'s [parse_zone(target_zone)].",
+ "
[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!",
+ "
[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)]!")
+ log_combat(user, target, "excised infected flesh in", addition="INTENT: [uppertext(user.a_intent)]")
+ surgery.operated_bodypart.receive_damage(brute=3, wound_bonus=CANT_WOUND)
+ pierce_wound.blood_flow -= 0.25
+ return ..()
+
+/datum/surgery_step/repair_innards/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
+ . = ..()
+ display_results(user, target, "
You jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)].",
+ "
[user] jerks apart some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!",
+ "
[user] jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)]!")
+ surgery.operated_bodypart.receive_damage(brute=rand(4,8), sharpness=SHARP_EDGED, wound_bonus = 10)
+
+///// Sealing the vessels back together
+/datum/surgery_step/seal_veins
+ name = "weld veins" // if your doctor says they're going to weld your blood vessels back together, you're either A) on SS13, or B) in grave mortal peril
+ implements = list(TOOL_CAUTERY = 100, /obj/item/gun/energy/laser = 90, TOOL_WELDER = 70, /obj/item = 30)
+ time = 4 SECONDS
+
+/datum/surgery_step/seal_veins/tool_check(mob/user, obj/item/tool)
+ if(implement_type == TOOL_WELDER || implement_type == /obj/item)
+ return tool.get_temperature()
+
+ return TRUE
+
+/datum/surgery_step/seal_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/datum/wound/pierce/pierce_wound = surgery.operated_wound
+ if(!pierce_wound)
+ user.visible_message("
[user] looks for [target]'s [parse_zone(user.zone_selected)].", "
You look for [target]'s [parse_zone(user.zone_selected)]...")
+ return
+ display_results(user, target, "
You begin to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)]...",
+ "
[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].",
+ "
[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)].")
+
+/datum/surgery_step/seal_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
+ var/datum/wound/pierce/pierce_wound = surgery.operated_wound
+ if(!pierce_wound)
+ to_chat(user, "
[target] has no puncture there!")
+ return ..()
+
+ display_results(user, target, "
You successfully meld some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool].",
+ "
[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!",
+ "
[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)]!")
+ log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]")
+ pierce_wound.blood_flow -= 0.5
+ if(pierce_wound.blood_flow > 0)
+ surgery.status = REALIGN_INNARDS
+ to_chat(user, "
There still seems to be misaligned blood vessels to finish...")
+ else
+ to_chat(user, "
You've repaired all the internal damage in [target]'s [parse_zone(target_zone)]!")
+ return ..()
+
+#undef REALIGN_INNARDS
+#undef WELD_VEINS
diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm
index aad9b0a1da1..defacbe1cd4 100644
--- a/code/modules/surgery/tools.dm
+++ b/code/modules/surgery/tools.dm
@@ -110,7 +110,7 @@
custom_materials = list(/datum/material/iron=4000, /datum/material/glass=1000)
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP_ACCURATE
+ sharpness = SHARP_EDGED
tool_behaviour = TOOL_SCALPEL
toolspeed = 1
bare_wound_bonus = 20
@@ -146,7 +146,7 @@
throw_range = 5
custom_materials = list(/datum/material/iron=1000)
attack_verb = list("attacked", "slashed", "sawed", "cut")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
tool_behaviour = TOOL_SAW
toolspeed = 1
wound_bonus = 10
@@ -259,7 +259,7 @@
force = 16
toolspeed = 0.7
light_color = LIGHT_COLOR_GREEN
- sharpness = IS_SHARP_ACCURATE
+ sharpness = SHARP_EDGED
/obj/item/scalpel/advanced/Initialize()
. = ..()
@@ -349,7 +349,7 @@
throw_range = 5
custom_materials = list(/datum/material/iron=8000, /datum/material/titanium=6000)
attack_verb = list("sheared", "snipped")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
custom_premium_price = 1800
/obj/item/shears/attack(mob/living/M, mob/user)
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index ee4ed492df1..fa4c2f20f77 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -570,8 +570,7 @@ GLOBAL_LIST_EMPTY(vending_products)
for(var/i in C.bodyparts)
var/obj/item/bodypart/squish_part = i
if(squish_part.is_organic_limb())
- //var/type_wound = pick(WOUND_LIST_BONE)
- var/type_wound = pick(list(/datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/moderate))
+ var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
squish_part.force_wound_upwards(type_wound)
else
squish_part.receive_damage(brute=30)
diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm
index 1c97853c466..ce844bf7db2 100644
--- a/code/modules/zombie/items.dm
+++ b/code/modules/zombie/items.dm
@@ -12,7 +12,7 @@
var/icon_right = "bloodhand_right"
hitsound = 'sound/hallucinations/growl1.ogg'
force = 21 // Just enough to break airlocks with melee attacks
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
wound_bonus = -30
bare_wound_bonus = 15
damtype = "brute"
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index cbad9a89ff3..50c644f01cd 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -61,7 +61,10 @@ h1.alert, h2.alert {color: #000000;}
.emote { font-style: italic;}
.userdanger {color: #ff0000; font-weight: bold; font-size: 3;}
+.danger {color: #ff0000; font-weight: bold;}
.danger {color: #ff0000;}
+.tinydanger {color: #ff0000; font-size: 85%;}
+.smalldanger {color: #ff0000; font-size: 90%;}
.warning {color: #ff0000; font-style: italic;}
.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
.announce {color: #228b22; font-weight: bold;}
@@ -70,6 +73,9 @@ h1.alert, h2.alert {color: #000000;}
.rose {color: #ff5050;}
.info {color: #0000CC;}
.notice {color: #000099;}
+.tinynotice {color: #000099; font-size: 85%;}
+.smallnotice {color: #000099; font-size: 90%;}
+.smallnoticeital {color: #000099; font-style: italic; font-size: 90%;}
.boldnotice {color: #000099; font-weight: bold;}
.hear {color: #000099; font-style: italic;}
.adminnotice {color: #0000ff;}
diff --git a/sound/effects/blood1.ogg b/sound/effects/wounds/blood1.ogg
similarity index 100%
rename from sound/effects/blood1.ogg
rename to sound/effects/wounds/blood1.ogg
diff --git a/sound/effects/blood2.ogg b/sound/effects/wounds/blood2.ogg
similarity index 100%
rename from sound/effects/blood2.ogg
rename to sound/effects/wounds/blood2.ogg
diff --git a/sound/effects/blood3.ogg b/sound/effects/wounds/blood3.ogg
similarity index 100%
rename from sound/effects/blood3.ogg
rename to sound/effects/wounds/blood3.ogg
diff --git a/sound/effects/crack1.ogg b/sound/effects/wounds/crack1.ogg
similarity index 100%
rename from sound/effects/crack1.ogg
rename to sound/effects/wounds/crack1.ogg
diff --git a/sound/effects/crack2.ogg b/sound/effects/wounds/crack2.ogg
similarity index 100%
rename from sound/effects/crack2.ogg
rename to sound/effects/wounds/crack2.ogg
diff --git a/sound/effects/wounds/crackandbleed.ogg b/sound/effects/wounds/crackandbleed.ogg
new file mode 100644
index 00000000000..ea07f13d482
Binary files /dev/null and b/sound/effects/wounds/crackandbleed.ogg differ
diff --git a/sound/effects/wounds/pierce1.ogg b/sound/effects/wounds/pierce1.ogg
new file mode 100644
index 00000000000..cd7b7c39610
Binary files /dev/null and b/sound/effects/wounds/pierce1.ogg differ
diff --git a/sound/effects/wounds/pierce2.ogg b/sound/effects/wounds/pierce2.ogg
new file mode 100644
index 00000000000..4977cab299f
Binary files /dev/null and b/sound/effects/wounds/pierce2.ogg differ
diff --git a/sound/effects/wounds/pierce3.ogg b/sound/effects/wounds/pierce3.ogg
new file mode 100644
index 00000000000..e81700b1348
Binary files /dev/null and b/sound/effects/wounds/pierce3.ogg differ
diff --git a/sound/effects/sizzle1.ogg b/sound/effects/wounds/sizzle1.ogg
similarity index 100%
rename from sound/effects/sizzle1.ogg
rename to sound/effects/wounds/sizzle1.ogg
diff --git a/sound/effects/sizzle2.ogg b/sound/effects/wounds/sizzle2.ogg
similarity index 100%
rename from sound/effects/sizzle2.ogg
rename to sound/effects/wounds/sizzle2.ogg
diff --git a/strings/wounds/bone_scar_desc.json b/strings/wounds/bone_scar_desc.json
new file mode 100644
index 00000000000..b1eb84bb8b7
--- /dev/null
+++ b/strings/wounds/bone_scar_desc.json
@@ -0,0 +1,26 @@
+{
+ "generic": ["general disfigurement"],
+
+ "bluntmoderate": [
+ "the bone equivalent of a faded bruise",
+ "a series of tiny chip marks"
+ ],
+
+ "bluntsevere": [
+ "a series of faded hairline cracks",
+ "a small bone dent"
+ ],
+
+ "bluntcritical": [
+ "large streaks of refilled cracks",
+ "a fractal of reformed stress marks",
+ "a cluster of calluses"
+ ],
+
+ "dismember": [
+ "is slightly misaligned",
+ "has clearly been dropped recently",
+ "has a damaged socket"
+ ]
+
+}
diff --git a/strings/wounds/flesh_scar_desc.json b/strings/wounds/flesh_scar_desc.json
new file mode 100644
index 00000000000..047e614b790
--- /dev/null
+++ b/strings/wounds/flesh_scar_desc.json
@@ -0,0 +1,86 @@
+{
+ "generic": ["general disfigurement"],
+
+ "bluntmoderate": [
+ "light discoloring",
+ "a slight blue tint"
+ ],
+
+ "bluntsevere": [
+ "a faded, fist-sized bruise",
+ "a vaguely triangular peel scar"
+ ],
+
+ "bluntcritical": [
+ "a section of janky skin lines and badly healed scars",
+ "a large patch of uneven skin tone",
+ "a cluster of calluses"
+ ],
+
+
+
+ "slashmoderate": [
+ "light, faded lines",
+ "minor cut marks",
+ "a small faded slit",
+ "a series of small scars"
+ ],
+
+ "slashsevere": [
+ "a twisted line of faded gashes",
+ "a gnarled sickle-shaped slice scar"
+ ],
+
+ "slashcritical": [
+ "a winding path of very badly healed scar tissue",
+ "a series of peaks and valleys along a gruesome line of cut scar tissue",
+ "a grotesque snake of indentations and stitching scars"
+ ],
+
+
+
+ "piercemoderate": [
+ "a small, faded bruise",
+ "a small twist of reformed skin",
+ "a thumb-sized puncture scar"
+ ],
+
+ "piercesevere": [
+ "an ink-splat shaped pocket of scar tissue",
+ "a long-faded puncture wound",
+ "a tumbling puncture hole with evidence of faded stitching"
+ ],
+
+ "piercecritical": [
+ "a rippling shockwave of scar tissue",
+ "a wide, scattered cloud of shrapnel marks",
+ "a gruesome multi-pronged puncture scar"
+ ],
+
+
+
+ "burnmoderate": [
+ "small amoeba-shaped skinmarks",
+ "a faded streak of depressed skin"
+ ],
+
+ "burnsevere": [
+ "a large, jagged patch of faded skin",
+ "random spots of shiny, smooth skin",
+ "spots of taut, leathery skin"
+ ],
+
+ "burncritical": [
+ "massive, disfiguring keloid scars",
+ "several long streaks of badly discolored and malformed skin",
+ "unmistakeable splotches of dead tissue from serious burns"
+ ],
+
+
+ "dismember": [
+ "is several skintone shades paler than the rest of the body",
+ "is a gruesome patchwork of artificial flesh",
+ "has a large series of attachment scars at the articulation points"
+ ]
+
+}
diff --git a/strings/wounds/scar_loc.json b/strings/wounds/scar_loc.json
new file mode 100644
index 00000000000..4d1a639a9a1
--- /dev/null
+++ b/strings/wounds/scar_loc.json
@@ -0,0 +1,52 @@
+{
+ "": ["general area"],
+
+ "head": [
+ "left eyebrow",
+ "cheekbone",
+ "neck",
+ "throat",
+ "jawline",
+ "entire face"
+ ],
+
+ "chest": [
+ "upper chest",
+ "lower abdomen",
+ "midsection",
+ "collarbone",
+ "lower back"
+ ],
+
+ "l_arm": [
+ "outer left forearm",
+ "inner left wrist",
+ "left elbow",
+ "left bicep",
+ "left shoulder"
+ ],
+
+ "r_arm": [
+ "outer right forearm",
+ "inner right wrist",
+ "right elbow",
+ "right bicep",
+ "right shoulder"
+ ],
+
+ "l_leg": [
+ "inner left thigh",
+ "outer left calf",
+ "outer left hip",
+ "left kneecap",
+ "lower left shin"
+ ],
+
+ "r_leg": [
+ "inner right thigh",
+ "outer right calf",
+ "outer right hip",
+ "right kneecap",
+ "lower right shin"
+ ]
+}
diff --git a/tgstation.dme b/tgstation.dme
index 678ef083b27..327f19a8065 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -654,7 +654,9 @@
#include "code\datums\wounds\_wounds.dm"
#include "code\datums\wounds\bones.dm"
#include "code\datums\wounds\burns.dm"
-#include "code\datums\wounds\cuts.dm"
+#include "code\datums\wounds\loss.dm"
+#include "code\datums\wounds\pierce.dm"
+#include "code\datums\wounds\slash.dm"
#include "code\datums\wounds\scars\_scars.dm"
#include "code\game\alternate_appearance.dm"
#include "code\game\atoms.dm"
@@ -3020,6 +3022,7 @@
#include "code\modules\surgery\plastic_surgery.dm"
#include "code\modules\surgery\prosthetic_replacement.dm"
#include "code\modules\surgery\remove_embedded_object.dm"
+#include "code\modules\surgery\repair_puncture.dm"
#include "code\modules\surgery\revival.dm"
#include "code\modules\surgery\stomachpump.dm"
#include "code\modules\surgery\surgery.dm"