section 2

This commit is contained in:
timothyteakettle
2020-07-24 23:44:57 +01:00
parent 7fb55a02a5
commit 8360bb1a7f
44 changed files with 760 additions and 99 deletions

View File

@@ -230,6 +230,6 @@
/obj/item/reagent_containers/hypospray/medipen/ekit,
/obj/item/reagent_containers/hypospray/medipen/blood_loss,
/obj/item/reagent_containers/hypospray/medipen/blood_loss,
/obj/item/reagent_containers/hypospray/medipen/blood_loss
/obj/item/reagent_containers/hypospray/medipen/blood_loss)
crate_name = "medipen crate"

View File

@@ -27,6 +27,12 @@
juice_results = list(/datum/reagent/consumable/banana = 0)
distill_reagent = /datum/reagent/consumable/ethanol/bananahonk
/obj/item/reagent_containers/food/snacks/grown/banana/generate_trash(atom/location)
. = ..()
var/obj/item/grown/bananapeel/peel = .
if(istype(peel))
peel.grind_results = list(/datum/reagent/consumable/banana_peel = seed.potency * 0.2)
/obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is aiming [src] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!</span>")
playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1)

View File

@@ -135,12 +135,13 @@
dtype = I.damtype
if(!blocked)
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
"<span class='userdanger'>You have been hit by [I].</span>")
var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration)
apply_damage(total_damage, dtype, impacting_zone, armor, sharpness=I.sharpness)
if(I.thrownby)
log_combat(I.thrownby, src, "threw and hit", I)
if(!nosell_hit)
visible_message("<span class='danger'>[src] is hit by [I]!</span>", \
"<span class='userdanger'>You're hit by [I]!</span>")
if(!I.throwforce)
return
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND))
else
return 1
else

View File

@@ -14,5 +14,5 @@
/obj/item/throwing_star/ninja
name = "ninja throwing star"
throwforce = 30
throwforce = 20
embedding = list("pain_mult" = 6, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15)

View File

