Merge remote-tracking branch 'origin/master' into TGUI-4

This commit is contained in:
Letter N
2020-07-30 14:43:52 +08:00
662 changed files with 13844 additions and 6845 deletions
+15 -12
View File
@@ -1,9 +1,9 @@
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]"
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[wound]"
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
. = locate(ARMORID)
if (!.)
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound)
/datum/armor
datum_flags = DF_USE_TAG
@@ -17,8 +17,9 @@
var/fire
var/acid
var/magic
var/wound
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
src.melee = melee
src.bullet = bullet
src.laser = laser
@@ -29,15 +30,16 @@
src.fire = fire
src.acid = acid
src.magic = magic
src.wound = wound
tag = ARMORID
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic)
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.wound+wound)
/datum/armor/proc/modifyAllRatings(modifier = 0)
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier)
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, wound+modifier)
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound)
return getArmor((isnull(melee) ? src.melee : melee),\
(isnull(bullet) ? src.bullet : bullet),\
(isnull(laser) ? src.laser : laser),\
@@ -47,19 +49,20 @@
(isnull(rad) ? src.rad : rad),\
(isnull(fire) ? src.fire : fire),\
(isnull(acid) ? src.acid : acid),\
(isnull(magic) ? src.magic : magic))
(isnull(magic) ? src.magic : magic),\
(isnull(wound) ? src.wound : wound))
/datum/armor/proc/getRating(rating)
return vars[rating]
/datum/armor/proc/getList()
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic, "wound" = wound)
/datum/armor/proc/attachArmor(datum/armor/AA)
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic)
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, wound+AA.wound)
/datum/armor/proc/detachArmor(datum/armor/AA)
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic)
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, wound-AA.wound)
/datum/armor/vv_edit_var(var_name, var_value)
if (var_name == NAMEOF(src, tag))
+221
View File
@@ -0,0 +1,221 @@
//similar to dog_fashion, but for beepsky, who has far more refined fashion tastes
/datum/beepsky_fashion
var/name //not setting the name and desc makes them go to the default
var/desc
var/icon_file = 'icons/mob/secbot_accessories.dmi' //we sell secbots and secbot accessories
var/obj_icon_state
var/obj_alpha
var/obj_color
var/list/stun_sounds //sound that replaces the stun attack when set
var/ignore_sound = FALSE //whether to ignore sounds entirely or not
//emotes (don't set them if you want the default value)
var/death_emote //what is said when beepsky dies
var/capture_one //what is said when cuffing someone
var/capture_two //what is said when cuffing someone, directly to the person being cuffed
var/infraction //the level of threat detected
var/taunt // beepsky pointing at a criminal
var/attack_one //text when attacking criminal
var/attack_two //text when attacking criminal, but directly to the criminal
var/patrol_emote //engaging patrol text
var/patrol_fail_emote //failing to engage patrol text
var/list/arrest_texts //first is for not-cuffing, second is for cuffing
var/arrest_emote //text stating that you're cuffing some criminal C with a threat of level X in location Y
//for reference, the following words are replaced when processed before speech:
//LOCATION = the location passed, if any (this is only used by arrest_emote)
//CRIMINAL = the name of the criminal (this is used by everything but patrol_emote and infraction)
//BOT = the name of the bot (this can be used on any of the emotes)
//THREAT_LEVEL = the level of the threat detected (can be used on arrest_emote and infraction)
/datum/beepsky_fashion/proc/get_overlay(var/dir)
if(icon_file && obj_icon_state)
var/image/beepsky_overlay = image(icon_file, obj_icon_state, dir = dir)
beepsky_overlay.alpha = obj_alpha
beepsky_overlay.color = obj_color
return beepsky_overlay
/datum/beepsky_fashion/proc/stun_attack(mob/living/carbon/C) //fired when beepsky does a stun attack with the fashion worn, for sounds/overlays/etc
return
//actual fashions from here on out
/datum/beepsky_fashion/wizard
obj_icon_state = "wizard"
name = "Archmage Beepsky"
desc = "A secbot stolen from the wizard federation."
death_emote = "BOT casts EI NATH on themselves!"
capture_one = "BOT is casting cable ties on CRIMINAL!"
capture_two = "BOT is casting cable ties on you!"
infraction = "Magical disturbance of magnitude THREAT_LEVEL detected!"
taunt = "BOT points his staff towards CRIMINAL!"
attack_one = "BOT casts magic missile on CRIMINAL!"
attack_two = "BOT casts magic missile on you!"
patrol_emote = "Beginning search for magical disturbances."
patrol_fail_emote = "Failure to find magical disturbances. Recallibrating."
arrest_emote = "ARREST_TYPE level THREAT_LEVEL magical practitioner CRIMINAL in LOCATION."
stun_sounds = list('sound/magic/lightningbolt.ogg',
'sound/magic/fireball.ogg',
'sound/weapons/zapbang.ogg',
'sound/magic/knock.ogg',
'sound/magic/fleshtostone.ogg',
'sound/effects/magic.ogg',
'sound/magic/disintegrate.ogg')
/datum/beepsky_fashion/cowboy
obj_icon_state = "cowboy"
name = "Sheriff Beepsky"
desc = "The sheriff of this here station."
capture_one = "BOT is tying CRIMINAL up!"
capture_two = "BOT is tying you up!"
infraction = "Outlaws with a bounty of THREAT_LEVEL000 space dollars detected!"
taunt = "BOT aims his revolver towards CRIMINAL!"
attack_one = "BOT unloads his revolver onto CRIMINAL!"
attack_two = "BOT unloads his revolver onto you!"
patrol_emote = "Engaging bounty hunting protocols."
patrol_fail_emote = "Unable to find any bounties due to error. Rebooting."
arrest_emote = "ARREST_TYPE outlaw CRIMINAL with a bounty of THREAT_LEVEL000 in LOCATION."
stun_sounds = list('sound/weapons/Gunshot.ogg',
'sound/weapons/Gunshot2.ogg',
'sound/weapons/Gunshot3.ogg',
'sound/weapons/Gunshot4.ogg')
/datum/beepsky_fashion/chef
obj_icon_state = "chef"
name = "Chef Beepsky"
desc = "Cooking up the finest foods the station has ever seen."
death_emote = "Mamma-mia!"
infraction = "Grade THREAT_LEVEL prosciutto detected!"
taunt = "BOT glares at CRIMINAL."
attack_one = "BOT CQCs CRIMINAL!"
attack_two = "BOT CQCs you!"
patrol_emote = "Beginning search for the bad prosciutto."
patrol_fail_emote = "All prosciutto is stale. Rebooting."
arrest_texts = list("Frying", "Grilling") //any good secoff knows the difference
arrest_emote = "ARREST_TYPE grade THREAT_LEVEL prosciutto CRIMINAL in LOCATION."
stun_sounds = list('sound/weapons/cqchit1.ogg',
'sound/weapons/cqchit2.ogg')
/datum/beepsky_fashion/cat
obj_icon_state = "cat"
name = "OwOfficer Bweepskwee"
desc = "A beepsky unit with cat ears. Catgirl science has gone too far."
death_emote = "Nya!"
capture_one = "BOT is tying CRIMINAL up!!"
capture_two = "BOT is tying you up!"
infraction = "Wevel THREAT_LEVEL infwactwion awert!!!"
taunt = "BOT points at CRIMINAL and nyas!"
attack_one = "BOT shoves CRIMINAL onto a table!"
attack_two = "BOT shoves you onto a table!"
patrol_emote = "Enwgagwing patwol mwodies.."
patrol_fail_emote = "Unawbwle two stwawt patwollies. Nya."
arrest_texts = list("Dwetwaining", "Awwesting")
arrest_emote = "ARREST_TYPE wevel THREAT_LEVEL scwumbwag CRIMINAL in LOCATION. Nya."
ignore_sound = TRUE //we instead make the stunned person fire the nya emote
/datum/beepsky_fashion/cat/stun_attack(var/mob/living/carbon/C) //makes a fake table under you on hit, makes cat people nya when hit
if(iscatperson(C))
C.emote("nya")
var/turf/target_turf = get_turf(C)
if(target_turf) //slams you on a fake table
playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1)
var/obj/effect/overlay_holder = new(target_turf)
overlay_holder.name = "Catboy Table"
overlay_holder.desc = "Where bad catboys go."
var/image/table_overlay = image('icons/obj/smooth_structures/table.dmi', "table")
overlay_holder.add_overlay(table_overlay)
QDEL_IN(overlay_holder, 10)
/datum/beepsky_fashion/cake //nothing else. it's just beepsky. with a cake on his head.
obj_icon_state = "cake"
name = "Cakesky"
desc = "It's a secbot, wearing a cake on his head!"
/datum/beepsky_fashion/captain
obj_icon_state = "captain"
name = "Captainsky"
desc = "The real captain of this station."
capture_one = "BOT is lecturing CRIMINAL on why he is the captain!"
capture_two = "BOT is lecturing you on why he is the captain!"
infraction = "Level THREAT_LEVEL greytider detected."
attack_one = "BOT beats CRIMINAL with the chain of command!"
attack_two = "BOT beats you with the chain of command!"
patrol_emote = "Uselessness protocols engaged."
patrol_fail_emote = "Unit has been found as useless. Rebooting."
arrest_texts = list("Demoting", "Firing")
arrest_emote = "ARREST_TYPE level THREAT_LEVEL lesser crewmember CRIMINAL in LOCATION."
stun_sounds = list('sound/weapons/chainhit.ogg')
/datum/beepsky_fashion/king
obj_icon_state = "king"
name = "King Beepsky"
desc = "He who has ascended to bare the right of king, sits atop the throne."
capture_one = "BOT is calling the guards onto CRIMINAL!"
capture_two = "BOT is calling the guards onto you!"
infraction = "Treason of level THREAT_LEVEL detected!"
attack_one = "BOT strikes CRIMINAL with his kingly authority!"
attack_two = "BOT strikes you with his kingly authority!"
patrol_emote = "Searching for peasants to beat up."
patrol_fail_emote = "Peasants are using dark magic. Recallibrating."
arrest_texts = list("Knighting", "Executing")
arrest_emote = "ARREST_TYPE level THREAT_LEVEL peasant CRIMINAL in LOCATION."
stun_sounds = list('sound/weapons/punch1.ogg',
'sound/weapons/punch2.ogg',
'sound/weapons/punch3.ogg',
'sound/weapons/punch4.ogg')
/datum/beepsky_fashion/pirate
obj_icon_state = "pirate"
name = "Beepsbeard the Pirate"
desc = "Sailor of the seven seas, all sea-faring bots fear the one known as Beepsbeard."
capture_one = "BOT is making CRIMINAL walk the plank!"
capture_two = "BOT is making you walk the plank!"
infraction = "Enemy vessel spotted with threat level THREAT_LEVEL!"
attack_one = "BOT strikes CRIMINAL with his cutlass!"
attack_two = "BOT strikes you with his cutlass!"
patrol_emote = "Searching for enemy vessels to board."
patrol_fail_emote = "No way to engage enemy vessels. Rebooting."
arrest_texts = list("Boarding", "Sinking")
arrest_emote = "ARREST_TYPE level THREAT_LEVEL vessel CRIMINAL in LOCATION."
stun_sounds = list('sound/weapons/bladeslice.ogg')
/datum/beepsky_fashion/engineer
obj_icon_state = "engineer"
name = "Chief Engineer Beepsky"
desc = "He fixes criminals with a wrench to the face."
capture_one = "BOT is tying CRIMINAL up!"
capture_two = "BOT is tying you up!"
infraction = "Structural integrity issue spotted with threat level THREAT_LEVEL"
attack_one = "BOT strikes CRIMINAL with his wrench!"
attack_two = "BOT strikes you with his wrench!"
arrest_texts = list("Fixing", "Repairing")
arrest_emote = "ARREST_TYPE level THREAT_LEVEL structural issue in LOCATION"
stun_sounds = list('sound/weapons/genhit.ogg')
/datum/beepsky_fashion/tophat
obj_icon_state = "tophat"
name = "Fancy Beepsky"
desc = "It's a secbot, wearing a top hat! How fancy."
/datum/beepsky_fashion/fedora
obj_icon_state = "fedora"
name = "Fedorasky"
desc = "It's a secbot, wearing a fedora!"
/datum/beepsky_fashion/sombrero
obj_icon_state = "sombrero"
name = "Sombrerosky"
desc = "A secbot wearing a sombrero. Truly, a hombre to all."
/datum/beepsky_fashion/santa
obj_icon_state = "santa"
name = "Saint Beepsky"
desc = "Have you been a level 7 infraction this holiday season?"
capture_one = "BOT is tying CRIMINAL up with fairy lights!"
capture_two = "BOT is tying you up with fairy lights!"
infraction = "Level THREAT_LEVEL threat to holiday cheer spotted!"
attack_one = "BOT crushes CRIMINAL with their holiday spirit!"
attack_two = "BOT crushes you with their holiday spirit!"
arrest_emote = "ARREST_TYPE level THREAT_LEVEL threat to holiday cheer in LOCATION"
+1 -1
View File
@@ -94,7 +94,7 @@
if(get_dist(owner, stalker) <= 1)
playsound(owner, 'sound/magic/demon_attack1.ogg', 50)
owner.visible_message("<span class='warning'>[owner] is torn apart by invisible claws!</span>", "<span class='userdanger'>Ghostly claws tear your body apart!</span>")
owner.take_bodypart_damage(rand(20, 45))
owner.take_bodypart_damage(rand(20, 45), wound_bonus=CANT_WOUND)
else if(prob(50))
stalker.forceMove(get_step_towards(stalker, owner))
if(get_dist(owner, stalker) <= 8)
+1 -2
View File
@@ -103,8 +103,7 @@
. = ..()
QDEL_IN(src, 300)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/effect/hallucination/simple/bluespace_stream/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/effect/hallucination/simple/bluespace_stream/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user != seer || !linked_to)
return
var/slip_in_message = pick("slides sideways in an odd way, and disappears", "jumps into an unseen dimension",\
+6 -3
View File
@@ -2,7 +2,7 @@
var/speed = 80 //time in deciseconds taken to butcher something
var/effectiveness = 100 //percentage effectiveness; numbers above 100 yield extra drops
var/bonus_modifier = 0 //percentage increase to bonus item chance
var/butcher_sound = 'sound/weapons/slice.ogg' //sound played when butchering
var/butcher_sound = 'sound/effects/butcher.ogg' //sound played when butchering
var/butchering_enabled = TRUE
var/can_be_blunt = FALSE
@@ -64,8 +64,11 @@
H.visible_message("<span class='danger'>[user] slits [H]'s throat!</span>", \
"<span class='userdanger'>[user] slits your throat...</span>")
log_combat(user, H, "finishes slicing the throat of")
H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD)
H.bleed_rate = clamp(H.bleed_rate + 20, 0, 30)
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
screaming_through_a_slit_throat.apply_wound(slit_throat)
H.apply_status_effect(/datum/status_effect/neck_slice)
/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat)
+1 -1
View File
@@ -48,7 +48,7 @@
var/damage = rand(min_damage, max_damage)
if(HAS_TRAIT(H, TRAIT_LIGHT_STEP))
damage *= 0.75
H.apply_damage(damage, BRUTE, picked_def_zone)
H.apply_damage(damage, BRUTE, picked_def_zone, wound_bonus = CANT_WOUND)
if(cooldown < world.time - 10) //cooldown to avoid message spam.
if(!H.incapacitated(ignore_restraints = TRUE))
@@ -324,6 +324,13 @@
result = /obj/item/toy/sword/cx
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
/datum/crafting_recipe/catgirlplushie
name = "Catgirl Plushie"
reqs = list(/obj/item/toy/plush/hairball = 3)
result = /obj/item/toy/plush/catgirl
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
////////////
//Unsorted//
+5 -5
View File
@@ -147,7 +147,7 @@
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)
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus=-30, sharpness = TRUE)
SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
else
victim.visible_message("<span class='danger'>[weapon] sticks itself to [victim]'s [limb.name]!</span>",ignored_mobs=victim)
@@ -163,7 +163,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)
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
to_chat(victim, "<span class='userdanger'>[weapon] embedded in your [limb.name] jostles and stings!</span>")
@@ -173,7 +173,7 @@
if(harmful)
var/damage = weapon.w_class * remove_pain_mult
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
victim.visible_message("<span class='danger'>[weapon] falls out of [victim.name]'s [limb.name]!</span>", ignored_mobs=victim)
to_chat(victim, "<span class='userdanger'>[weapon] falls out of your [limb.name]!</span>")
else
@@ -199,7 +199,7 @@
if(harmful)
var/damage = weapon.w_class * remove_pain_mult
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage) //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=TRUE) //It hurts to rip it out, get surgery you dingus.
victim.emote("scream")
victim.visible_message("<span class='notice'>[victim] successfully rips [weapon] out of [victim.p_their()] [limb.name]!</span>", "<span class='notice'>You successfully remove [weapon] from your [limb.name].</span>")
else
@@ -276,7 +276,7 @@
damage *= 0.7
if(harmful && prob(chance))
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
to_chat(victim, "<span class='userdanger'>[weapon] embedded in your [limb.name] hurts!</span>")
if(prob(fall_chance))
+4 -4
View File
@@ -98,16 +98,16 @@
/datum/component/simple_rotation/proc/HandRot(datum/source, mob/user, rotation = default_rotation_direction)
if(can_be_rotated)
if(!can_be_rotated.Invoke(user, default_rotation_direction))
if(!can_be_rotated.Invoke(user, rotation))
return
else
if(!default_can_be_rotated(user, default_rotation_direction))
if(!default_can_be_rotated(user, rotation))
return
if(can_user_rotate)
if(!can_user_rotate.Invoke(user, default_rotation_direction))
if(!can_user_rotate.Invoke(user, rotation))
return
else
if(!default_can_user_rotate(user, default_rotation_direction))
if(!default_can_user_rotate(user, rotation))
return
BaseRot(user, rotation)
return TRUE
+1
View File
@@ -62,6 +62,7 @@
///Store the thrownthing datum for later use
/datum/component/tackler/proc/registerTackle(mob/living/carbon/user, datum/thrownthing/TT)
tackle = TT
tackle.thrower = user
///See if we can tackle or not. If we can, leap!
/datum/component/tackler/proc/checkTackle(mob/living/carbon/user, atom/A, params)
+2
View File
@@ -78,6 +78,8 @@
/datum/datacore/proc/manifest()
for(var/mob/dead/new_player/N in GLOB.player_list)
if(!N?.client)
continue
if(N.new_character)
log_manifest(N.ckey,N.new_character.mind,N.new_character)
if(ishuman(N.new_character))
@@ -64,7 +64,8 @@ Bonus
if(bleed)
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.bleed_rate += 5 * power
var/obj/item/bodypart/random_part = pick(H.bodyparts)
random_part.generic_bleedstacks += 5 * power
return 1
/*
+6 -6
View File
@@ -131,9 +131,9 @@
L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color)
L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)
L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color)
L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"])
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"])
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"])
L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"], 6)
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6)
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6)
if(!GLOB.mam_tails_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
@@ -239,11 +239,11 @@
if(DNA_HAIR_STYLE_BLOCK)
setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len))
if(DNA_COLOR_ONE_BLOCK)
sanitize_hexcolor(features["mcolor"])
sanitize_hexcolor(features["mcolor"], 6)
if(DNA_COLOR_TWO_BLOCK)
sanitize_hexcolor(features["mcolor2"])
sanitize_hexcolor(features["mcolor2"], 6)
if(DNA_COLOR_THREE_BLOCK)
sanitize_hexcolor(features["mcolor3"])
sanitize_hexcolor(features["mcolor3"], 6)
if(DNA_MUTANTTAIL_BLOCK)
construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
if(DNA_MUTANTEAR_BLOCK)
-2
View File
@@ -38,7 +38,6 @@
corgI.color = obj_color
return corgI
/datum/dog_fashion/head
icon_file = 'icons/mob/corgi_head.dmi'
@@ -53,7 +52,6 @@
name = "Sous chef REAL_NAME"
desc = "Your food will be taste-tested. All of it."
/datum/dog_fashion/head/captain
name = "Captain REAL_NAME"
desc = "Probably better than the last captain."
@@ -60,6 +60,7 @@
output_atoms -= remove_thing
if(init_timerid)
deltimer(init_timerid)
init_timerid = null
if(!timerid)
return
on_stop()
+2 -2
View File
@@ -223,8 +223,8 @@
/obj/item/clothing/gloves/krav_maga/combatglovesplus
name = "combat gloves plus"
desc = "These tactical gloves are fireproof and shock resistant, and using nanochip technology it teaches you the powers of krav maga."
icon_state = "combat"
item_state = "blackgloves"
icon_state = "fightglovesblack"
item_state = "fightglovesblack"
siemens_coefficient = 0
permeability_coefficient = 0.05
strip_delay = 80
+7 -7
View File
@@ -44,7 +44,7 @@
else
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1)
log_combat(A, D, "strong punched (Sleeping Carp)")//so as to not double up on logging
D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting)
D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting, wound_bonus = CANT_WOUND)
return TRUE
///Crashing Wave Kick: Harm Disarm combo, throws people seven tiles backwards
@@ -56,7 +56,7 @@
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
var/atom/throw_target = get_edge_target_turf(D, A.dir)
D.throw_at(throw_target, 7, 14, A)
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST)
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST, wound_bonus = CANT_WOUND, wound_bonus = CANT_WOUND)
log_combat(A, D, "launchkicked (Sleeping Carp)")
return TRUE
@@ -66,14 +66,14 @@
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
if((D.mobility_flags & MOBILITY_STAND))
D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD)
D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
D.DefaultCombatKnockdown(50, override_hardstun = 0.01, override_stamdmg = 0)
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD) //A cit specific change form the tg port to really punish anyone who tries to stand up
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND) //A cit specific change form the tg port to really punish anyone who tries to stand up
D.visible_message("<span class='warning'>[A] kicks [D] in the head, sending them face first into the floor!</span>", \
"<span class='userdanger'>You are kicked in the head by [A], sending you crashing to the floor!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
else
D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD)
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD)
D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
D.drop_all_held_items()
D.visible_message("<span class='warning'>[A] kicks [D] in the head!</span>", \
"<span class='userdanger'>You are kicked in the head by [A]!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
@@ -99,7 +99,7 @@
D.visible_message("<span class='danger'>[A] [atk_verb]s [D]!</span>", \
"<span class='userdanger'>[A] [atk_verb]s you!</span>", null, null, A)
to_chat(A, "<span class='danger'>You [atk_verb] [D]!</span>")
D.apply_damage(damage, BRUTE, affecting)
D.apply_damage(damage, BRUTE, affecting, wound_bonus = CANT_WOUND)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1)
if(CHECK_MOBILITY(D, MOBILITY_STAND) && damage >= stunthreshold)
to_chat(D, "<span class='danger'>You stumble and fall!</span>")
+3
View File
@@ -66,6 +66,9 @@
/// Our skill holder.
var/datum/skill_holder/skill_holder
///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not
var/mob/original_character
/datum/mind/New(var/key)
skill_holder = new(src)
src.key = key
@@ -77,10 +77,14 @@
description = "<span class='boldwarning'>Pull it out!</span>\n"
mood_change = -7
/datum/mood_event/table
description = "<span class='warning'>Someone threw me on a table!</span>\n"
mood_change = -2
timeout = 2 MINUTES
/datum/mood_event/table_limbsmash
description = "<span class='warning'>That fucking table, man that hurts...</span>\n"
mood_change = -3
timeout = 3 MINUTES
/datum/mood_event/table_limbsmash/add_effects(obj/item/bodypart/banged_limb)
if(banged_limb)
description = "<span class='warning'>My fucking [banged_limb.name], man that hurts...</span>\n"
/datum/mood_event/table/add_effects()
if(ishuman(owner))
@@ -270,3 +274,13 @@
description = "<span class='warning'>I've produced better art than that from my ass.</span>\n"
mood_change = -2
timeout = 1200
/datum/mood_event/tripped
description = "<span class='boldwarning'>I can't believe I fell for the oldest trick in the book!</span>\n"
mood_change = -6
timeout = 2 MINUTES
/datum/mood_event/untied
description = "<span class='boldwarning'>I hate when my shoes come untied!</span>\n"
mood_change = -3
timeout = 1 MINUTES
@@ -196,3 +196,7 @@
description = "<span class='nicegreen'>That work of art was so great it made me believe in the goodness of humanity. Says a lot in a place like this.</span>\n"
mood_change = 4
timeout = 4 MINUTES
/datum/mood_event/cleared_stomach
description = "<span class='nicegreen'>Feels nice to get that out of the way!</span>\n"
mood_change = 3
+5 -1
View File
@@ -21,7 +21,11 @@
/datum/mutation/human/hulk/on_attack_hand(atom/target, proximity, act_intent, unarmed_attack_flags)
if(proximity && (act_intent == INTENT_HARM)) //no telekinetic hulk attack
return target.attack_hulk(owner)
if(!owner.CheckActionCooldown(CLICK_CD_MELEE))
return INTERRUPT_UNARMED_ATTACK | NO_AUTO_CLICKDELAY_HANDLING
owner.DelayNextAction()
target.attack_hulk(owner)
return INTERRUPT_UNARMED_ATTACK | NO_AUTO_CLICKDELAY_HANDLING
/datum/mutation/human/hulk/on_life()
if(owner.health < 0)
+4
View File
@@ -441,6 +441,10 @@
owner.adjustBruteLoss(-10, FALSE)
owner.adjustFireLoss(-5, FALSE)
owner.adjustOxyLoss(-10)
if(!iscarbon(owner))
return
var/mob/living/carbon/C = owner
QDEL_LIST(C.all_scars)
/obj/screen/alert/status_effect/fleshmend
name = "Fleshmend"
+10 -6
View File
@@ -144,7 +144,6 @@
id = "tased"
alert_type = null
var/movespeed_mod = /datum/movespeed_modifier/status_effect/tased
var/nextmove_modifier = 1
var/stamdmg_per_ds = 0 //a 20 duration would do 20 stamdmg, disablers do 24 or something
var/last_tick = 0 //fastprocess processing speed is a goddamn sham, don't trust it.
@@ -173,13 +172,9 @@
C.adjustStaminaLoss(max(0, stamdmg_per_ds * diff)) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing.
last_tick = world.time
/datum/status_effect/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y
return nextmove_modifier
/datum/status_effect/electrode/no_combat_mode
id = "tased_strong"
movespeed_mod = /datum/movespeed_modifier/status_effect/tased/no_combat_mode
nextmove_modifier = 2
blocks_combatmode = TRUE
stamdmg_per_ds = 1
@@ -430,10 +425,19 @@
/datum/status_effect/neck_slice/tick()
var/mob/living/carbon/human/H = owner
if(H.stat == DEAD || H.bleed_rate <= 8)
var/obj/item/bodypart/throat = H.get_bodypart(BODY_ZONE_HEAD)
if(H.stat == DEAD || !throat)
H.remove_status_effect(/datum/status_effect/neck_slice)
if(prob(10))
H.emote(pick("gasp", "gag", "choke"))
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)
still_bleeding = TRUE
break
if(!still_bleeding)
H.remove_status_effect(/datum/status_effect/neck_slice)
/mob/living/proc/apply_necropolis_curse(set_curse, duration = 10 MINUTES)
var/datum/status_effect/necropolis_curse/C = has_status_effect(STATUS_EFFECT_NECROPOLIS_CURSE)
+8 -5
View File
@@ -90,13 +90,12 @@
return
duration = world.time + original_duration
//clickdelay/nextmove modifiers!
/datum/status_effect/proc/nextmove_modifier()
/**
* Multiplied to clickdelays
*/
/datum/status_effect/proc/action_cooldown_mod()
return 1
/datum/status_effect/proc/nextmove_adjust()
return 0
////////////////
// ALERT HOOK //
////////////////
@@ -279,3 +278,7 @@
/datum/status_effect/grouped/before_remove(source)
sources -= source
return !length(sources)
//do_after modifier!
/datum/status_effect/proc/interact_speed_modifier()
return 1
+188
View File
@@ -0,0 +1,188 @@
// The shattered remnants of your broken limbs fill you with determination!
/obj/screen/alert/status_effect/determined
name = "Determined"
desc = "The serious wounds you've sustained have put your body into fight-or-flight mode! Now's the time to look for an exit!"
icon_state = "regenerative_core"
/datum/status_effect/determined
id = "determined"
alert_type = /obj/screen/alert/status_effect/determined
/datum/status_effect/determined/on_apply()
. = ..()
owner.visible_message("<span class='danger'>[owner] grits [owner.p_their()] teeth in pain!</span>", "<span class='notice'><b>Your senses sharpen as your body tenses up from the wounds you've sustained!</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
/datum/status_effect/determined/on_remove()
owner.visible_message("<span class='danger'>[owner]'s body slackens noticeably!</span>", "<span class='warning'><b>Your adrenaline rush dies off, and the pain from your wounds come aching back in...</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
return ..()
/datum/status_effect/limp
id = "limp"
status_type = STATUS_EFFECT_REPLACE
tick_interval = 10
alert_type = /obj/screen/alert/status_effect/limp
var/msg_stage = 0//so you dont get the most intense messages immediately
/// The left leg of the limping person
var/obj/item/bodypart/l_leg/left
/// The right leg of the limping person
var/obj/item/bodypart/r_leg/right
/// Which leg we're limping with next
var/obj/item/bodypart/next_leg
/// How many deciseconds we limp for on the left leg
var/slowdown_left = 0
/// How many deciseconds we limp for on the right leg
var/slowdown_right = 0
/datum/status_effect/limp/on_apply()
if(!iscarbon(owner))
return FALSE
var/mob/living/carbon/C = owner
left = C.get_bodypart(BODY_ZONE_L_LEG)
right = C.get_bodypart(BODY_ZONE_R_LEG)
update_limp()
RegisterSignal(C, COMSIG_MOVABLE_MOVED, .proc/check_step)
RegisterSignal(C, list(COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB), .proc/update_limp)
return ..()
/datum/status_effect/limp/on_remove()
UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB))
return ..()
/obj/screen/alert/status_effect/limp
name = "Limping"
desc = "One or more of your legs has been wounded, slowing down steps with that leg! Get it fixed, or at least splinted!"
/datum/status_effect/limp/proc/check_step(mob/whocares, OldLoc, Dir, forced)
if(!owner.client || !(owner.mobility_flags & MOBILITY_STAND) || !owner.has_gravity() || (owner.movement_type & FLYING) || forced)
return
var/determined_mod = 1
if(owner.has_status_effect(STATUS_EFFECT_DETERMINED))
determined_mod = 0.25
if(next_leg == left)
owner.client.move_delay += slowdown_left * determined_mod
next_leg = right
else
owner.client.move_delay += slowdown_right * determined_mod
next_leg = left
/datum/status_effect/limp/proc/update_limp()
var/mob/living/carbon/C = owner
left = C.get_bodypart(BODY_ZONE_L_LEG)
right = C.get_bodypart(BODY_ZONE_R_LEG)
if(!left && !right)
C.remove_status_effect(src)
return
slowdown_left = 0
slowdown_right = 0
if(left)
for(var/thing in left.wounds)
var/datum/wound/W = thing
slowdown_left += W.limp_slowdown
if(right)
for(var/thing in right.wounds)
var/datum/wound/W = thing
slowdown_right += W.limp_slowdown
// this handles losing your leg with the limp and the other one being in good shape as well
if(!slowdown_left && !slowdown_right)
C.remove_status_effect(src)
return
/////////////////////////
//////// WOUNDS /////////
/////////////////////////
// wound alert
/obj/screen/alert/status_effect/wound
name = "Wounded"
desc = "Your body has sustained serious damage, click here to inspect yourself."
/obj/screen/alert/status_effect/wound/Click()
var/mob/living/carbon/C = usr
C.check_self_for_injuries()
// wound status effect base
/datum/status_effect/wound
id = "wound"
status_type = STATUS_EFFECT_MULTIPLE
var/obj/item/bodypart/linked_limb
var/datum/wound/linked_wound
alert_type = NONE
/datum/status_effect/wound/on_creation(mob/living/new_owner, incoming_wound)
. = ..()
var/datum/wound/W = incoming_wound
linked_wound = W
linked_limb = linked_wound.limb
/datum/status_effect/wound/on_remove()
linked_wound = null
linked_limb = null
UnregisterSignal(owner, COMSIG_CARBON_LOSE_WOUND)
return ..()
/datum/status_effect/wound/on_apply()
if(!iscarbon(owner))
return FALSE
RegisterSignal(owner, COMSIG_CARBON_LOSE_WOUND, .proc/check_remove)
return ..()
/// check if the wound getting removed is the wound we're tied to
/datum/status_effect/wound/proc/check_remove(mob/living/L, datum/wound/W)
if(W == linked_wound)
qdel(src)
// bones
/datum/status_effect/wound/bone
/datum/status_effect/wound/bone/interact_speed_modifier()
var/mob/living/carbon/C = owner
if(C.get_active_hand() == linked_limb)
to_chat(C, "<span class='warning'>The [lowertext(linked_wound)] in your [linked_limb.name] slows your progress!</span>")
return linked_wound.interaction_efficiency_penalty
return 1
/datum/status_effect/wound/bone/action_cooldown_mod()
var/mob/living/carbon/C = owner
if(C.get_active_hand() == linked_limb)
return linked_wound.interaction_efficiency_penalty
return 1
/datum/status_effect/wound/bone/moderate
id = "disjoint"
/datum/status_effect/wound/bone/severe
id = "hairline"
/datum/status_effect/wound/bone/critical
id = "compound"
// cuts
/datum/status_effect/wound/cut/moderate
id = "abrasion"
/datum/status_effect/wound/cut/severe
id = "laceration"
/datum/status_effect/wound/cut/critical
id = "avulsion"
// 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"
+3 -3
View File
@@ -56,7 +56,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
if("Medical Doctor")
heirloom_type = /obj/item/healthanalyzer/advanced
if("Paramedic")
heirloom_type = pick(/obj/item/clothing/neck/stethoscope, /obj/item/bodybag)
heirloom_type = /obj/item/lighter
if("Station Engineer")
heirloom_type = /obj/item/wirecutters/brass
if("Atmospheric Technician")
@@ -452,8 +452,8 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
mob_trait = TRAIT_COLDBLOODED
gain_text = "<span class='notice'>You feel cold-blooded.</span>"
lose_text = "<span class='notice'>You feel more warm-blooded.</span>"
/datum/quirk/monophobia
/datum/quirk/monophobia
name = "Monophobia"
desc = "You will become increasingly stressed when not in company of others, triggering panic reactions ranging from sickness to heart attacks."
value = -3 // Might change it to 4.
+16
View File
@@ -122,3 +122,19 @@
if(H)
var/datum/species/species = H.dna.species
species.disliked_food &= ~ALCOHOL
/datum/quirk/longtimer
name = "Longtimer"
desc = "You've been around for a long time and seen more than your fair share of action, suffering some pretty nasty scars along the way. For whatever reason, you've declined to get them removed or augmented."
value = 0
gain_text = "<span class='notice'>Your body has seen better days.</span>"
lose_text = "<span class='notice'>Your sins may wash away, but those scars are here to stay...</span>"
medical_record_text = "Patient has withstood significant physical trauma and declined plastic surgery procedures to heal scarring."
/// the minimum amount of scars we can generate
var/min_scars = 3
/// the maximum amount of scars we can generate
var/max_scars = 7
/datum/quirk/longtimer/on_spawn()
var/mob/living/carbon/C = quirk_holder
C.generate_fake_scars(rand(min_scars, max_scars))
+134
View File
@@ -0,0 +1,134 @@
/**
* scars are cosmetic datums that are assigned to bodyparts once they recover from wounds. Each wound type and severity have their own descriptions for what the scars
* look like, and then each body part has a list of "specific locations" like your elbow or wrist or wherever the scar can appear, to make it more interesting than "right arm"
*
*
* Arguments:
* *
*/
/datum/scar
var/obj/item/bodypart/limb
var/mob/living/carbon/victim
var/severity
var/description
var/precise_location
/// Scars from the longtimer quirk are "fake" and won't be saved with persistent scarring, since it makes you spawn with a lot by default
var/fake=FALSE
/// How many tiles away someone can see this scar, goes up with severity. Clothes covering this limb will decrease visibility by 1 each, except for the head/face which is a binary "is mask obscuring face" check
var/visibility = 2
/// Whether this scar can actually be covered up by clothing
var/coverable = TRUE
/// What zones this scar can be applied to
var/list/applicable_zones = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_ARM, BODY_ZONE_R_LEG)
/datum/scar/Destroy(force, ...)
if(limb)
LAZYREMOVE(limb.scars, src)
if(victim)
LAZYREMOVE(victim.all_scars, src)
. = ..()
/**
* generate() is used to actually fill out the info for a scar, according to the limb and wound it is provided.
*
* After creating a scar, call this on it while targeting the scarred bodypart with a given wound to apply the scar.
*
* Arguments:
* * BP- The bodypart being targeted
* * W- The wound being used to generate the severity and description info
* * add_to_scars- Should always be TRUE unless you're just storing a scar for later usage, like how cuts want to store a scar for the highest severity of cut, rather than the severity when the wound is fully healed (probably demoted to moderate)
*/
/datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE)
if(!(BP.body_zone in applicable_zones))
qdel(src)
return
limb = BP
severity = W.severity
if(limb.owner)
victim = limb.owner
if(add_to_scars)
LAZYADD(limb.scars, src)
if(victim)
LAZYADD(victim.all_scars, src)
description = pick(W.scarring_descriptions)
precise_location = pick(limb.specific_locations)
switch(W.severity)
if(WOUND_SEVERITY_MODERATE)
visibility = 2
if(WOUND_SEVERITY_SEVERE)
visibility = 3
if(WOUND_SEVERITY_CRITICAL)
visibility = 5
/// Used when we finalize a scar from a healing cut
/datum/scar/proc/lazy_attach(obj/item/bodypart/BP, datum/wound/W)
LAZYADD(BP.scars, src)
if(BP.owner)
victim = BP.owner
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))
qdel(src)
return
limb = BP
src.severity = severity
LAZYADD(limb.scars, src)
if(BP.owner)
victim = BP.owner
LAZYADD(victim.all_scars, src)
src.description = description
precise_location = specific_location
switch(severity)
if(WOUND_SEVERITY_MODERATE)
visibility = 2
if(WOUND_SEVERITY_SEVERE)
visibility = 3
if(WOUND_SEVERITY_CRITICAL)
visibility = 5
return TRUE
/// What will show up in examine_more() if this scar is visible
/datum/scar/proc/get_examine_description(mob/viewer)
if(!victim || !is_visible(viewer))
return
var/msg = "[victim.p_they(TRUE)] [victim.p_have()] [description] on [victim.p_their()] [precise_location]."
switch(severity)
if(WOUND_SEVERITY_MODERATE)
msg = "<span class='tinynotice'>[msg]</span>"
if(WOUND_SEVERITY_SEVERE)
msg = "<span class='smallnotice'>[msg]</span>"
if(WOUND_SEVERITY_CRITICAL)
msg = "<span class='smallnotice'><b>[msg]</b></span>"
return "\t[msg]"
/// Whether a scar can currently be seen by the viewer
/datum/scar/proc/is_visible(mob/viewer)
if(!victim || !viewer)
return
if(get_dist(viewer, victim) > visibility)
return
if(!ishuman(victim) || isobserver(viewer) || victim == viewer)
return TRUE
var/mob/living/carbon/human/H = 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)))
return FALSE
else if(limb.scars_covered_by_clothes)
var/num_covers = LAZYLEN(H.clothingonpart(limb))
if(num_covers + get_dist(viewer, victim) >= visibility)
return FALSE
return TRUE
/// 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]"
+318
View File
@@ -0,0 +1,318 @@
/*
Wounds are specific medical complications that can arise and be applied to (currently) carbons, with a focus on humans. All of the code for and related to this is heavily WIP,
and the documentation will be slanted towards explaining what each part/piece is leading up to, until such a time as I finish the core implementations. The original design doc
can be found at https://hackmd.io/@Ryll/r1lb4SOwU
Wounds are datums that operate like a mix of diseases, brain traumas, and components, and are applied to a /obj/item/bodypart (preferably attached to a carbon) when they take large spikes of damage
or under other certain conditions (thrown hard against a wall, sustained exposure to plasma fire, etc). Wounds are categorized by the three following criteria:
1. Severity: Either MODERATE, SEVERE, or CRITICAL. See the hackmd for more details
2. Viable zones: What body parts the wound is applicable to. Generic wounds like broken bones and severe burns can apply to every zone, but you may want to add special wounds for certain limbs
like a twisted ankle for legs only, or open air exposure of the organs for particularly gruesome chest wounds. Wounds should be able to function for every zone they are marked viable for.
3. Damage type: Currently either BRUTE or BURN. Again, see the hackmd for a breakdown of my plans for each type.
When a body part suffers enough damage to get a wound, the severity (determined by a roll or something, worse damage leading to worse wounds), affected limb, and damage type sustained are factored into
deciding what specific wound will be applied. I'd like to have a few different types of wounds for at least some of the choices, but I'm just doing rough generals for now. Expect polishing
*/
/datum/wound
/// What it's named
var/name = "ouchie"
/// The description shown on the scanners
var/desc = ""
/// The basic treatment suggested by health analyzers
var/treat_text = ""
/// What the limb looks like on a cursory examine
var/examine_desc = "is badly hurt"
/// needed for "your arm has a compound fracture" vs "your arm has some third degree burns"
var/a_or_from = "a"
/// The visible message when this happens
var/occur_text = ""
/// This sound will be played upon the wound being applied
var/sound_effect
/// 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
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
/// Specific items such as bandages or sutures that can try directly treating this wound
var/list/treatable_by
/// Specific items such as bandages or sutures that can try directly treating this wound only if the user has the victim in an aggressive grab or higher
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
/// Using this limb in a do_after interaction will multiply the length by this duration (arms)
var/interaction_efficiency_penalty = 1
/// Incoming damage on this limb will be multiplied by this, to simulate tenderness and vulnerability (mostly burns).
var/damage_mulitplier_penalty = 1
/// If set and this wound is applied to a leg, we take this many deciseconds extra per step on this leg
var/limp_slowdown
/// 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
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
/// What status effect we assign on application
var/status_effect_type
/// The status effect we're linked to
var/datum/status_effect/linked_status_effect
/// If we're operating on this wound and it gets healed, we'll nix the surgery too
var/datum/surgery/attached_surgery
/// if you're a lazy git and just throw them in cryo, the wound will go away after accumulating severity * 25 power
var/cryo_progress
/// What kind of scars this wound will create description wise once healed
var/list/scarring_descriptions = list("general disfigurement")
/// 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
/datum/wound/Destroy()
if(attached_surgery)
QDEL_NULL(attached_surgery)
if(limb?.wounds && (src in limb.wounds)) // destroy can call remove_wound() and remove_wound() calls qdel, so we check to make sure there's anything to remove first
remove_wound()
limb = null
victim = null
return ..()
/**
* apply_wound() is used once a wound type is instantiated to assign it to a bodypart, and actually come into play.
*
*
* Arguments:
* * L: The bodypart we're wounding, we don't care about the person, we can get them through the limb
* * silent: Not actually necessary I don't think, was originally used for demoting wounds so they wouldn't make new messages, but I believe old_wound took over that, I may remove this shortly
* * old_wound: If our new wound is a replacement for one of the same time (promotion or demotion), we can reference the old one just before it's removed to copy over necessary vars
* * 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))
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()))
qdel(src)
return
// we accept promotions and demotions, but no point in redundancy. This should have already been checked wherever the wound was rolled and applied for (see: bodypart damage code), but we do an extra check
// in case we ever directly add wounds
for(var/i in L.wounds)
var/datum/wound/preexisting_wound = i
if((preexisting_wound.type == type) && (preexisting_wound != old_wound))
qdel(src)
return
victim = L.owner
limb = L
LAZYADD(victim.all_wounds, src)
LAZYADD(limb.wounds, src)
limb.update_wounds()
if(status_effect_type)
linked_status_effect = victim.apply_status_effect(status_effect_type, src)
SEND_SIGNAL(victim, COMSIG_CARBON_GAIN_WOUND, src, limb)
if(!victim.alerts["wound"]) // only one alert is shared between all of the wounds
victim.throw_alert("wound", /obj/screen/alert/status_effect/wound)
var/demoted
if(old_wound)
demoted = (severity <= old_wound.severity)
if(severity == WOUND_SEVERITY_TRIVIAL)
return
if(!(silent || demoted))
var/msg = "<span class='danger'>[victim]'s [limb.name] [occur_text]!</span>"
var/vis_dist = COMBAT_MESSAGE_RANGE
if(severity != WOUND_SEVERITY_MODERATE)
msg = "<b>[msg]</b>"
vis_dist = DEFAULT_MESSAGE_RANGE
victim.visible_message(msg, "<span class='userdanger'>Your [limb.name] [occur_text]!</span>", vision_distance = vis_dist)
if(sound_effect)
playsound(L.owner, sound_effect, 60 + 20 * severity, TRUE)
if(!demoted)
wound_injury(old_wound)
second_wind()
/// Remove the wound from whatever it's afflicting, and cleans up whateverstatus effects it had or modifiers it had on interaction times. ignore_limb is used for detachments where we only want to forget the victim
/datum/wound/proc/remove_wound(ignore_limb, replaced = FALSE)
//TODO: have better way to tell if we're getting removed without replacement (full heal) scar stuff
if(limb && !already_scarred && !replaced)
already_scarred = TRUE
var/datum/scar/new_scar = new
new_scar.generate(limb, src)
if(victim)
LAZYREMOVE(victim.all_wounds, src)
if(!victim.all_wounds)
victim.clear_alert("wound")
SEND_SIGNAL(victim, COMSIG_CARBON_LOSE_WOUND, src, limb)
if(limb && !ignore_limb)
LAZYREMOVE(limb.wounds, src)
limb.update_wounds()
/**
* replace_wound() is used when you want to replace the current wound with a new wound, presumably of the same category, just of a different severity (either up or down counts)
*
* This proc actually instantiates the new wound based off the specific type path passed, then returns the new instantiated wound datum.
*
* Arguments:
* * new_type- The TYPE PATH of the wound you want to replace this, like /datum/wound/brute/cut/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)
var/datum/wound/new_wound = new new_type
already_scarred = TRUE
remove_wound(replaced=TRUE)
new_wound.apply_wound(limb, old_wound = src, smited = smited)
qdel(src)
return new_wound
/// The immediate negative effects faced as a result of the wound
/datum/wound/proc/wound_injury(datum/wound/old_wound = null)
return
/// 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()
switch(severity)
if(WOUND_SEVERITY_MODERATE)
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_MODERATE)
if(WOUND_SEVERITY_SEVERE)
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_SEVERE)
if(WOUND_SEVERITY_CRITICAL)
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_CRITICAL)
/**
* 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.
*
* 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:
* * I: The item we're trying to use
* * user: The mob trying to use it on us
*/
/datum/wound/proc/try_treating(obj/item/I, mob/user)
// first we weed out if we're not dealing with our wound's bodypart, or if it might be an attack
if(!I || limb.body_zone != user.zone_selected || (I.force && user.a_intent != INTENT_HELP))
return FALSE
var/allowed = FALSE
// check if we have a valid treatable tool (or, if cauteries are allowed, if we have something hot)
if((I.tool_behaviour == treatable_tool) || (treatable_tool == TOOL_CAUTERY && I.get_temperature()))
allowed = TRUE
// failing that, see if we're aggro grabbing them and if we have an item that works for aggro grabs only
else if(user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE && check_grab_treatments(I, user))
allowed = TRUE
// failing THAT, we check if we have a generally allowed item
else
for(var/allowed_type in treatable_by)
if(istype(I, allowed_type))
allowed = TRUE
break
// if none of those apply, we return false to avoid interrupting
if(!allowed)
return FALSE
// now that we've determined we have a valid attempt at treating, we can stomp on their dreams if we're already interacting with the patient
if(INTERACTING_WITH(user, victim))
to_chat(user, "<span class='warning'>You're already interacting with [victim]!</span>")
return TRUE
// lastly, treat them
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()]
/datum/wound/proc/check_grab_treatments(obj/item/I, mob/user)
return FALSE
/// Like try_treating() but for unhanded interactions from humans, used by joint dislocations for manual bodypart chiropractice for example.
/datum/wound/proc/try_handling(mob/living/carbon/human/user)
return FALSE
/// Someone is using something that might be used for treating the wound on this limb
/datum/wound/proc/treat(obj/item/I, mob/user)
return
/// If var/processing is TRUE, this is run on each life tick
/datum/wound/proc/handle_process()
return
/// For use in do_after callback checks
/datum/wound/proc/still_exists()
return (!QDELETED(src) && limb)
/// When our parent bodypart is hurt
/datum/wound/proc/receive_damage(wounding_type, wounding_dmg, wound_bonus)
return
/// Called from cryoxadone and pyroxadone when they're proc'ing. Wounds will slowly be fixed separately from other methods when these are in effect. crappy name but eh
/datum/wound/proc/on_xadone(power)
cryo_progress += power
if(cryo_progress > 33 * severity)
qdel(src)
/// Called when we're crushed in an airlock or firedoor, for one of the improvised joint dislocation fixes
/datum/wound/proc/crush()
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.
*
* Return the full string line you want to show, note that we're already dealing with the 'warning' span at this point, and that \n is already appended for you in the place this is called from
*
* Arguments:
* * mob/user: The user examining the wound's owner, if that matters
*/
/datum/wound/proc/get_examine_description(mob/user)
return "<B>[victim.p_their(TRUE)] [limb.name] [examine_desc]!</B>"
/datum/wound/proc/get_scanner_description(mob/user)
return "Type: [name]\nSeverity: [severity_text()]\nDescription: [desc]\nRecommended Treatment: [treat_text]"
/datum/wound/proc/severity_text()
switch(severity)
if(WOUND_SEVERITY_TRIVIAL)
return "Trivial"
if(WOUND_SEVERITY_MODERATE)
return "Moderate"
if(WOUND_SEVERITY_SEVERE)
return "Severe"
if(WOUND_SEVERITY_CRITICAL)
return "Critical"
+453
View File
@@ -0,0 +1,453 @@
/*
Bones
*/
// TODO: well, a lot really, but i'd kill to get overlays and a bonebreaking effect like Blitz: The League, similar to electric shock skeletons
/*
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
/// Have we been taped?
var/taped
/// Have we been bone gel'd?
var/gelled
/// If we did the gel + surgical tape healing method for fractures, how many regen points we need
var/regen_points_needed
/// Our current counter for gel + surgical tape regeneration
var/regen_points_current
/// If we suffer severe head booboos, we can get brain traumas tied to them
var/datum/brain_trauma/active_trauma
/// What brain trauma group, if any, we can draw from for head wounds
var/brain_trauma_group
/// If we deal brain traumas, when is the next one due?
var/next_trauma_cycle
/// How long do we wait +/- 20% for the next trauma?
var/trauma_cycle_cooldown
/// If this is a chest wound and this is set, we have this chance to cough up blood when hit in the chest
var/chance_internal_bleeding = 0
/*
Overwriting of base procs
*/
/datum/wound/brute/bone/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)
next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown)
RegisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, .proc/attack_with_hurt_hand)
if(limb.held_index && victim.get_item_for_held_index(limb.held_index) && (disabling || prob(30 * severity)))
var/obj/item/I = victim.get_item_for_held_index(limb.held_index)
if(istype(I, /obj/item/offhand))
I = victim.get_inactive_held_item()
if(I && victim.dropItemToGround(I))
victim.visible_message("<span class='danger'>[victim] drops [I] in shock!</span>", "<span class='warning'><b>The force on your [limb.name] causes you to drop [I]!</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
update_inefficiencies()
/datum/wound/brute/bone/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()
. = ..()
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle)
if(active_trauma)
QDEL_NULL(active_trauma)
else
active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND)
next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown)
if(!regen_points_needed)
return
regen_points_current++
if(prob(severity * 2))
victim.take_bodypart_damage(rand(2, severity * 2), stamina=rand(2, severity * 2.5), wound_bonus=CANT_WOUND)
if(prob(33))
to_chat(victim, "<span class='danger'>You feel a sharp pain in your body as your bones are reforming!</span>")
if(regen_points_current > regen_points_needed)
if(!victim || !limb)
qdel(src)
return
to_chat(victim, "<span class='green'>Your [limb.name] has recovered from your fracture!</span>")
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)
if(victim.get_active_hand() != limb || victim.a_intent == INTENT_HELP || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE)
return
// With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit
if(prob((severity - 1) * 15))
// And you have a 70% or 50% chance to actually land the blow, respectively
if(prob(70 - 20 * (severity - 1)))
to_chat(victim, "<span class='userdanger'>The fracture in your [limb.name] shoots with pain as you strike [target]!</span>")
limb.receive_damage(brute=rand(1,5))
else
victim.visible_message("<span class='danger'>[victim] weakly strikes [target] with [victim.p_their()] broken [limb.name], recoiling from pain!</span>", \
"<span class='userdanger'>You fail to strike [target] as the fracture in your [limb.name] lights up in unbearable pain!</span>", vision_distance=COMBAT_MESSAGE_RANGE)
victim.emote("scream")
victim.Stun(0.5 SECONDS)
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)
return
if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(chance_internal_bleeding + wounding_dmg))
var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound
switch(blood_bled)
if(1 to 6)
victim.bleed(blood_bled, TRUE)
if(7 to 13)
victim.visible_message("<span class='danger'>[victim] coughs up a bit of blood from the blow to [victim.p_their()] chest.</span>", "<span class='danger'>You cough up a bit of blood from the blow to your chest.</span>")
victim.bleed(blood_bled, TRUE)
if(14 to 19)
victim.visible_message("<span class='danger'>[victim] spits out a string of blood from the blow to [victim.p_their()] chest!</span>", "<span class='danger'>You spit out a string of blood from the blow to your chest!</span>")
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.bleed(blood_bled)
if(20 to INFINITY)
victim.visible_message("<span class='danger'>[victim] chokes up a spray of blood from the blow to [victim.p_their()] chest!</span>", "<span class='danger'><b>You choke up on a spray of blood from the blow to your chest!</b></span>")
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("<span class='danger'>The splint securing [victim]'s [limb.name] is [destroyed_verb] away!</span>", "<span class='danger'><b>The splint securing your [limb.name] is [destroyed_verb] away!</b></span>", 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)
return ..()
var/msg = ""
if(!splinted)
msg = "<B>[victim.p_their(TRUE)] [limb.name] [examine_desc]"
else
var/splint_condition = ""
// how much life we have left in these bandages
switch(splinted.obj_integrity / splinted.max_integrity * 100)
if(0 to 25)
splint_condition = "just barely "
if(25 to 50)
splint_condition = "loosely "
if(50 to 75)
splint_condition = "mostly "
if(75 to INFINITY)
splint_condition = "tightly "
msg = "<B>[victim.p_their(TRUE)] [limb.name] is [splint_condition] fastened in a splint of [splinted.name]</B>"
if(taped)
msg += ", <span class='notice'>and appears to be reforming itself under some surgical tape!</span>"
else if(gelled)
msg += ", <span class='notice'>with fizzing flecks of blue bone gel sparking off the bone!</span>"
else
msg += "!"
return "[msg]</B>"
/*
New common procs for /datum/wound/brute/bone/
*/
/datum/wound/brute/bone/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
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)
else
interaction_efficiency_penalty = interaction_efficiency_penalty
if(initial(disabling) && splinted)
disabling = FALSE
else if(initial(disabling))
disabling = TRUE
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, "<span class='warning'>The splint already on [user == victim ? "your" : "[victim]'s"] [limb.name] is better than you can do with [I].</span>")
return
user.visible_message("<span class='danger'>[user] begins splinting [victim]'s [limb.name] with [I].</span>", "<span class='warning'>You begin splinting [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
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("<span class='green'>[user] finishes splinting [victim]'s [limb.name]!</span>", "<span class='green'>You finish splinting [user == victim ? "your" : "[victim]'s"] [limb.name]!</span>")
treat_priority = FALSE
splinted = new I.type(limb)
splinted.amount = 1
I.use(1)
update_inefficiencies()
/*
Moderate (Joint Dislocation)
*/
/datum/wound/brute/bone/moderate
name = "Joint Dislocation"
desc = "Patient's bone has been unset from socket, causing pain and reduced motor function."
treat_text = "Recommended application of bonesetter to affected limb, though manual relocation by applying an aggressive grab to the patient and helpfully interacting with afflicted limb may suffice."
examine_desc = "is awkwardly jammed out of place"
occur_text = "jerks violently and becomes unseated"
severity = WOUND_SEVERITY_MODERATE
viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
interaction_efficiency_penalty = 1.5
limp_slowdown = 3
threshold_minimum = 35
threshold_penalty = 15
treatable_tool = TOOL_BONESET
status_effect_type = /datum/status_effect/wound/bone/moderate
scarring_descriptions = list("light discoloring", "a slight blue tint")
/datum/wound/brute/bone/moderate/crush()
if(prob(33))
victim.visible_message("<span class='danger'>[victim]'s dislocated [limb.name] pops back into place!</span>", "<span class='userdanger'>Your dislocated [limb.name] pops back into place! Ow!</span>")
remove_wound()
/datum/wound/brute/bone/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
if(user.grab_state == GRAB_PASSIVE)
to_chat(user, "<span class='warning'>You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!</span>")
return TRUE
if(user.grab_state >= GRAB_AGGRESSIVE)
user.visible_message("<span class='danger'>[user] begins twisting and straining [victim]'s dislocated [limb.name]!</span>", "<span class='notice'>You begin twisting and straining [victim]'s dislocated [limb.name]...</span>", ignored_mobs=victim)
to_chat(victim, "<span class='userdanger'>[user] begins twisting and straining your dislocated [limb.name]!</span>")
if(user.a_intent == INTENT_HELP)
chiropractice(user)
else
malpractice(user)
return TRUE
/// If someone is snapping our dislocated joint back into place by hand with an aggro grab and help intent
/datum/wound/brute/bone/moderate/proc/chiropractice(mob/living/carbon/human/user)
var/time = base_treat_time
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
if(prob(65))
user.visible_message("<span class='danger'>[user] snaps [victim]'s dislocated [limb.name] back into place!</span>", "<span class='notice'>You snap [victim]'s dislocated [limb.name] back into place!</span>", ignored_mobs=victim)
to_chat(victim, "<span class='userdanger'>[user] snaps your dislocated [limb.name] back into place!</span>")
victim.emote("scream")
limb.receive_damage(brute=20, wound_bonus=CANT_WOUND)
qdel(src)
else
user.visible_message("<span class='danger'>[user] wrenches [victim]'s dislocated [limb.name] around painfully!</span>", "<span class='danger'>You wrench [victim]'s dislocated [limb.name] around painfully!</span>", ignored_mobs=victim)
to_chat(victim, "<span class='userdanger'>[user] wrenches your dislocated [limb.name] around painfully!</span>")
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
chiropractice(user)
/// If someone is snapping our dislocated joint into a fracture by hand with an aggro grab and harm or disarm intent
/datum/wound/brute/bone/moderate/proc/malpractice(mob/living/carbon/human/user)
var/time = base_treat_time
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
if(prob(65))
user.visible_message("<span class='danger'>[user] snaps [victim]'s dislocated [limb.name] with a sickening crack!</span>", "<span class='danger'>You snap [victim]'s dislocated [limb.name] with a sickening crack!</span>", ignored_mobs=victim)
to_chat(victim, "<span class='userdanger'>[user] snaps your dislocated [limb.name] with a sickening crack!</span>")
victim.emote("scream")
limb.receive_damage(brute=25, wound_bonus=30)
else
user.visible_message("<span class='danger'>[user] wrenches [victim]'s dislocated [limb.name] around painfully!</span>", "<span class='danger'>You wrench [victim]'s dislocated [limb.name] around painfully!</span>", ignored_mobs=victim)
to_chat(victim, "<span class='userdanger'>[user] wrenches your dislocated [limb.name] around painfully!</span>")
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
malpractice(user)
/datum/wound/brute/bone/moderate/treat(obj/item/I, mob/user)
if(victim == user)
victim.visible_message("<span class='danger'>[user] begins resetting [victim.p_their()] [limb.name] with [I].</span>", "<span class='warning'>You begin resetting your [limb.name] with [I]...</span>")
else
user.visible_message("<span class='danger'>[user] begins resetting [victim]'s [limb.name] with [I].</span>", "<span class='notice'>You begin resetting [victim]'s [limb.name] with [I]...</span>")
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
return
if(victim == user)
limb.receive_damage(brute=15, wound_bonus=CANT_WOUND)
victim.visible_message("<span class='danger'>[user] finishes resetting [victim.p_their()] [limb.name]!</span>", "<span class='userdanger'>You reset your [limb.name]!</span>")
else
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
user.visible_message("<span class='danger'>[user] finishes resetting [victim]'s [limb.name]!</span>", "<span class='nicegreen'>You finish resetting [victim]'s [limb.name]!</span>", victim)
to_chat(victim, "<span class='userdanger'>[user] resets your [limb.name]!</span>")
victim.emote("scream")
qdel(src)
/*
Severe (Hairline Fracture)
*/
/datum/wound/brute/bone/severe
name = "Hairline Fracture"
desc = "Patient's bone has suffered a crack in the foundation, causing serious pain and reduced limb functionality."
treat_text = "Recommended light surgical application of bone gel, though splinting will prevent worsening situation."
examine_desc = "appears bruised and grotesquely swollen"
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")
brain_trauma_group = BRAIN_TRAUMA_MILD
trauma_cycle_cooldown = 1.5 MINUTES
chance_internal_bleeding = 40
/datum/wound/brute/bone/critical
name = "Compound Fracture"
desc = "Patient's bones have suffered multiple gruesome fractures, causing significant pain and near uselessness of limb."
treat_text = "Immediate binding of affected limb, followed by surgical intervention ASAP."
examine_desc = "has a cracked bone sticking out of it"
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'
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")
brain_trauma_group = BRAIN_TRAUMA_SEVERE
trauma_cycle_cooldown = 2.5 MINUTES
chance_internal_bleeding = 60
// 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)
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)
if(gelled)
to_chat(user, "<span class='warning'>[user == victim ? "Your" : "[victim]'s"] [limb.name] is already coated with bone gel!</span>")
return
user.visible_message("<span class='danger'>[user] begins hastily applying [I] to [victim]'s' [limb.name]...</span>", "<span class='warning'>You begin hastily applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name], disregarding the warning label...</span>")
if(!do_after(user, base_treat_time * 1.5 * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
return
I.use(1)
victim.emote("scream")
if(user != victim)
user.visible_message("<span class='notice'>[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!</span>", "<span class='notice'>You finish applying [I] to [victim]'s [limb.name]!</span>", ignored_mobs=victim)
to_chat(victim, "<span class='userdanger'>[user] finishes applying [I] to your [limb.name], and you can feel the bones exploding with pain as they begin melting and reforming!</span>")
else
var/painkiller_bonus = 0
if(victim.drunkenness)
painkiller_bonus += 5
if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/medicine/morphine))
painkiller_bonus += 10
if(victim.reagents && 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
victim.visible_message("<span class='danger'>[victim] fails to finish applying [I] to [victim.p_their()] [limb.name], passing out from the pain!</span>", "<span class='notice'>You black out from the pain of applying [I] to your [limb.name] before you can finish!</span>")
victim.AdjustUnconscious(5 SECONDS)
return
victim.visible_message("<span class='notice'>[victim] finishes applying [I] to [victim.p_their()] [limb.name], grimacing from the pain!</span>", "<span class='notice'>You finish applying [I] to your [limb.name], and your bones explode in pain!</span>")
limb.receive_damage(30, stamina=100, wound_bonus=CANT_WOUND)
if(!gelled)
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)
if(!gelled)
to_chat(user, "<span class='warning'>[user == victim ? "Your" : "[victim]'s"] [limb.name] must be coated with bone gel to perform this emergency operation!</span>")
return
if(taped)
to_chat(user, "<span class='warning'>[user == victim ? "Your" : "[victim]'s"] [limb.name] is already wrapped in [I.name] and reforming!</span>")
return
user.visible_message("<span class='danger'>[user] begins applying [I] to [victim]'s' [limb.name]...</span>", "<span class='warning'>You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]...</span>")
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
return
regen_points_current = 0
regen_points_needed = 30 SECONDS * (user == victim ? 1.5 : 1) * (severity - 1)
I.use(1)
if(user != victim)
user.visible_message("<span class='notice'>[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!</span>", "<span class='notice'>You finish applying [I] to [victim]'s [limb.name]!</span>", ignored_mobs=victim)
to_chat(victim, "<span class='green'>[user] finishes applying [I] to your [limb.name], you immediately begin to feel your bones start to reform!</span>")
else
victim.visible_message("<span class='notice'>[victim] finishes applying [I] to [victim.p_their()] [limb.name], !</span>", "<span class='green'>You finish applying [I] to your [limb.name], and you immediately begin to feel your bones start to reform!</span>")
taped = TRUE
processes = TRUE
/datum/wound/brute/bone/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)
. = ..()
. += "<div class='ml-3'>"
if(!gelled)
. += "Alternative Treatment: Apply bone gel directly to injured limb, then apply surgical tape to begin bone regeneration. This is both excruciatingly painful and slow, and only recommended in dire circumstances.\n"
else if(!taped)
. += "<span class='notice'>Continue Alternative Treatment: Apply surgical tape directly to injured limb to begin bone regeneration. Note, this is both excruciatingly painful and slow.</span>\n"
else
. += "<span class='notice'>Note: Bone regeneration in effect. Bone is [round((regen_points_current*100)/regen_points_needed,0.1)]% regenerated.</span>\n"
if(limb.body_zone == BODY_ZONE_HEAD)
. += "Cranial Trauma Detected: Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired."
else if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume)
. += "Ribcage Trauma Detected: Further trauma to chest is likely to worsen internal bleeding until bone is repaired."
. += "</div>"
+323
View File
@@ -0,0 +1,323 @@
// 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
processes = TRUE
sound_effect = 'sound/effects/sizzle1.ogg'
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
// Flesh damage vars
/// How much damage to our flesh we currently have. Once both this and infestation reach 0, the wound is considered healed
var/flesh_damage = 5
/// Our current counter for how much flesh regeneration we have stacked from regenerative mesh/synthflesh/whatever, decrements each tick and lowers flesh_damage
var/flesh_healing = 0
// Infestation vars (only for severe and critical)
/// How quickly infection breeds on this burn if we don't have disinfectant
var/infestation_rate = 0
/// Our current level of infection
var/infestation = 0
/// Our current level of sanitization/anti-infection, from disinfectants/alcohol/UV lights. While positive, totally pauses and slowly reverses infestation effects each tick
var/sanitization = 0
/// Once we reach infestation beyond WOUND_INFESTATION_SEPSIS, we get this many warnings before the limb is completely paralyzed (you'd have to ignore a really bad burn for a really long time for this to happen)
var/strikes_to_lose_limb = 3
/// 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()
. = ..()
if(strikes_to_lose_limb == 0)
victim.adjustToxLoss(0.5)
if(prob(1))
victim.visible_message("<span class='danger'>The infection on the remnants of [victim]'s [limb.name] shift and bubble nauseatingly!</span>", "<span class='warning'>You can feel the infection on the remnants of your [limb.name] coursing through your veins!</span>")
return
if(victim.reagents)
if(victim.reagents.has_reagent(/datum/reagent/medicine/spaceacillin))
sanitization += 0.9
if(victim.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine/))
sanitization += 0.9
if(victim.reagents.has_reagent(/datum/reagent/medicine/mine_salve))
sanitization += 0.3
flesh_healing += 0.5
if(current_bandage)
current_bandage.absorption_capacity -= WOUND_BURN_SANITIZATION_RATE
if(current_bandage.absorption_capacity <= 0)
victim.visible_message("<span class='danger'>Pus soaks through \the [current_bandage] on [victim]'s [limb.name].</span>", "<span class='warning'>Pus soaks through \the [current_bandage] on your [limb.name].</span>", vision_distance=COMBAT_MESSAGE_RANGE)
QDEL_NULL(current_bandage)
treat_priority = TRUE
if(flesh_healing > 0)
var/bandage_factor = (current_bandage ? current_bandage.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
// here's the check to see if we're cleared up
if((flesh_damage <= 0) && (infestation <= 1))
to_chat(victim, "<span class='green'>The burns on your [limb.name] have cleared up!</span>")
qdel(src)
return
// 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)
infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE)
sanitization = max(0, sanitization - (WOUND_BURN_SANITIZATION_RATE * bandage_factor))
return
infestation += infestation_rate
switch(infestation)
if(0 to WOUND_INFECTION_MODERATE)
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
if(prob(30))
victim.adjustToxLoss(0.2)
if(prob(6))
to_chat(victim, "<span class='warning'>The blisters on your [limb.name] ooze a strange pus...</span>")
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
if(!disabling && prob(2))
to_chat(victim, "<span class='warning'><b>Your [limb.name] completely locks up, as you struggle for control against the infection!</b></span>")
disabling = TRUE
else if(disabling && prob(8))
to_chat(victim, "<span class='notice'>You regain sensation in your [limb.name], but it's still in terrible shape!</span>")
disabling = FALSE
else if(prob(20))
victim.adjustToxLoss(0.5)
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
if(!disabling && prob(3))
to_chat(victim, "<span class='warning'><b>You suddenly lose all sensation of the festering infection in your [limb.name]!</b></span>")
disabling = TRUE
else if(disabling && prob(3))
to_chat(victim, "<span class='notice'>You can barely feel your [limb.name] again, and you have to strain to retain motor control!</span>")
disabling = FALSE
else if(prob(1))
to_chat(victim, "<span class='warning'>You contemplate life without your [limb.name]...</span>")
victim.adjustToxLoss(0.75)
else if(prob(4))
victim.adjustToxLoss(1)
if(WOUND_INFECTION_SEPTIC to INFINITY)
if(prob(infestation))
switch(strikes_to_lose_limb)
if(3 to INFINITY)
to_chat(victim, "<span class='deadsay'>The skin on your [limb.name] is literally dripping off, you feel awful!</span>")
if(2)
to_chat(victim, "<span class='deadsay'><b>The infection in your [limb.name] is literally dripping off, you feel horrible!</b></span>")
if(1)
to_chat(victim, "<span class='deadsay'><b>Infection has just about completely claimed your [limb.name]!</b></span>")
if(0)
to_chat(victim, "<span class='deadsay'><b>The last of the nerve endings in your [limb.name] wither away, as the infection completely paralyzes your joint connector.</b></span>")
threshold_penalty = 120 // piss easy to destroy
var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone)
victim.gain_trauma(sepsis)
strikes_to_lose_limb--
/datum/wound/burn/get_examine_description(mob/user)
if(strikes_to_lose_limb <= 0)
return "<span class='deadsay'><B>[victim.p_their(TRUE)] [limb.name] is completely dead and unrecognizable as organic.</B></span>"
var/condition = ""
if(current_bandage)
var/bandage_condition
switch(current_bandage.absorption_capacity)
if(0 to 1.25)
bandage_condition = "nearly ruined "
if(1.25 to 2.75)
bandage_condition = "badly worn "
if(2.75 to 4)
bandage_condition = "slightly pus-stained "
if(4 to INFINITY)
bandage_condition = "clean "
condition += " underneath a dressing of [bandage_condition] [current_bandage.name]"
else
switch(infestation)
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
condition += ", <span class='deadsay'>with small spots of discoloration along the nearby veins!</span>"
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
condition += ", <span class='deadsay'>with dark clouds spreading outwards under the skin!</span>"
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
condition += ", <span class='deadsay'>with streaks of rotten infection pulsating outward!</span>"
if(WOUND_INFECTION_SEPTIC to INFINITY)
return "<span class='deadsay'><B>[victim.p_their(TRUE)] [limb.name] is a mess of char and rot, skin literally dripping off the bone with infection!</B></span>"
else
condition += "!"
return "<B>[victim.p_their(TRUE)] [limb.name] [examine_desc][condition]</B>"
/datum/wound/burn/get_scanner_description(mob/user)
if(strikes_to_lose_limb == 0)
var/oopsie = "Type: [name]\nSeverity: [severity_text()]"
oopsie += "<div class='ml-3'>Infection Level: <span class='deadsay'>The infection is total. The bodypart is lost. Amputate or augment limb immediately.</span></div>"
return oopsie
. = ..()
. += "<div class='ml-3'>"
if(infestation <= sanitization && flesh_damage <= flesh_healing)
. += "No further treatment required: Burns will heal shortly."
else
switch(infestation)
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
. += "Infection Level: Moderate\n"
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
. += "Infection Level: Severe\n"
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
. += "Infection Level: <span class='deadsay'>CRITICAL</span>\n"
if(WOUND_INFECTION_SEPTIC to INFINITY)
. += "Infection Level: <span class='deadsay'>LOSS IMMINENT</span>\n"
if(infestation > sanitization)
. += "\tSurgical debridement, antiobiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n"
if(flesh_damage > 0)
. += "Flesh damage detected: Please apply ointment or regenerative mesh to allow recovery.\n"
. += "</div>"
/*
new burn common procs
*/
/// if someone is using ointment on our burns
/datum/wound/burn/proc/ointment(obj/item/stack/medical/ointment/I, mob/user)
user.visible_message("<span class='notice'>[user] begins applying [I] to [victim]'s [limb.name]...</span>", "<span class='notice'>You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]...</span>")
if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target = victim))
return
limb.heal_damage(I.heal_brute, I.heal_burn)
user.visible_message("<span class='green'>[user] applies [I] to [victim].</span>", "<span class='green'>You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].</span>")
I.use(1)
sanitization += I.sanitization
flesh_healing += I.flesh_regeneration
if((infestation <= 0 || sanitization >= infestation) && (flesh_damage <= 0 || flesh_healing > flesh_damage))
to_chat(user, "<span class='notice'>You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.name] to recover.</span>")
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, "<span class='warning'>The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!</span>")
return
user.visible_message("<span class='warning'>[user] begins to redress the burns on [victim]'s [limb.name] with [I]...</span>", "<span class='warning'>You begin redressing the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
else
user.visible_message("<span class='notice'>[user] begins to dress the burns on [victim]'s [limb.name] with [I]...</span>", "<span class='notice'>You begin dressing the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
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("<span class='green'>[user] applies [I] to [victim].</span>", "<span class='green'>You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].</span>")
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("<span class='notice'>[user] begins wrapping [victim]'s [limb.name] with [I]...</span>", "<span class='notice'>You begin wrapping [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
limb.heal_damage(I.heal_brute, I.heal_burn)
user.visible_message("<span class='green'>[user] applies [I] to [victim].</span>", "<span class='green'>You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].</span>")
I.use(1)
sanitization += I.sanitization
flesh_healing += I.flesh_regeneration
if(sanitization >= infestation && flesh_healing > flesh_damage)
to_chat(user, "<span class='notice'>You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.name] to recover.</span>")
else
try_treating(I, user)
/// Paramedic UV penlights
/datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user)
if(I.uv_cooldown > world.time)
to_chat(user, "<span class='notice'>[I] is still recharging!</span>")
return
if(infestation <= 0 || infestation < sanitization)
to_chat(user, "<span class='notice'>There's no infection to treat on [victim]'s [limb.name]!</span>")
return
user.visible_message("<span class='notice'>[user] flashes the burns on [victim]'s [limb] with [I].</span>", "<span class='notice'>You flash the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I].</span>", vision_distance=COMBAT_MESSAGE_RANGE)
sanitization += I.uv_power
I.uv_cooldown = world.time + 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))
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)
flesh_healing += amount * 0.5 // 20u patch will heal 10 flesh standard
// we don't even care about first degree burns, straight to second
/datum/wound/burn/moderate
name = "Second Degree Burns"
desc = "Patient is suffering considerable burns with mild skin penetration, weakening limb integrity and increased burning sensations."
treat_text = "Recommended application of topical ointment or regenerative mesh to affected region."
examine_desc = "is badly burned and breaking out in blisters"
occur_text = "breaks out with violent red burns"
severity = WOUND_SEVERITY_MODERATE
damage_mulitplier_penalty = 1.1
threshold_minimum = 40
threshold_penalty = 30 // burns cause significant decrease in limb integrity compared to other wounds
status_effect_type = /datum/status_effect/wound/burn/moderate
flesh_damage = 5
scarring_descriptions = list("small amoeba-shaped skinmarks", "a faded streak of depressed skin")
/datum/wound/burn/severe
name = "Third Degree Burns"
desc = "Patient is suffering extreme burns with full skin penetration, creating serious risk of infection and greatly reduced limb integrity."
treat_text = "Recommended immediate disinfection and excision of any infected skin, followed by bandaging and ointment."
examine_desc = "appears seriously charred, with aggressive red splotches"
occur_text = "chars rapidly, exposing ruined tissue and spreading angry red burns"
severity = WOUND_SEVERITY_SEVERE
damage_mulitplier_penalty = 1.2
threshold_minimum = 80
threshold_penalty = 40
status_effect_type = /datum/status_effect/wound/burn/severe
treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/gauze, /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")
/datum/wound/burn/critical
name = "Catastrophic Burns"
desc = "Patient is suffering near complete loss of tissue and significantly charred muscle and bone, creating life-threatening risk of infection and negligible limb integrity."
treat_text = "Immediate surgical debriding of any infected skin, followed by potent tissue regeneration formula and bandaging."
examine_desc = "is a ruined mess of blanched bone, melted fat, and charred tissue"
occur_text = "vaporizes as flesh, bone, and fat melt together in a horrifying mess"
severity = WOUND_SEVERITY_CRITICAL
damage_mulitplier_penalty = 1.3
sound_effect = 'sound/effects/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)
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")
+314
View File
@@ -0,0 +1,314 @@
/*
Cuts
*/
/datum/wound/brute/cut
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)
treatable_by_grabbed = list(/obj/item/gun/energy/laser)
treatable_tool = TOOL_CAUTERY
treat_priority = TRUE
base_treat_time = 3 SECONDS
/// How much blood we start losing when this wound is first applied
var/initial_flow
/// When we have less than this amount of flow, either from treatment or clotting, we demote to a lower cut or are healed of the wound
var/minimum_flow
/// How fast our blood flow will naturally decrease per tick, not only do larger cuts bleed more faster, they clot slower
var/clot_rate
/// Once the blood flow drops below minimum_flow, we demote it to this type of wound. If there's none, we're all better
var/demotes_to
/// How much staunching per type (cautery, suturing, bandaging) you can have before that type is no longer effective for this cut NOT IMPLEMENTED
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)
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)
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)
return ..()
var/bandage_condition = ""
// how much life we have left in these bandages
switch(current_bandage.absorption_capacity)
if(0 to 1.25)
bandage_condition = "nearly ruined "
if(1.25 to 2.75)
bandage_condition = "badly worn "
if(2.75 to 4)
bandage_condition = "slightly bloodied "
if(4 to INFINITY)
bandage_condition = "clean "
return "<B>The cuts on [victim.p_their()] [limb.name] are wrapped with [bandage_condition] [current_bandage.name]!</B>"
/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
blood_flow += 0.05 * wounding_dmg
/datum/wound/brute/cut/handle_process()
blood_flow = min(blood_flow, WOUND_CUT_MAX_BLOODFLOW)
if(victim.reagents && 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(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("<span class='danger'>Blood soaks through \the [current_bandage] on [victim]'s [limb.name].</span>", "<span class='warning'>Blood soaks through \the [current_bandage] on your [limb.name].</span>", vision_distance=COMBAT_MESSAGE_RANGE)
QDEL_NULL(current_bandage)
treat_priority = TRUE
else
blood_flow -= clot_rate
if(blood_flow > highest_flow)
highest_flow = blood_flow
if(blood_flow < minimum_flow)
if(demotes_to)
replace_wound(demotes_to)
else
to_chat(victim, "<span class='green'>The cut on your [limb.name] has stopped bleeding!</span>")
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)
if(istype(I, /obj/item/gun/energy/laser))
return TRUE
/datum/wound/brute/cut/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)
if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB)
return FALSE
if(!iscatperson(user))
return FALSE
if(!(user.client?.prefs.vore_flags & LICKABLE))
return FALSE
lick_wounds(user)
return TRUE
/// if a felinid is licking this cut to reduce bleeding
/datum/wound/brute/cut/proc/lick_wounds(mob/living/carbon/human/user)
if(INTERACTING_WITH(user, victim))
to_chat(user, "<span class='warning'>You're already interacting with [victim]!</span>")
return
user.visible_message("<span class='notice'>[user] begins licking the wounds on [victim]'s [limb.name].</span>", "<span class='notice'>You begin licking the wounds on [victim]'s [limb.name]...</span>", ignored_mobs=victim)
to_chat(victim, "<span class='notice'>[user] begins to lick the wounds on your [limb.name].</span")
if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
user.visible_message("<span class='notice'>[user] licks the wounds on [victim]'s [limb.name].</span>", "<span class='notice'>You lick some of the wounds on [victim]'s [limb.name]</span>", ignored_mobs=victim)
to_chat(victim, "<span class='green'>[user] licks the wounds on your [limb.name]!</span")
blood_flow -= 0.5
if(isinsect(victim) || iscatperson(victim) || ismammal(victim) || isdwarf(victim) || ismonkey(victim)) // Yep you can lick monkeys.
user.reagents.add_reagent(/datum/reagent/hairball, 2)
else if(ishumanbasic(victim) || isflyperson(victim) || islizard(victim) || isdullahan(victim))
user.reagents.add_reagent(/datum/reagent/hairball, 1)
if(blood_flow > minimum_flow)
try_handling(user)
else if(demotes_to)
to_chat(user, "<span class='green'>You successfully lower the severity of [victim]'s cuts.</span>")
/datum/wound/brute/cut/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
/// 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)
var/self_penalty_mult = (user == victim ? 1.25 : 1)
user.visible_message("<span class='warning'>[user] begins aiming [lasgun] directly at [victim]'s [limb.name]...</span>", "<span class='userdanger'>You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [limb.name]...</span>")
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
var/damage = lasgun.chambered.BB.damage
lasgun.chambered.BB.wound_bonus -= 30
lasgun.chambered.BB.damage *= self_penalty_mult
if(!lasgun.process_fire(victim, victim, TRUE, null, limb.body_zone))
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("<span class='warning'>The cuts on [victim]'s [limb.name] scar over!</span>")
/// 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)
var/self_penalty_mult = (user == victim ? 1.5 : 1)
user.visible_message("<span class='danger'>[user] begins cauterizing [victim]'s [limb.name] with [I]...</span>", "<span class='danger'>You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
user.visible_message("<span class='green'>[user] cauterizes some of the bleeding on [victim].</span>", "<span class='green'>You cauterize some of the bleeding on [victim].</span>")
limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND)
if(prob(30))
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)
else if(demotes_to)
to_chat(user, "<span class='green'>You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.</span>")
/// If someone is using a suture to close this cut
/datum/wound/brute/cut/proc/suture(obj/item/stack/medical/suture/I, mob/user)
var/self_penalty_mult = (user == victim ? 1.4 : 1)
user.visible_message("<span class='notice'>[user] begins stitching [victim]'s [limb.name] with [I]...</span>", "<span class='notice'>You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
user.visible_message("<span class='green'>[user] stitches up some of the bleeding on [victim].</span>", "<span class='green'>You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].</span>")
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)
try_treating(I, user)
else if(demotes_to)
to_chat(user, "<span class='green'>You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.</span>")
/// 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, "<span class='warning'>The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!</span>")
return
else
user.visible_message("<span class='warning'>[user] begins rewrapping the cuts on [victim]'s [limb.name] with [I]...</span>", "<span class='warning'>You begin rewrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
else
user.visible_message("<span class='warning'>[user] begins wrapping the cuts on [victim]'s [limb.name] with [I]...</span>", "<span class='warning'>You begin wrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
return
user.visible_message("<span class='green'>[user] applies [I] to [victim]'s [limb.name].</span>", "<span class='green'>You bandage some of the bleeding on [user == victim ? "yourself" : "[victim]"].</span>")
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
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'
severity = WOUND_SEVERITY_MODERATE
initial_flow = 2
minimum_flow = 0.5
max_per_type = 3
clot_rate = 0.15
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")
/datum/wound/brute/cut/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'
severity = WOUND_SEVERITY_SEVERE
initial_flow = 3.25
minimum_flow = 2.75
clot_rate = 0.07
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")
/datum/wound/brute/cut/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"
occur_text = "is torn open, spraying blood wildly"
sound_effect = 'sound/effects/blood3.ogg'
severity = WOUND_SEVERITY_CRITICAL
initial_flow = 4.25
minimum_flow = 4
clot_rate = -0.05 // critical cuts actively get worse instead of better
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)