more changes

This commit is contained in:
timothyteakettle
2020-07-18 01:26:38 +01:00
parent 584e74590f
commit 7714fcfaba
66 changed files with 1587 additions and 393 deletions
+1
View File
@@ -308,6 +308,7 @@
#define GRAB_PIXEL_SHIFT_NECK 16
#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
#define INTERACTING_WITH(X, Y) (Y in X.do_afters)
/// Field of vision defines.
#define FOV_90_DEGREES 90
+320
View File
@@ -0,0 +1,320 @@
/*
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()
if(HAS_TRAIT(victim, TRAIT_NOMETABOLISM))
return
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"
+3 -6
View File
@@ -179,8 +179,7 @@
/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>")
var/time_mod = user.mind?.get_skill_modifier(/datum/skill/healing, SKILL_SPEED_MODIFIER) || 1
if(!do_after(user, base_treat_time * time_mod * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
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>")
@@ -200,8 +199,7 @@
/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>")
var/time_mod = user.mind?.get_skill_modifier(/datum/skill/healing, SKILL_SPEED_MODIFIER) || 1
if(!do_after(user, base_treat_time * time_mod * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
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
@@ -224,8 +222,7 @@
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>")
var/time_mod = user.mind?.get_skill_modifier(/datum/skill/healing, SKILL_SPEED_MODIFIER) || 1
if(!do_after(user, base_treat_time * time_mod, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
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>")
+5
View File
@@ -10,6 +10,11 @@
var/damtype = BRUTE
var/force = 0
/// How good a given object is at causing wounds on carbons. Higher values equal better shots at creating serious wounds.
var/wound_bonus = 0
/// If this attacks a human with no wound armor on the affected body part, add this to the wound mod. Some attacks may be significantly worse at wounding if there's even a slight layer of armor to absorb some of it vs bare flesh
var/bare_wound_bonus = 0
var/datum/armor/armor
var/obj_integrity //defaults to max_integrity
var/max_integrity = 500
@@ -79,7 +79,7 @@
send_item_attack_message(I, user, affecting.name, totitemdamage)
I.do_stagger_action(src, user, totitemdamage)
if(I.force)
apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage
apply_damage(totitemdamage, I.damtype, affecting, wound_bonus = I.wound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness()) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
var/basebloodychance = affecting.brute_dam + totitemdamage
if(prob(basebloodychance))
@@ -132,6 +132,9 @@
if(S.next_step(user, user.a_intent))
return TRUE
for(var/datum/wound/W in all_wounds)
if(W.try_handling(user))
return 1
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
@@ -467,3 +470,8 @@
if (BP.status < 2)
amount += BP.burn_dam
return amount
/mob/living/carbon/proc/get_interaction_efficiency(zone)
var/obj/item/bodypart/limb = get_bodypart(zone)
if(!limb)
return
@@ -64,3 +64,8 @@
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
var/tackling = FALSE //Whether or not we are tackling, this will prevent the knock into effects for carbons
/// All of the wounds a carbon has afflicted throughout their limbs
var/list/all_wounds
/// All of the scars a carbon has afflicted throughout their limbs
var/list/all_scars
+15 -6
View File
@@ -1,6 +1,6 @@
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
var/hit_percent = (100-blocked)/100
if(!forced && hit_percent <= 0)
@@ -21,13 +21,13 @@
switch(damagetype)
if(BRUTE)
if(BP)
if(damage > 0 ? BP.receive_damage(damage_amount) : BP.heal_damage(abs(damage_amount), 0))
if(BP.receive_damage(damage_amount, 0, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
update_damage_overlays()
else //no bodypart, we deal damage with a more general method.
adjustBruteLoss(damage_amount, forced = forced)
if(BURN)
if(BP)
if(damage > 0 ? BP.receive_damage(0, damage_amount) : BP.heal_damage(0, abs(damage_amount)))
if(BP.receive_damage(0, damage_amount, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
update_damage_overlays()
else
adjustFireLoss(damage_amount, forced = forced)
@@ -202,12 +202,12 @@
//Damages ONE bodypart randomly selected from damagable ones.
//It automatically updates damage overlays if necessary
//It automatically updates health status
/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0)
/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
if(!parts.len)
return
var/obj/item/bodypart/picked = pick(parts)
if(picked.receive_damage(brute, burn, stamina))
if(picked.receive_damage(brute, burn, stamina,check_armor ? run_armor_check(picked, (brute ? "melee" : burn ? "fire" : stamina ? "bullet" : null)) : FALSE, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
update_damage_overlays()
//Heal MANY bodyparts, in random order
@@ -253,7 +253,7 @@
var/stamina_was = picked.stamina_dam
update |= picked.receive_damage(brute_per_part, burn_per_part, stamina_per_part, FALSE)
update |= picked.receive_damage(brute_per_part, burn_per_part, stamina_per_part, FALSE, required_status, wound_bonus = CANT_WOUND) // disabling wounds from these for now cuz your entire body snapping cause your heart stopped would suck
brute = round(brute - (picked.brute_dam - brute_was), DAMAGE_PRECISION)
burn = round(burn - (picked.burn_dam - burn_was), DAMAGE_PRECISION)
@@ -265,3 +265,12 @@
if(update)
update_damage_overlays()
update_stamina()
///Returns a list of bodyparts with wounds (in case someone has a wound on an otherwise fully healed limb)
/mob/living/carbon/proc/get_wounded_bodyparts(brute = FALSE, burn = FALSE, stamina = FALSE, status)
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(LAZYLEN(BP.wounds))
parts += BP
return parts
+40
View File
@@ -44,6 +44,8 @@
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!</B>\n"
else
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
for(var/datum/wound/W in BP.wounds)
msg += "[W.get_examine_description(user)]\n"
for(var/X in disabled)
var/obj/item/bodypart/BP = X
@@ -99,6 +101,22 @@
if(pulledby && pulledby.grab_state)
msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n"
var/scar_severity = 0
for(var/i in all_scars)
var/datum/scar/S = i
if(S.is_visible(user))
scar_severity += S.severity
switch(scar_severity)
if(1 to 2)
msg += "<span class='smallnotice'>[t_He] [t_has] visible scarring, you can look again to take a closer look...</span>\n"
if(3 to 4)
msg += "<span class='notice'><i>[t_He] [t_has] several bad scars, you can look again to take a closer look...</i></span>\n"
if(5 to 6)
msg += "<span class='notice'><b><i>[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...</i></b></span>\n"
if(7 to INFINITY)
msg += "<span class='notice'><b><i>[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...</i></b></span>\n"
if(msg.len)
. += "<span class='warning'>[msg.Join("")]</span>"
@@ -135,3 +153,25 @@
. += "[t_He] look[p_s()] ecstatic."
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
. += "*---------*</span>"
/mob/living/carbon/examine_more(mob/user)
if(!all_scars)
return ..()
var/list/visible_scars
for(var/i in all_scars)
var/datum/scar/S = i
if(S.is_visible(user))
LAZYADD(visible_scars, S)
if(!visible_scars)
return ..()
var/msg = list("<span class='notice'><i>You examine [src] closer, and note the following...</i></span>")
for(var/i in visible_scars)
var/datum/scar/S = i
var/scar_text = S.get_examine_description(user)
if(scar_text)
msg += "[scar_text]"
return msg
@@ -1,5 +1,5 @@
// depending on the species, it will run the corresponding apply_damage code there
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness)
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage)
// depending on the species, it will run the corresponding apply_damage code there
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage)
+55 -14
View File
@@ -163,16 +163,18 @@
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!</B>\n"
else
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
for(var/datum/wound/W in BP.wounds)
msg += "[W.get_examine_description(user)]\n"
for(var/X in disabled)
var/obj/item/bodypart/BP = X
var/damage_text
if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //Stamina is disabling the limb
damage_text = "limp and lifeless"
else
damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg
msg += "<B>[capitalize(t_his)] [BP.name] is [damage_text]!</B>\n"
if(BP.is_disabled() != BODYPART_DISABLED_WOUND) // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!)
if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //we don't care if it's stamcritted
damage_text = "limp and lifeless"
else
damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg
msg += "<B>[capitalize(t_his)] [BP.name] is [damage_text]!</B>\n"
//stores missing limbs
var/l_limbs_missing = 0
var/r_limbs_missing = 0
@@ -246,16 +248,40 @@
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
msg += "[t_He] look[p_s()] extremely disgusted.\n"
if(ShowAsPaleExamine())
msg += "[t_He] [t_has] pale skin.\n"
var/apparent_blood_volume = blood_volume
if(skin_tone == "albino")
apparent_blood_volume -= 150 // enough to knock you down one tier
switch(apparent_blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
msg += "<b>[t_He] look[p_s()] like pale death.</b>\n"
if(-INFINITY to BLOOD_VOLUME_BAD)
msg += "<span class='deadsay'><b>[t_He] resemble[p_s()] a crushed, empty juice pouch.</b></span>\n"
if(bleedsuppress)
msg += "[t_He] [t_is] bandaged with something.\n"
else if(bleed_rate)
if(bleed_rate >= 8) //8 is the rate at which heparin causes you to bleed
msg += "<b>[t_He] [t_is] bleeding uncontrollably!</b>\n"
else
msg += "<B>[t_He] [t_is] bleeding!</B>\n"
msg += "[t_He] [t_is] embued with a power that defies bleeding.\n" // only statues and highlander sword can cause this so whatever
else if(is_bleeding())
var/list/obj/item/bodypart/bleeding_limbs = list()
for(var/i in bodyparts)
var/obj/item/bodypart/BP = i
if(BP.get_bleed_rate())
bleeding_limbs += BP
var/num_bleeds = LAZYLEN(bleeding_limbs)
var/bleed_text = "<B>[t_He] [t_is] bleeding from [t_his]"
switch(num_bleeds)
if(1 to 2)
bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]"
if(3 to INFINITY)
for(var/i in 1 to (num_bleeds - 1))
var/obj/item/bodypart/BP = bleeding_limbs[i]
bleed_text += " [BP.name],"
bleed_text += " and [bleeding_limbs[num_bleeds].name]"
bleed_text += "!</B>\n"
msg += bleed_text
if(reagents.has_reagent(/datum/reagent/teslium))
msg += "[t_He] [t_is] emitting a gentle blue glow!\n"
@@ -331,6 +357,21 @@
if(digitalcamo)
msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n"
var/scar_severity = 0
for(var/i in all_scars)
var/datum/scar/S = i
if(S.is_visible(user))
scar_severity += S.severity
switch(scar_severity)
if(1 to 2)
msg += "<span class='smallnotice'>[t_He] [t_has] visible scarring, you can look again to take a closer look...</span>\n"
if(3 to 4)
msg += "<span class='notice'><i>[t_He] [t_has] several bad scars, you can look again to take a closer look...</i></span>\n"
if(5 to 6)
msg += "<span class='notice'><b><i>[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...</i></b></span>\n"
if(7 to INFINITY)
msg += "<span class='notice'><b><i>[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...</i></b></span>\n"
if (length(msg))
. += "<span class='warning'>[msg.Join("")]</span>"
@@ -1055,10 +1055,21 @@
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
/mob/living/carbon/human/do_after_coefficent()
. = ..()
. *= physiology.do_after_speed
/mob/living/carbon/human/is_bleeding()
if(NOBLOOD in dna.species.species_traits || bleedsuppress)
return FALSE
return ..()
/mob/living/carbon/human/get_total_bleed_rate()
if(NOBLOOD in dna.species.species_traits)
return FALSE
return ..()
/mob/living/carbon/human/species
var/race = null
@@ -34,6 +34,19 @@
protection += physiology.armor.getRating(d_type)
return protection
///Get all the clothing on a specific body part
/mob/living/carbon/human/proc/clothingonpart(obj/item/bodypart/def_zone)
var/list/covering_part = list()
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
for(var/bp in body_parts)
if(!bp)
continue
if(bp && istype(bp , /obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
covering_part += C
return covering_part
/mob/living/carbon/human/on_hit(obj/item/projectile/P)
if(dna && dna.species)
dna.species.on_hit(P, src)
@@ -106,7 +119,7 @@
visible_message("<span class='danger'>[user] [hulk_verb_continous] [src]!</span>", \
"<span class='userdanger'>[user] [hulk_verb_continous] you!</span>", null, COMBAT_MESSAGE_RANGE, null, user,
"<span class='danger'>You [hulk_verb_simple] [src]!</span>")
adjustBruteLoss(15)
apply_damage(15, BRUTE, wound_bonus=10)
return 1
/mob/living/carbon/human/attack_hand(mob/user)
@@ -217,16 +230,17 @@
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration)
apply_damage(damage, M.melee_damage_type, affecting, armor)
apply_damage(damage, M.melee_damage_type, affecting, armor, wound_bonus = M.wound_bonus, bare_wound_bonus = M.bare_wound_bonus, sharpness = M.sharpness)
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
. = ..()
if(!.) //unsuccessful slime attack
return
var/damage = rand(5, 25)
var/wound_mod = -45 // 25^1.4=90, 90-45=45
if(M.is_adult)
damage = rand(10, 35)
wound_mod = -90 // 35^1.4=145, 145-90=55
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
if(!dam_zone) //Dismemberment successful
@@ -236,7 +250,7 @@
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
apply_damage(damage, BRUTE, affecting, armor_block, wound_bonus=wound_mod)
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM)
@@ -614,6 +628,20 @@
no_damage = TRUE
to_send += "\t <span class='[no_damage ? "notice" : "warning"]'>Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].</span>\n"
for(var/thing in LB.wounds)
var/datum/wound/W = thing
var/msg
switch(W.severity)
if(WOUND_SEVERITY_TRIVIAL)
msg = "\t <span class='danger'>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)].</span>"
if(WOUND_SEVERITY_MODERATE)
msg = "\t <span class='warning'>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!</span>"
if(WOUND_SEVERITY_SEVERE)
msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!</b></span>"
if(WOUND_SEVERITY_CRITICAL)
msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!!</b></span>"
to_chat(src, msg)
for(var/obj/item/I in LB.embedded_objects)
if(I.isEmbedHarmless())
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>")
@@ -623,8 +651,25 @@
for(var/t in missing)
to_send += "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>\n"
if(bleed_rate)
to_send += "<span class='danger'>You are bleeding!</span>\n"
if(is_bleeding())
var/list/obj/item/bodypart/bleeding_limbs = list()
for(var/i in bodyparts)
var/obj/item/bodypart/BP = i
if(BP.get_bleed_rate())
bleeding_limbs += BP
var/num_bleeds = LAZYLEN(bleeding_limbs)
var/bleed_text = "<span class='danger'>You are bleeding from your"
switch(num_bleeds)
if(1 to 2)
bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]"
if(3 to INFINITY)
for(var/i in 1 to (num_bleeds - 1))
var/obj/item/bodypart/BP = bleeding_limbs[i]
bleed_text += " [BP.name],"
bleed_text += " and [bleeding_limbs[num_bleeds].name]"
bleed_text += "!</span>"
to_chat(src, bleed_text)
if(getStaminaLoss())
if(getStaminaLoss() > 30)
to_send += "<span class='info'>You're completely exhausted.</span>\n"
@@ -49,7 +49,6 @@
var/special_voice = "" // For changing our voice. Used by a symptom.
var/bleed_rate = 0 //how much are we bleeding
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
var/blood_state = BLOOD_STATE_NOT_BLOODY
@@ -151,3 +151,22 @@
if(blood_dna.len)
last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works
last_blood_DNA = blood_dna[blood_dna.len]*/
/// For use formatting all of the scars this human has for saving for persistent scarring
/mob/living/carbon/human/proc/format_scars()
if(!all_scars)
return
var/scars = ""
for(var/i in all_scars)
var/datum/scar/S = i
scars += "[S.format()];"
return scars
/// Takes a single scar from the persistent scar loader and recreates it from the saved data
/mob/living/carbon/human/proc/load_scar(scar_line)
var/list/scar_data = splittext(scar_line, "|")
if(LAZYLEN(scar_data) != 4)
return // invalid, should delete
var/obj/item/bodypart/BP = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
var/datum/scar/S = new
return S.load(BP, scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]))
@@ -1728,9 +1728,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/armor_block = H.run_armor_check(affecting, "melee", "<span class='notice'>Your armor has protected your [hit_area].</span>", "<span class='notice'>Your armor has softened a hit to your [hit_area].</span>",I.armour_penetration)
armor_block = min(90,armor_block) //cap damage reduction at 90%
var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
var/Iwound_bonus = I.wound_bonus
// this way, you can't wound with a surgical tool on help intent if they have a surgery active and are laying down, so a misclick with a circular saw on the wrong limb doesn't bleed them dry (they still get hit tho)
if((I.item_flags & SURGICAL_TOOL) && user.a_intent == INTENT_HELP && (H.mobility_flags & ~MOBILITY_STAND) && (LAZYLEN(H.surgeries) > 0))
Iwound_bonus = CANT_WOUND
var/weakness = H.check_weakness(I, user)
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H) //CIT CHANGE - replaces I.force with totitemdamage
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H, wound_bonus = Iwound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness())
H.send_item_attack_message(I, user, hit_area, totitemdamage)
@@ -1945,8 +1951,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
append_message += ", causing them to drop [target_held_item]"
log_combat(user, target, "shoved", append_message)
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE)
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness) // make sure putting wound_bonus here doesn't screw up other signals or uses for this signal
var/hit_percent = (100-(blocked+armor))/100
hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100
if(!forced && hit_percent <= 0)
@@ -1973,7 +1979,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.damageoverlaytemp = 20
var/damage_amount = forced ? damage : damage * hit_percent * brutemod * H.physiology.brute_mod
if(BP)
if(damage > 0 ? BP.receive_damage(damage_amount, 0) : BP.heal_damage(abs(damage_amount), 0))
if(BP.receive_damage(damage_amount, 0, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
H.update_damage_overlays()
if(HAS_TRAIT(H, TRAIT_MASO) && prob(damage_amount))
H.mob_climax(forced_climax=TRUE)
@@ -1984,7 +1990,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.damageoverlaytemp = 20
var/damage_amount = forced ? damage : damage * hit_percent * burnmod * H.physiology.burn_mod
if(BP)
if(damage > 0 ? BP.receive_damage(0, damage_amount) : BP.heal_damage(0, abs(damage_amount)))
if(BP.receive_damage(0, damage_amount, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
H.update_damage_overlays()
else
H.adjustFireLoss(damage_amount)
@@ -3,7 +3,7 @@
id = "human"
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR)
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,CAN_SCAR)
mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None")
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
skinned_type = /obj/item/stack/sheet/animalhide/human
@@ -4,7 +4,7 @@
id = "lizard"
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR)
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,CAN_SCAR)
mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur", "deco_wings")
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
mutanttongue = /obj/item/organ/tongue/lizard
@@ -8,7 +8,7 @@
nojumpsuit = TRUE
say_mod = "poofs" //what does a mushroom sound like
species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL)
species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL,CAN_SCAR)
inherent_traits = list(TRAIT_NOBREATH)
speedmod = 1.5 //faster than golems but not by much
@@ -3,7 +3,7 @@
name = "Anthromorphic Plant"
id = "pod"
default_color = "59CE00"
species_traits = list(MUTCOLORS,EYECOLOR)
species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR)
attack_verb = "slash"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
@@ -10,7 +10,7 @@
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
species_traits = list(NOBLOOD,NOEYES)
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH)
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH,CAN_SCAR)
dangerous_existence = 1
mutanteyes = /obj/item/organ/eyes/night_vision
@@ -8,7 +8,7 @@
sexes = 0
blacklisted = 1
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING)
species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING,CAN_SCAR)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutanttongue = /obj/item/organ/tongue/zombie
@@ -45,7 +45,7 @@
/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount)
. = min(20, amount)
/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE)
/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
. = ..()
if(.)
regen_cooldown = world.time + REGENERATION_DELAY
@@ -62,6 +62,10 @@
heal_amt *= 2
C.heal_overall_damage(heal_amt,heal_amt)
C.adjustToxLoss(-heal_amt)
for(var/i in C.all_wounds)
var/datum/wound/W = i
if(prob(4-W.severity))
W.remove_wound()
if(!C.InCritical() && prob(4))
playsound(C, pick(spooks), 50, TRUE, 10)
+6
View File
@@ -404,6 +404,12 @@
if(stat != DEAD || D.process_dead)
D.stage_act()
/mob/living/carbon/handle_wounds()
for(var/thing in all_wounds)
var/datum/wound/W = thing
if(W.processes) // meh
W.handle_process()
//todo generalize this and move hud out
/mob/living/carbon/proc/handle_changeling()
if(mind && hud_used && hud_used.lingchemdisplay)
@@ -26,6 +26,8 @@
//These have to be after the parent new to ensure that the monkey
//bodyparts are actually created before we try to equip things to
//those slots
if(ancestor_chain > 1)
generate_fake_scars(rand(ancestor_chain, ancestor_chain * 4))
if(relic_hat)
equip_to_slot_or_del(new relic_hat, SLOT_HEAD)
if(relic_mask)
+2 -2
View File
@@ -14,7 +14,7 @@
*
* Returns TRUE if damage applied
*/
/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
var/hit_percent = (100-blocked)/100
if(!damage || (hit_percent <= 0))
return 0
@@ -245,7 +245,7 @@
update_stamina()
// damage ONE external organ, organ gets randomly selected from damaged ones.
/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE)
/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
adjustBruteLoss(brute, FALSE) //zero as argument for no instant health update
adjustFireLoss(burn, FALSE)
adjustStaminaLoss(stamina, FALSE)
+5
View File
@@ -45,6 +45,8 @@
/mob/living/proc/BiologicalLife(seconds, times_fired)
handle_diseases()// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not.
handle_wounds()
// Everything after this shouldn't process while dead (as of the time of writing)
if(stat == DEAD)
return FALSE
@@ -109,6 +111,9 @@
/mob/living/proc/handle_diseases()
return
/mob/living/proc/handle_wounds()
return
/mob/living/proc/handle_diginvis()
if(!digitaldisguise)
src.digitaldisguise = image(loc = src)
+1 -1
View File
@@ -636,7 +636,7 @@
TH.transfer_mob_blood_dna(src)
/mob/living/carbon/human/makeTrail(turf/T)
if((NOBLOOD in dna.species.species_traits) || !bleed_rate || bleedsuppress)
if((NOBLOOD in dna.species.species_traits) || !is_bleeding() || bleedsuppress)
return
..()
+2 -2
View File
@@ -85,7 +85,7 @@
totaldamage = block_calculate_resultant_damage(totaldamage, returnlist)
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
if(!P.nodamage)
apply_damage(totaldamage, P.damage_type, def_zone, armor)
apply_damage(P.damage, P.damage_type, def_zone, armor, wound_bonus=P.wound_bonus, bare_wound_bonus=P.bare_wound_bonus, sharpness=P.sharpness)
if(P.dismemberment)
check_projectile_dismemberment(P, def_zone)
var/missing = 100 - final_percent
@@ -138,7 +138,7 @@
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)
apply_damage(total_damage, dtype, impacting_zone, armor, sharpness=I.sharpness)
if(I.thrownby)
log_combat(I.thrownby, src, "threw and hit", I)
else
@@ -1,5 +1,5 @@
/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
var/hit_percent = (100-blocked)/100
if(!damage || (!forced && hit_percent <= 0))
return 0
@@ -334,9 +334,11 @@
/obj/item/surgicaldrill,
/obj/item/scalpel,
/obj/item/circular_saw,
/obj/item/bonesetter,
/obj/item/roller/robo,
/obj/item/borg/cyborghug/medical,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/stack/medical/bone_gel/cyborg,
/obj/item/organ_storage,
/obj/item/borg/lollipop,
/obj/item/sensor_device,
@@ -29,8 +29,11 @@
var/armored = FALSE
obj_damage = 60
melee_damage_lower = 20
melee_damage_upper = 30
melee_damage_lower = 15 // i know it's like half what it used to be, but bears cause bleeding like crazy now so it works out
melee_damage_upper = 15
wound_bonus = -5
bare_wound_bonus = 10 // BEAR wound bonus am i right
sharpness = TRUE
attack_verb_continuous = "claws"
attack_verb_simple = "claw"
attack_sound = 'sound/weapons/bladeslice.ogg'
@@ -69,8 +72,9 @@
icon_dead = "combatbear_dead"
faction = list("russian")
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1, /obj/item/bear_armor = 1)
melee_damage_lower = 25
melee_damage_upper = 35
melee_damage_lower = 18
melee_damage_upper = 20
wound_bonus = 0
armour_penetration = 20
health = 120
maxHealth = 120
@@ -99,8 +103,9 @@
A.maxHealth += 60
A.health += 60
A.armour_penetration += 20
A.melee_damage_lower += 5
A.melee_damage_lower += 3
A.melee_damage_upper += 5
A.wound_bonus += 5
A.update_icons()
to_chat(user, "<span class='info'>You strap the armor plating to [A] and sharpen [A.p_their()] claws with the nail filer. This was a great idea.</span>")
qdel(src)
@@ -643,7 +643,7 @@ Difficulty: Normal
to_chat(L, "<span class='userdanger'>You're struck by a [name]!</span>")
var/limb_to_hit = L.get_bodypart(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
var/armor = L.run_armor_check(limb_to_hit, "melee", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!")
L.apply_damage(damage, BURN, limb_to_hit, armor)
L.apply_damage(damage, BURN, limb_to_hit, armor, wound_bonus=CANT_WOUND)
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L //mobs find and damage you...
if(H.stat == CONSCIOUS && !H.target && H.AIStatus != AI_OFF && !H.client)
@@ -52,6 +52,8 @@ Difficulty: Medium
elimination = 1
appearance_flags = 0
mouse_opacity = MOUSE_OPACITY_ICON
wound_bonus = -40
bare_wound_bonus = 20
/mob/living/simple_animal/hostile/megafauna/legion/Initialize()
. = ..()
@@ -129,7 +129,7 @@ Difficulty: Hard
to_chat(L, "<span class='userdanger'>[src]'s ground slam shockwave sends you flying!</span>")
var/turf/thrownat = get_ranged_target_turf_direct(src, L, 8, rand(-10, 10))
L.throw_at(thrownat, 8, 2, src, TRUE) //, force = MOVE_FORCE_OVERPOWERING, gentle = TRUE)
L.apply_damage(20, BRUTE)
L.apply_damage(20, BRUTE, wound_bonus=CANT_WOUND)
shake_camera(L, 2, 1)
all_turfs -= T
sleep(delay)
@@ -77,6 +77,9 @@
/mob/living/simple_animal/hostile/syndicate/melee
melee_damage_lower = 15
melee_damage_upper = 15
wound_bonus = -10
bare_wound_bonus = 20
sharpness = TRUE
icon_state = "syndicate_knife"
icon_living = "syndicate_knife"
loot = list(/obj/effect/gibspawner/human)
@@ -140,6 +140,13 @@
///What kind of footstep this mob should have. Null if it shouldn't have any.
var/footstep_type
//How much wounding power it has
var/wound_bonus = CANT_WOUND
//How much bare wounding power it has
var/bare_wound_bonus = 0
//If the attacks from this are sharp
var/sharpness = FALSE
/mob/living/simple_animal/Initialize()
. = ..()
GLOB.simple_animals[AIStatus] += src
@@ -8,6 +8,18 @@
projectile_type = /obj/item/projectile/bullet/shotgun_slug
custom_materials = list(/datum/material/iron=4000)
obj/item/ammo_casing/shotgun/executioner
name = "executioner slug"
desc = "A 12 gauge lead slug purpose built to annihilate flesh on impact."
icon_state = "stunshell"
projectile_type = /obj/projectile/bullet/shotgun_slug/executioner
/obj/item/ammo_casing/shotgun/pulverizer
name = "pulverizer slug"
desc = "A 12 gauge lead slug purpose built to annihilate bones on impact."
icon_state = "stunshell"
projectile_type = /obj/projectile/bullet/shotgun_slug/pulverizer
/obj/item/ammo_casing/shotgun/beanbag
name = "beanbag slug"
desc = "A weak beanbag slug for riot control."
@@ -37,6 +37,11 @@
select_name = "anti-vehicle"
fire_sound = 'sound/weapons/lasercannonfire.ogg'
/obj/item/ammo_casing/energy/laser/hellfire
projectile_type = /obj/projectile/beam/laser/hellfire
e_cost = 130
select_name = "maim"
/obj/item/ammo_casing/energy/laser/pulse
projectile_type = /obj/item/projectile/beam/pulse
e_cost = 200
+5
View File
@@ -184,6 +184,11 @@
return
if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected)
return
if(iscarbon(target))
var/mob/living/carbon/C = target
for(var/datum/wound/W in C.all_wounds)
if(W.try_treating(src, user))
return // another coward cured!
if(istype(user))//Check if the user can use the gun, if the user isn't alive(turrets) assume it can.
var/mob/living/L = user
@@ -44,6 +44,12 @@
ammo_type = list(/obj/item/ammo_casing/energy/lasergun/old)
ammo_x_offset = 3
/obj/item/gun/energy/laser/hellgun
name ="hellfire laser gun"
desc = "A relic of a weapon, built before NT began installing regulators on its laser weaponry. This pattern of laser gun became infamous for the gruesome burn wounds it caused, and was quietly discontinued once it began to affect NT's reputation."
icon_state = "hellgun"
ammo_type = list(/obj/item/ammo_casing/energy/laser/hellfire)
/obj/item/gun/energy/laser/captain
name = "antique laser gun"
icon_state = "caplaser"
+4
View File
@@ -154,6 +154,10 @@
///If TRUE, hit mobs even if they're on the floor and not our target
var/hit_stunned_targets = FALSE
wound_bonus = CANT_WOUND
/// For telling whether we want to roll for bone breaking or lacerations if we're bothering with wounds
var/sharpness = FALSE
/obj/item/projectile/Initialize()
. = ..()
permutated = list()
@@ -14,11 +14,26 @@
ricochets_max = 50 //Honk!
ricochet_chance = 80
is_reflectable = TRUE
wound_bonus = -20
bare_wound_bonus = 10
/obj/item/projectile/beam/laser
tracer_type = /obj/effect/projectile/tracer/laser
muzzle_type = /obj/effect/projectile/muzzle/laser
impact_type = /obj/effect/projectile/impact/laser
wound_bonus = -30
bare_wound_bonus = 40
//overclocked laser, does a bit more damage but has much higher wound power (-0 vs -20)
/obj/projectile/beam/laser/hellfire
name = "hellfire laser"
wound_bonus = 0
damage = 25
speed = 0.6 // higher power = faster, that's how light works right
/obj/projectile/beam/laser/hellfire/Initialize()
. = ..()
transform *= 2
/obj/item/projectile/beam/laser/heavylaser
name = "heavy laser"
@@ -90,6 +105,7 @@
tracer_type = /obj/effect/projectile/tracer/pulse
muzzle_type = /obj/effect/projectile/muzzle/pulse
impact_type = /obj/effect/projectile/impact/pulse
wound_bonus = 10
/obj/item/projectile/beam/pulse/on_hit(atom/target, blocked = FALSE)
. = ..()
@@ -116,6 +132,8 @@
damage = 30
impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
light_color = LIGHT_COLOR_GREEN
wound_bonus = -40
bare_wound_bonus = 70
/obj/item/projectile/beam/emitter/singularity_pull()
return
@@ -8,3 +8,4 @@
flag = "bullet"
hitsound_wall = "ricochet"
impact_effect_type = /obj/effect/temp_visual/impact_effect
sharpness = TRUE
@@ -19,6 +19,8 @@
ricochet_chance = 50
ricochet_auto_aim_angle = 10
ricochet_auto_aim_range = 3
wound_bonus = -35
sharpness = TRUE
/obj/item/projectile/bullet/c38/match
name = ".38 Match bullet"
@@ -29,6 +31,7 @@
ricochet_incidence_leeway = 50
ricochet_decay_chance = 1
ricochet_decay_damage = 1
wound_bonus = 0
/obj/item/projectile/bullet/c38/match/bouncy
name = ".38 Rubber bullet"
@@ -2,10 +2,22 @@
name = "12g shotgun slug"
damage = 60
/obj/projectile/bullet/shotgun_slug/executioner
name = "executioner slug" // admin only, can dismember limbs
sharpness = TRUE
wound_bonus = 0
/obj/projectile/bullet/shotgun_slug/pulverizer
name = "pulverizer slug" // admin only, can crush bones
sharpness = FALSE
wound_bonus = 0
/obj/item/projectile/bullet/shotgun_beanbag
name = "beanbag slug"
damage = 5
damage = 10
stamina = 70
wound_bonus = 20
sharpness = FALSE
/obj/item/projectile/bullet/incendiary/shotgun
name = "incendiary slug"
@@ -77,6 +89,7 @@
/obj/item/projectile/bullet/pellet/shotgun_buckshot
name = "buckshot pellet"
damage = 12.5
wound_bonus = -10
/obj/item/projectile/bullet/pellet/shotgun_rubbershot
name = "rubbershot pellet"
@@ -144,6 +144,9 @@
M.adjustFireLoss(-power, 0)
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)
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) //fixes common causes for disfiguration
. = 1
metabolization_rate = REAGENTS_METABOLISM * (0.00001 * (M.bodytemperature ** 2) + 0.5)
@@ -192,6 +195,9 @@
M.adjustFireLoss(-1.5 * power, 0)
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)
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC)
. = 1
..()
@@ -231,7 +237,7 @@
/datum/reagent/medicine/spaceacillin
name = "Spaceacillin"
description = "Spaceacillin will prevent a patient from conventionally spreading any diseases they are currently infected with."
description = "Spaceacillin will prevent a patient from conventionally spreading any diseases they are currently infected with. Also reduces infection in serious burns."
color = "#f2f2f2"
metabolization_rate = 0.1 * REAGENTS_METABOLISM
pH = 8.1
@@ -403,7 +409,7 @@
/datum/reagent/medicine/mine_salve
name = "Miner's Salve"
description = "A powerful painkiller. Restores bruising and burns in addition to making the patient believe they are fully healed."
description = "A powerful painkiller. Restores bruising and burns in addition to making the patient believe they are fully healed. Also great for treating severe burn wounds in a pinch."
reagent_state = LIQUID
color = "#6D6374"
metabolization_rate = 0.4 * REAGENTS_METABOLISM
@@ -432,7 +438,7 @@
// +10% success propability on each step, useful while operating in less-than-perfect conditions
if(show_message)
to_chat(M, "<span class='danger'>You feel your wounds fade away to nothing!</span>" )
to_chat(M, "<span class='danger'>You feel your injuries fade away to nothing!</span>" )
..()
/datum/reagent/medicine/mine_salve/on_mob_end_metabolize(mob/living/M)
@@ -453,10 +459,10 @@
/datum/reagent/medicine/synthflesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M))
if (M.stat == DEAD)
var/mob/living/carbon/C = M
if(M.stat == DEAD)
show_message = 0
if(method in list(INGEST, VAPOR))
var/mob/living/carbon/C = M
C.losebreath++
C.emote("cough")
to_chat(M, "<span class='danger'>You feel your throat closing up!</span>")
@@ -465,6 +471,8 @@
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)
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)
@@ -1552,10 +1560,6 @@
/datum/reagent/medicine/polypyr/on_mob_life(mob/living/carbon/M) //I wanted a collection of small positive effects, this is as hard to obtain as coniine after all.
M.adjustOrganLoss(ORGAN_SLOT_LUNGS, -0.25)
M.adjustBruteLoss(-0.35, 0)
if(prob(50))
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.bleed_rate = max(H.bleed_rate - 1, 0)
..()
. = 1
@@ -1588,3 +1592,10 @@
to_chat(C, "[pick(GLOB.wisdoms)]") //give them a random wisdom
..()
// handled in cut wounds process
/datum/reagent/medicine/coagulant
name = "Sanguirite"
description = "A coagulant used to help open cuts clot faster."
reagent_state = LIQUID
color = "#bb2424"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
@@ -2296,3 +2296,36 @@
if(data["blood_DNA"])
S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
/datum/reagent/determination
name = "Determination"
description = "For when you need to push on a little more. Do NOT allow near plants."
reagent_state = LIQUID
color = "#D2FFFA"
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
/datum/reagent/determination/on_mob_end_metabolize(mob/living/carbon/M)
if(significant)
var/stam_crash = 0
for(var/thing in M.all_wounds)
var/datum/wound/W = thing
stam_crash += (W.severity + 1) * 3 // spike of 3 stam damage per wound severity (moderate = 6, severe = 9, critical = 12) when the determination wears off if it was a combat rush
M.adjustStaminaLoss(stam_crash)
M.remove_status_effect(STATUS_EFFECT_DETERMINED)
..()
/datum/reagent/determination/on_mob_life(mob/living/carbon/M)
if(!significant && volume >= WOUND_DETERMINATION_SEVERE)
significant = TRUE
M.apply_status_effect(STATUS_EFFECT_DETERMINED) // in addition to the slight healing, limping cooldowns are divided by 4 during the combat high
volume = min(volume, WOUND_DETERMINATION_MAX)
for(var/thing in M.all_wounds)
var/datum/wound/W = thing
var/obj/item/bodypart/wounded_part = W.limb
if(wounded_part)
wounded_part.heal_damage(0.25, 0.25)
M.adjustStaminaLoss(-0.25*REM) // the more wounds, the more stamina regen
..()
@@ -154,6 +154,11 @@
pH = 12
value = REAGENT_VALUE_RARE
/datum/reagent/toxin/carpotoxin/on_mob_life(mob/living/carbon/M)
. = ..()
for(var/i in M.all_scars)
qdel(i)
/datum/reagent/toxin/zombiepowder
name = "Zombie Powder"
description = "A strong neurotoxin that puts the subject into a death-like state."
@@ -736,22 +741,13 @@
/datum/reagent/toxin/heparin //Based on a real-life anticoagulant. I'm not a doctor, so this won't be realistic.
name = "Heparin"
description = "A powerful anticoagulant. Victims will bleed uncontrollably and suffer scaling bruising."
description = "A powerful anticoagulant. All open cut wounds on the victim will open up and bleed much faster"
reagent_state = LIQUID
color = "#C8C8C8" //RGB: 200, 200, 200
metabolization_rate = 0.2 * REAGENTS_METABOLISM
toxpwr = 0
value = REAGENT_VALUE_VERY_RARE
/datum/reagent/toxin/heparin/on_mob_life(mob/living/carbon/M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.bleed_rate = min(H.bleed_rate + 2, 8)
H.adjustBruteLoss(1, 0) //Brute damage increases with the amount they're bleeding
. = 1
return ..() || .
/datum/reagent/toxin/rotatium //Rotatium. Fucks up your rotation and is hilarious
name = "Rotatium"
description = "A constantly swirling, oddly colourful fluid. Causes the consumer's sense of direction and hand-eye coordination to become wild."
@@ -90,12 +90,12 @@
item_state = "medipen"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
amount_per_transfer_from_this = 13
volume = 13
amount_per_transfer_from_this = 15
volume = 15
ignore_flags = 1 //so you can medipen through hardsuits
reagent_flags = DRAWABLE
flags_1 = null
list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/preservahyde = 3)
list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/preservahyde = 3, /datum/reagent/medicine/coagulant = 2)
custom_premium_price = PRICE_ALMOST_EXPENSIVE
/obj/item/reagent_containers/hypospray/medipen/suicide_act(mob/living/carbon/user)
@@ -133,6 +133,13 @@
else
. += "<span class='notice'>It is spent.</span>"
/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."
volume = 15
amount_per_transfer_from_this = 15
list_reagents = list(/datum/reagent/medicine/epinephrine = 12, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/medicine/spaceacillin = 0.5)
/obj/item/reagent_containers/hypospray/medipen/stimulants
name = "illegal stimpack medipen"
desc = "A highly illegal medipen due to its load and small injections, allow for five uses before being drained"
@@ -119,6 +119,24 @@
category = list("initial", "Medical","Tool Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/bonesetter
name = "Bonesetter"
id = "bonesetter"
build_type = AUTOLATHE | PROTOLATHE
materials = list(/datum/material/iron = 1000)
build_path = /obj/item/bonesetter
category = list("initial", "Medical", "Tool Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/sticky_tape/surgical
name = "Surgical Tape"
id = "surgical_tape"
build_type = PROTOLATHE
materials = list(/datum/material/plastic = 500)
build_path = /obj/item/stack/sticky_tape/surgical
category = list("initial", "Medical")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/beaker
name = "Beaker"
id = "beaker"
@@ -104,7 +104,7 @@
display_name = "Advanced Surgery Tools"
description = "Refined and improved redesigns for the run-of-the-mill medical utensils."
prereq_ids = list("adv_biotech", "adv_surgery")
design_ids = list("drapes", "retractor_adv", "surgicaldrill_adv", "scalpel_adv")
design_ids = list("drapes", "retractor_adv", "surgicaldrill_adv", "scalpel_adv", "bonesetter", "surgical_tape")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/adv_surgery
@@ -25,6 +25,11 @@
/obj/effect/proc_holder/spell/bloodcrawl/perform(obj/effect/decal/cleanable/target, recharge = 1, mob/living/user = usr)
if(istype(user))
if(istype(user, /mob/living/simple_animal/slaughter))
var/mob/living/simple_animal/slaughter/slaught = user
slaught.current_hitstreak = 0
slaught.wound_bonus = initial(slaught.wound_bonus)
slaught.bare_wound_bonus = initial(slaught.bare_wound_bonus)
if(phased)
if(user.phasein(target))
phased = 0
@@ -105,7 +105,7 @@
var/damage_percent = (stored.maxHealth - stored.health)/stored.maxHealth;
var/damapply = damage_percent * shape.maxHealth;
shape.apply_damage(damapply, source.convert_damage_type, forced = TRUE);
shape.apply_damage(damapply, source.convert_damage_type, forced = TRUE, wound_bonus=CANT_WOUND);
slink = soullink(/datum/soullink/shapeshift, stored , shape)
slink.source = src
@@ -158,7 +158,7 @@
var/damage_percent = (shape.maxHealth - shape.health)/shape.maxHealth;
var/damapply = stored.maxHealth * damage_percent
stored.apply_damage(damapply, source.convert_damage_type, forced = TRUE)
stored.apply_damage(damapply, source.convert_damage_type, forced = TRUE, wound_bonus=CANT_WOUND)
qdel(shape)
qdel(src)
@@ -71,6 +71,28 @@
var/medium_burn_msg = "blistered"
var/heavy_burn_msg = "peeling away"
/// The wounds currently afflicting this body part
var/list/wounds
/// The scars currently afflicting this body part
var/list/scars
/// Our current stored wound damage multiplier
var/wound_damage_multiplier = 1
/// This number is subtracted from all wound rolls on this bodypart, higher numbers mean more defense, negative means easier to wound
var/wound_resistance = 0
/// When this bodypart hits max damage, this number is added to all wound rolls. Obviously only relevant for bodyparts that have damage caps.
var/disabled_wound_penalty = 15
/// 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
/obj/item/bodypart/examine(mob/user)
. = ..()
if(brute_dam > DAMAGE_PRECISION)
@@ -149,7 +171,7 @@
//Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all.
//Damage will not exceed max_damage using this proc
//Cannot apply negative damage
/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE)
/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) // maybe separate BRUTE_SHARP and BRUTE_OTHER eventually somehow hmm
if(owner && (owner.status_flags & GODMODE))
return FALSE //godmode
var/dmg_mlt = CONFIG_GET(number/damage_multiplier)
@@ -163,20 +185,38 @@
if(!brute && !burn && !stamina)
return FALSE
brute *= wound_damage_multiplier
burn *= wound_damage_multiplier
switch(animal_origin)
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)
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
check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
var/can_inflict = max_damage - get_damage()
if(can_inflict <= 0)
return FALSE
var/total_damage = brute + burn
if(total_damage > can_inflict)
if(total_damage > can_inflict && total_damage > 0) // TODO: the second part of this check should be removed once disabling is all done
brute = round(brute * (max_damage / total_damage),DAMAGE_PRECISION)
burn = round(burn * (max_damage / total_damage),DAMAGE_PRECISION)
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
@@ -196,6 +236,107 @@
update_disabled()
return update_bodypart_damage_state()
/**
* 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 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.
* * 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
*/
/obj/item/bodypart/proc/check_wounding(woundtype, damage, wound_bonus, bare_wound_bonus)
// actually roll wounds if applicable
if(HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE))
damage *= 1.5
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
switch(woundtype)
if(WOUND_SHARP)
wounds_checking = WOUND_LIST_CUT
if(WOUND_BRUTE)
wounds_checking = WOUND_LIST_BONE
if(WOUND_BURN)
wounds_checking = WOUND_LIST_BURN
//cycle through the wounds of the relevant category from the most severe down
for(var/PW in wounds_checking)
var/datum/wound/possible_wound = PW
var/datum/wound/replaced_wound
for(var/i in wounds)
var/datum/wound/existing_wound = i
if(existing_wound.type in wounds_checking)
if(existing_wound.severity >= initial(possible_wound.severity))
return
else
replaced_wound = existing_wound
if(initial(possible_wound.threshold_minimum) < injury_roll)
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)
else
var/datum/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
// 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.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
var/datum/wound/new_wound = new potential_wound
new_wound.apply_wound(src, smited = smited)
/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)
for(var/c in clothing)
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)
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)
if(!armor_ablation)
injury_mod += bare_wound_bonus
injury_mod -= armor_ablation
injury_mod += wound_bonus
for(var/thing in wounds)
var/datum/wound/W = thing
injury_mod += W.threshold_penalty
var/part_mod = -wound_resistance
if(is_disabled())
part_mod += disabled_wound_penalty
injury_mod += part_mod
return injury_mod
//Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all.
//Damage cannot go below zero.
//Cannot remove negative damage (i.e. apply damage)
@@ -227,16 +368,29 @@
//Checks disabled status thresholds
/obj/item/bodypart/proc/update_disabled()
if(!owner)
return
set_disabled(is_disabled())
/obj/item/bodypart/proc/is_disabled()
if(!owner)
return
if(HAS_TRAIT(owner, TRAIT_PARALYSIS))
return BODYPART_DISABLED_PARALYSIS
for(var/i in wounds)
var/datum/wound/W = i
if(W.disabling)
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%
return BODYPART_DISABLED_DAMAGE
if(disabled && (get_damage(TRUE) <= (max_damage * 0.5)))
if(!last_maxed)
owner.emote("scream")
last_maxed = TRUE
if(!is_organic_limb())
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
return BODYPART_NOT_DISABLED
else
return BODYPART_NOT_DISABLED
@@ -251,9 +405,11 @@
/obj/item/bodypart/proc/set_disabled(new_disabled)
if(disabled == new_disabled)
if(disabled == new_disabled || !owner)
return FALSE
disabled = new_disabled
if(disabled && owner.get_item_for_held_index(held_index))
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
owner.update_health_hud() //update the healthdoll
owner.update_body()
owner.update_mobility()
@@ -581,293 +737,41 @@
drop_organs()
qdel(src)
/obj/item/bodypart/chest
name = BODY_ZONE_CHEST
desc = "It's impolite to stare at a person's chest."
icon_state = "default_human_chest"
max_damage = 200
body_zone = BODY_ZONE_CHEST
body_part = CHEST
px_x = 0
px_y = 0
stam_damage_coeff = 1
max_stamina_damage = 200
var/obj/item/cavity_item
/obj/item/bodypart/chest/can_dismember(obj/item/I)
if(!((owner.stat == DEAD) || owner.InFullCritical()))
return FALSE
return ..()
/obj/item/bodypart/chest/Destroy()
if(cavity_item)
qdel(cavity_item)
return ..()
/obj/item/bodypart/chest/drop_organs(mob/user)
if(cavity_item)
cavity_item.forceMove(user.loc)
cavity_item = null
..()
/obj/item/bodypart/chest/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_chest"
animal_origin = MONKEY_BODYPART
/obj/item/bodypart/chest/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_chest"
dismemberable = 0
max_damage = 500
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/chest/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/chest/larva
icon = 'icons/mob/animal_parts.dmi'
icon_state = "larva_chest"
dismemberable = 0
max_damage = 50
animal_origin = LARVA_BODYPART
/obj/item/bodypart/l_arm
name = "left arm"
desc = "Did you know that the word 'sinister' stems originally from the \
Latin 'sinestra' (left hand), because the left hand was supposed to \
be possessed by the devil? This arm appears to be possessed by no \
one though."
icon_state = "default_human_l_arm"
attack_verb = list("slapped", "punched")
max_damage = 50
max_stamina_damage = 50
body_zone = BODY_ZONE_L_ARM
body_part = ARM_LEFT
aux_icons = list(BODY_ZONE_PRECISE_L_HAND = HANDS_PART_LAYER, "l_hand_behind" = BODY_BEHIND_LAYER)
body_damage_coeff = 0.75
held_index = 1
px_x = -6
px_y = 0
stam_heal_tick = STAM_RECOVERY_LIMB
/obj/item/bodypart/l_arm/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/l_arm/set_disabled(new_disabled)
. = ..()
if(!.)
/// Get whatever wound of the given type is currently attached to this limb, if any
/obj/item/bodypart/proc/get_wound_type(checking_type)
if(isnull(wounds))
return
if(owner.stat < UNCONSCIOUS)
switch(disabled)
if(BODYPART_DISABLED_DAMAGE)
owner.emote("scream")
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
if(BODYPART_DISABLED_PARALYSIS)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(owner.hud_used)
var/obj/screen/inventory/hand/L = owner.hud_used.hand_slots["[held_index]"]
if(L)
L.update_icon()
for(var/thing in wounds)
var/datum/wound/W = thing
if(istype(W, checking_type))
return W
/obj/item/bodypart/l_arm/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_l_arm"
animal_origin = MONKEY_BODYPART
px_x = -5
px_y = -3
/// 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()
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
wound_damage_multiplier = dam_mul
update_disabled()
/obj/item/bodypart/l_arm/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_l_arm"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/l_arm/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/r_arm
name = "right arm"
desc = "Over 87% of humans are right handed. That figure is much lower \
among humans missing their right arm."
icon_state = "default_human_r_arm"
attack_verb = list("slapped", "punched")
max_damage = 50
body_zone = BODY_ZONE_R_ARM
body_part = ARM_RIGHT
aux_icons = list(BODY_ZONE_PRECISE_R_HAND = HANDS_PART_LAYER, "r_hand_behind" = BODY_BEHIND_LAYER)
body_damage_coeff = 0.75
held_index = 2
px_x = 6
px_y = 0
stam_heal_tick = STAM_RECOVERY_LIMB
max_stamina_damage = 50
/obj/item/bodypart/r_arm/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/r_arm/set_disabled(new_disabled)
. = ..()
if(!.)
/obj/item/bodypart/proc/get_bleed_rate()
if(status != BODYPART_ORGANIC) // maybe in the future we can bleed oil from aug parts, but not now
return
if(owner.stat < UNCONSCIOUS)
switch(disabled)
if(BODYPART_DISABLED_DAMAGE)
owner.emote("scream")
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
if(BODYPART_DISABLED_PARALYSIS)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(owner.hud_used)
var/obj/screen/inventory/hand/R = owner.hud_used.hand_slots["[held_index]"]
if(R)
R.update_icon()
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)
for(var/obj/item/embeddies in embedded_objects)
if(!embeddies.isEmbedHarmless())
bleed_rate += 0.5
/obj/item/bodypart/r_arm/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_r_arm"
animal_origin = MONKEY_BODYPART
px_x = 5
px_y = -3
for(var/thing in wounds)
var/datum/wound/W = thing
bleed_rate += W.blood_flow
/obj/item/bodypart/r_arm/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_r_arm"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/r_arm/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/l_leg
name = "left leg"
desc = "Some athletes prefer to tie their left shoelaces first for good \
luck. In this instance, it probably would not have helped."
icon_state = "default_human_l_leg"
attack_verb = list("kicked", "stomped")
max_damage = 50
body_zone = BODY_ZONE_L_LEG
body_part = LEG_LEFT
body_damage_coeff = 0.75
px_x = -2
px_y = 12
stam_heal_tick = STAM_RECOVERY_LIMB
max_stamina_damage = 50
/obj/item/bodypart/l_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/l_leg/set_disabled(new_disabled)
. = ..()
if(!. || owner.stat >= UNCONSCIOUS)
return
switch(disabled)
if(BODYPART_DISABLED_DAMAGE)
owner.emote("scream")
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
if(BODYPART_DISABLED_PARALYSIS)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
/obj/item/bodypart/l_leg/digitigrade
name = "left digitigrade leg"
use_digitigrade = FULL_DIGITIGRADE
/obj/item/bodypart/l_leg/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_l_leg"
animal_origin = MONKEY_BODYPART
px_y = 4
/obj/item/bodypart/l_leg/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_l_leg"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/l_leg/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/r_leg
name = "right leg"
desc = "You put your right leg in, your right leg out. In, out, in, out, \
shake it all about. And apparently then it detaches.\n\
The hokey pokey has certainly changed a lot since space colonisation."
// alternative spellings of 'pokey' are availible
icon_state = "default_human_r_leg"
attack_verb = list("kicked", "stomped")
max_damage = 50
body_zone = BODY_ZONE_R_LEG
body_part = LEG_RIGHT
body_damage_coeff = 0.75
px_x = 2
px_y = 12
max_stamina_damage = 50
stam_heal_tick = STAM_RECOVERY_LIMB
/obj/item/bodypart/r_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/r_leg/set_disabled(new_disabled)
. = ..()
if(!. || owner.stat >= UNCONSCIOUS)
return
switch(disabled)
if(BODYPART_DISABLED_DAMAGE)
owner.emote("scream")
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
if(BODYPART_DISABLED_PARALYSIS)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
/obj/item/bodypart/r_leg/digitigrade
name = "right digitigrade leg"
use_digitigrade = FULL_DIGITIGRADE
/obj/item/bodypart/r_leg/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_r_leg"
animal_origin = MONKEY_BODYPART
px_y = 4
/obj/item/bodypart/r_leg/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_r_leg"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/r_leg/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
return bleed_rate
@@ -15,7 +15,7 @@
if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
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)) //Damage the chest based on limb's existing damage
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>")
C.emote("scream")
SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "dismembered", /datum/mood_event/dismembered)
@@ -83,11 +83,12 @@
//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)
/obj/item/bodypart/proc/drop_limb(special, dismembered)
if(!owner)
return
var/atom/Tsec = owner.drop_location()
var/mob/living/carbon/C = owner
SEND_SIGNAL(C, COMSIG_CARBON_REMOVE_LIMB, src, dismembered)
update_limb(1)
C.bodyparts -= src
@@ -95,6 +96,15 @@
C.dropItemToGround(owner.get_item_for_held_index(held_index), 1)
C.hand_bodyparts[held_index] = null
for(var/thing in scars)
var/datum/scar/S = thing
S.victim = null
LAZYREMOVE(owner.all_scars, S)
for(var/thing in wounds)
var/datum/wound/W = thing
W.remove_wound(TRUE)
owner = null
for(var/X in C.surgeries) //if we had an ongoing surgery on that limb, we stop it.
@@ -298,6 +308,15 @@
for(var/obj/item/organ/O in contents)
O.Insert(C)
for(var/thing in scars)
var/datum/scar/S = thing
S.victim = C
LAZYADD(C.all_scars, thing)
for(var/i in wounds)
var/datum/wound/W = i
W.apply_wound(src, TRUE)
update_bodypart_damage_state()
update_disabled()
+4
View File
@@ -35,6 +35,10 @@
//If the head is a special sprite
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()))
return FALSE
+10
View File
@@ -10,6 +10,16 @@
if(L.body_zone == zone)
return L
///Get the bodypart for whatever hand we have active, Only relevant for carbons
/mob/proc/get_active_hand()
return FALSE
/mob/living/carbon/get_active_hand()
var/which_hand = BODY_ZONE_PRECISE_L_HAND
if(!(active_hand_index % 2))
which_hand = BODY_ZONE_PRECISE_R_HAND
return get_bodypart(check_zone(which_hand))
/mob/living/carbon/has_hand_for_held_index(i)
if(i)
var/obj/item/bodypart/L = hand_bodyparts[i]
+307
View File
@@ -0,0 +1,307 @@
/obj/item/bodypart/chest
name = BODY_ZONE_CHEST
desc = "It's impolite to stare at a person's chest."
icon_state = "default_human_chest"
max_damage = 200
body_zone = BODY_ZONE_CHEST
body_part = CHEST
px_x = 0
px_y = 0
stam_damage_coeff = 1
max_stamina_damage = 120
var/obj/item/cavity_item
specific_locations = list("upper chest", "lower abdomen", "midsection", "collarbone", "lower back")
wound_resistance = 10
/obj/item/bodypart/chest/can_dismember(obj/item/I)
if(!((owner.stat == DEAD) || owner.InFullCritical()))
return FALSE
return ..()
/obj/item/bodypart/chest/Destroy()
QDEL_NULL(cavity_item)
return ..()
/obj/item/bodypart/chest/drop_organs(mob/user, violent_removal)
if(cavity_item)
cavity_item.forceMove(drop_location())
cavity_item = null
..()
/obj/item/bodypart/chest/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_chest"
animal_origin = MONKEY_BODYPART
wound_resistance = -10
/obj/item/bodypart/chest/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_chest"
dismemberable = 0
max_damage = 500
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/chest/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/chest/larva
icon = 'icons/mob/animal_parts.dmi'
icon_state = "larva_chest"
dismemberable = 0
max_damage = 50
animal_origin = LARVA_BODYPART
/obj/item/bodypart/l_arm
name = "left arm"
desc = "Did you know that the word 'sinister' stems originally from the \
Latin 'sinestra' (left hand), because the left hand was supposed to \
be possessed by the devil? This arm appears to be possessed by no \
one though."
icon_state = "default_human_l_arm"
attack_verb = list("slapped", "punched")
max_damage = 50
max_stamina_damage = 50
body_zone = BODY_ZONE_L_ARM
body_part = ARM_LEFT
aux_zone = BODY_ZONE_PRECISE_L_HAND
aux_layer = HANDS_PART_LAYER
body_damage_coeff = 0.75
held_index = 1
px_x = -6
px_y = 0
specific_locations = list("outer left forearm", "inner left wrist", "left elbow", "left bicep", "left shoulder")
/obj/item/bodypart/l_arm/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/l_arm/set_disabled(new_disabled)
. = ..()
if(!.)
return
if(disabled == BODYPART_DISABLED_DAMAGE)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
else if(disabled == BODYPART_DISABLED_PARALYSIS)
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(owner.hud_used)
var/obj/screen/inventory/hand/L = owner.hud_used.hand_slots["[held_index]"]
if(L)
L.update_icon()
/obj/item/bodypart/l_arm/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_l_arm"
animal_origin = MONKEY_BODYPART
wound_resistance = -10
px_x = -5
px_y = -3
/obj/item/bodypart/l_arm/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_l_arm"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/l_arm/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/r_arm
name = "right arm"
desc = "Over 87% of humans are right handed. That figure is much lower \
among humans missing their right arm."
icon_state = "default_human_r_arm"
attack_verb = list("slapped", "punched")
max_damage = 50
body_zone = BODY_ZONE_R_ARM
body_part = ARM_RIGHT
aux_zone = BODY_ZONE_PRECISE_R_HAND
aux_layer = HANDS_PART_LAYER
body_damage_coeff = 0.75
held_index = 2
px_x = 6
px_y = 0
max_stamina_damage = 50
specific_locations = list("outer right forearm", "inner right wrist", "right elbow", "right bicep", "right shoulder")
/obj/item/bodypart/r_arm/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/r_arm/set_disabled(new_disabled)
. = ..()
if(!.)
return
if(disabled == BODYPART_DISABLED_DAMAGE)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
else if(disabled == BODYPART_DISABLED_PARALYSIS)
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
if(held_index)
owner.dropItemToGround(owner.get_item_for_held_index(held_index))
if(owner.hud_used)
var/obj/screen/inventory/hand/R = owner.hud_used.hand_slots["[held_index]"]
if(R)
R.update_icon()
/obj/item/bodypart/r_arm/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_r_arm"
animal_origin = MONKEY_BODYPART
wound_resistance = -10
px_x = 5
px_y = -3
/obj/item/bodypart/r_arm/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_r_arm"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/r_arm/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/l_leg
name = "left leg"
desc = "Some athletes prefer to tie their left shoelaces first for good \
luck. In this instance, it probably would not have helped."
icon_state = "default_human_l_leg"
attack_verb = list("kicked", "stomped")
max_damage = 50
body_zone = BODY_ZONE_L_LEG
body_part = LEG_LEFT
body_damage_coeff = 0.75
px_x = -2
px_y = 12
max_stamina_damage = 50
specific_locations = list("inner left thigh", "outer left calf", "outer left hip", " left kneecap", "lower left shin")
/obj/item/bodypart/l_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/l_leg/set_disabled(new_disabled)
. = ..()
if(!.)
return
if(disabled == BODYPART_DISABLED_DAMAGE)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
else if(disabled == BODYPART_DISABLED_PARALYSIS)
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
/obj/item/bodypart/l_leg/digitigrade
name = "left digitigrade leg"
use_digitigrade = FULL_DIGITIGRADE
/obj/item/bodypart/l_leg/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_l_leg"
animal_origin = MONKEY_BODYPART
wound_resistance = -10
px_y = 4
/obj/item/bodypart/l_leg/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_l_leg"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/l_leg/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/r_leg
name = "right leg"
desc = "You put your right leg in, your right leg out. In, out, in, out, \
shake it all about. And apparently then it detaches.\n\
The hokey pokey has certainly changed a lot since space colonisation."
// alternative spellings of 'pokey' are availible
icon_state = "default_human_r_leg"
attack_verb = list("kicked", "stomped")
max_damage = 50
body_zone = BODY_ZONE_R_LEG
body_part = LEG_RIGHT
body_damage_coeff = 0.75
px_x = 2
px_y = 12
max_stamina_damage = 50
specific_locations = list("inner right thigh", "outer right calf", "outer right hip", "right kneecap", "lower right shin")
/obj/item/bodypart/r_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
return BODYPART_DISABLED_PARALYSIS
return ..()
/obj/item/bodypart/r_leg/set_disabled(new_disabled)
. = ..()
if(!.)
return
if(disabled == BODYPART_DISABLED_DAMAGE)
if(owner.stat < UNCONSCIOUS)
owner.emote("scream")
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>Your [name] is too damaged to function!</span>")
else if(disabled == BODYPART_DISABLED_PARALYSIS)
if(owner.stat < DEAD)
to_chat(owner, "<span class='userdanger'>You can't feel your [name]!</span>")
/obj/item/bodypart/r_leg/digitigrade
name = "right digitigrade leg"
use_digitigrade = FULL_DIGITIGRADE
/obj/item/bodypart/r_leg/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_r_leg"
animal_origin = MONKEY_BODYPART
wound_resistance = -10
px_y = 4
/obj/item/bodypart/r_leg/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_r_leg"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 100
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/r_leg/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
+142
View File
@@ -0,0 +1,142 @@
/////BONE FIXING SURGERIES//////
///// Repair Hairline Fracture (Severe)
/datum/surgery/repair_bone_hairline
name = "Repair bone fracture (hairline)"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/repair_bone_hairline, /datum/surgery_step/close)
target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
targetable_wound = /datum/wound/brute/bone/severe
/datum/surgery/repair_bone_hairline/can_start(mob/living/user, mob/living/carbon/target)
if(..())
var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected)
return(targeted_bodypart.get_wound_type(targetable_wound))
///// Repair Compound Fracture (Critical)
/datum/surgery/repair_bone_compound
name = "Repair Compound Fracture"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/reset_compound_fracture, /datum/surgery_step/repair_bone_compound, /datum/surgery_step/close)
target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
targetable_wound = /datum/wound/brute/bone/critical
/datum/surgery/repair_bone_compound/can_start(mob/living/user, mob/living/carbon/target)
if(..())
var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected)
return(targeted_bodypart.get_wound_type(targetable_wound))
//SURGERY STEPS
///// Repair Hairline Fracture (Severe)
/datum/surgery_step/repair_bone_hairline
name = "repair hairline fracture (bonesetter/bone gel/tape)"
implements = list(/obj/item/bonesetter = 100, /obj/item/stack/medical/bone_gel = 100, /obj/item/stack/sticky_tape/surgical = 100, /obj/item/stack/sticky_tape/super = 50, /obj/item/stack/sticky_tape = 30)
time = 40
experience_given = MEDICAL_SKILL_MEDIUM
/datum/surgery_step/repair_bone_hairline/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(surgery.operated_wound)
display_results(user, target, "<span class='notice'>You begin to repair the fracture in [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to repair the fracture in [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to repair the fracture in [target]'s [parse_zone(user.zone_selected)].</span>")
else
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>")
/datum/surgery_step/repair_bone_hairline/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
if(surgery.operated_wound)
if(istype(tool, /obj/item/stack))
var/obj/item/stack/used_stack = tool
used_stack.use(1)
display_results(user, target, "<span class='notice'>You successfully repair the fracture in [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] successfully repairs the fracture in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully repairs the fracture in [target]'s [parse_zone(target_zone)]!</span>")
log_combat(user, target, "repaired a hairline fracture in", addition="INTENT: [uppertext(user.a_intent)]")
qdel(surgery.operated_wound)
else
to_chat(user, "<span class='warning'>[target] has no hairline fracture there!</span>")
return ..()
/datum/surgery_step/repair_bone_hairline/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
..()
if(istype(tool, /obj/item/stack))
var/obj/item/stack/used_stack = tool
used_stack.use(1)
///// Reset Compound Fracture (Crticial)
/datum/surgery_step/reset_compound_fracture
name = "reset bone"
implements = list(/obj/item/bonesetter = 100, /obj/item/stack/sticky_tape/surgical = 60, /obj/item/stack/sticky_tape/super = 40, /obj/item/stack/sticky_tape = 20)
time = 40
experience_given = MEDICAL_SKILL_MEDIUM
/datum/surgery_step/reset_compound_fracture/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(surgery.operated_wound)
display_results(user, target, "<span class='notice'>You begin to reset the bone in [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to reset the bone in [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to reset the bone in [target]'s [parse_zone(user.zone_selected)].</span>")
else
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>")
/datum/surgery_step/reset_compound_fracture/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
if(surgery.operated_wound)
if(istype(tool, /obj/item/stack))
var/obj/item/stack/used_stack = tool
used_stack.use(1)
display_results(user, target, "<span class='notice'>You successfully reset the bone in [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] successfully resets the bone in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully resets the bone in [target]'s [parse_zone(target_zone)]!</span>")
log_combat(user, target, "reset a compound fracture in", addition="INTENT: [uppertext(user.a_intent)]")
else
to_chat(user, "<span class='warning'>[target] has no compound fracture there!</span>")
return ..()
/datum/surgery_step/reset_compound_fracture/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
..()
if(istype(tool, /obj/item/stack))
var/obj/item/stack/used_stack = tool
used_stack.use(1)
///// Repair Compound Fracture (Crticial)
/datum/surgery_step/repair_bone_compound
name = "repair compound fracture (bone gel/tape)"
implements = list(/obj/item/stack/medical/bone_gel = 100, /obj/item/stack/sticky_tape/surgical = 100, /obj/item/stack/sticky_tape/super = 50, /obj/item/stack/sticky_tape = 30)
time = 40
experience_given = MEDICAL_SKILL_MEDIUM
/datum/surgery_step/repair_bone_compound/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(surgery.operated_wound)
display_results(user, target, "<span class='notice'>You begin to repair the fracture in [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to repair the fracture in [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to repair the fracture in [target]'s [parse_zone(user.zone_selected)].</span>")
else
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>")
/datum/surgery_step/repair_bone_compound/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
if(surgery.operated_wound)
if(istype(tool, /obj/item/stack))
var/obj/item/stack/used_stack = tool
used_stack.use(1)
display_results(user, target, "<span class='notice'>You successfully repair the fracture in [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] successfully repairs the fracture in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully repairs the fracture in [target]'s [parse_zone(target_zone)]!</span>")
log_combat(user, target, "repaired a compound fracture in", addition="INTENT: [uppertext(user.a_intent)]")
qdel(surgery.operated_wound)
else
to_chat(user, "<span class='warning'>[target] has no compound fracture there!</span>")
return ..()
/datum/surgery_step/repair_bone_compound/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
..()
if(istype(tool, /obj/item/stack))
var/obj/item/stack/used_stack = tool
used_stack.use(1)
+108
View File
@@ -0,0 +1,108 @@
/////BURN FIXING SURGERIES//////
///// Debride burnt flesh
/datum/surgery/debride
name = "Debride infected flesh"
steps = list(/datum/surgery_step/debride, /datum/surgery_step/dress)
target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
targetable_wound = /datum/wound/burn
/datum/surgery/debride/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/burn_wound = targeted_bodypart.get_wound_type(targetable_wound)
return(burn_wound && burn_wound.infestation > 0)
//SURGERY STEPS
///// Debride
/datum/surgery_step/debride
name = "excise infection"
implements = list(TOOL_HEMOSTAT = 100, TOOL_SCALPEL = 85, TOOL_SAW = 60, TOOL_WIRECUTTER = 40)
time = 30
repeatable = TRUE
experience_given = MEDICAL_SKILL_MEDIUM
/datum/surgery_step/debride/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(surgery.operated_wound)
var/datum/wound/burn/burn_wound = surgery.operated_wound
if(burn_wound.infestation <= 0)
to_chat(user, "<span class='notice'>[target]'s [parse_zone(user.zone_selected)] has no infected flesh to remove!</span>")
surgery.status++
repeatable = FALSE
return
display_results(user, target, "<span class='notice'>You begin to excise infected flesh from [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to excise infected flesh from [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to excise infected flesh from [target]'s [parse_zone(user.zone_selected)].</span>")
else
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>")
/datum/surgery_step/debride/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/burn/burn_wound = surgery.operated_wound
if(burn_wound)
display_results(user, target, "<span class='notice'>You successfully excise some of the infected flesh from [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] successfully excises some of the infected flesh from [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully excises some of the infected flesh from [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)
burn_wound.infestation -= 0.5
burn_wound.sanitization += 0.5
if(burn_wound.infestation <= 0)
repeatable = FALSE
else
to_chat(user, "<span class='warning'>[target] has no infected flesh there!</span>")
return ..()
/datum/surgery_step/debride/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 carve away some of the healthy flesh from [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] carves away some of the healthy flesh from [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] carves away some of the healthy flesh from [target]'s [parse_zone(target_zone)]!</span>")
surgery.operated_bodypart.receive_damage(brute=rand(4,8), sharpness=TRUE)
/datum/surgery_step/debride/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
if(!..())
return
var/datum/wound/burn/burn_wound = surgery.operated_wound
while(burn_wound && burn_wound.infestation > 0.25)
if(!..())
break
///// Dressing burns
/datum/surgery_step/dress
name = "bandage burns"
implements = list(/obj/item/stack/medical/gauze = 100, /obj/item/stack/sticky_tape/surgical = 100)
time = 40
experience_given = MEDICAL_SKILL_MEDIUM
/datum/surgery_step/dress/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/datum/wound/burn/burn_wound = surgery.operated_wound
if(burn_wound)
display_results(user, target, "<span class='notice'>You begin to dress the burns on [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to dress the burns on [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to dress the burns on [target]'s [parse_zone(user.zone_selected)].</span>")
else
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>")
/datum/surgery_step/dress/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/burn/burn_wound = surgery.operated_wound
if(burn_wound)
display_results(user, target, "<span class='notice'>You successfully wrap [target]'s [parse_zone(target_zone)] with [tool].</span>",
"<span class='notice'>[user] successfully wraps [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully wraps [target]'s [parse_zone(target_zone)]!</span>")
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)
else
to_chat(user, "<span class='warning'>[target] has no burns there!</span>")
return ..()
/datum/surgery_step/dress/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
..()
if(istype(tool, /obj/item/stack))
var/obj/item/stack/used_stack = tool
used_stack.use(1)
+6 -3
View File
@@ -31,7 +31,8 @@
display_results(user, target, "<span class='notice'>Blood pools around the incision in [H]'s heart.</span>",
"Blood pools around the incision in [H]'s heart.",
"")
H.bleed_rate += 10
var/obj/item/bodypart/BP = H.get_bodypart(target_zone)
BP.generic_bleedstacks += 10
H.adjustBruteLoss(10)
return TRUE
@@ -41,7 +42,8 @@
display_results(user, target, "<span class='warning'>You screw up, cutting too deeply into the heart!</span>",
"<span class='warning'>[user] screws up, causing blood to spurt out of [H]'s chest!</span>",
"<span class='warning'>[user] screws up, causing blood to spurt out of [H]'s chest!</span>")
H.bleed_rate += 20
var/obj/item/bodypart/BP = H.get_bodypart(target_zone)
BP.generic_bleedstacks += 10
H.adjustOrganLoss(ORGAN_SLOT_HEART, 10)
H.adjustBruteLoss(10)
@@ -73,5 +75,6 @@
"<span class='warning'>[user] screws up, causing blood to spurt out of [H]'s chest profusely!</span>",
"<span class='warning'>[user] screws up, causing blood to spurt out of [H]'s chest profusely!</span>")
H.adjustOrganLoss(ORGAN_SLOT_HEART, 20)
H.bleed_rate += 30
var/obj/item/bodypart/BP = H.get_bodypart(target_zone)
BP.generic_bleedstacks += 30
return FALSE
@@ -78,7 +78,7 @@
"[user] dissects [target]!")
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points_earned))
var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
target.apply_damage(80, BRUTE, L)
target.apply_damage(80, BRUTE, L, wound_bonus=CANT_WOUND)
ADD_TRAIT(target, TRAIT_DISSECTED, "[surgery.name]")
repeatable = FALSE
return TRUE
@@ -89,7 +89,7 @@
"[user] dissects [target], but looks a little dissapointed.")
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (round(check_value(target, surgery) * 0.01))))
var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
target.apply_damage(80, BRUTE, L)
target.apply_damage(80, BRUTE, L, wound_bonus=CANT_WOUND)
return TRUE
/datum/surgery/advanced/experimental_dissection/adv
+1 -1
View File
@@ -87,7 +87,7 @@
urdamageamt_brute += round((target.getBruteLoss()/ (missinghpbonus*2)),0.1)
urdamageamt_burn += round((target.getFireLoss()/ (missinghpbonus*2)),0.1)
target.take_bodypart_damage(urdamageamt_brute, urdamageamt_burn)
target.take_bodypart_damage(urdamageamt_brute, urdamageamt_burn, wound_bonus=CANT_WOUND)
return FALSE
/***************************BRUTE***************************/
+10 -4
View File
@@ -21,7 +21,9 @@
display_results(user, target, "<span class='notice'>Blood pools around the incision in [H]'s [parse_zone(target_zone)].</span>",
"Blood pools around the incision in [H]'s [parse_zone(target_zone)].",
"")
H.bleed_rate += 3
var/obj/item/bodypart/BP = target.get_bodypart(target_zone)
if(BP)
BP.generic_bleedstacks += 10
return TRUE
/datum/surgery_step/incise/nobleed //silly friendly!
@@ -50,7 +52,9 @@
target.heal_bodypart_damage(20,0)
if (ishuman(target))
var/mob/living/carbon/human/H = target
H.bleed_rate = max( (H.bleed_rate - 3), 0)
var/obj/item/bodypart/BP = H.get_bodypart(target_zone)
if(BP)
BP.generic_bleedstacks -= 3
return ..()
//retract skin
/datum/surgery_step/retract_skin
@@ -86,7 +90,9 @@
target.heal_bodypart_damage(45,0)
if (ishuman(target))
var/mob/living/carbon/human/H = target
H.bleed_rate = max( (H.bleed_rate - 3), 0)
var/obj/item/bodypart/BP = H.get_bodypart(target_zone)
if(BP)
BP.generic_bleedstacks -= 3
return ..()
//saw bone
/datum/surgery_step/saw
@@ -100,7 +106,7 @@
"[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].")
/datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
target.apply_damage(50, BRUTE, "[target_zone]")
target.apply_damage(50, BRUTE, "[target_zone]", wound_bonus=CANT_WOUND)
display_results(user, target, "<span class='notice'>You saw [target]'s [parse_zone(target_zone)] open.</span>",
"[user] saws [target]'s [parse_zone(target_zone)] open!",
"[user] saws [target]'s [parse_zone(target_zone)] open!")
+3 -2
View File
@@ -318,13 +318,14 @@
cooldown = COOLDOWN_DAMAGE
for(var/V in listeners)
var/mob/living/L = V
L.apply_damage(15 * power_multiplier, def_zone = BODY_ZONE_CHEST)
L.apply_damage(15 * power_multiplier, def_zone = BODY_ZONE_CHEST, wound_bonus=CANT_WOUND)
//BLEED
else if((findtext(message, bleed_words)))
cooldown = COOLDOWN_DAMAGE
for(var/mob/living/carbon/human/H in listeners)
H.bleed_rate += (5 * power_multiplier)
var/obj/item/bodypart/BP = pick(H.bodyparts)
BP.generic_bleedstacks += 5
//FIRE
else if((findtext(message, burn_words)))
+7
View File
@@ -18,6 +18,8 @@
var/lying_required = TRUE //Does the vicitm needs to be lying down.
var/requires_tech = FALSE
var/replaced_by
var/datum/wound/operated_wound //The actual wound datum instance we're targeting
var/datum/wound/targetable_wound //The wound type this surgery targets
/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart)
..()
@@ -28,8 +30,13 @@
location = surgery_location
if(surgery_bodypart)
operated_bodypart = surgery_bodypart
if(targetable_wound)
operated_wound = operated_bodypart.get_wound_type(targetable_wound)
operated_wound.attached_surgery = src
/datum/surgery/Destroy()
if(operated_wound)
operated_wound.attached_surgery = null
if(target)
target.surgeries -= src
target = null