@@ -28,6 +28,7 @@
var/degrees = 0
var/font = PEN_FONT
embedding = list()
sharpness = SHARP_POINTY
/obj/item/pen/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is scribbling numbers all over [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit sudoku...</span>")

View File

@@ -47,7 +47,7 @@
/obj/item/ammo_box/c38/dumdum
name = "speed loader (.38 DumDum)"
desc = "Designed to quickly reload revolvers. DumDum bullets shatter on impact and shred the target's innards, likely getting caught inside."
desc = "Designed to quickly reload revolvers. These rounds expand on impact, allowing them to shred the target and cause massive bleeding. Very weak against armor and distant targets."
ammo_type = /obj/item/ammo_casing/c38/dumdum
/obj/item/ammo_box/c38/match

View File

@@ -186,7 +186,8 @@
return
if(iscarbon(target))
var/mob/living/carbon/C = target
for(var/datum/wound/W in C.all_wounds)
for(var/i in C.all_wounds)
var/datum/wound/W = i
if(W.try_treating(src, user))
return // another coward cured!

View File

@@ -149,19 +149,28 @@
var/temporary_unstoppable_movement = FALSE
///If defined, on hit we create an item of this type then call hitby() on the hit target with this
///If defined, on hit we create an item of this type then call hitby() on the hit target with this, mainly used for embedding items (bullets) in targets
var/shrapnel_type
///If TRUE, hit mobs even if they're on the floor and not our target
var/hit_stunned_targets = FALSE
wound_bonus = CANT_WOUND
///How much we want to drop both wound_bonus and bare_wound_bonus (to a minimum of 0 for the latter) per tile, for falloff purposes
var/wound_falloff_tile
///How much we want to drop the embed_chance value, if we can embed, per tile, for falloff purposes
var/embed_falloff_tile
/// For telling whether we want to roll for bone breaking or lacerations if we're bothering with wounds
sharpness = SHARP_NONE
///If we have a shrapnel_type defined, these embedding stats will be passed to the spawned shrapnel type, which will roll for embedding on the target
var/list/embedding
/obj/item/projectile/Initialize()
. = ..()
permutated = list()
decayedRange = range
if(embedding)
updateEmbedding()
/**
* Artificially modified to be called at around every world.icon_size pixels of movement.
@@ -169,6 +178,11 @@
*/
/obj/item/projectile/proc/Range()
range--
if(wound_bonus != CANT_WOUND)
wound_bonus += wound_falloff_tile
bare_wound_bonus = max(0, bare_wound_bonus + wound_falloff_tile)
if(embedding)
embedding["embed_chance"] += embed_falloff_tile
if(range <= 0 && loc)
on_range()
@@ -815,6 +829,26 @@
/obj/item/projectile/experience_pressure_difference()
return
///Like [/obj/item/proc/updateEmbedding] but for projectiles instead, call this when you want to add embedding or update the stats on the embedding element
/obj/projectile/proc/updateEmbedding()
if(!shrapnel_type || !LAZYLEN(embedding))
return
AddElement(/datum/element/embed,\
embed_chance = (!isnull(embedding["embed_chance"]) ? embedding["embed_chance"] : EMBED_CHANCE),\
fall_chance = (!isnull(embedding["fall_chance"]) ? embedding["fall_chance"] : EMBEDDED_ITEM_FALLOUT),\
pain_chance = (!isnull(embedding["pain_chance"]) ? embedding["pain_chance"] : EMBEDDED_PAIN_CHANCE),\
pain_mult = (!isnull(embedding["pain_mult"]) ? embedding["pain_mult"] : EMBEDDED_PAIN_MULTIPLIER),\
remove_pain_mult = (!isnull(embedding["remove_pain_mult"]) ? embedding["remove_pain_mult"] : EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER),\
rip_time = (!isnull(embedding["rip_time"]) ? embedding["rip_time"] : EMBEDDED_UNSAFE_REMOVAL_TIME),\
ignore_throwspeed_threshold = (!isnull(embedding["ignore_throwspeed_threshold"]) ? embedding["ignore_throwspeed_threshold"] : FALSE),\
impact_pain_mult = (!isnull(embedding["impact_pain_mult"]) ? embedding["impact_pain_mult"] : EMBEDDED_IMPACT_PAIN_MULTIPLIER),\
jostle_chance = (!isnull(embedding["jostle_chance"]) ? embedding["jostle_chance"] : EMBEDDED_JOSTLE_CHANCE),\
jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\
pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\
projectile_payload = shrapnel_type)
return TRUE
/////// MISC HELPERS ////////
/// Is this atom reflectable with ""standardized"" reflection methods like you know eshields and deswords and similar
/proc/is_energy_reflectable_projectile(atom/A)

View File

@@ -8,4 +8,12 @@
flag = "bullet"
hitsound_wall = "ricochet"
impact_effect_type = /obj/effect/temp_visual/impact_effect
sharpness = SHARP_EDGED
sharpness = SHARP_POINTY
shrapnel_type = /obj/item/shrapnel/bullet
embedding = list(embed_chance=15, fall_chance=2, jostle_chance=0, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.5, pain_mult=3, rip_time=10)
wound_falloff_tile = -5
embed_falloff_tile = -5
/obj/projectile/bullet/smite
name = "divine retribution"
damage = 10

View File

@@ -25,8 +25,10 @@
/obj/item/projectile/bullet/mm195x129
name = "1.95x129mm bullet"
damage = 45
damage = 40
armour_penetration = 5
wound_bonus = -50
wound_falloff_tile = 0
/obj/item/projectile/bullet/mm195x129_ap
name = "1.95x129mm armor-piercing bullet"
@@ -35,8 +37,12 @@
/obj/item/projectile/bullet/mm195x129_hp
name = "1.95x129mm hollow-point bullet"
damage = 60
damage = 50
armour_penetration = -60
sharpness = SHARP_EDGED
wound_bonus = -40
bare_wound_bonus = 30
wound_falloff_tile = -8
/obj/item/projectile/bullet/incendiary/mm195x129
name = "1.95x129mm incendiary bullet"

View File

@@ -3,11 +3,13 @@
/obj/item/projectile/bullet/c9mm
name = "9mm bullet"
damage = 20
embedding = list(embed_chance=15, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
/obj/item/projectile/bullet/c9mm_ap
name = "9mm armor-piercing bullet"
damage = 15
armour_penetration = 40
embedding = null
/obj/item/projectile/bullet/incendiary/c9mm
name = "9mm incendiary bullet"

View File

@@ -19,8 +19,9 @@
ricochet_chance = 50
ricochet_auto_aim_angle = 10
ricochet_auto_aim_range = 3
wound_bonus = -35
sharpness = SHARP_EDGED
wound_bonus = -20
bare_wound_bonus = 10
embedding = list(embed_chance=15, fall_chance=2, jostle_chance=2, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=5, rip_time=10)
/obj/item/projectile/bullet/c38/match
name = ".38 Match bullet"
@@ -43,13 +44,21 @@
ricochet_chance = 130
ricochet_decay_damage = 0.8
shrapnel_type = NONE
sharpness = SHARP_NONE
embedding = null
// premium .38 ammo from cargo, weak against armor, lower base damage, but excellent at embedding and causing slice wounds at close range
/obj/item/projectile/bullet/c38/dumdum
name = ".38 DumDum bullet"
damage = 15
armour_penetration = -30
ricochets_max = 0
shrapnel_type = /obj/item/shrapnel/bullet/c38/dumdum
sharpness = SHARP_EDGED
wound_bonus = 20
bare_wound_bonus = 20
embedding = list(embed_chance=75, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
wound_falloff_tile = -5
embed_falloff_tile = -15
/obj/item/projectile/bullet/c38/rubber
name = ".38 rubber bullet"
@@ -102,6 +111,7 @@
/obj/item/projectile/bullet/a357
name = ".357 bullet"
damage = 60
wound_bonus = -70
/obj/item/projectile/bullet/a357/ap
name = ".357 armor-piercing bullet"

View File

@@ -3,12 +3,15 @@
/obj/item/projectile/bullet/a556
name = "5.56mm bullet"
damage = 35
wound_bonus = -40
// 7.62 (Nagant Rifle)
/obj/item/projectile/bullet/a762
name = "7.62 bullet"
damage = 60
wound_bonus = -35
wound_falloff_tile = 0
/obj/item/projectile/bullet/a762_enchanted
name = "enchanted 7.62 bullet"

View File

@@ -1,16 +1,18 @@
/obj/item/projectile/bullet/shotgun_slug
name = "12g shotgun slug"
damage = 60
damage = 50
sharpness = SHARP_POINTY
wound_bonus = 0
/obj/item/projectile/bullet/shotgun_slug/executioner
name = "executioner slug" // admin only, can dismember limbs
sharpness = SHARP_EDGED
wound_bonus = 0
wound_bonus = 80
/obj/item/projectile/bullet/shotgun_slug/pulverizer
name = "pulverizer slug" // admin only, can crush bones
sharpness = SHARP_NONE
wound_bonus = 0
wound_bonus = 80
/obj/item/projectile/bullet/shotgun_beanbag
name = "beanbag slug"
@@ -18,6 +20,7 @@
stamina = 70
wound_bonus = 20
sharpness = SHARP_NONE
embedding = null
/obj/item/projectile/bullet/incendiary/shotgun
name = "incendiary slug"
@@ -83,18 +86,22 @@
return BULLET_ACT_HIT
/obj/item/projectile/bullet/pellet
var/tile_dropoff = 0.75
var/tile_dropoff = 0.45
var/tile_dropoff_s = 1.25
/obj/item/projectile/bullet/pellet/shotgun_buckshot
name = "buckshot pellet"
damage = 12.5
wound_bonus = -10
damage = 7.5
wound_bonus = 5
bare_wound_bonus = 5
wound_falloff_tile = -2.5 // low damage + additional dropoff will already curb wounding potential anything past point blank
/obj/item/projectile/bullet/pellet/shotgun_rubbershot
name = "rubbershot pellet"
damage = 2
stamina = 15
sharpness = SHARP_NONE
embedding = null
/obj/item/projectile/bullet/pellet/Range()
..()
@@ -106,8 +113,10 @@
qdel(src)
/obj/item/projectile/bullet/pellet/shotgun_improvised
tile_dropoff = 0.55 //Come on it does 6 damage don't be like that.
tile_dropoff = 0.35 //Come on it does 6 damage don't be like that.
damage = 6
wound_bonus = 0
bare_wound_bonus = 7.5
/obj/item/projectile/bullet/pellet/shotgun_improvised/Initialize()
. = ..()

View File

@@ -3,6 +3,8 @@
/obj/item/projectile/bullet/c45
name = ".45 bullet"
damage = 30
wound_bonus = -10
wound_falloff_tile = -10
/obj/item/projectile/bullet/c45_cleaning
name = ".45 bullet"
@@ -51,11 +53,15 @@
/obj/item/projectile/bullet/c46x30mm
name = "4.6x30mm bullet"
damage = 15
wound_bonus = -5
bare_wound_bonus = 5
embed_falloff_tile = -4
/obj/item/projectile/bullet/c46x30mm_ap
name = "4.6x30mm armor-piercing bullet"
damage = 12.5
armour_penetration = 40
embedding = null
/obj/item/projectile/bullet/incendiary/c46x30mm
name = "4.6x30mm incendiary bullet"

View File

@@ -1017,3 +1017,22 @@
M.adjustToxLoss(-1, 0)
..()
. = TRUE
// i googled "natural coagulant" and a couple of results came up for banana peels, so after precisely 30 more seconds of research, i now dub grinding banana peels good for your blood
/datum/reagent/consumable/banana_peel
name = "Pulped Banana Peel"
description = "Okay, so you put a banana peel in a grinder... Why, exactly?"
color = "#863333" // rgb: 175, 175, 0
reagent_state = SOLID
taste_description = "stringy, bitter pulp"
glass_name = "glass of banana peel pulp"
glass_desc = "Okay, so you put a banana peel in a grinder... Why, exactly?"
/datum/reagent/consumable/baked_banana_peel
name = "Baked Banana Peel Powder"
description = "You took a banana peel... pulped it... baked it... Where are you going with this?"
color = "#863333" // rgb: 175, 175, 0
reagent_state = SOLID
taste_description = "bitter powder"
glass_name = "glass of banana peel powder"
description = "You took a banana peel... pulped it... baked it... Where are you going with this?"

View File

@@ -145,8 +145,8 @@
M.adjustToxLoss(-power, 0, TRUE) //heals TOXINLOVERs
M.adjustCloneLoss(-power, 0)
for(var/i in M.all_wounds)
var/datum/wound/W = i
W.on_xadone(power)
var/datum/wound/iter_wound = i
iter_wound.on_xadone(power)
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) //fixes common causes for disfiguration
. = 1
metabolization_rate = REAGENTS_METABOLISM * (0.00001 * (M.bodytemperature ** 2) + 0.5)
@@ -196,8 +196,8 @@
M.adjustToxLoss(-power, 0, TRUE)
M.adjustCloneLoss(-power, 0)
for(var/i in M.all_wounds)
var/datum/wound/W = i
W.on_xadone(power)
var/datum/wound/iter_wound = i
iter_wound.on_xadone(power)
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC)
. = 1
..()
@@ -365,7 +365,7 @@
/datum/reagent/medicine/salglu_solution
name = "Saline-Glucose Solution"
description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute."
description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute, as well as slowly speeding blood regeneration."
reagent_state = LIQUID
color = "#DCDCDC"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
@@ -373,6 +373,7 @@
taste_description = "sweetness and salt"
var/last_added = 0
var/maximum_reachable = BLOOD_VOLUME_NORMAL - 10 //So that normal blood regeneration can continue with salglu active
var/extra_regen = 0.25 // in addition to acting as temporary blood, also add this much to their actual blood per tick
pH = 5.5
/datum/reagent/medicine/salglu_solution/on_mob_life(mob/living/carbon/M)
@@ -385,7 +386,7 @@
var/amount_to_add = min(M.blood_volume, volume*5)
var/new_blood_level = min(M.blood_volume + amount_to_add, maximum_reachable)
last_added = new_blood_level - M.blood_volume
M.blood_volume = new_blood_level
M.blood_volume = new_blood_level + extra_regen
if(prob(33))
M.adjustBruteLoss(-0.5*REM, 0)
M.adjustFireLoss(-0.5*REM, 0)
@@ -471,8 +472,9 @@
else if(method in list(PATCH, TOUCH))
M.adjustBruteLoss(-1 * reac_volume)
M.adjustFireLoss(-1 * reac_volume)
for(var/datum/wound/burn/burn_wound in C.all_wounds)
burn_wound.regenerate_flesh(reac_volume)
for(var/i in carbies.all_wounds)
var/datum/wound/iter_wound = i
iter_wound.on_synthflesh(reac_volume)
if(show_message)
to_chat(M, "<span class='danger'>You feel your burns and bruises healing! It stings like hell!</span>")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine)
@@ -1592,10 +1594,57 @@
to_chat(C, "[pick(GLOB.wisdoms)]") //give them a random wisdom
..()
// handled in cut wounds process
// helps bleeding wounds clot faster
/datum/reagent/medicine/coagulant
name = "Sanguirite"
description = "A coagulant used to help open cuts clot faster."
description = "A proprietary coagulant used to help bleeding wounds clot faster."
reagent_state = LIQUID
color = "#bb2424"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
overdose_threshold = 20
/// How much base clotting we do per bleeding wound, multiplied by the below number for each bleeding wound
var/clot_rate = 0.25
/// If we have multiple bleeding wounds, we count the number of bleeding wounds, then multiply the clot rate by this^(n) before applying it to each cut, so more cuts = less clotting per cut (though still more total clotting)
var/clot_coeff_per_wound = 0.9
/datum/reagent/medicine/coagulant/on_mob_life(mob/living/carbon/M)
. = ..()
if(!M.blood_volume || !M.all_wounds)
return
var/effective_clot_rate = clot_rate
for(var/i in M.all_wounds)
var/datum/wound/iter_wound = i
if(iter_wound.blood_flow)
effective_clot_rate *= clot_coeff_per_wound
for(var/i in M.all_wounds)
var/datum/wound/iter_wound = i
iter_wound.blood_flow = max(0, iter_wound.blood_flow - effective_clot_rate)
/datum/reagent/medicine/coagulant/overdose_process(mob/living/M)
. = ..()
if(!M.blood_volume)
return
if(prob(15))
M.losebreath += rand(2,4)
M.adjustOxyLoss(rand(1,3))
if(prob(30))
to_chat(M, "<span class='danger'>You can feel your blood clotting up in your veins!</span>")
else if(prob(10))
to_chat(M, "<span class='userdanger'>You feel like your blood has stopped moving!</span>")
if(prob(50))
var/obj/item/organ/lungs/our_lungs = M.getorganslot(ORGAN_SLOT_LUNGS)
our_lungs.applyOrganDamage(1)
else
var/obj/item/organ/heart/our_heart = M.getorganslot(ORGAN_SLOT_HEART)
our_heart.applyOrganDamage(1)
// can be synthesized on station rather than bought. made by grinding a banana peel, heating it up, then mixing the banana peel powder with salglu
/datum/reagent/medicine/coagulant/weak
name = "Synthi-Sanguirite"
description = "A synthetic coagulant used to help bleeding wounds clot faster. Not quite as effective as name brand Sanguirite, especially on patients with lots of cuts."
clot_coeff_per_wound = 0.8

