more changes
This commit is contained in:
+194
-290
@@ -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()
|
||||
|
||||
|
||||
@@ -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,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]
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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***************************/
|
||||
|
||||
@@ -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!")
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user