Merge branch 'master' into cool-ipcs

This commit is contained in:
Timothy Teakettle
2020-09-16 05:09:02 +01:00
2723 changed files with 184768 additions and 215036 deletions
+11 -3
View File
@@ -25,12 +25,12 @@
return TRUE
/datum/surgery_step/revive
name = "electrically stimulate brain"
implements = list(/obj/item/twohanded/shockpaddles = 100, /obj/item/abductor/gizmo = 100, /obj/item/melee/baton = 75, /obj/item/organ/cyberimp/arm/baton = 75, /obj/item/organ/cyberimp/arm/gun/taser = 60, /obj/item/gun/energy/e_gun/advtaser = 60, /obj/item/gun/energy/taser = 60)
implements = list(/obj/item/shockpaddles = 100, /obj/item/abductor/gizmo = 100, /obj/item/melee/baton = 75, /obj/item/organ/cyberimp/arm/baton = 75, /obj/item/organ/cyberimp/arm/gun/taser = 60, /obj/item/gun/energy/e_gun/advtaser = 60, /obj/item/gun/energy/taser = 60)
time = 120
/datum/surgery_step/revive/tool_check(mob/user, obj/item/tool)
. = TRUE
if(istype(tool, /obj/item/twohanded/shockpaddles))
var/obj/item/twohanded/shockpaddles/S = tool
if(istype(tool, /obj/item/shockpaddles))
var/obj/item/shockpaddles/S = tool
if((S.req_defib && !S.defib.powered) || !S.wielded || S.cooldown || S.busy)
to_chat(user, "<span class='warning'>You need to wield both paddles, and [S.defib] must be powered!</span>")
return FALSE
@@ -60,6 +60,7 @@
playsound(get_turf(target), 'sound/magic/lightningbolt.ogg', 50, 1)
target.adjustOxyLoss(-50, 0)
target.updatehealth()
var/tplus = world.time - target.timeofdeath
if(target.revive())
user.visible_message("...[target] wakes up, alive and aware!", "<span class='notice'><b>IT'S ALIVE!</b></span>")
target.visible_message("...[target] wakes up, alive and aware!")
@@ -68,6 +69,13 @@
for(var/obj/item/organ/O in target.internal_organs)//zap those buggers back to life!
if(O.organ_flags & ORGAN_FAILING)
O.applyOrganDamage(-5)
var/list/policies = CONFIG_GET(keyed_list/policyconfig)
var/timelimit = CONFIG_GET(number/defib_cmd_time_limit)
var/late = timelimit && (tplus > timelimit)
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
if(policy)
to_chat(target, policy)
target.log_message("revived using surgical revival, [tplus] deciseconds from time of death, considered [late? "late" : "memory-intact"] revival under configured policy limits.", LOG_GAME)
return TRUE
else
user.visible_message("...[target.p_they()] convulses, then lies still.")
+1 -1
View File
@@ -6,7 +6,7 @@
requires_bodypart_type = 0
/datum/surgery_step/sever_limb
name = "sever limb"
implements = list(TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/transforming/energy/sword/cyborg/saw = 100, /obj/item/melee/arm_blade = 80, /obj/item/twohanded/required/chainsaw = 80, /obj/item/mounted_chainsaw = 80, /obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25)
implements = list(TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/transforming/energy/sword/cyborg/saw = 100, /obj/item/melee/arm_blade = 80, /obj/item/chainsaw = 80, /obj/item/mounted_chainsaw = 80, /obj/item/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25)
time = 64
/datum/surgery_step/sever_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
@@ -73,6 +73,28 @@
var/render_like_organic = FALSE // forces limb to render as if it were an organic limb
/// 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
/// So we know if we need to scream if this limb hits max damage
var/last_maxed
/// How much generic bleedstacks we have on this bodypart
var/generic_bleedstacks
/// If we have a gauze wrapping currently applied (not including splints)
var/obj/item/stack/current_gauze
/obj/item/bodypart/examine(mob/user)
. = ..()
if(brute_dam > DAMAGE_PRECISION)
@@ -131,8 +153,20 @@
var/turf/T = get_turf(src)
if(status != BODYPART_ROBOTIC)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
for(var/obj/item/I in src)
I.forceMove(T)
if(current_gauze)
QDEL_NULL(current_gauze)
for(var/obj/item/organ/drop_organ in get_organs())
drop_organ.transfer_to_limb(src, owner)
///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have
/obj/item/bodypart/proc/get_organs()
if(!owner)
return
. = list()
for(var/i in owner.internal_organs) //internal organs inside the dismembered limb are dropped.
var/obj/item/organ/organ_check = i
if(check_zone(organ_check.zone) == body_zone)
. += organ_check
/obj/item/bodypart/proc/consider_processing()
if(stamina_dam > DAMAGE_PRECISION)
@@ -151,7 +185,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 = SHARP_NONE) // 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)
@@ -165,20 +199,82 @@
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
/*
// START WOUND HANDLING
*/
// what kind of wounds we're gonna roll for, take the greater between brute and burn, then if it's brute, we subdivide based on sharpness
var/wounding_type = (brute > burn ? WOUND_BLUNT : WOUND_BURN)
var/wounding_dmg = max(brute, burn)
var/mangled_state = get_mangled_state()
var/bio_state = owner.get_biological_state()
var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
if(wounding_type == WOUND_BLUNT)
if(sharpness == SHARP_EDGED)
wounding_type = WOUND_SLASH
else if(sharpness == SHARP_POINTY)
wounding_type = WOUND_PIERCE
//Handling for bone only/flesh only(none right now)/flesh and bone targets
switch(bio_state)
// if we're bone only, all cutting attacks go straight to the bone
if(BIO_JUST_BONE)
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.5)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.75)
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
// note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
// standard humanoids
if(BIO_FLESH_BONE)
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area
if(wounding_type == WOUND_PIERCE && !easy_dismember)
wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
wounding_type = WOUND_BLUNT
else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
// now we have our wounding_type and are ready to carry on with wounds and dealing the actual damage
if(owner && wounding_dmg >= WOUND_MINIMUM_DAMAGE && wound_bonus != CANT_WOUND)
check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
for(var/i in wounds)
var/datum/wound/iter_wound = i
iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus)
/*
// END WOUND HANDLING
*/
//back to our regularly scheduled program, we now actually apply damage if there's room below limb damage cap
var/can_inflict = max_damage - get_damage()
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
brute_dam += brute
burn_dam += burn
@@ -198,6 +294,165 @@
update_disabled()
return update_bodypart_damage_state()
/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds
/obj/item/bodypart/proc/painless_wound_roll(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus, sharpness=SHARP_NONE)
if(!owner || phantom_wounding_dmg <= WOUND_MINIMUM_DAMAGE || wound_bonus == CANT_WOUND)
return
var/mangled_state = get_mangled_state()
var/bio_state = owner.get_biological_state()
var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
if(wounding_type == WOUND_BLUNT)
if(sharpness == SHARP_EDGED)
wounding_type = WOUND_SLASH
else if(sharpness == SHARP_POINTY)
wounding_type = WOUND_PIERCE
//Handling for bone only/flesh only(none right now)/flesh and bone targets
switch(bio_state)
// if we're bone only, all cutting attacks go straight to the bone
if(BIO_JUST_BONE)
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
phantom_wounding_dmg *= (easy_dismember ? 1 : 0.5)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75)
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
return
// note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
// standard humanoids
if(BIO_FLESH_BONE)
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
phantom_wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area
if(wounding_type == WOUND_PIERCE && !easy_dismember)
phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
wounding_type = WOUND_BLUNT
else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
return
check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)
/**
* check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria
*
* We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [/obj/item/bodypart/proc/check_wounding_mods], then go down the list from most severe to least severe wounds in that category.
* We can promote a wound from a lesser to a higher severity this way, but we give up if we have a wound of the given type and fail to roll a higher severity, so no sidegrades/downgrades
*
* Arguments:
* * woundtype- Either WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE, or WOUND_BURN based on the attack type.
* * damage- How much damage is tied to this attack, since wounding potential scales with damage in an attack (see: WOUND_DAMAGE_EXPONENT)
* * wound_bonus- The wound_bonus of an attack
* * bare_wound_bonus- The bare_wound_bonus of an attack
*/
/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
else
damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE)
var/base_roll = rand(max(damage/1.5,25), 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 = GLOB.global_wound_types[woundtype]
// quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow
if(ishuman(owner))
var/mob/living/carbon/human/human_wearer = owner
var/list/clothing = human_wearer.clothingonpart(src)
for(var/i in clothing)
var/obj/item/clothing/clothes_check = i
// unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
if(clothes_check.armor.getRating("wound"))
bare_wound_bonus = 0
break
//cycle through the wounds of the relevant category from the most severe down
for(var/PW in wounds_checking)
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)
var/datum/wound/new_wound
if(replaced_wound)
new_wound = replaced_wound.replace_wound(possible_wound)
log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) // dismembering wounds are logged in the apply_wound() for loss wounds since they delete themselves immediately, these will be immediately returned
else
new_wound = new possible_wound
new_wound.apply_wound(src)
log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll)
return new_wound
// try forcing a specific wound, but only if there isn't already a wound of that severity or greater for that type on this bodypart
/obj/item/bodypart/proc/force_wound_upwards(specific_woundtype, smited = FALSE)
var/datum/wound/potential_wound = specific_woundtype
for(var/i in wounds)
var/datum/wound/existing_wound = i
if(existing_wound.wound_type == initial(potential_wound.wound_type))
if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force
existing_wound.replace_wound(potential_wound, smited)
return
var/datum/wound/new_wound = new potential_wound
new_wound.apply_wound(src, smited = smited)
/**
* check_wounding_mods() is where we handle the various modifiers of a wound roll
*
* A short list of things we consider: any armor a human target may be wearing, and if they have no wound armor on the limb, if we have a bare_wound_bonus to apply, plus the plain wound_bonus
* We also flick through all of the wounds we currently have on this limb and add their threshold penalties, so that having lots of bad wounds makes you more liable to get hurt worse
* Lastly, we add the inherent wound_resistance variable the bodypart has (heads and chests are slightly harder to wound), and a small bonus if the limb is already disabled
*
* Arguments:
* * It's the same ones on [receive_damage]
*/
/obj/item/bodypart/proc/check_woundings_mods(wounding_type, damage, wound_bonus, bare_wound_bonus)
var/armor_ablation = 0
var/injury_mod = 0
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_SLASH)
C.take_damage_zone(body_zone, damage, BRUTE, armour_penetration)
else if(wounding_type == WOUND_BURN && damage >= 10) // lazy way to block freezing from shredding clothes without adding another var onto apply_damage()
C.take_damage_zone(body_zone, damage, BURN, armour_penetration)
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(get_damage(TRUE) >= max_damage)
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)
@@ -229,16 +484,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(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0%
if(!last_maxed)
owner.emote("scream")
last_maxed = TRUE
if(!is_organic_limb() || stamina_dam >= max_damage)
return BODYPART_DISABLED_DAMAGE
else if(disabled && (get_damage(TRUE) <= (max_damage * 0.8))) // reenabled at 80% now instead of 50% as of wounds update
last_maxed = FALSE
return BODYPART_NOT_DISABLED
else
return BODYPART_NOT_DISABLED
@@ -253,9 +521,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()
@@ -330,22 +600,21 @@
var/datum/species/S = H.dna.species
base_bp_icon = S?.icon_limbs || DEFAULT_BODYPART_ICON
species_id = S.limbs_id
species_id = S.mutant_bodyparts["limbs_id"]
species_flags_list = H.dna.species.species_traits
//body marking memes
var/list/colorlist = list()
colorlist.Cut()
colorlist += ReadRGB("[H.dna.features["mcolor"]]0")
colorlist += ReadRGB("[H.dna.features["mcolor2"]]0")
colorlist += ReadRGB("[H.dna.features["mcolor3"]]0")
colorlist += ReadRGB("[H.dna.features["mcolor"]]00")
colorlist += ReadRGB("[H.dna.features["mcolor2"]]00")
colorlist += ReadRGB("[H.dna.features["mcolor3"]]00")
colorlist += list(0,0,0, S.hair_alpha)
for(var/index=1, index<=colorlist.len, index++)
colorlist[index] = colorlist[index]/255
if(S.use_skintones)
skin_tone = H.skin_tone
base_bp_icon = (base_bp_icon == DEFAULT_BODYPART_ICON) ? DEFAULT_BODYPART_ICON_ORGANIC : base_bp_icon
else
skin_tone = ""
@@ -358,13 +627,9 @@
species_color = S.fixed_mut_color
else
species_color = H.dna.features["mcolor"]
base_bp_icon = (base_bp_icon == DEFAULT_BODYPART_ICON) ? DEFAULT_BODYPART_ICON_ORGANIC : base_bp_icon
else
species_color = ""
if(base_bp_icon != DEFAULT_BODYPART_ICON)
color_src = mut_colors ? MUTCOLORS : ((H.dna.skin_tone_override && S.use_skintones == USE_SKINTONES_GRAYSCALE_CUSTOM) ? CUSTOM_SKINTONE : SKINTONE)
if(S.mutant_bodyparts["legs"])
if(body_zone == BODY_ZONE_L_LEG || body_zone == BODY_ZONE_R_LEG)
if(DIGITIGRADE in S.species_traits)
@@ -384,11 +649,16 @@
body_markings = "plain"
aux_marking = "plain"
markings_color = list(colorlist)
else
body_markings = null
aux_marking = null
if(species_id in GLOB.greyscale_limb_types) //should they have greyscales?
base_bp_icon = DEFAULT_BODYPART_ICON_ORGANIC
if(base_bp_icon != DEFAULT_BODYPART_ICON)
color_src = mut_colors ? MUTCOLORS : ((H.dna.skin_tone_override && S.use_skintones == USE_SKINTONES_GRAYSCALE_CUSTOM) ? CUSTOM_SKINTONE : SKINTONE)
if(!dropping_limb && H.dna.check_mutation(HULK))
mutation_color = "00aa00"
else
@@ -584,293 +854,86 @@
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 = 4
/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/i in wounds)
if(istype(i, checking_type))
return i
/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
/**
* update_wounds() is called whenever a wound is gained or lost on this bodypart, as well as if there's a change of some kind on a bone wound possibly changing disabled status
*
* Covers tabulating the damage multipliers we have from wounds (burn specifically), as well as deleting our gauze wrapping if we don't have any wounds that can use bandaging
*
* Arguments:
* * replaced- If true, this is being called from the remove_wound() of a wound that's being replaced, so the bandage that already existed is still relevant, but the new wound hasn't been added yet
*/
/obj/item/bodypart/proc/update_wounds(replaced = FALSE)
var/dam_mul = 1 //initial(wound_damage_multiplier)
// we can only have one wound per type, but remember there's multiple types
// we can (normally) only have one wound per type, but remember there's multiple types (smites like :B:loodless can generate multiple cuts on a limb)
for(var/i in wounds)
var/datum/wound/iter_wound = i
dam_mul *= iter_wound.damage_mulitplier_penalty
/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
if(!LAZYLEN(wounds) && current_gauze && !replaced)
owner.visible_message("<span class='notice'>\The [current_gauze] on [owner]'s [name] fall away.</span>", "<span class='notice'>The [current_gauze] on your [name] fall away.</span>")
QDEL_NULL(current_gauze)
wound_damage_multiplier = dam_mul
update_disabled()
/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 = 4
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++
//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
if(owner.mobility_flags & ~MOBILITY_STAND)
bleed_rate *= 0.75
return bleed_rate
/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 = 4
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)
/**
* apply_gauze() is used to- well, apply gauze to a bodypart
*
* As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons).
* The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze
* applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared,
* the gauze falls off.
*
* Arguments:
* * gauze- Just the gauze stack we're taking a sheet from to apply here
*/
/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze)
if(!istype(gauze) || !gauze.absorption_capacity)
return
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>")
QDEL_NULL(current_gauze)
current_gauze = new gauze.type(src, 1)
gauze.use(1)
/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 = 4
/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)
/**
* seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity.
*
* The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandages fall off and we're left with nothing.
*
* Arguments:
* * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?)
*/
/obj/item/bodypart/proc/seep_gauze(seep_amt = 0)
if(!current_gauze)
return
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
current_gauze.absorption_capacity -= seep_amt
if(current_gauze.absorption_capacity < 0)
owner.visible_message("<span class='danger'>\The [current_gauze] on [owner]'s [name] fall away in rags.</span>", "<span class='warning'>\The [current_gauze] on your [name] fall away in rags.</span>", vision_distance=COMBAT_MESSAGE_RANGE)
QDEL_NULL(current_gauze)
@@ -4,7 +4,7 @@
return TRUE
//Dismember a limb
/obj/item/bodypart/proc/dismember(dam_type = BRUTE)
/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE)
if(!owner)
return FALSE
var/mob/living/carbon/C = owner
@@ -15,8 +15,9 @@
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
C.visible_message("<span class='danger'><B>[C]'s [src.name] has been violently dismembered!</B></span>")
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
if(!silent)
C.visible_message("<span class='danger'><B>[C]'s [name] is violently dismembered!</B></span>")
C.emote("scream")
SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "dismembered", /datum/mood_event/dismembered)
drop_limb()
@@ -30,6 +31,7 @@
burn()
return TRUE
add_mob_blood(C)
C.bleed(rand(20, 40))
var/direction = pick(GLOB.cardinals)
var/t_range = rand(2,max(throw_range/2, 2))
var/turf/target_turf = get_turf(src)
@@ -80,14 +82,13 @@
if(organ_spilled)
C.visible_message("<span class='danger'><B>[C]'s internal organs spill out onto the floor!</B></span>")
//limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in.
/obj/item/bodypart/proc/drop_limb(special)
/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.
@@ -143,7 +153,52 @@
forceMove(Tsec)
/**
* get_mangled_state() is relevant for flesh and bone bodyparts, and returns whether this bodypart has mangled skin, mangled bone, or both (or neither i guess)
*
* Dismemberment for flesh and bone requires the victim to have the skin on their bodypart destroyed (either a critical cut or piercing wound), and at least a hairline fracture
* (severe bone), at which point we can start rolling for dismembering. The attack must also deal at least 10 damage, and must be a brute attack of some kind (sorry for now, cakehat, maybe later)
*
* Returns: BODYPART_MANGLED_NONE if we're fine, BODYPART_MANGLED_FLESH if our skin is broken, BODYPART_MANGLED_BONE if our bone is broken, or BODYPART_MANGLED_BOTH if both are broken and we're up for dismembering
*/
/obj/item/bodypart/proc/get_mangled_state()
. = BODYPART_MANGLED_NONE
for(var/i in wounds)
var/datum/wound/iter_wound = i
if((iter_wound.wound_flags & MANGLES_BONE))
. |= BODYPART_MANGLED_BONE
if((iter_wound.wound_flags & MANGLES_FLESH))
. |= BODYPART_MANGLED_FLESH
/**
* try_dismember() is used, once we've confirmed that a flesh and bone bodypart has both the skin and bone mangled, to actually roll for it
*
* Mangling is described in the above proc, [/obj/item/bodypart/proc/get_mangled_state()]. This simply makes the roll for whether we actually dismember or not
* using how damaged the limb already is, and how much damage this blow was for. If we have a critical bone wound instead of just a severe, we add +10% to the roll.
* Lastly, we choose which kind of dismember we want based on the wounding type we hit with. Note we don't care about all the normal mods or armor for this
*
* Arguments:
* * wounding_type: Either WOUND_BLUNT, WOUND_SLASH, or WOUND_PIERCE, basically only matters for the dismember message
* * wounding_dmg: The damage of the strike that prompted this roll, higher damage = higher chance
* * wound_bonus: Not actually used right now, but maybe someday
* * bare_wound_bonus: ditto above
*/
/obj/item/bodypart/proc/try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
if(wounding_dmg < DISMEMBER_MINIMUM_DAMAGE)
return
var/base_chance = wounding_dmg + (get_damage() / max_damage * 50) // how much damage we dealt with this blow, + 50% of the damage percentage we already had on this bodypart
if(locate(/datum/wound/blunt/critical) in wounds) // we only require a severe bone break, but if there's a critical bone break, we'll add 10% more
base_chance += 10
if(!prob(base_chance))
return
var/datum/wound/loss/dismembering = new
dismembering.apply_dismember(src, wounding_type)
return TRUE
//when a limb is dropped, the internal organs are removed from the mob and put into the limb
/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C)
@@ -298,6 +353,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()
@@ -359,7 +423,7 @@
/mob/living/carbon/regenerate_limb(limb_zone, noheal)
var/obj/item/bodypart/L
if(get_bodypart(limb_zone))
return 0
return FALSE
L = newBodyPart(limb_zone, 0, 0)
if(L)
if(!noheal)
@@ -367,6 +431,8 @@
L.burn_dam = 0
L.brutestate = 0
L.burnstate = 0
var/datum/scar/scaries = new
var/datum/wound/loss/phantom_loss = new // stolen valor, really
scaries.generate(L, phantom_loss)
L.attach_limb(src, 1)
return 1
return TRUE
+4 -1
View File
@@ -35,8 +35,11 @@
//If the head is a special sprite
var/custom_head
wound_resistance = 10
scars_covered_by_clothes = FALSE
/obj/item/bodypart/head/can_dismember(obj/item/I)
if(!((owner.stat == DEAD) || owner.InFullCritical()))
if(owner && !((owner.stat == DEAD) || owner.InFullCritical()))
return FALSE
return ..()
+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]
+289
View File
@@ -0,0 +1,289 @@
/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()) || !get_organs())
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(!.)
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()
/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
/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(!.)
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()
/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
/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
+139
View File
@@ -0,0 +1,139 @@
/////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/blunt/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/blunt/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
/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
/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
/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)
+107
View File
@@ -0,0 +1,107 @@
/////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
/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
/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
var/obj/item/bodypart/the_part = target.get_bodypart(target_zone)
the_part.apply_gauze(tool)
else
to_chat(user, "<span class='warning'>[target] has no burns there!</span>")
return ..()
/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
@@ -32,7 +32,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
@@ -42,7 +43,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)
@@ -74,5 +76,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
@@ -7,13 +7,13 @@
/datum/surgery_step/ventricular_electrotherapy
name = "ventricular electrotherapy"
implements = list(/obj/item/twohanded/shockpaddles = 90, /obj/item/defibrillator = 75, /obj/item/inducer = 55, /obj/item/stock_parts/cell = 25) //Just because the idea of a new player using the whole magine to defib is hillarious to me
implements = list(/obj/item/shockpaddles = 90, /obj/item/defibrillator = 75, /obj/item/inducer = 55, /obj/item/stock_parts/cell = 25) //Just because the idea of a new player using the whole magine to defib is hillarious to me
time = 50
repeatable = TRUE //So you can retry
/datum/surgery_step/ventricular_electrotherapy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(istype(tool, /obj/item/twohanded/shockpaddles))
var/obj/item/twohanded/shockpaddles/pads = tool
if(istype(tool, /obj/item/shockpaddles))
var/obj/item/shockpaddles/pads = tool
if(!pads.wielded)
to_chat(user, "<span class='warning'>You need to wield the paddles in both hands before you can use them!</span>")
return FALSE
@@ -24,8 +24,8 @@
playsound(src, 'sound/machines/defib_charge.ogg', 75, 0)
/datum/surgery_step/ventricular_electrotherapy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(istype(tool, /obj/item/twohanded/shockpaddles))
var/obj/item/twohanded/shockpaddles/pads = tool
if(istype(tool, /obj/item/shockpaddles))
var/obj/item/shockpaddles/pads = tool
if(!pads.wielded)
return FALSE
var/mob/living/carbon/human/H = target
@@ -53,7 +53,7 @@
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, -5)
H.electrocute_act(0, (tool), 1, SHOCK_ILLUSION)
//If we're using a defib, let the defib handle the revive.
if(istype(tool, /obj/item/twohanded/shockpaddles))
if(istype(tool, /obj/item/shockpaddles))
return
//Otherwise, we're ad hocing it
if(!(do_after(user, 50, target = target)))
@@ -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***************************/
+5 -4
View File
@@ -62,7 +62,7 @@
time = 64
name = "manipulate organs"
repeatable = 1
implements = list(/obj/item/organ = 100, /obj/item/reagent_containers/food/snacks/organ = 0, /obj/item/organ_storage = 100)
implements = list(/obj/item/organ = 100, /obj/item/organ_storage = 100)
var/implements_extract = list(TOOL_HEMOSTAT = 100, TOOL_CROWBAR = 55)
var/current_type
var/obj/item/organ/I = null
@@ -86,6 +86,10 @@
if(target_zone != I.zone || target.getorganslot(I.slot))
to_chat(user, "<span class='notice'>There is no room for [I] in [target]'s [parse_zone(target_zone)]!</span>")
return -1
var/obj/item/organ/meatslab = tool
if(!meatslab.useable)
to_chat(user, "<span class='warning'>[I] seems to have been chewed on, you can't use this!</span>")
return -1
display_results(user, target, "<span class='notice'>You begin to insert [tool] into [target]'s [parse_zone(target_zone)]...</span>",
"[user] begins to insert [tool] into [target]'s [parse_zone(target_zone)].",
"[user] begins to insert something into [target]'s [parse_zone(target_zone)].")
@@ -112,9 +116,6 @@
else
return -1
else if(istype(tool, /obj/item/reagent_containers/food/snacks/organ))
to_chat(user, "<span class='warning'>[tool] was bitten by someone! It's too damaged to use!</span>")
return -1
/datum/surgery_step/manipulate_organs/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(current_type == "insert")
if(istype(tool, /obj/item/organ_storage))
+11 -5
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,12 +90,14 @@
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
name = "saw bone"
implements = list(TOOL_SAW = 100, /obj/item/melee/arm_blade = 75, /obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 35, /obj/item/kitchen/knife/butcher = 25)
implements = list(TOOL_SAW = 100, /obj/item/melee/arm_blade = 75, /obj/item/fireaxe = 50, /obj/item/hatchet = 35, /obj/item/kitchen/knife/butcher = 25)
time = 54
/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
@@ -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!")
-6
View File
@@ -37,9 +37,3 @@
..()
if(inflamed)
M.ForceContractDisease(new /datum/disease/appendicitis(), FALSE, TRUE)
/obj/item/organ/appendix/prepare_eat()
var/obj/S = ..()
if(inflamed)
S.reagents.add_reagent(/datum/reagent/toxin/bad_food, 5)
return S
+20 -2
View File
@@ -132,6 +132,7 @@
"<span class='notice'>You extend [holder] from your [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm.</span>",
"<span class='italics'>You hear a short mechanical noise.</span>")
playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1)
return TRUE
/obj/item/organ/cyberimp/arm/ui_action_click()
if(crit_fail || (organ_flags & ORGAN_FAILING) || (!holder && !contents.len))
@@ -273,12 +274,29 @@
desc = "A deployable riot shield to help deal with civil unrest."
contents = newlist(/obj/item/shield/riot/implant)
/obj/item/organ/cyberimp/arm/shield/Extend(obj/item/I)
/obj/item/organ/cyberimp/arm/shield/Extend(obj/item/I, silent = FALSE)
if(I.obj_integrity == 0) //that's how the shield recharge works
to_chat(owner, "<span class='warning'>[I] is still too unstable to extend. Give it some time!</span>")
if(!silent)
to_chat(owner, "<span class='warning'>[I] is still too unstable to extend. Give it some time!</span>")
return FALSE
return ..()
/obj/item/organ/cyberimp/arm/shield/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE)
. = ..()
if(.)
RegisterSignal(M, COMSIG_LIVING_ACTIVE_BLOCK_START, .proc/on_signal)
/obj/item/organ/cyberimp/arm/shield/Remove(special = FALSE)
UnregisterSignal(owner, COMSIG_LIVING_ACTIVE_BLOCK_START)
return ..()
/obj/item/organ/cyberimp/arm/shield/proc/on_signal(datum/source, obj/item/blocking_item, list/other_items)
if(!blocking_item) //if they don't have something
var/obj/item/shield/S = locate() in contents
if(!Extend(S, TRUE))
return
other_items += S
/obj/item/organ/cyberimp/arm/shield/emag_act()
. = ..()
if(obj_flags & EMAGGED)
+5 -1
View File
@@ -265,6 +265,10 @@
var/C = input(owner, "Select Color", "Select color", "#ffffff") as color|null
if(!C || QDELETED(src) || QDELETED(user) || QDELETED(owner) || owner != user)
return
var/list/hsv = ReadHSV(RGBtoHSV(C))
if(hsv[2] > 125)
to_chat(user, "<span class='warning'>A color that saturated? Surely not!</span>")
return
var/range = input(user, "Enter range (0 - [max_light_beam_distance])", "Range Select", 0) as null|num
if(!isnum(range))
return
@@ -405,4 +409,4 @@
#undef BLURRY_VISION_ONE
#undef BLURRY_VISION_TWO
#undef BLIND_VISION_THREE
#undef BLIND_VISION_THREE
+4 -4
View File
@@ -61,10 +61,10 @@
return "a healthy"
return "<span class='danger'>an unstable</span>"
/obj/item/organ/heart/prepare_eat()
var/obj/S = ..()
S.icon_state = "[icon_base]-off"
return S
/obj/item/organ/heart/OnEatFrom(eater, feeder)
. = ..()
beating = FALSE
update_icon()
/obj/item/organ/heart/on_life()
. = ..()
+3 -7
View File
@@ -23,6 +23,7 @@
var/toxLethality = LIVER_DEFAULT_TOX_LETHALITY//affects how much damage toxins do to the liver
var/filterToxins = TRUE //whether to filter toxins
var/cachedmoveCalc = 1
food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/iron = 5)
/obj/item/organ/liver/on_life()
. = ..()
@@ -44,11 +45,6 @@
if(damage > 10 && prob(damage/3))//the higher the damage the higher the probability
to_chat(owner, "<span class='warning'>You feel a dull pain in your abdomen.</span>")
/obj/item/organ/liver/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent(/datum/reagent/iron, 5)
return S
/obj/item/organ/liver/applyOrganDamage(d, maximum = maxHealth)
. = ..()
if(!. || QDELETED(owner))
@@ -77,8 +73,8 @@
/obj/item/organ/liver/proc/sizeMoveMod(value, mob/living/carbon/C)
if(cachedmoveCalc == value)
return
C.next_move_modifier /= cachedmoveCalc
C.next_move_modifier *= value
C.action_cooldown_mod /= cachedmoveCalc
C.action_cooldown_mod *= value
cachedmoveCalc = value
/obj/item/organ/liver/fly
+39 -45
View File
@@ -24,6 +24,8 @@
now_fixed = "<span class='warning'>Your lungs seem to once again be able to hold air.</span>"
high_threshold_cleared = "<span class='info'>The constriction around your chest loosens as your breathing calms down.</span>"
food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/medicine/salbutamol = 5)
//Breath damage
var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa
@@ -131,13 +133,11 @@
var/gas_breathed = 0
var/list/breath_gases = breath.gases
//Partial pressures in our breath
var/O2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/oxygen])+(8*breath.get_breath_partial_pressure(breath_gases[/datum/gas/pluoxium]))
var/N2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrogen])
var/Toxins_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/plasma])
var/CO2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/carbon_dioxide])
var/O2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/oxygen))+(8*breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/pluoxium)))
var/N2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrogen))
var/Toxins_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/plasma))
var/CO2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/carbon_dioxide))
//-- OXY --//
@@ -145,7 +145,7 @@
//Too much oxygen! //Yes, some species may not like it.
if(safe_oxygen_max)
if((O2_pp > safe_oxygen_max) && safe_oxygen_max == 0) //I guess plasma men technically need to have a check.
var/ratio = (breath_gases[/datum/gas/oxygen]/safe_oxygen_max) * 10
var/ratio = (breath.get_moles(/datum/gas/oxygen)/safe_oxygen_max) * 10
H.apply_damage_type(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type)
H.throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy)
@@ -168,18 +168,18 @@
//Too little oxygen!
if(safe_oxygen_min)
if(O2_pp < safe_oxygen_min)
gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath_gases[/datum/gas/oxygen])
gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath.get_moles(/datum/gas/oxygen))
H.throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy)
else
H.failed_last_breath = FALSE
if(H.health >= H.crit_threshold)
H.adjustOxyLoss(-breathModifier) //More damaged lungs = slower oxy rate up to a factor of half
gas_breathed = breath_gases[/datum/gas/oxygen]
gas_breathed = breath.get_moles(/datum/gas/oxygen)
H.clear_alert("not_enough_oxy")
//Exhale
breath_gases[/datum/gas/oxygen] -= gas_breathed
breath_gases[/datum/gas/carbon_dioxide] += gas_breathed
breath.adjust_moles(/datum/gas/oxygen, -gas_breathed)
breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed)
gas_breathed = 0
//-- Nitrogen --//
@@ -187,7 +187,7 @@
//Too much nitrogen!
if(safe_nitro_max)
if(N2_pp > safe_nitro_max)
var/ratio = (breath_gases[/datum/gas/nitrogen]/safe_nitro_max) * 10
var/ratio = (breath.get_moles(/datum/gas/nitrogen)/safe_nitro_max) * 10
H.apply_damage_type(clamp(ratio, nitro_breath_dam_min, nitro_breath_dam_max), nitro_damage_type)
H.throw_alert("too_much_nitro", /obj/screen/alert/too_much_nitro)
H.losebreath += 2
@@ -197,18 +197,18 @@
//Too little nitrogen!
if(safe_nitro_min)
if(N2_pp < safe_nitro_min)
gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath_gases[/datum/gas/nitrogen])
gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath.get_moles(/datum/gas/nitrogen))
H.throw_alert("nitro", /obj/screen/alert/not_enough_nitro)
else
H.failed_last_breath = FALSE
if(H.health >= H.crit_threshold)
H.adjustOxyLoss(-breathModifier)
gas_breathed = breath_gases[/datum/gas/nitrogen]
gas_breathed = breath.get_moles(/datum/gas/nitrogen)
H.clear_alert("nitro")
//Exhale
breath_gases[/datum/gas/nitrogen] -= gas_breathed
breath_gases[/datum/gas/carbon_dioxide] += gas_breathed
breath.adjust_moles(/datum/gas/nitrogen, -gas_breathed)
breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed)
gas_breathed = 0
//-- CO2 --//
@@ -234,18 +234,18 @@
//Too little CO2!
if(safe_co2_min)
if(CO2_pp < safe_co2_min)
gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath_gases[/datum/gas/carbon_dioxide])
gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath.get_moles(/datum/gas/carbon_dioxide))
H.throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2)
else
H.failed_last_breath = FALSE
if(H.health >= H.crit_threshold)
H.adjustOxyLoss(-breathModifier)
gas_breathed = breath_gases[/datum/gas/carbon_dioxide]
gas_breathed = breath.get_moles(/datum/gas/carbon_dioxide)
H.clear_alert("not_enough_co2")
//Exhale
breath_gases[/datum/gas/carbon_dioxide] -= gas_breathed
breath_gases[/datum/gas/oxygen] += gas_breathed
breath.adjust_moles(/datum/gas/carbon_dioxide, -gas_breathed)
breath.adjust_moles(/datum/gas/oxygen, gas_breathed)
gas_breathed = 0
@@ -254,7 +254,7 @@
//Too much toxins!
if(safe_toxins_max)
if(Toxins_pp > safe_toxins_max)
var/ratio = (breath_gases[/datum/gas/plasma]/safe_toxins_max) * 10
var/ratio = (breath.get_moles(/datum/gas/plasma)/safe_toxins_max) * 10
H.apply_damage_type(clamp(ratio, tox_breath_dam_min, tox_breath_dam_max), tox_damage_type)
H.throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
else
@@ -264,18 +264,18 @@
//Too little toxins!
if(safe_toxins_min)
if(Toxins_pp < safe_toxins_min)
gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath_gases[/datum/gas/plasma])
gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath.get_moles(/datum/gas/plasma))
H.throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox)
else
H.failed_last_breath = FALSE
if(H.health >= H.crit_threshold)
H.adjustOxyLoss(-breathModifier)
gas_breathed = breath_gases[/datum/gas/plasma]
gas_breathed = breath.get_moles(/datum/gas/plasma)
H.clear_alert("not_enough_tox")
//Exhale
breath_gases[/datum/gas/plasma] -= gas_breathed
breath_gases[/datum/gas/carbon_dioxide] += gas_breathed
breath.adjust_moles(/datum/gas/plasma, -gas_breathed)
breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed)
gas_breathed = 0
@@ -285,7 +285,7 @@
// N2O
var/SA_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrous_oxide])
var/SA_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrous_oxide))
if(SA_pp > SA_para_min) // Enough to make us stunned for a bit
H.Unconscious(60) // 60 gives them one second to wake up and run away a bit!
if(SA_pp > SA_sleep_min) // Enough to make us sleep as well
@@ -299,7 +299,7 @@
// BZ
var/bz_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/bz])
var/bz_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/bz))
if(bz_pp > BZ_trip_balls_min)
H.hallucination += 10
H.reagents.add_reagent(/datum/reagent/bz_metabolites,5)
@@ -312,14 +312,14 @@
// Tritium
var/trit_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/tritium])
var/trit_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/tritium))
if (trit_pp > 50)
H.radiation += trit_pp/2 //If you're breathing in half an atmosphere of radioactive gas, you fucked up.
else
H.radiation += trit_pp/10
// Nitryl
var/nitryl_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitryl])
var/nitryl_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitryl))
if (prob(nitryl_pp))
to_chat(H, "<span class='alert'>Your mouth feels like it's burning!</span>")
if (nitryl_pp >40)
@@ -330,22 +330,22 @@
H.silent = max(H.silent, 3)
else
H.adjustFireLoss(nitryl_pp/4)
gas_breathed = breath_gases[/datum/gas/nitryl]
gas_breathed = breath.get_moles(/datum/gas/nitryl)
if (gas_breathed > gas_stimulation_min)
H.reagents.add_reagent(/datum/reagent/nitryl,1)
breath_gases[/datum/gas/nitryl]-=gas_breathed
breath.adjust_moles(/datum/gas/nitryl, -gas_breathed)
// Stimulum
gas_breathed = breath_gases[/datum/gas/stimulum]
gas_breathed = breath.get_moles(/datum/gas/stimulum)
if (gas_breathed > gas_stimulation_min)
var/existing = H.reagents.get_reagent_amount(/datum/reagent/stimulum)
H.reagents.add_reagent(/datum/reagent/stimulum, max(0, 5 - existing))
breath_gases[/datum/gas/stimulum]-=gas_breathed
breath.adjust_moles(/datum/gas/stimulum, -gas_breathed)
// Miasma
if (breath_gases[/datum/gas/miasma])
var/miasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/miasma])
if (breath.get_moles(/datum/gas/miasma))
var/miasma_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/miasma))
if(miasma_pp > MINIMUM_MOLES_DELTA_TO_MOVE)
//Miasma sickness
@@ -385,14 +385,13 @@
// Then again, this is a purely hypothetical scenario and hardly reachable
owner.adjust_disgust(0.1 * miasma_pp)
breath_gases[/datum/gas/miasma]-=gas_breathed
breath.adjust_moles(/datum/gas/miasma, -gas_breathed)
// Clear out moods when no miasma at all
else
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "smell")
handle_breath_temperature(breath, H)
GAS_GARBAGE_COLLECT(breath.gases)
return TRUE
@@ -414,7 +413,7 @@
/obj/item/organ/lungs/proc/handle_breath_temperature(datum/gas_mixture/breath, mob/living/carbon/human/H) // called by human/life, handles temperatures
var/breath_temperature = breath.temperature
var/breath_temperature = breath.return_temperature()
if(!HAS_TRAIT(H, TRAIT_RESISTCOLD)) // COLD DAMAGE
var/cold_modifier = H.dna.species.coldmod
@@ -458,11 +457,6 @@
else if(!(organ_flags & ORGAN_FAILING))
failed = FALSE
/obj/item/organ/lungs/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent(/datum/reagent/medicine/salbutamol, 5)
return S
/obj/item/organ/lungs/ipc
name = "ipc cooling system"
icon_state = "lungs-c"
@@ -547,8 +541,8 @@
/obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H)
. = ..()
if (breath && breath.gases[/datum/gas/plasma])
var/plasma_pp = breath.get_breath_partial_pressure(breath.gases[/datum/gas/plasma])
if (breath)
var/plasma_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/plasma))
owner.blood_volume += (0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you.
/obj/item/organ/lungs/yamerol
+22 -45
View File
@@ -8,7 +8,7 @@
var/zone = BODY_ZONE_CHEST
var/slot
// DO NOT add slots with matching names to different zones - it will break internal_organs_slot list!
var/organ_flags = NONE
var/organ_flags = ORGAN_EDIBLE
var/maxHealth = STANDARD_ORGAN_THRESHOLD
var/damage = 0 //total damage this organ has sustained
///Healing factor and decay factor function on % of maxhealth, and do not work by applying a static number per tick
@@ -25,7 +25,23 @@
var/now_fixed
var/high_threshold_cleared
var/low_threshold_cleared
rad_flags = RAD_NO_CONTAMINATE
///When you take a bite you cant jam it in for surgery anymore.
var/useable = TRUE
var/list/food_reagents = list(/datum/reagent/consumable/nutriment = 5)
/obj/item/organ/Initialize()
. = ..()
if(organ_flags & ORGAN_EDIBLE)
AddComponent(/datum/component/edible, food_reagents, null, RAW | MEAT | GROSS, null, 10, null, null, null, CALLBACK(src, .proc/OnEatFrom))
START_PROCESSING(SSobj, src)
/obj/item/organ/Destroy()
if(owner)
// The special flag is important, because otherwise mobs can die
// while undergoing transformation into different mobs.
Remove(TRUE)
return ..()
/obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
if(!iscarbon(M) || owner == M)
@@ -106,7 +122,7 @@
if(istype(loc, /turf/))//Only concern is adding an organ to a freezer when the area around it is cold.
var/turf/T = loc
var/datum/gas_mixture/enviro = T.return_air()
local_temp = enviro.temperature
local_temp = enviro.return_temperature()
else if(!owner && ismob(loc))
var/mob/M = loc
@@ -116,7 +132,7 @@
return TRUE
var/turf/T = M.loc
var/datum/gas_mixture/enviro = T.return_air()
local_temp = enviro.temperature
local_temp = enviro.return_temperature()
if(owner)
//Don't interfere with bodies frozen by structures.
@@ -157,47 +173,8 @@
if(damage > high_threshold)
. += "<span class='warning'>[src] is starting to look discolored.</span>"
/obj/item/organ/proc/prepare_eat()
var/obj/item/reagent_containers/food/snacks/organ/S = new
S.name = name
S.desc = desc
S.icon = icon
S.icon_state = icon_state
S.w_class = w_class
return S
/obj/item/reagent_containers/food/snacks/organ
name = "appendix"
icon_state = "appendix"
icon = 'icons/obj/surgery.dmi'
list_reagents = list(/datum/reagent/consumable/nutriment = 5)
foodtype = RAW | MEAT | GROSS
/obj/item/organ/Initialize()
. = ..()
START_PROCESSING(SSobj, src)
/obj/item/organ/Destroy()
if(owner)
// The special flag is important, because otherwise mobs can die
// while undergoing transformation into different mobs.
Remove(TRUE)
return ..()
/obj/item/organ/attack(mob/living/carbon/M, mob/user)
if(M == user && ishuman(user))
var/mob/living/carbon/human/H = user
if(status == ORGAN_ORGANIC)
var/obj/item/reagent_containers/food/snacks/S = prepare_eat()
if(S)
qdel(src)
if(H.put_in_active_hand(S))
S.attack(H, H)
else
..()
/obj/item/organ/proc/OnEatFrom(eater, feeder)
useable = FALSE //You can't use it anymore after eating it you spaztic
/obj/item/organ/item_action_slot_check(slot,mob/user)
return //so we don't grant the organ's action to mobs who pick up the organ.
+32
View File
@@ -103,3 +103,35 @@
if(2)
owner.nutrition = min(owner.nutrition - 100, 0)
to_chat(owner, "<span class='warning'>Alert: Minor battery discharge!</span>")
/obj/item/organ/stomach/ethereal
name = "biological battery"
icon_state = "stomach-p" //Welp. At least it's more unique in functionaliy.
desc = "A crystal-like organ that stores the electric charge of ethereals."
var/crystal_charge = ETHEREAL_CHARGE_FULL
/obj/item/organ/stomach/ethereal/on_life()
..()
adjust_charge(-ETHEREAL_CHARGE_FACTOR)
/obj/item/organ/stomach/ethereal/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
RegisterSignal(owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, .proc/charge)
RegisterSignal(owner, COMSIG_LIVING_ELECTROCUTE_ACT, .proc/on_electrocute)
/obj/item/organ/stomach/ethereal/Remove(mob/living/carbon/M, special = 0)
UnregisterSignal(owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT)
UnregisterSignal(owner, COMSIG_LIVING_ELECTROCUTE_ACT)
..()
/obj/item/organ/stomach/ethereal/proc/charge(datum/source, amount, repairs)
adjust_charge(amount / 70)
/obj/item/organ/stomach/ethereal/proc/on_electrocute(datum/source, shock_damage, siemens_coeff = 1, flags = NONE)
if(flags & SHOCK_ILLUSION)
return
adjust_charge(shock_damage * siemens_coeff * 2)
to_chat(owner, "<span class='notice'>You absorb some of the shock into your body!</span>")
/obj/item/organ/stomach/ethereal/proc/adjust_charge(amount)
crystal_charge = clamp(crystal_charge + amount, ETHEREAL_CHARGE_NONE, ETHEREAL_CHARGE_DANGEROUS)
+11 -5
View File
@@ -45,14 +45,20 @@
/obj/item/organ/tail/lizard/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = TRUE)
..()
if(istype(H))
// Checks here are necessary so it wouldn't overwrite the tail of a lizard it spawned in
// Checks here are necessary so it wouldn't overwrite the tail of a lizard it spawned in //yes, the if checks may cause snowflakes so that you can't insert another person's tail (haven't actually tested it but I assume that's the result of my addition) but it makes it so never again will lizards break their spine if set_species is called twice in a row (hopefully)
if(!H.dna.species.mutant_bodyparts["tail_lizard"])
H.dna.features["tail_lizard"] = tail_type
H.dna.species.mutant_bodyparts["tail_lizard"] = tail_type
if (!H.dna.features["tail_lizard"])
H.dna.features["tail_lizard"] = tail_type
H.dna.species.mutant_bodyparts["tail_lizard"] = tail_type
else
H.dna.species.mutant_bodyparts["tail_lizard"] = H.dna.features["tail_lizard"]
if(!H.dna.species.mutant_bodyparts["spines"])
H.dna.features["spines"] = spines
H.dna.species.mutant_bodyparts["spines"] = spines
if (!H.dna.features["spines"])
H.dna.features["spines"] = spines
H.dna.species.mutant_bodyparts["spines"] = spines
else
H.dna.species.mutant_bodyparts["spines"] = H.dna.features["spines"]
H.update_body()
/obj/item/organ/tail/lizard/Remove(special = FALSE)
+24
View File
@@ -252,6 +252,7 @@
name = "robotic voicebox"
desc = "A voice synthesizer that can interface with organic lifeforms."
status = ORGAN_ROBOTIC
organ_flags = ORGAN_NO_SPOIL
icon_state = "tonguerobot"
say_mod = "states"
attack_verb = list("beeped", "booped")
@@ -311,3 +312,26 @@
desc = "A voice synthesizer used by IPCs to smoothly interface with organic lifeforms."
electronics_magic = FALSE
organ_flags = ORGAN_SYNTHETIC
/obj/item/organ/tongue/ethereal
name = "electric discharger"
desc = "A sophisticated ethereal organ, capable of synthesising speech via electrical discharge."
icon_state = "electrotongue"
say_mod = "crackles"
attack_verb = list("shocked", "jolted", "zapped")
taste_sensitivity = 101 // Not a tongue, they can't taste shit
var/static/list/languages_possible_ethereal = typecacheof(list(
/datum/language/common,
/datum/language/draconic,
/datum/language/codespeak,
/datum/language/monkey,
/datum/language/narsie,
/datum/language/beachbum,
/datum/language/aphasia,
/datum/language/sylvan,
/datum/language/voltaic
))
/obj/item/organ/tongue/ethereal/Initialize(mapload)
. = ..()
languages_possible = languages_possible_ethereal
+3 -36
View File
@@ -254,7 +254,6 @@
var/static/regex/clap_words = regex("clap|applaud")
var/static/regex/honk_words = regex("ho+nk") //hooooooonk
var/static/regex/multispin_words = regex("like a record baby|right round")
var/static/regex/orgasm_words = regex("cum|orgasm|climax|squirt|heyo") //CITADEL CHANGE
var/static/regex/dab_words = regex("dab|mood") //CITADEL CHANGE
var/static/regex/snap_words = regex("snap") //CITADEL CHANGE
var/static/regex/bwoink_words = regex("what the fuck are you doing|bwoink|hey you got a moment?") //CITADEL CHANGE
@@ -319,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)))
@@ -572,16 +572,6 @@
var/mob/living/L = V
L.SpinAnimation(speed = 10, loops = 5)
//CITADEL CHANGES
//ORGASM
else if((findtext(message, orgasm_words)))
cooldown = COOLDOWN_MEME
for(var/V in listeners)
var/mob/living/carbon/human/H = V
if(H.client && H.client.prefs && H.client.prefs.cit_toggles & HYPNO) // probably a redundant check but for good measure
H.mob_climax(forced_climax=TRUE)
//DAB
else if((findtext(message, dab_words)))
cooldown = COOLDOWN_DAMAGE
@@ -765,7 +755,6 @@
var/static/regex/forget_words = regex("forget|muddled|awake and forget")
var/static/regex/attract_words = regex("come here|come to me|get over here|attract")
//phase 2
var/static/regex/orgasm_words = regex("cum|orgasm|climax|squirt|heyo") //wah, lewd
var/static/regex/awoo_words = regex("howl|awoo|bark")
var/static/regex/nya_words = regex("nya|meow|mewl")
var/static/regex/sleep_words = regex("sleep|slumber|rest")
@@ -1092,28 +1081,6 @@
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='notice'>You are drawn towards [user]!</b></span>"), 5)
to_chat(user, "<span class='notice'><i>You draw [L] towards you!</i></span>")
//teir 2
/* removed for now
//ORGASM
else if((findtext(message, orgasm_words)))
for(var/V in listeners)
var/mob/living/carbon/human/H = V
var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall)
if(E.phase > 1)
if(E.lewd) // probably a redundant check but for good measure
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='love'>Your [E.enthrallGender] pushes you over the limit, overwhelming your body with pleasure.</b></span>"), 5)
H.mob_climax(forced_climax=TRUE)
H.SetStun(20)
E.resistanceTally = 0 //makes resistance 0, but resets arousal, resistance buildup is faster unaroused (massively so).
E.enthrallTally += power_multiplier
E.cooldown += 6
else
H.throw_at(get_step_towards(user,H), 3 * power_multiplier, 1 * power_multiplier)
*/
//awoo
else if((findtext(message, awoo_words)))
for(var/V in listeners)
@@ -13,7 +13,7 @@
return 1
/datum/surgery_step/add_prosthetic
name = "add prosthetic"
implements = list(/obj/item/bodypart = 100, /obj/item/organ_storage = 100, /obj/item/twohanded/required/chainsaw = 100, /obj/item/melee/synthetic_arm_blade = 100)
implements = list(/obj/item/bodypart = 100, /obj/item/organ_storage = 100, /obj/item/chainsaw = 100, /obj/item/melee/synthetic_arm_blade = 100)
time = 32
var/organ_rejection_dam = 0
/datum/surgery_step/add_prosthetic/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
@@ -79,7 +79,7 @@
"[user] finishes attaching [tool]!",
"[user] finishes the attachment procedure!")
qdel(tool)
if(istype(tool, /obj/item/twohanded/required/chainsaw))
if(istype(tool, /obj/item/chainsaw))
var/obj/item/mounted_chainsaw/new_arm = new(target)
target_zone == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm)
return 1
+108
View File
@@ -0,0 +1,108 @@
/////BURN FIXING SURGERIES//////
//the step numbers of each of these two, we only currently use the first to switch back and forth due to advancing after finishing steps anyway
#define REALIGN_INNARDS 1
#define WELD_VEINS 2
///// Repair puncture wounds
/datum/surgery/repair_puncture
name = "Repair puncture"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/repair_innards, /datum/surgery_step/seal_veins, /datum/surgery_step/close) // repeat between steps 2 and 3 until healed
target_mobtypes = list(/mob/living/carbon)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
targetable_wound = /datum/wound/pierce
/datum/surgery/repair_puncture/can_start(mob/living/user, mob/living/carbon/target)
. = ..()
if(.)
var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected)
var/datum/wound/burn/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound)
return(pierce_wound && pierce_wound.blood_flow > 0)
//SURGERY STEPS
///// realign the blood vessels so we can reweld them
/datum/surgery_step/repair_innards
name = "realign blood vessels"
implements = list(TOOL_HEMOSTAT = 100, TOOL_SCALPEL = 85, TOOL_WIRECUTTER = 40)
time = 3 SECONDS
/datum/surgery_step/repair_innards/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
if(!pierce_wound)
user.visible_message("<span class='notice'>[user] looks for [target]'s [parse_zone(user.zone_selected)].</span>", "<span class='notice'>You look for [target]'s [parse_zone(user.zone_selected)]...</span>")
return
if(pierce_wound.blood_flow <= 0)
to_chat(user, "<span class='notice'>[target]'s [parse_zone(user.zone_selected)] has no puncture to repair!</span>")
surgery.status++
return
display_results(user, target, "<span class='notice'>You begin to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)].</span>")
/datum/surgery_step/repair_innards/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
if(!pierce_wound)
to_chat(user, "<span class='warning'>[target] has no puncture wound there!</span>")
return ..()
display_results(user, target, "<span class='notice'>You successfully realign some of the blood vessels in [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)]!</span>")
log_combat(user, target, "excised infected flesh in", addition="INTENT: [uppertext(user.a_intent)]")
surgery.operated_bodypart.receive_damage(brute=3, wound_bonus=CANT_WOUND)
pierce_wound.blood_flow -= 0.25
return ..()
/datum/surgery_step/repair_innards/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
. = ..()
display_results(user, target, "<span class='notice'>You jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)].</span>",
"<span class='notice'>[user] jerks apart some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)]!</span>")
surgery.operated_bodypart.receive_damage(brute=rand(4,8), sharpness=SHARP_EDGED, wound_bonus = 10)
///// Sealing the vessels back together
/datum/surgery_step/seal_veins
name = "weld veins" // if your doctor says they're going to weld your blood vessels back together, you're either A) on SS13, or B) in grave mortal peril
implements = list(TOOL_CAUTERY = 100, /obj/item/gun/energy/laser = 90, TOOL_WELDER = 70, /obj/item = 30)
time = 4 SECONDS
/datum/surgery_step/seal_veins/tool_check(mob/user, obj/item/tool)
if(implement_type == TOOL_WELDER || implement_type == /obj/item)
return tool.get_temperature()
return TRUE
/datum/surgery_step/seal_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
if(!pierce_wound)
user.visible_message("<span class='notice'>[user] looks for [target]'s [parse_zone(user.zone_selected)].</span>", "<span class='notice'>You look for [target]'s [parse_zone(user.zone_selected)]...</span>")
return
display_results(user, target, "<span class='notice'>You begin to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)]...</span>",
"<span class='notice'>[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].</span>",
"<span class='notice'>[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)].</span>")
/datum/surgery_step/seal_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
var/datum/wound/pierce/pierce_wound = surgery.operated_wound
if(!pierce_wound)
to_chat(user, "<span class='warning'>[target] has no puncture there!</span>")
return ..()
display_results(user, target, "<span class='notice'>You successfully meld some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool].</span>",
"<span class='notice'>[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!</span>",
"<span class='notice'>[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)]!</span>")
log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]")
pierce_wound.blood_flow -= 0.5
if(pierce_wound.blood_flow > 0)
surgery.status = REALIGN_INNARDS
to_chat(user, "<span class='notice'><i>There still seems to be misaligned blood vessels to finish...<i></span>")
else
to_chat(user, "<span class='green'>You've repaired all the internal damage in [target]'s [parse_zone(target_zone)]!</span>")
return ..()
#undef REALIGN_INNARDS
#undef WELD_VEINS
+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
+23 -5
View File
@@ -163,9 +163,10 @@
item_flags = SURGICAL_TOOL
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP_ACCURATE
sharpness = SHARP_POINTY
tool_behaviour = TOOL_SCALPEL
toolspeed = 1
bare_wound_bonus = 20
/obj/item/scalpel/Initialize()
. = ..()
@@ -180,7 +181,7 @@
force = 16
toolspeed = 0.7
light_color = LIGHT_COLOR_GREEN
sharpness = IS_SHARP_ACCURATE
sharpness = SHARP_POINTY
/obj/item/scalpel/advanced/Initialize()
. = ..()
@@ -220,7 +221,7 @@
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
toolspeed = 0.5
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP_ACCURATE
sharpness = SHARP_POINTY
/obj/item/scalpel/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is slitting [user.p_their()] [pick("wrists", "throat", "stomach")] with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -244,9 +245,11 @@
throw_range = 5
custom_materials = list(/datum/material/iron=10000, /datum/material/glass=6000)
attack_verb = list("attacked", "slashed", "sawed", "cut")
sharpness = IS_SHARP
sharpness = SHARP_EDGED
tool_behaviour = TOOL_SAW
toolspeed = 1
wound_bonus = 5
bare_wound_bonus = 10
/obj/item/circular_saw/Initialize()
. = ..()
@@ -269,7 +272,7 @@
custom_materials = list(/datum/material/iron=10000, /datum/material/glass=6000)
toolspeed = 0.5
attack_verb = list("attacked", "slashed", "sawed", "cut")
sharpness = IS_SHARP
sharpness = SHARP_EDGED
/obj/item/surgical_drapes
name = "surgical drapes"
@@ -374,3 +377,18 @@
advanced_surgeries |= OC.advanced_surgeries
return TRUE
return
/obj/item/bonesetter
name = "bonesetter"
desc = "For setting things right."
icon = 'icons/obj/surgery.dmi'
icon_state = "bone setter"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
custom_materials = list(/datum/material/iron=5000, /datum/material/glass=2500)
flags_1 = CONDUCT_1
item_flags = SURGICAL_TOOL
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("corrected", "properly set")
tool_behaviour = TOOL_BONESET
toolspeed = 1