View File

@@ -244,6 +244,11 @@
glass_desc = "The father of all refreshments."
shot_glass_icon_state = "shotglassclear"
/datum/reagent/water/on_mob_life(mob/living/carbon/M)
. = ..()
if(M.blood_volume)
M.blood_volume += 0.1 // water is good for you!
/*
* Water reaction to turf
*/
@@ -334,6 +339,8 @@
return ..()
/datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M)
if(M.blood_volume)
M.blood_volume += 0.1 // water is good for you!
if(!data)
data = list("misc" = 1)
data["misc"]++
@@ -2304,6 +2311,7 @@
metabolization_rate = 0.75 * REAGENTS_METABOLISM // 5u (WOUND_DETERMINATION_CRITICAL) will last for ~17 ticks
/// Whether we've had at least WOUND_DETERMINATION_SEVERE (2.5u) of determination at any given time. No damage slowdown immunity or indication we're having a second wind if it's just a single moderate wound
var/significant = FALSE
self_consuming = TRUE
/datum/reagent/determination/on_mob_end_metabolize(mob/living/carbon/M)
if(significant)

View File

@@ -50,6 +50,18 @@
results = list(/datum/reagent/medicine/salglu_solution = 3)
required_reagents = list(/datum/reagent/consumable/sodiumchloride = 1, /datum/reagent/water = 1, /datum/reagent/consumable/sugar = 1)
/datum/chemical_reaction/baked_banana_peel
results = list(/datum/reagent/consumable/baked_banana_peel = 1)
required_temp = 413.15 // if it's good enough for caramel it's good enough for this
required_reagents = list(/datum/reagent/consumable/banana_peel = 1)
mix_message = "The pulp dries up and takes on a powdery state!"
mob_react = FALSE
/datum/chemical_reaction/coagulant_weak
results = list(/datum/reagent/medicine/coagulant/weak = 3)
required_reagents = list(/datum/reagent/medicine/salglu_solution = 2, /datum/reagent/consumable/baked_banana_peel = 1)
mob_react = FALSE
/datum/chemical_reaction/mine_salve
name = "Miner's Salve"
id = /datum/reagent/medicine/mine_salve

View File

@@ -135,7 +135,7 @@
/obj/item/reagent_containers/hypospray/medipen/ekit
name = "emergency first-aid autoinjector"
desc = "An epinephrine medipen with trace amounts of coagulants and antibiotics to help stabilize bad cuts and burns."
desc = "An epinephrine medipen with extra coagulant and antibiotics to help stabilize bad cuts and burns."
volume = 15
amount_per_transfer_from_this = 15
list_reagents = list(/datum/reagent/medicine/epinephrine = 12, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/medicine/spaceacillin = 0.5)

View File

@@ -16,6 +16,7 @@
custom_materials = list(/datum/material/iron=10, /datum/material/glass=20)
reagent_flags = TRANSPARENT
custom_price = PRICE_CHEAP_AS_FREE
sharpness = SHARP_POINTY
/obj/item/reagent_containers/syringe/Initialize()
. = ..()

View File

@@ -86,12 +86,12 @@
/// A hat won't cover your face, but a shirt covering your chest will cover your... you know, chest
var/scars_covered_by_clothes = TRUE
/// Descriptions for the locations on the limb for scars to be assigned, just cosmetic
var/list/specific_locations = list("general area")
/// So we know if we need to scream if this limb hits max damage
var/last_maxed
/// How much generic bleedstacks we have on this bodypart
var/generic_bleedstacks
/// If we have a gauze wrapping currently applied (not including splints)
var/obj/item/stack/current_gauze
/obj/item/bodypart/examine(mob/user)
. = ..()
@@ -151,8 +151,20 @@
var/turf/T = get_turf(src)
if(status != BODYPART_ROBOTIC)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
for(var/obj/item/I in src)
I.forceMove(T)
if(current_gauze)
QDEL_NULL(current_gauze)
for(var/obj/item/organ/drop_organ in get_organs())
drop_organ.transfer_to_limb(src, owner)
///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have
/obj/item/bodypart/proc/get_organs()
if(!owner)
return
. = list()
for(var/i in owner.internal_organs) //internal organs inside the dismembered limb are dropped.
var/obj/item/organ/organ_check = i
if(check_zone(organ_check.zone) == body_zone)
. += organ_check
/obj/item/bodypart/proc/consider_processing()
if(stamina_dam > DAMAGE_PRECISION)
@@ -192,16 +204,64 @@
if(ALIEN_BODYPART,LARVA_BODYPART) //aliens take some additional burn //nothing can burn with so much snowflake code around
burn *= 1.2
var/wounding_type = (brute > burn ? WOUND_BRUTE : WOUND_BURN)
/*
// START WOUND HANDLING
*/
// what kind of wounds we're gonna roll for, take the greater between brute and burn, then if it's brute, we subdivide based on sharpness
var/wounding_type = (brute > burn ? WOUND_BLUNT : WOUND_BURN)
var/wounding_dmg = max(brute, burn)
if(wounding_type == WOUND_BRUTE && sharpness)
wounding_type = WOUND_SHARP
// i know this is effectively the same check as above but i don't know if those can null the damage by rounding and want to be safe
if(owner && wounding_dmg > 4 && wound_bonus != CANT_WOUND)
// if you want to make tox wounds or some other type, this will need to be expanded and made more modular
// handle all our wounding stuff
var/mangled_state = get_mangled_state()
var/bio_state = owner.get_biological_state()
var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
if(wounding_type == WOUND_BLUNT)
if(sharpness == SHARP_EDGED)
wounding_type = WOUND_SLASH
else if(sharpness == SHARP_POINTY)
wounding_type = WOUND_PIERCE
//Handling for bone only/flesh only(none right now)/flesh and bone targets
switch(bio_state)
// if we're bone only, all cutting attacks go straight to the bone
if(BIO_JUST_BONE)
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.5)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.75)
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
// note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
// standard humanoids
if(BIO_FLESH_BONE)
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area
if(wounding_type == WOUND_PIERCE && !easy_dismember)
wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
wounding_type = WOUND_BLUNT
else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
// now we have our wounding_type and are ready to carry on with wounds and dealing the actual damage
if(owner && wounding_dmg >= WOUND_MINIMUM_DAMAGE && wound_bonus != CANT_WOUND)
check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
for(var/i in wounds)
var/datum/wound/iter_wound = i
iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus)
/*
// END WOUND HANDLING
*/
//back to our regularly scheduled program, we now actually apply damage if there's room below limb damage cap
var/can_inflict = max_damage - get_damage()
var/total_damage = brute + burn
@@ -213,10 +273,6 @@
if(can_inflict <= 0)
return FALSE
for(var/i in wounds)
var/datum/wound/W = i
W.receive_damage(wounding_type, wounding_dmg, wound_bonus)
brute_dam += brute
burn_dam += burn
@@ -236,14 +292,58 @@
update_disabled()
return update_bodypart_damage_state()
/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds
/obj/item/bodypart/proc/painless_wound_roll(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus, sharpness=SHARP_NONE)
if(!owner || phantom_wounding_dmg <= WOUND_MINIMUM_DAMAGE || wound_bonus == CANT_WOUND)
return
var/mangled_state = get_mangled_state()
var/bio_state = owner.get_biological_state()
var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
if(wounding_type == WOUND_BLUNT)
if(sharpness == SHARP_EDGED)
wounding_type = WOUND_SLASH
else if(sharpness == SHARP_POINTY)
wounding_type = WOUND_PIERCE
//Handling for bone only/flesh only(none right now)/flesh and bone targets
switch(bio_state)
// if we're bone only, all cutting attacks go straight to the bone
if(BIO_JUST_BONE)
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
phantom_wounding_dmg *= (easy_dismember ? 1 : 0.5)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75)
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
return
// note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
// standard humanoids
if(BIO_FLESH_BONE)
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
phantom_wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area
if(wounding_type == WOUND_PIERCE && !easy_dismember)
phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
wounding_type = WOUND_BLUNT
else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
return
check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)
/**
* check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria
*
* We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [check_wounding_mods()], then go down the list from most severe to least severe wounds in that category.
* We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [/obj/item/bodypart/proc/check_wounding_mods], then go down the list from most severe to least severe wounds in that category.
* We can promote a wound from a lesser to a higher severity this way, but we give up if we have a wound of the given type and fail to roll a higher severity, so no sidegrades/downgrades
*
* Arguments:
* * woundtype- Either WOUND_SHARP, WOUND_BRUTE, or WOUND_BURN based on the attack type.
* * woundtype- Either WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE, or WOUND_BURN based on the attack type.
* * damage- How much damage is tied to this attack, since wounding potential scales with damage in an attack (see: WOUND_DAMAGE_EXPONENT)
* * wound_bonus- The wound_bonus of an attack
* * bare_wound_bonus- The bare_wound_bonus of an attack
@@ -252,19 +352,24 @@
// actually roll wounds if applicable
if(HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE))
damage *= 1.5
else
damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE)
var/base_roll = rand(1, round(damage ** WOUND_DAMAGE_EXPONENT))
var/injury_roll = base_roll
injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus)
var/list/wounds_checking
var/list/wounds_checking = GLOB.global_wound_types[woundtype]
switch(woundtype)
if(WOUND_SHARP)
wounds_checking = WOUND_LIST_SLASH
if(WOUND_BRUTE)
wounds_checking = WOUND_LIST_BLUNT
if(WOUND_BURN)
wounds_checking = WOUND_LIST_BURN
// quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow
if(ishuman(owner))
var/mob/living/carbon/human/human_wearer = owner
var/list/clothing = human_wearer.clothingonpart(src)
for(var/i in clothing)
var/obj/item/clothing/clothes_check = i
// unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
if(clothes_check.armor.getRating("wound"))
bare_wound_bonus = 0
break
//cycle through the wounds of the relevant category from the most severe down
for(var/PW in wounds_checking)
@@ -279,21 +384,22 @@
replaced_wound = existing_wound
if(initial(possible_wound.threshold_minimum) < injury_roll)
var/datum/wound/new_wound
if(replaced_wound)
var/datum/wound/new_wound = replaced_wound.replace_wound(possible_wound)
log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll)
new_wound = replaced_wound.replace_wound(possible_wound)
log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) // dismembering wounds are logged in the apply_wound() for loss wounds since they delete themselves immediately, these will be immediately returned
else
var/datum/wound/new_wound = new possible_wound
new_wound = new possible_wound
new_wound.apply_wound(src)
log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll)
return
return new_wound
// try forcing a specific wound, but only if there isn't already a wound of that severity or greater for that type on this bodypart
/obj/item/bodypart/proc/force_wound_upwards(specific_woundtype, smited = FALSE)
var/datum/wound/potential_wound = specific_woundtype
for(var/i in wounds)
var/datum/wound/existing_wound = i
if(existing_wound.type in (initial(potential_wound.wound_type)))
if(existing_wound.wound_type == initial(potential_wound.wound_type))
if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force
existing_wound.replace_wound(potential_wound, smited)
return
@@ -301,12 +407,20 @@
var/datum/wound/new_wound = new potential_wound
new_wound.apply_wound(src, smited = smited)
/**
* check_wounding_mods() is where we handle the various modifiers of a wound roll
*
* A short list of things we consider: any armor a human target may be wearing, and if they have no wound armor on the limb, if we have a bare_wound_bonus to apply, plus the plain wound_bonus
* We also flick through all of the wounds we currently have on this limb and add their threshold penalties, so that having lots of bad wounds makes you more liable to get hurt worse
* Lastly, we add the inherent wound_resistance variable the bodypart has (heads and chests are slightly harder to wound), and a small bonus if the limb is already disabled
*
* Arguments:
* * It's the same ones on [receive_damage]
*/
/obj/item/bodypart/proc/check_woundings_mods(wounding_type, damage, wound_bonus, bare_wound_bonus)
var/armor_ablation = 0
var/injury_mod = 0
//var/bwb = 0
if(owner && ishuman(owner))
var/mob/living/carbon/human/H = owner
var/list/clothing = H.clothingonpart(src)
@@ -314,7 +428,7 @@
var/obj/item/clothing/C = c
// unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
armor_ablation += C.armor.getRating("wound")
if(wounding_type == WOUND_SHARP)
if(wounding_type == WOUND_SLASH)
C.take_damage_zone(body_zone, damage, BRUTE, armour_penetration)
else if(wounding_type == WOUND_BURN && damage >= 10) // lazy way to block freezing from shredding clothes without adding another var onto apply_damage()
C.take_damage_zone(body_zone, damage, BURN, armour_penetration)
@@ -330,7 +444,7 @@
injury_mod += W.threshold_penalty
var/part_mod = -wound_resistance
if(is_disabled())
if(get_damage(TRUE) >= max_damage)
part_mod += disabled_wound_penalty
injury_mod += part_mod
@@ -383,11 +497,11 @@
return BODYPART_DISABLED_WOUND
if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER))
. = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
if((get_damage(TRUE) >= max_damage) || (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) && (get_damage(TRUE) >= (max_damage * 0.6)))) //Easy limb disable disables the limb at 40% health instead of 0%
if(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0%
if(!last_maxed)
owner.emote("scream")
last_maxed = TRUE
if(!is_organic_limb())
if(!is_organic_limb() || stamina_dam >= max_damage)
return BODYPART_DISABLED_DAMAGE
else if(disabled && (get_damage(TRUE) <= (max_damage * 0.8))) // reenabled at 80% now instead of 50% as of wounds update
last_maxed = FALSE
@@ -741,17 +855,29 @@
/obj/item/bodypart/proc/get_wound_type(checking_type)
if(isnull(wounds))
return
for(var/thing in wounds)
var/datum/wound/W = thing
if(istype(W, checking_type))
return W
for(var/i in wounds)
if(istype(i, checking_type))
return i
/// very rough start for updating efficiency and other stats on a body part whenever a wound is gained/lost
/obj/item/bodypart/proc/update_wounds()
/**
* update_wounds() is called whenever a wound is gained or lost on this bodypart, as well as if there's a change of some kind on a bone wound possibly changing disabled status
*
* Covers tabulating the damage multipliers we have from wounds (burn specifically), as well as deleting our gauze wrapping if we don't have any wounds that can use bandaging
*
* Arguments:
* * replaced- If true, this is being called from the remove_wound() of a wound that's being replaced, so the bandage that already existed is still relevant, but the new wound hasn't been added yet
*/
/obj/item/bodypart/proc/update_wounds(replaced = FALSE)
var/dam_mul = 1 //initial(wound_damage_multiplier)
// we can only have one wound per type, but remember there's multiple types
for(var/datum/wound/W in wounds)
dam_mul *= W.damage_mulitplier_penalty
// we can (normally) only have one wound per type, but remember there's multiple types (smites like :B:loodless can generate multiple cuts on a limb)
for(var/i in wounds)
var/datum/wound/iter_wound = i
dam_mul *= iter_wound.damage_mulitplier_penalty
if(!LAZYLEN(wounds) && current_gauze && !replaced)
owner.visible_message("<span class='notice'>\The [current_gauze] on [owner]'s [name] fall away.</span>", "<span class='notice'>The [current_gauze] on your [name] fall away.</span>")
QDEL_NULL(current_gauze)
wound_damage_multiplier = dam_mul
update_disabled()
@@ -761,8 +887,6 @@
var/bleed_rate = 0
if(generic_bleedstacks > 0)
bleed_rate++
if(brute_dam >= 40)
bleed_rate += (brute_dam * 0.008)
//We want an accurate reading of .len
listclearnulls(embedded_objects)
@@ -773,5 +897,40 @@
for(var/thing in wounds)
var/datum/wound/W = thing
bleed_rate += W.blood_flow
if(owner.mobility_flags & ~MOBILITY_STAND)
bleed_rate *= 0.75
return bleed_rate
/**
* apply_gauze() is used to- well, apply gauze to a bodypart
*
* As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons).
* The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze
* applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared,
* the gauze falls off.
*
* Arguments:
* * gauze- Just the gauze stack we're taking a sheet from to apply here
*/
/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze)
if(!istype(gauze) || !gauze.absorption_capacity)
return
QDEL_NULL(current_gauze)
current_gauze = new gauze.type(src, 1)
gauze.use(1)
/**
* seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity.
*
* The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandages fall off and we're left with nothing.
*
* Arguments:
* * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?)
*/
/obj/item/bodypart/proc/seep_gauze(seep_amt = 0)
if(!current_gauze)
return
current_gauze.absorption_capacity -= seep_amt
if(current_gauze.absorption_capacity < 0)
owner.visible_message("<span class='danger'>\The [current_gauze] on [owner]'s [name] fall away in rags.</span>", "<span class='warning'>\The [current_gauze] on your [name] fall away in rags.</span>", vision_distance=COMBAT_MESSAGE_RANGE)
QDEL_NULL(current_gauze)

View File

@@ -4,7 +4,7 @@
return TRUE
//Dismember a limb
/obj/item/bodypart/proc/dismember(dam_type = BRUTE)
/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE)
if(!owner)
return FALSE
var/mob/living/carbon/C = owner
@@ -16,7 +16,8 @@
return FALSE
var/obj/item/bodypart/affecting = C.get_bodypart(BODY_ZONE_CHEST)
affecting.receive_damage(clamp(brute_dam/2 * affecting.body_damage_coeff, 15, 50), clamp(burn_dam/2 * affecting.body_damage_coeff, 0, 50), wound_bonus=CANT_WOUND) //Damage the chest based on limb's existing damage
C.visible_message("<span class='danger'><B>[C]'s [src.name] has been violently dismembered!</B></span>")
if(!silent)
C.visible_message("<span class='danger'><B>[C]'s [name] is violently dismembered!</B></span>")
C.emote("scream")
SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "dismembered", /datum/mood_event/dismembered)
drop_limb()
@@ -30,6 +31,7 @@
burn()
return TRUE
add_mob_blood(C)
C.bleed(rand(20, 40))
var/direction = pick(GLOB.cardinals)
var/t_range = rand(2,max(throw_range/2, 2))
var/turf/target_turf = get_turf(src)
@@ -80,8 +82,6 @@
if(organ_spilled)
C.visible_message("<span class='danger'><B>[C]'s internal organs spill out onto the floor!</B></span>")
//limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in.
/obj/item/bodypart/proc/drop_limb(special, dismembered)
if(!owner)
@@ -153,7 +153,52 @@
forceMove(Tsec)
/**
* get_mangled_state() is relevant for flesh and bone bodyparts, and returns whether this bodypart has mangled skin, mangled bone, or both (or neither i guess)
*
* Dismemberment for flesh and bone requires the victim to have the skin on their bodypart destroyed (either a critical cut or piercing wound), and at least a hairline fracture
* (severe bone), at which point we can start rolling for dismembering. The attack must also deal at least 10 damage, and must be a brute attack of some kind (sorry for now, cakehat, maybe later)
*
* Returns: BODYPART_MANGLED_NONE if we're fine, BODYPART_MANGLED_FLESH if our skin is broken, BODYPART_MANGLED_BONE if our bone is broken, or BODYPART_MANGLED_BOTH if both are broken and we're up for dismembering
*/
/obj/item/bodypart/proc/get_mangled_state()
. = BODYPART_MANGLED_NONE
for(var/i in wounds)
var/datum/wound/iter_wound = i
if((iter_wound.wound_flags & MANGLES_BONE))
. |= BODYPART_MANGLED_BONE
if((iter_wound.wound_flags & MANGLES_FLESH))
. |= BODYPART_MANGLED_FLESH
/**
* try_dismember() is used, once we've confirmed that a flesh and bone bodypart has both the skin and bone mangled, to actually roll for it
*
* Mangling is described in the above proc, [/obj/item/bodypart/proc/get_mangled_state()]. This simply makes the roll for whether we actually dismember or not
* using how damaged the limb already is, and how much damage this blow was for. If we have a critical bone wound instead of just a severe, we add +10% to the roll.
* Lastly, we choose which kind of dismember we want based on the wounding type we hit with. Note we don't care about all the normal mods or armor for this
*
* Arguments:
* * wounding_type: Either WOUND_BLUNT, WOUND_SLASH, or WOUND_PIERCE, basically only matters for the dismember message
* * wounding_dmg: The damage of the strike that prompted this roll, higher damage = higher chance
* * wound_bonus: Not actually used right now, but maybe someday
* * bare_wound_bonus: ditto above
*/
/obj/item/bodypart/proc/try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
if(wounding_dmg < DISMEMBER_MINIMUM_DAMAGE)
return
var/base_chance = wounding_dmg + (get_damage() / max_damage * 50) // how much damage we dealt with this blow, + 50% of the damage percentage we already had on this bodypart
if(locate(/datum/wound/blunt/critical) in wounds) // we only require a severe bone break, but if there's a critical bone break, we'll add 10% more
base_chance += 10
if(!prob(base_chance))
return
var/datum/wound/loss/dismembering = new
dismembering.apply_dismember(src, wounding_type)
return TRUE
//when a limb is dropped, the internal organs are removed from the mob and put into the limb
/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C)
@@ -378,7 +423,7 @@
/mob/living/carbon/regenerate_limb(limb_zone, noheal)
var/obj/item/bodypart/L
if(get_bodypart(limb_zone))
return 0
return FALSE
L = newBodyPart(limb_zone, 0, 0)
if(L)
if(!noheal)
@@ -386,6 +431,8 @@
L.burn_dam = 0
L.brutestate = 0
L.burnstate = 0
var/datum/scar/scaries = new
var/datum/wound/loss/phantom_loss = new // stolen valor, really
scaries.generate(L, phantom_loss)
L.attach_limb(src, 1)
return 1
return TRUE

View File

@@ -36,11 +36,10 @@
var/custom_head
wound_resistance = 10
specific_locations = list("left eyebrow", "cheekbone", "neck", "throat", "jawline", "entire face")
scars_covered_by_clothes = FALSE
/obj/item/bodypart/head/can_dismember(obj/item/I)
if(!((owner.stat == DEAD) || owner.InFullCritical()))
if(owner && !((owner.stat == DEAD) || owner.InFullCritical()))
return FALSE
return ..()

View File

@@ -12,7 +12,7 @@
var/obj/item/cavity_item
/obj/item/bodypart/chest/can_dismember(obj/item/I)
if(!((owner.stat == DEAD) || owner.InFullCritical()))
if(!((owner.stat == DEAD) || owner.InFullCritical()) || !get_organs())
return FALSE
return ..()

View File

@@ -94,7 +94,8 @@
log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]")
burn_wound.sanitization += 3
burn_wound.flesh_healing += 5
burn_wound.force_bandage(tool)
var/obj/item/bodypart/the_part = target.get_bodypart(target_zone)
the_part.apply_gauze(tool)
else
to_chat(user, "<span class='warning'>[target] has no burns there!</span>")
return ..()

View File

@@ -0,0 +1,108 @@
/////BURN FIXING SURGERIES//////
//the step numbers of each of these two, we only currently use the first to switch back and forth due to advancing after finishing steps anyway
#define REALIGN_INNARDS 1
#define WELD_VEINS 2
///// Repair puncture wounds
/datum/surgery/repair_puncture
name = "Repair puncture"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/repair_innards, /datum/surgery_step/seal_veins, /datum/surgery_step/close) // repeat between steps 2 and 3 until healed
target_mobtypes = list(/mob/living/carbon)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
targetable_wound = /datum/wound/pierce
/datum/surgery/repair_puncture/can_start(mob/living/user, mob/living/carbon/target)
. = ..()
if(.)
var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected)
var/datum/wound/burn/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound)
return(pierce_wound && pierce_wound.blood_flow > 0)
//SURGERY STEPS
///// realign the blood vessels so we can reweld them
/datum/surgery_step/repair_innards
name = "realign blood vessels"
implements = list(TOOL_HEMOSTAT = 100, TOOL_SCALPEL = 85, TOOL_WIRECUTTER = 40)
time = 3 SECONDS
/datum/surgery_step/repair_innards/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
if(!pierce_wound)
user.visible_message("<span class='notice'>[user] looks for [target]'s [parse_zone(user.zone_selected)].</span>", "<span class='notice'>You look for [target]'s [parse_zone(user.zone_selected)]...</span>")
return
if(pierce_wound.blood_flow <= 0)
to_chat(user, "<span class='notice'>[target]'s [parse_zone(user.zone_selected)] has no puncture to repair!</span>")
surgery.status++
return
display_results(user, target, "<span class='notice'>You begin to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)].</span>")
/datum/surgery_step/repair_innards/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
if(!pierce_wound)
to_chat(user, "<span class='warning'>[target] has no puncture wound there!</span>")
return ..()
display_results(user, target, "<span class='notice'>You successfully realign some of the blood vessels in [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)]!</span>")
log_combat(user, target, "excised infected flesh in", addition="INTENT: [uppertext(user.a_intent)]")
surgery.operated_bodypart.receive_damage(brute=3, wound_bonus=CANT_WOUND)
pierce_wound.blood_flow -= 0.25
return ..()
/datum/surgery_step/repair_innards/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
. = ..()
display_results(user, target, "<span class='notice'>You jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] jerks apart some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)]!</span>")
surgery.operated_bodypart.receive_damage(brute=rand(4,8), sharpness=SHARP_EDGED, wound_bonus = 10)
///// Sealing the vessels back together
/datum/surgery_step/seal_veins
name = "weld veins" // if your doctor says they're going to weld your blood vessels back together, you're either A) on SS13, or B) in grave mortal peril
implements = list(TOOL_CAUTERY = 100, /obj/item/gun/energy/laser = 90, TOOL_WELDER = 70, /obj/item = 30)
time = 4 SECONDS
/datum/surgery_step/seal_veins/tool_check(mob/user, obj/item/tool)
if(implement_type == TOOL_WELDER || implement_type == /obj/item)
return tool.get_temperature()
return TRUE
/datum/surgery_step/seal_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
if(!pierce_wound)
user.visible_message("<span class='notice'>[user] looks for [target]'s [parse_zone(user.zone_selected)].</span>", "<span class='notice'>You look for [target]'s [parse_zone(user.zone_selected)]...</span>")
return
display_results(user, target, "<span class='notice'>You begin to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)].</span>")
/datum/surgery_step/seal_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
if(!pierce_wound)
to_chat(user, "<span class='warning'>[target] has no puncture there!</span>")
return ..()
display_results(user, target, "<span class='notice'>You successfully meld some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool].</span>",
"<span class='notice'>[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)]!</span>")
log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]")
pierce_wound.blood_flow -= 0.5
if(pierce_wound.blood_flow > 0)
surgery.status = REALIGN_INNARDS
to_chat(user, "<span class='notice'><i>There still seems to be misaligned blood vessels to finish...<i></span>")
else
to_chat(user, "<span class='green'>You've repaired all the internal damage in [target]'s [parse_zone(target_zone)]!</span>")
return ..()
#undef REALIGN_INNARDS
#undef WELD_VEINS

View File

@@ -530,8 +530,7 @@ GLOBAL_LIST_EMPTY(vending_products)
for(var/i in C.bodyparts)
var/obj/item/bodypart/squish_part = i
if(squish_part.is_organic_limb())
//var/type_wound = pick(WOUND_LIST_BLUNT)
var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
squish_part.force_wound_upwards(type_wound)
else
squish_part.receive_damage(brute=30)

View File

@@ -66,7 +66,9 @@ h1.alert, h2.alert {color: #000000;}
.passive {color: #660000;}
.userdanger {color: #ff0000; font-weight: bold; font-size: 3;}
.danger {color: #ff0000;}
.danger {color: #ff0000; font-weight: bold;}
.tinydanger {color: #ff0000; font-size: 85%;}
.smalldanger {color: #ff0000; font-size: 90%;}
.warning {color: #ff0000; font-style: italic;}
.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
.announce {color: #228b22; font-weight: bold;}
@@ -75,6 +77,9 @@ h1.alert, h2.alert {color: #000000;}
.rose {color: #ff5050;}
.info {color: #0000CC;}
.notice {color: #000099;}
.tinynotice {color: #000099; font-size: 85%;}
.smallnotice {color: #000099; font-size: 90%;}
.smallnoticeital {color: #000099; font-style: italic; font-size: 90%;}
.boldnotice {color: #000099; font-weight: bold;}
.adminnotice {color: #0000ff;}
.adminhelp {color: #ff0000; font-weight: bold;}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,26 @@
{
"generic": ["general disfigurement"],
"bluntmoderate": [
"the bone equivalent of a faded bruise",
"a series of tiny chip marks"
],
"bluntsevere": [
"a series of faded hairline cracks",
"a small bone dent"
],
"bluntcritical": [
"large streaks of refilled cracks",
"a fractal of reformed stress marks",
"a cluster of calluses"
],
"dismember": [
"is slightly misaligned",
"has clearly been dropped recently",
"has a damaged socket"
]
}

View File

@@ -0,0 +1,86 @@
{
"generic": ["general disfigurement"],
"bluntmoderate": [
"light discoloring",
"a slight blue tint"
],
"bluntsevere": [
"a faded, fist-sized bruise",
"a vaguely triangular peel scar"
],
"bluntcritical": [
"a section of janky skin lines and badly healed scars",
"a large patch of uneven skin tone",
"a cluster of calluses"
],
"slashmoderate": [
"light, faded lines",
"minor cut marks",
"a small faded slit",
"a series of small scars"
],
"slashsevere": [
"a twisted line of faded gashes",
"a gnarled sickle-shaped slice scar"
],
"slashcritical": [
"a winding path of very badly healed scar tissue",
"a series of peaks and valleys along a gruesome line of cut scar tissue",
"a grotesque snake of indentations and stitching scars"
],
"piercemoderate": [
"a small, faded bruise",
"a small twist of reformed skin",
"a thumb-sized puncture scar"
],
"piercesevere": [
"an ink-splat shaped pocket of scar tissue",
"a long-faded puncture wound",
"a tumbling puncture hole with evidence of faded stitching"
],
"piercecritical": [
"a rippling shockwave of scar tissue",
"a wide, scattered cloud of shrapnel marks",
"a gruesome multi-pronged puncture scar"
],
"burnmoderate": [
"small amoeba-shaped skinmarks",
"a faded streak of depressed skin"
],
"burnsevere": [
"a large, jagged patch of faded skin",
"random spots of shiny, smooth skin",
"spots of taut, leathery skin"
],
"burncritical": [
"massive, disfiguring keloid scars",
"several long streaks of badly discolored and malformed skin",
"unmistakeable splotches of dead tissue from serious burns"
],
"dismember": [
"is several skintone shades paler than the rest of the body",
"is a gruesome patchwork of artificial flesh",
"has a large series of attachment scars at the articulation points"
]
}

View File

@@ -0,0 +1,52 @@
{
"": ["general area"],
"head": [
"left eyebrow",
"cheekbone",
"neck",
"throat",
"jawline",
"entire face"
],
"chest": [
"upper chest",
"lower abdomen",
"midsection",
"collarbone",
"lower back"
],
"l_arm": [
"outer left forearm",
"inner left wrist",
"left elbow",
"left bicep",
"left shoulder"
],
"r_arm": [
"outer right forearm",
"inner right wrist",
"right elbow",
"right bicep",
"right shoulder"
],
"l_leg": [
"inner left thigh",
"outer left calf",
"outer left hip",
"left kneecap",
"lower left shin"
],
"r_leg": [
"inner right thigh",
"outer right calf",
"outer right hip",
"right kneecap",
"lower right shin"
]
}

View File

@@ -659,7 +659,9 @@
#include "code\datums\wounds\_wounds.dm"
#include "code\datums\wounds\bones.dm"
#include "code\datums\wounds\burns.dm"
#include "code\datums\wounds\cuts.dm"
#include "code\datums\wounds\loss.dm"
#include "code\datums\wounds\pierce.dm"
#include "code\datums\wounds\slash.dm"
#include "code\game\alternate_appearance.dm"
#include "code\game\atoms.dm"
#include "code\game\atoms_movable.dm"
@@ -3290,6 +3292,7 @@
#include "code\modules\surgery\plastic_surgery.dm"
#include "code\modules\surgery\prosthetic_replacement.dm"
#include "code\modules\surgery\remove_embedded_object.dm"
#include "code\modules\surgery\repair_puncture.dm"
#include "code\modules\surgery\surgery.dm"
#include "code\modules\surgery\surgery_step.dm"
#include "code\modules\surgery\tools.dm"