Carbon Dismemberment , second attempt. (#20461)

* - I rearranged X_defense.dm mob files, more damage_procs.dm.Here's what's inside:
* X_defense.dm: is for the procs of attacks onto the mob, all the XXX_act() proc (things happening to the mob), as well as protection check and get procs (armor, ear prot, projectile dismemberment)
* damage_procs.dm: actual damage procs like adjustBruteLoss() getfireloss, any proc that handles damaging.

- some bugfixes with gibspawner effects.
- monkey's bodyparts can be dismembered and are used to create its icon.
- brains are no longer carbons.
- all carbon have bodyparts that can be dropped when the mob is gibbed.
- adminspawned bodyparts now have a default icon.
- robotic parts are now a child of bodyparts.
- health analyzer on alien/monkey shows damage on each limb
- added admin option to add/remove bodyparts for all carbon (instead of just remove on humans)
- Fixes keycheck message spam for janicart and all when trying to move.
- Fixes bug with buckling to a scooter while limbless.
- removed arg "hit_zone" in proj's on_hit() because we can already use the def_zone var (where hit_zone got its value)
- Fixes mob not getting any damage when hit by a projectile on their missing limb, despite a hit message shown). carbon/apply_damage() now when we specify a def_zone and the corresponding BP is missing we default to the chest instead of stopping the proc. Consistently with how human/attacked_by() default to its attack to chest if missing limb.
- Fixes mini uzi icon when empty and no mag (typo).
- I renamed and changed a bit check_eye_prot and ear prot
- renamed flash_eyes to flash_act()
- I made a soundbang_act() similar to flash_act but for loud bangs.
- added a gib and dust animation to larva.
- husked monkeys
- no damage overlay for husk or skeleton.
- damage overlay for robotic limb now.
- no damage overlay when organic bodypart husked.
- one handed human with a bloody hand still get a bloody single hand overlay.
- fix admin heal being unable to heal robotic bodyparts.
- slightly touched robotic bodypart sprites (head one pixel too high)
- Fixes 18532 "beheaded husk has hair".
- Fixes 18584 "Ling stasis appearance bug"
- no more eyes or lipstick on husks.
- can remove flashes/wires/cells from robot chest and head with crowbar.
- Fixes not being able to surgically amputate robotic arm/leg.

* More merge conflict fixes and adding the new files I forgot to add.

* of course I forgot birdstation

* More typos and stuff I forgot to undo.

* Fixing a typo in examine.dm
Removing an unnecessary check.
Making admin heal regenerate limbs on all carbons.
Monkey-human transformation now transfer missing limbs info and presence of a cavity implant.
NODISMEMBER species can still lack a limb if the mob lacked a limb and changed into that new species.
Changeling Regenerate ability now also regenerate limbs when in monkey form. (and remove some cryptic useless code)

* Fixing more conflicts with remie's multihands PR.

* Fixes runtime with hud when calling build_hand_slots().
Fixes lightgeist healing not working.
Fixes null.handle_fall() runtimes with pirate mobs.
Fixes typo in has_left_hadn() and has_right_hand().

* Derp, forgot to remove debug message.
This commit is contained in:
phil235
2016-09-12 19:33:50 +02:00
committed by AnturK
parent 2a58dd54a9
commit 443a4501ec
234 changed files with 4926 additions and 4116 deletions
+5 -4
View File
@@ -2,8 +2,10 @@
/datum/surgery/amputation
name = "amputation"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/sever_limb)
species = list(/mob/living/carbon/human)
species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list("r_arm", "l_arm", "l_leg", "r_leg", "head")
requires_organic_bodypart = 0
/datum/surgery_step/sever_limb
name = "sever limb"
@@ -16,7 +18,6 @@
/datum/surgery_step/sever_limb/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/mob/living/carbon/human/L = target
user.visible_message("[user] severs [L]'s [parse_zone(target_zone)]!", "<span class='notice'>You sever [L]'s [parse_zone(target_zone)].</span>")
var/obj/item/bodypart/BP = L.get_bodypart(target_zone)
if(BP)
BP.drop_limb()
if(surgery.operated_bodypart)
surgery.operated_bodypart.drop_limb()
return 1
+227 -66
View File
@@ -4,10 +4,11 @@
desc = "why is it detached..."
force = 3
throwforce = 3
icon = 'icons/mob/human_parts.dmi'
icon_state = ""
layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor
var/mob/living/carbon/human/owner = null
var/status = ORGAN_ORGANIC
var/mob/living/carbon/owner = null
var/status = BODYPART_ORGANIC
var/body_zone //"chest", "l_arm", etc , used for def_zone
var/body_part = null //bitflag used to check which clothes cover this bodypart
var/brutestate = 0
@@ -28,10 +29,14 @@
var/mutation_color = ""
var/no_update = 0
var/animal_origin = null //for nonhuman bodypart (e.g. monkey)
var/dismemberable = 1 //whether it can be dismembered with a weapon.
var/px_x = 0
var/px_y = 0
var/state_flags
var/species_flags_list = list()
var/dmg_overlay_type //the type of damage overlay (if any) to use when this bodypart is bruised/burned.
/obj/item/bodypart/examine(mob/user)
..()
@@ -53,7 +58,7 @@
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(EASYLIMBATTACHMENT in H.dna.species.specflags)
if(!H.get_bodypart(body_zone))
if(!H.get_bodypart(body_zone) && !animal_origin)
if(H == user)
H.visible_message("<span class='warning'>[H] jams [src] into \his empty socket!</span>",\
"<span class='notice'>You force [src] into your empty socket, and it locks into place!</span>")
@@ -72,8 +77,8 @@
user << "<span class='warning'>There is nothing left inside [src]!</span>"
return
playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
user.visible_message("<span class='warning'>[user] begins to cut through the bone in [src].</span>",\
"<span class='notice'>You begin to cut through the bone in [src]...</span>")
user.visible_message("<span class='warning'>[user] begins to cut open [src].</span>",\
"<span class='notice'>You begin to cut open [src]...</span>")
if(do_after(user, 54, target = src))
drop_organs(user)
else
@@ -81,27 +86,30 @@
/obj/item/bodypart/throw_impact(atom/hit_atom)
..()
playsound(get_turf(src), 'sound/misc/splort.ogg', 50, 1, -1)
if(status != BODYPART_ROBOTIC)
playsound(get_turf(src), 'sound/misc/splort.ogg', 50, 1, -1)
pixel_x = rand(-3, 3)
pixel_y = rand(-3, 3)
//empties the bodypart from its organs and other things inside it
/obj/item/bodypart/proc/drop_organs(mob/user)
var/turf/T = get_turf(src)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
if(status != BODYPART_ROBOTIC)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
for(var/obj/item/I in src)
I.loc = T
I.forceMove(T)
//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/take_damage(brute, burn)
/obj/item/bodypart/proc/take_damage(brute, burn, updating_health = 1)
if(owner && (owner.status_flags & GODMODE))
return 0 //godmode
brute = max(brute * config.damage_multiplier,0)
burn = max(burn * config.damage_multiplier,0)
if(status == ORGAN_ROBOTIC) //This makes robolimbs not damageable by chems and makes it stronger
if(status == BODYPART_ROBOTIC) //This makes robolimbs not damageable by chems and makes it stronger
brute = max(0, brute - 5)
burn = max(0, burn - 4)
@@ -126,7 +134,7 @@
burn_dam += can_inflict
else
return 0
if(owner)
if(owner && updating_health)
owner.updatehealth()
return update_bodypart_damage_state()
@@ -134,17 +142,17 @@
//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)
/obj/item/bodypart/proc/heal_damage(brute, burn, robotic)
/obj/item/bodypart/proc/heal_damage(brute, burn, only_robotic = 0, only_organic = 1, updating_health = 1)
if(robotic && status != ORGAN_ROBOTIC) //This makes organic limbs not heal when the proc is in Robotic mode.
if(only_robotic && status != BODYPART_ROBOTIC) //This makes organic limbs not heal when the proc is in Robotic mode.
return
if(!robotic && status == ORGAN_ROBOTIC) //This makes robolimbs not healable by chems.
if(only_organic && status != BODYPART_ORGANIC) //This makes robolimbs not healable by chems.
return
brute_dam = max(brute_dam - brute, 0)
burn_dam = max(burn_dam - burn, 0)
if(owner)
if(owner && updating_health)
owner.updatehealth()
return update_bodypart_damage_state()
@@ -157,14 +165,13 @@
//Updates an organ's brute/burn states for use by update_damage_overlays()
//Returns 1 if we need to update overlays. 0 otherwise.
/obj/item/bodypart/proc/update_bodypart_damage_state()
if(status == ORGAN_ORGANIC) //Robotic limbs show no damage - RR
var/tbrute = round( (brute_dam/max_damage)*3, 1 )
var/tburn = round( (burn_dam/max_damage)*3, 1 )
if((tbrute != brutestate) || (tburn != burnstate))
brutestate = tbrute
burnstate = tburn
return 1
return 0
var/tbrute = round( (brute_dam/max_damage)*3, 1 )
var/tburn = round( (burn_dam/max_damage)*3, 1 )
if((tbrute != brutestate) || (tburn != burnstate))
brutestate = tbrute
burnstate = tburn
return 1
return 0
@@ -183,47 +190,57 @@
owner.update_damage_overlays()
//we inform the bodypart of the changes that happened to the owner, or give it the informations from a source mob.
/obj/item/bodypart/proc/update_limb(dropping_limb, mob/living/carbon/human/source)
var/mob/living/carbon/human/H
/obj/item/bodypart/proc/update_limb(dropping_limb, mob/living/carbon/source)
var/mob/living/carbon/C
if(source)
H = source
C = source
else
H = owner
if(!istype(H))
return
C = owner
should_draw_greyscale = FALSE
if(!animal_origin)
var/mob/living/carbon/human/H = C
should_draw_greyscale = FALSE
var/datum/species/S = H.dna.species
species_id = S.limbs_id
var/datum/species/S = H.dna.species
species_id = S.limbs_id
species_flags_list = H.dna.species.specflags
if(S.use_skintones)
skin_tone = H.skin_tone
should_draw_greyscale = TRUE
else
skin_tone = ""
body_gender = H.gender
should_draw_gender = S.sexes
if(MUTCOLORS in S.specflags)
if(S.fixed_mut_color)
species_color = S.fixed_mut_color
if(S.use_skintones)
skin_tone = H.skin_tone
should_draw_greyscale = TRUE
else
species_color = H.dna.features["mcolor"]
should_draw_greyscale = TRUE
else
species_color = ""
skin_tone = ""
if(H.disabilities & HUSK)
species_id = "husk"
body_gender = H.gender
should_draw_gender = S.sexes
if(MUTCOLORS in S.specflags)
if(S.fixed_mut_color)
species_color = S.fixed_mut_color
else
species_color = H.dna.features["mcolor"]
should_draw_greyscale = TRUE
else
species_color = ""
if(!dropping_limb && H.dna.check_mutation(HULK))
mutation_color = "00aa00"
else
mutation_color = ""
dmg_overlay_type = S.damage_overlay_type
else if(animal_origin == MONKEY_BODYPART) //currently monkeys are the only non human mob to have damage overlays.
dmg_overlay_type = animal_origin
if(C.disabilities & HUSK)
species_id = "husk" //overrides species_id
dmg_overlay_type = "" //no damage overlay shown when husked
should_draw_gender = FALSE
should_draw_greyscale = FALSE
if(!dropping_limb && H.dna.check_mutation(HULK))
mutation_color = "00aa00"
else
mutation_color = ""
if(status == BODYPART_ROBOTIC)
dmg_overlay_type = "robotic"
if(dropping_limb)
no_update = 1 //when attached, the limb won't be affected by the appearance changes of its mob owner.
@@ -231,25 +248,49 @@
//to update the bodypart's icon when not attached to a mob
/obj/item/bodypart/proc/update_icon_dropped()
cut_overlays()
var/image/I = get_limb_icon(1)
if(I)
var/list/standing = get_limb_icon(1)
if(!standing.len)
icon_state = initial(icon_state)//no overlays found, we default back to initial icon.
return
for(var/image/I in standing)
I.pixel_x = px_x
I.pixel_y = px_y
add_overlay(I)
add_overlay(standing)
//Gives you a proper icon appearance for the dismembered limb
/obj/item/bodypart/proc/get_limb_icon(dropped)
var/image/I
icon_state = "" //to erase the default sprite, we're building the visual aspects of the bodypart through overlays alone.
var/list/standing = list()
var/image_dir
if(dropped)
image_dir = SOUTH
if(dmg_overlay_type)
if(brutestate)
standing += image("icon"='icons/mob/dam_mob.dmi', "icon_state"="[dmg_overlay_type]_[body_zone]_[brutestate]0", "layer"=-DAMAGE_LAYER, "dir"=image_dir)
if(burnstate)
standing += image("icon"='icons/mob/dam_mob.dmi', "icon_state"="[dmg_overlay_type]_[body_zone]_0[burnstate]", "layer"=-DAMAGE_LAYER, "dir"=image_dir)
if(animal_origin)
if(status == BODYPART_ORGANIC)
if(species_id == "husk")
standing += image("icon"='icons/mob/animal_parts.dmi', "icon_state"="[animal_origin]_husk_[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
else
standing += image("icon"='icons/mob/animal_parts.dmi', "icon_state"="[animal_origin]_[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
else
standing += image("icon"='icons/mob/augments.dmi', "icon_state"="[animal_origin]_[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
return standing
var/icon_gender = (body_gender == FEMALE) ? "f" : "m" //gender of the icon, if applicable
if((body_zone != "head" && body_zone != "chest"))
should_draw_gender = FALSE
var/image_dir
if(dropped)
image_dir = SOUTH
if(status == ORGAN_ORGANIC)
var/image/I
if(status == BODYPART_ORGANIC)
if(should_draw_greyscale)
if(should_draw_gender)
I = image("icon"='icons/mob/human_parts_greyscale.dmi', "icon_state"="[species_id]_[body_zone]_[icon_gender]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
@@ -265,11 +306,13 @@
I = image("icon"='icons/mob/augments.dmi', "icon_state"="[body_zone]_[icon_gender]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
else
I = image("icon"='icons/mob/augments.dmi', "icon_state"="[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
return I
standing += I
return standing
if(!should_draw_greyscale)
return I
standing += I
return standing
//Greyscale Colouring
var/draw_color
@@ -284,13 +327,15 @@
if(draw_color)
I.color = "#[draw_color]"
//End Greyscale Colouring
standing += I
return I
return standing
/obj/item/bodypart/chest
name = "chest"
desc = "It's impolite to stare at a person's chest."
icon_state = "default_human_chest"
max_damage = 200
body_zone = "chest"
body_part = CHEST
@@ -303,12 +348,43 @@
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_s"
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_s"
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
body_zone ="l_arm"
@@ -316,10 +392,32 @@
px_x = -6
px_y = 0
/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_s"
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 = "r_arm"
@@ -327,10 +425,32 @@
px_x = 6
px_y = 0
/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_s"
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 = "l_leg"
@@ -338,12 +458,33 @@
px_x = -2
px_y = 12
/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_s"
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 = "r_leg"
@@ -351,6 +492,26 @@
px_x = 2
px_y = 12
/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_s"
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
/////////////////////////////////////////////////////////////////////////
+136 -131
View File
@@ -1,26 +1,33 @@
/obj/item/bodypart/proc/can_dismember(obj/item/I)
. = (get_damage() >= (max_damage - I.armour_penetration/2))
if(dismemberable)
. = (get_damage() >= (max_damage - I.armour_penetration/2))
//Dismember a limb
/obj/item/bodypart/proc/dismember(dam_type = BRUTE)
var/mob/living/carbon/human/H = owner
if(!istype(H) || (NODISMEMBER in H.dna.species.specflags)) // species don't allow dismemberment
if(!owner)
return 0
var/mob/living/carbon/C = owner
if(!dismemberable)
return 0
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(NODISMEMBER in H.dna.species.specflags) // species don't allow dismemberment
return 0
var/obj/item/bodypart/affecting = H.get_bodypart("chest")
var/obj/item/bodypart/affecting = C.get_bodypart("chest")
affecting.take_damage(Clamp(brute_dam/2, 15, 50), Clamp(burn_dam/2, 0, 50)) //Damage the chest based on limb's existing damage
H.visible_message("<span class='danger'><B>[H]'s [src.name] has been violently dismembered!</B></span>")
H.emote("scream")
C.visible_message("<span class='danger'><B>[C]'s [src.name] has been violently dismembered!</B></span>")
C.emote("scream")
drop_limb()
if(dam_type == BURN)
burn()
return 1
add_mob_blood(H)
var/turf/location = H.loc
add_mob_blood(C)
var/turf/location = C.loc
if(istype(location))
H.add_splatter_floor(location)
C.add_splatter_floor(location)
var/direction = pick(cardinal)
var/t_range = rand(2,max(throw_range/2, 2))
var/turf/target_turf = get_turf(src)
@@ -34,92 +41,100 @@
/obj/item/bodypart/chest/dismember()
var/mob/living/carbon/human/H = owner
if(!istype(H) || (NODISMEMBER in H.dna.species.specflags)) //human's species don't allow dismemberment
if(!owner)
return 0
var/mob/living/carbon/C = owner
if(!dismemberable)
return 0
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(NODISMEMBER in H.dna.species.specflags) // species don't allow dismemberment
return 0
var/organ_spilled = 0
var/turf/T = get_turf(H)
H.add_splatter_floor(T)
playsound(get_turf(owner), 'sound/misc/splort.ogg', 80, 1)
for(var/X in owner.internal_organs)
var/turf/T = get_turf(C)
C.add_splatter_floor(T)
playsound(get_turf(C), 'sound/misc/splort.ogg', 80, 1)
for(var/X in C.internal_organs)
var/obj/item/organ/O = X
if(O.zone != "chest")
var/org_zone = check_zone(O.zone)
if(org_zone != "chest")
continue
O.Remove(owner)
O.loc = T
O.Remove(C)
O.forceMove(T)
organ_spilled = 1
if(cavity_item)
cavity_item.loc = T
cavity_item.forceMove(T)
cavity_item = null
organ_spilled = 1
if(organ_spilled)
owner.visible_message("<span class='danger'><B>[owner]'s internal organs spill out onto the floor!</B></span>")
C.visible_message("<span class='danger'><B>[C]'s internal organs spill out onto the floor!</B></span>")
return 1
//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)
if(!ishuman(owner))
if(!owner)
return
var/turf/T = get_turf(owner)
var/mob/living/carbon/human/H = owner
var/mob/living/carbon/C = owner
if(!no_update)
update_limb(1)
H.bodyparts -= src
C.bodyparts -= src
if(held_index)
H.unEquip(owner.get_item_for_held_index(held_index), 1)
H.hand_bodyparts[held_index] = null
C.unEquip(owner.get_item_for_held_index(held_index), 1)
C.hand_bodyparts[held_index] = null
owner = null
for(var/X in H.surgeries) //if we had an ongoing surgery on that limb, we stop it.
for(var/X in C.surgeries) //if we had an ongoing surgery on that limb, we stop it.
var/datum/surgery/S = X
if(S.organ == src)
H.surgeries -= S
if(S.operated_bodypart == src)
C.surgeries -= S
qdel(S)
break
for(var/obj/item/I in embedded_objects)
embedded_objects -= I
I.loc = src
if(!H.has_embedded_objects())
H.clear_alert("embeddedobject")
if(!C.has_embedded_objects())
C.clear_alert("embeddedobject")
if(!special)
for(var/X in H.dna.mutations) //some mutations require having specific limbs to be kept.
var/datum/mutation/human/MT = X
if(MT.limb_req && MT.limb_req == body_zone)
MT.force_lose(H)
if(C.dna)
for(var/X in C.dna.mutations) //some mutations require having specific limbs to be kept.
var/datum/mutation/human/MT = X
if(MT.limb_req && MT.limb_req == body_zone)
MT.force_lose(C)
for(var/X in H.internal_organs) //internal organs inside the dismembered limb are dropped.
for(var/X in C.internal_organs) //internal organs inside the dismembered limb are dropped.
var/obj/item/organ/O = X
var/org_zone = check_zone(O.zone)
if(org_zone != body_zone)
continue
O.transfer_to_limb(src, H)
O.transfer_to_limb(src, C)
update_icon_dropped()
src.loc = T
H.update_health_hud() //update the healthdoll
H.update_body()
H.update_hair()
H.update_canmove()
forceMove(T)
C.update_health_hud() //update the healthdoll
C.update_body()
C.update_hair()
C.update_canmove()
//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/human/H)
Remove(H)
/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C)
Remove(C)
loc = LB
/obj/item/organ/brain/transfer_to_limb(obj/item/bodypart/head/LB, mob/living/carbon/human/H)
if(H.mind && H.mind.changeling)
/obj/item/organ/brain/transfer_to_limb(obj/item/bodypart/head/LB, mob/living/carbon/human/C)
if(C.mind && C.mind.changeling)
LB.brain = new //changeling doesn't lose its real brain organ, we drop a decoy.
LB.brain.loc = LB
else //if not a changeling, we put the brain organ inside the dropped head
Remove(H) //and put the player in control of the brainmob
Remove(C) //and put the player in control of the brainmob
loc = LB
LB.brain = src
LB.brainmob = brainmob
@@ -133,39 +148,39 @@
return
/obj/item/bodypart/r_arm/drop_limb(special)
var/mob/living/carbon/human/H = owner
var/mob/living/carbon/C = owner
..()
if(istype(H) && !special)
if(H.handcuffed)
H.handcuffed.loc = H.loc
H.handcuffed.dropped(H)
H.handcuffed = null
H.update_handcuffed()
if(H.hud_used)
var/obj/screen/inventory/hand/R = H.hud_used.hand_slots["[held_index]"]
if(C && !special)
if(C.handcuffed)
C.handcuffed.loc = C.loc
C.handcuffed.dropped(C)
C.handcuffed = null
C.update_handcuffed()
if(C.hud_used)
var/obj/screen/inventory/hand/R = C.hud_used.hand_slots["[held_index]"]
if(R)
R.update_icon()
if(H.gloves)
H.unEquip(H.gloves, 1)
H.update_inv_gloves() //to remove the bloody hands overlay
if(C.gloves)
C.unEquip(C.gloves, 1)
C.update_inv_gloves() //to remove the bloody hands overlay
/obj/item/bodypart/l_arm/drop_limb(special)
var/mob/living/carbon/human/H = owner
var/mob/living/carbon/C = owner
..()
if(istype(H) && !special)
if(H.handcuffed)
H.handcuffed.loc = H.loc
H.handcuffed.dropped(H)
H.handcuffed = null
H.update_handcuffed()
if(H.hud_used)
var/obj/screen/inventory/hand/L = H.hud_used.hand_slots["[held_index]"]
if(C && !special)
if(C.handcuffed)
C.handcuffed.loc = C.loc
C.handcuffed.dropped(C)
C.handcuffed = null
C.update_handcuffed()
if(C.hud_used)
var/obj/screen/inventory/hand/L = C.hud_used.hand_slots["[held_index]"]
if(L)
L.update_icon()
if(H.gloves)
H.unEquip(H.gloves, 1)
H.update_inv_gloves() //to remove the bloody hands overlay
if(C.gloves)
C.unEquip(C.gloves, 1)
C.update_inv_gloves() //to remove the bloody hands overlay
/obj/item/bodypart/r_leg/drop_limb(special)
@@ -176,10 +191,8 @@
owner.legcuffed.dropped(owner)
owner.legcuffed = null
owner.update_inv_legcuffed()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.shoes)
H.unEquip(H.shoes, 1)
if(owner.shoes)
owner.unEquip(owner.shoes, 1)
..()
/obj/item/bodypart/l_leg/drop_limb(special) //copypasta
@@ -190,21 +203,17 @@
owner.legcuffed.dropped(owner)
owner.legcuffed = null
owner.update_inv_legcuffed()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.shoes)
H.unEquip(H.shoes, 1)
if(owner.shoes)
owner.unEquip(owner.shoes, 1)
..()
/obj/item/bodypart/head/drop_limb(special)
var/mob/living/carbon/human/H = owner
if(istype(H))
if(!special)
//Drop all worn head items
for(var/X in list(H.glasses, H.ears, H.wear_mask, H.head))
var/obj/item/I = X
H.unEquip(I, 1)
name = "[H]'s head"
if(!special)
//Drop all worn head items
for(var/X in list(owner.glasses, owner.ears, owner.wear_mask, owner.head))
var/obj/item/I = X
owner.unEquip(I, 1)
name = "[owner]'s head"
..()
@@ -213,81 +222,76 @@
//Attach a limb to a human and drop any existing limb of that type.
/obj/item/bodypart/proc/replace_limb(mob/living/carbon/human/H, special)
if(!istype(H))
/obj/item/bodypart/proc/replace_limb(mob/living/carbon/C, special)
if(!istype(C))
return
var/obj/item/bodypart/O = locate(src.type) in H.bodyparts
var/obj/item/bodypart/O = locate(src.type) in C.bodyparts
if(O)
O.drop_limb(1)
attach_limb(H, special)
attach_limb(C, special)
/obj/item/bodypart/head/replace_limb(mob/living/carbon/human/H, special)
if(!istype(H))
/obj/item/bodypart/head/replace_limb(mob/living/carbon/C, special)
if(!istype(C))
return
var/obj/item/bodypart/head/O = locate(src.type) in H.bodyparts
var/obj/item/bodypart/head/O = locate(src.type) in C.bodyparts
if(O)
if(!special)
return
else
O.drop_limb(1)
attach_limb(H, special)
attach_limb(C, special)
/obj/item/bodypart/proc/attach_limb(mob/living/carbon/human/H, special)
/obj/item/bodypart/proc/attach_limb(mob/living/carbon/C, special)
loc = null
owner = H
H.bodyparts += src
owner = C
C.bodyparts += src
if(held_index)
C.hand_bodyparts += src
if(C.hud_used)
var/obj/screen/inventory/hand/hand = C.hud_used.hand_slots["[held_index]"]
if(hand)
hand.update_icon()
C.update_inv_gloves()
if(special) //non conventional limb attachment
for(var/X in H.surgeries) //if we had an ongoing surgery to attach a new limb, we stop it.
for(var/X in C.surgeries) //if we had an ongoing surgery to attach a new limb, we stop it.
var/datum/surgery/S = X
var/surgery_zone = check_zone(S.location)
if(surgery_zone == body_zone)
H.surgeries -= S
C.surgeries -= S
qdel(S)
break
update_bodypart_damage_state()
H.updatehealth()
H.update_body()
H.update_hair()
H.update_damage_overlays()
H.update_canmove()
C.updatehealth()
C.update_body()
C.update_hair()
C.update_damage_overlays()
C.update_canmove()
/obj/item/bodypart/r_arm/attach_limb(mob/living/carbon/human/H, special)
..()
if(H.hud_used)
var/obj/screen/inventory/hand/R = H.hud_used.hand_slots["[held_index]"]
if(R)
R.update_icon()
/obj/item/bodypart/l_arm/attach_limb(mob/living/carbon/human/H, special)
..()
if(H.hud_used)
var/obj/screen/inventory/hand/L = H.hud_used.hand_slots["[held_index]"]
if(L)
L.update_icon()
/obj/item/bodypart/head/attach_limb(mob/living/carbon/human/H, special)
/obj/item/bodypart/head/attach_limb(mob/living/carbon/C, special)
//Transfer some head appearance vars over
if(brain)
brainmob.container = null //Reset brainmob head var.
brainmob.loc = brain //Throw mob into brain.
brain.brainmob = brainmob //Set the brain to use the brainmob
brainmob = null //Set head brainmob var to null
brain.Insert(H) //Now insert the brain proper
brain.Insert(C) //Now insert the brain proper
brain = null //No more brain in the head
H.hair_color = hair_color
H.hair_style = hair_style
H.facial_hair_color = facial_hair_color
H.facial_hair_style = facial_hair_style
H.eye_color = eye_color
H.lip_style = lip_style
H.lip_color = lip_color
if(ishuman(C))
var/mob/living/carbon/human/H = C
H.hair_color = hair_color
H.hair_style = hair_style
H.facial_hair_color = facial_hair_color
H.facial_hair_style = facial_hair_style
H.eye_color = eye_color
H.lip_style = lip_style
H.lip_color = lip_color
if(real_name)
H.real_name = real_name
C.real_name = real_name
real_name = ""
name = initial(name)
..()
@@ -297,21 +301,22 @@
/mob/living/proc/regenerate_limbs(noheal, excluded_limbs)
return 0
/mob/living/carbon/human/regenerate_limbs(noheal, list/excluded_limbs)
/mob/living/carbon/regenerate_limbs(noheal, list/excluded_limbs)
var/list/limb_list = list("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg")
if(excluded_limbs)
limb_list -= excluded_limbs
for(var/Z in limb_list)
. += regenerate_limb(Z, noheal)
/
/mob/living/proc/regenerate_limb(limb_zone, noheal)
return
/mob/living/carbon/human/regenerate_limb(limb_zone, noheal)
/mob/living/carbon/regenerate_limb(limb_zone, noheal)
var/obj/item/bodypart/L
if(get_bodypart(limb_zone))
return 0
L = newBodyPart(limb_zone, 0, 0, src)
L = newBodyPart(limb_zone, 0, 0)
if(L)
if(!noheal)
L.brute_dam = 0
+103 -60
View File
@@ -1,6 +1,8 @@
/obj/item/bodypart/head
name = "head"
desc = "Didn't make sense not to live for fun, your brain gets smart but your head gets dumb."
icon = 'icons/mob/human_parts.dmi'
icon_state = "default_human_head"
max_damage = 200
body_zone = "head"
body_part = HEAD
@@ -10,7 +12,7 @@
px_x = 0
px_y = -8
var/mob/living/carbon/brain/brainmob = null //The current occupant.
var/mob/living/brain/brainmob = null //The current occupant.
var/obj/item/organ/brain/brain = null //The brain organ
//Limb appearance info:
@@ -30,7 +32,8 @@
/obj/item/bodypart/head/drop_organs(mob/user)
var/turf/T = get_turf(src)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
if(status != BODYPART_ROBOTIC)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
for(var/obj/item/I in src)
if(I == brain)
if(user)
@@ -46,67 +49,77 @@
else
I.loc = T
/obj/item/bodypart/head/update_limb(dropping_limb, mob/living/carbon/human/source)
var/mob/living/carbon/human/H
/obj/item/bodypart/head/update_limb(dropping_limb, mob/living/carbon/source)
var/mob/living/carbon/C
if(source)
H = source
C = source
else
H = owner
if(!istype(H))
return
var/datum/species/S = H.dna.species
//First of all, name.
real_name = H.real_name
C = owner
//Facial hair
if(H.facial_hair_style && (FACEHAIR in S.specflags))
facial_hair_style = H.facial_hair_style
if(S.hair_color)
if(S.hair_color == "mutcolor")
facial_hair_color = H.dna.features["mcolor"]
else
facial_hair_color = S.hair_color
else
facial_hair_color = H.facial_hair_color
hair_alpha = S.hair_alpha
else
facial_hair_style = "Shaved"
facial_hair_color = "000"
hair_alpha = 255
//Hair
if(H.hair_style && (HAIR in S.specflags))
hair_style = H.hair_style
if(S.hair_color)
if(S.hair_color == "mutcolor")
hair_color = H.dna.features["mcolor"]
else
hair_color = S.hair_color
else
hair_color = H.hair_color
hair_alpha = S.hair_alpha
else
real_name = C.real_name
if(C.disabilities & HUSK)
real_name = "Unknown"
hair_style = "Bald"
hair_color = "000"
hair_alpha = initial(hair_alpha)
// lipstick
if(H.lip_style && (LIPS in S.specflags))
lip_style = H.lip_style
lip_color = H.lip_color
else
lip_style = null
lip_color = "white"
// eyes
if(EYECOLOR in S.specflags)
eyes = S.eyes
eye_color = H.eye_color
else
facial_hair_style = "Shaved"
eyes = "eyes"
eye_color = ""
lip_style = null
else if(!animal_origin)
var/mob/living/carbon/human/H = C
var/datum/species/S = H.dna.species
//Facial hair
if(H.facial_hair_style && (FACEHAIR in S.specflags))
facial_hair_style = H.facial_hair_style
if(S.hair_color)
if(S.hair_color == "mutcolor")
facial_hair_color = H.dna.features["mcolor"]
else
facial_hair_color = S.hair_color
else
facial_hair_color = H.facial_hair_color
hair_alpha = S.hair_alpha
else
facial_hair_style = "Shaved"
facial_hair_color = "000"
hair_alpha = 255
//Hair
if(H.hair_style && (HAIR in S.specflags))
hair_style = H.hair_style
if(S.hair_color)
if(S.hair_color == "mutcolor")
hair_color = H.dna.features["mcolor"]
else
hair_color = S.hair_color
else
hair_color = H.hair_color
hair_alpha = S.hair_alpha
else
hair_style = "Bald"
hair_color = "000"
hair_alpha = initial(hair_alpha)
// lipstick
if(H.lip_style && (LIPS in S.specflags))
lip_style = H.lip_style
lip_color = H.lip_color
else
lip_style = null
lip_color = "white"
// eyes
if(EYECOLOR in S.specflags)
eyes = S.eyes
eye_color = H.eye_color
else
eyes = "eyes"
eye_color = ""
..()
/obj/item/bodypart/head/update_icon_dropped()
var/list/standing = get_limb_icon(1)
if(!standing)
if(!standing.len)
icon_state = initial(icon_state)//no overlays found, we default back to initial icon.
return
for(var/image/I in standing)
I.pixel_x = px_x
@@ -115,13 +128,11 @@
/obj/item/bodypart/head/get_limb_icon(dropped)
cut_overlays()
var/image/I = ..()
var/list/standing = list()
standing += I
var/list/standing = ..()
if(dropped) //certain overlays only appear when the limb is being detached from its owner.
var/datum/sprite_accessory/S
if(status != ORGAN_ROBOTIC) //having a robotic head hides certain features.
if(status != BODYPART_ROBOTIC) //having a robotic head hides certain features.
//facial hair
if(facial_hair_style)
S = facial_hair_styles_list[facial_hair_style]
@@ -133,7 +144,12 @@
//Applies the debrained overlay if there is no brain
if(!brain)
standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER, "dir"=SOUTH)
if(animal_origin == ALIEN_BODYPART)
standing += image("icon"='icons/mob/animal_parts.dmi', "icon_state" = "debrained_alien_s", "layer" = -HAIR_LAYER, "dir"=SOUTH)
else if(animal_origin == LARVA_BODYPART)
standing += image("icon"='icons/mob/animal_parts.dmi', "icon_state" = "debrained_larva_s", "layer" = -HAIR_LAYER, "dir"=SOUTH)
else if(!(NOBLOOD in species_flags_list))
standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER, "dir"=SOUTH)
else
if(hair_style)
S = hair_styles_list[hair_style]
@@ -156,9 +172,36 @@
img_eyes_s.color = "#" + eye_color
standing += img_eyes_s
if(standing.len)
return standing
return standing
/obj/item/bodypart/head/burn()
drop_organs()
..()
/obj/item/bodypart/head/monkey
icon = 'icons/mob/animal_parts.dmi'
icon_state = "default_monkey_head"
animal_origin = MONKEY_BODYPART
/obj/item/bodypart/head/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_head_s"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 500
animal_origin = ALIEN_BODYPART
/obj/item/bodypart/head/devil
dismemberable = 0
max_damage = 5000
animal_origin = DEVIL_BODYPART
/obj/item/bodypart/head/larva
icon = 'icons/mob/animal_parts.dmi'
icon_state = "larva_head_s"
px_x = 0
px_y = 0
dismemberable = 0
max_damage = 50
animal_origin = LARVA_BODYPART
+112 -31
View File
@@ -10,47 +10,48 @@
if(L.body_zone == zone)
return L
/mob/living/carbon/human/has_hand_for_held_index(i)
/mob/living/carbon/has_hand_for_held_index(i)
if(i)
var/obj/item/bodypart/L = hand_bodyparts[i]
if(L)
return L
return FALSE
/mob/proc/has_left_hand()
return TRUE
/mob/living/carbon/human/has_left_hand()
/mob/living/carbon/has_left_hand()
for(var/obj/item/bodypart/L in hand_bodyparts)
if(L.held_index % 2)
return TRUE
return FALSE
/mob/living/carbon/alien/larva/has_left_hand()
return 1
/mob/proc/has_right_hand()
return TRUE
/mob/living/carbon/has_right_hand()
for(var/obj/item/bodypart/L in hand_bodyparts)
if(!(L.held_index % 2))
return TRUE
return FALSE
/mob/proc/has_right_hand()
return TRUE
/mob/living/carbon/alien/larva/has_right_hand()
return 1
/mob/living/carbon/human/has_right_hand()
for(var/obj/item/bodypart/L in hand_bodyparts)
if(L.held_index % 2)
return TRUE
return FALSE
//Limb numbers
/mob/proc/get_num_arms()
return 2
/mob/proc/get_num_legs()
return 2
/mob/proc/get_leg_ignore()
return 0
/mob/living/carbon/human/get_leg_ignore()
if(FLYING in dna.species.specflags)
return 1
/mob/living/carbon/human/get_num_arms()
/mob/living/carbon/get_num_arms()
. = 0
for(var/X in bodyparts)
var/obj/item/bodypart/affecting = X
@@ -59,7 +60,19 @@
if(affecting.body_part == ARM_LEFT)
.++
/mob/living/carbon/human/get_num_legs()
//sometimes we want to ignore that we don't have the required amount of arms.
/mob/proc/get_arm_ignore()
return 0
/mob/living/carbon/alien/larva/get_arm_ignore()
return 1 //so we can still handcuff larvas.
/mob/proc/get_num_legs()
return 2
/mob/living/carbon/get_num_legs()
. = 0
for(var/X in bodyparts)
var/obj/item/bodypart/affecting = X
@@ -68,19 +81,36 @@
if(affecting.body_part == LEG_LEFT)
.++
//sometimes we want to ignore that we don't have the required amount of legs.
/mob/proc/get_leg_ignore()
return 0
/mob/living/carbon/alien/larva/get_leg_ignore()
return 1
/mob/living/carbon/human/get_leg_ignore()
if(FLYING in dna.species.specflags)
return 1
/mob/living/proc/get_missing_limbs()
return list()
/mob/living/carbon/human/get_missing_limbs()
/mob/living/carbon/get_missing_limbs()
var/list/full = list("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg")
for(var/zone in full)
if(get_bodypart(zone))
full -= zone
return full
/mob/living/carbon/alien/larva/get_missing_limbs()
var/list/full = list("head", "chest")
for(var/zone in full)
if(get_bodypart(zone))
full -= zone
return full
//Remove all embedded objects from all limbs on the human mob
/mob/living/carbon/human/proc/remove_all_embedded_objects()
//Remove all embedded objects from all limbs on the carbon mob
/mob/living/carbon/proc/remove_all_embedded_objects()
var/turf/T = get_turf(src)
for(var/X in bodyparts)
@@ -91,7 +121,7 @@
clear_alert("embeddedobject")
/mob/living/carbon/human/proc/has_embedded_objects()
/mob/living/carbon/proc/has_embedded_objects()
. = 0
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
@@ -100,7 +130,7 @@
//Helper for quickly creating a new limb - used by augment code in species.dm spec_attacked_by
/proc/newBodyPart(zone, robotic, fixed_icon, mob/living/carbon/human/source)
/mob/living/carbon/proc/newBodyPart(zone, robotic, fixed_icon)
var/obj/item/bodypart/L
switch(zone)
if("l_arm")
@@ -116,13 +146,64 @@
if("chest")
L = new /obj/item/bodypart/chest()
if(L)
if(source)
L.update_limb(fixed_icon, source)
else if(fixed_icon)
L.no_update = 1//when attached, the limb won't be affected by the appearance changes of its mob owner.
L.update_limb(fixed_icon, src)
if(robotic)
L.change_bodypart_status(ORGAN_ROBOTIC)
L.change_bodypart_status(BODYPART_ROBOTIC)
. = L
/mob/living/carbon/monkey/newBodyPart(zone, robotic, fixed_icon)
var/obj/item/bodypart/L
switch(zone)
if("l_arm")
L = new /obj/item/bodypart/l_arm/monkey()
if("r_arm")
L = new /obj/item/bodypart/r_arm/monkey()
if("head")
L = new /obj/item/bodypart/head/monkey()
if("l_leg")
L = new /obj/item/bodypart/l_leg/monkey()
if("r_leg")
L = new /obj/item/bodypart/r_leg/monkey()
if("chest")
L = new /obj/item/bodypart/chest/monkey()
if(L)
L.update_limb(fixed_icon, src)
if(robotic)
L.change_bodypart_status(BODYPART_ROBOTIC)
. = L
/mob/living/carbon/alien/larva/newBodyPart(zone, robotic, fixed_icon)
var/obj/item/bodypart/L
switch(zone)
if("head")
L = new /obj/item/bodypart/head/larva()
if("chest")
L = new /obj/item/bodypart/chest/larva()
if(L)
L.update_limb(fixed_icon, src)
if(robotic)
L.change_bodypart_status(BODYPART_ROBOTIC)
. = L
/mob/living/carbon/alien/humanoid/newBodyPart(zone, robotic, fixed_icon)
var/obj/item/bodypart/L
switch(zone)
if("l_arm")
L = new /obj/item/bodypart/l_arm/alien()
if("r_arm")
L = new /obj/item/bodypart/r_arm/alien()
if("head")
L = new /obj/item/bodypart/head/alien()
if("l_leg")
L = new /obj/item/bodypart/l_leg/alien()
if("r_leg")
L = new /obj/item/bodypart/r_leg/alien()
if("chest")
L = new /obj/item/bodypart/chest/alien()
if(L)
L.update_limb(fixed_icon, src)
if(robotic)
L.change_bodypart_status(BODYPART_ROBOTIC)
. = L
@@ -0,0 +1,162 @@
/obj/item/bodypart/l_arm/robot
name = "cyborg left arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
attack_verb = list("slapped", "punched")
item_state = "buildpipe"
icon = 'icons/obj/robot_parts.dmi'
flags = CONDUCT
icon_state = "l_arm"
status = BODYPART_ROBOTIC
/obj/item/bodypart/r_arm/robot
name = "cyborg right arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
attack_verb = list("slapped", "punched")
item_state = "buildpipe"
icon = 'icons/obj/robot_parts.dmi'
flags = CONDUCT
icon_state = "r_arm"
status = BODYPART_ROBOTIC
/obj/item/bodypart/l_leg/robot
name = "cyborg left leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
attack_verb = list("kicked", "stomped")
item_state = "buildpipe"
icon = 'icons/obj/robot_parts.dmi'
flags = CONDUCT
icon_state = "l_leg"
status = BODYPART_ROBOTIC
/obj/item/bodypart/r_leg/robot
name = "cyborg right leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
attack_verb = list("kicked", "stomped")
item_state = "buildpipe"
icon = 'icons/obj/robot_parts.dmi'
flags = CONDUCT
icon_state = "r_leg"
status = BODYPART_ROBOTIC
/obj/item/bodypart/chest/robot
name = "cyborg torso"
desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell."
item_state = "buildpipe"
icon = 'icons/obj/robot_parts.dmi'
flags = CONDUCT
icon_state = "chest"
status = BODYPART_ROBOTIC
var/wired = 0
var/obj/item/weapon/stock_parts/cell/cell = null
/obj/item/bodypart/chest/robot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/stock_parts/cell))
if(src.cell)
user << "<span class='warning'>You have already inserted a cell!</span>"
return
else
if(!user.unEquip(W))
return
W.loc = src
src.cell = W
user << "<span class='notice'>You insert the cell.</span>"
else if(istype(W, /obj/item/stack/cable_coil))
if(src.wired)
user << "<span class='warning'>You have already inserted wire!</span>"
return
var/obj/item/stack/cable_coil/coil = W
if (coil.use(1))
src.wired = 1
user << "<span class='notice'>You insert the wire.</span>"
else
user << "<span class='warning'>You need one length of coil to wire it!</span>"
else
return ..()
/obj/item/bodypart/chest/robot/Destroy()
if(cell)
qdel(cell)
cell = null
return ..()
/obj/item/bodypart/chest/robot/drop_organs(mob/user)
if(wired)
new /obj/item/stack/cable_coil(user.loc, 1)
if(cell)
cell.forceMove(user.loc)
cell = null
..()
/obj/item/bodypart/head/robot
name = "cyborg head"
desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals."
item_state = "buildpipe"
icon = 'icons/obj/robot_parts.dmi'
flags = CONDUCT
icon_state = "head"
status = BODYPART_ROBOTIC
var/obj/item/device/assembly/flash/handheld/flash1 = null
var/obj/item/device/assembly/flash/handheld/flash2 = null
/obj/item/bodypart/head/robot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/device/assembly/flash/handheld))
var/obj/item/device/assembly/flash/handheld/F = W
if(src.flash1 && src.flash2)
user << "<span class='warning'>You have already inserted the eyes!</span>"
return
else if(F.crit_fail)
user << "<span class='warning'>You can't use a broken flash!</span>"
return
else
if(!user.unEquip(W))
return
F.loc = src
if(src.flash1)
src.flash2 = F
else
src.flash1 = F
user << "<span class='notice'>You insert the flash into the eye socket.</span>"
else if(istype(W, /obj/item/weapon/crowbar))
if(flash1 || flash2)
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
user << "<span class='notice'>You remove the flash from [src].</span>"
if(flash1)
flash1.forceMove(user.loc)
flash1 = null
if(flash2)
flash2.forceMove(user.loc)
flash2 = null
else
user << "<span class='warning'>There are no flash to remove from [src].</span>"
else
return ..()
/obj/item/bodypart/head/robot/Destroy()
if(flash1)
qdel(flash1)
flash1 = null
if(flash2)
qdel(flash2)
flash2 = null
return ..()
/obj/item/bodypart/head/robot/drop_organs(mob/user)
if(flash1)
flash1.forceMove(user.loc)
flash1 = null
if(flash2)
flash2.forceMove(user.loc)
flash2 = null
..()
+3 -5
View File
@@ -21,7 +21,7 @@
/datum/surgery_step/clamp_bleeders/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(locate(/datum/surgery_step/saw) in surgery.steps)
target.heal_organ_damage(20,0)
target.heal_bodypart_damage(20,0)
return ..()
@@ -69,7 +69,7 @@
/datum/surgery_step/close/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(locate(/datum/surgery_step/saw) in surgery.steps)
target.heal_organ_damage(45,0)
target.heal_bodypart_damage(45,0)
return ..()
@@ -84,9 +84,7 @@
user.visible_message("[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].", "<span class='notice'>You begin to saw through the bone in [target]'s [parse_zone(target_zone)]...</span>")
/datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.apply_damage(50,"brute","[target_zone]")
target.apply_damage(50,"brute","[target_zone]")
user.visible_message("[user] saws [target]'s [parse_zone(target_zone)] open!", "<span class='notice'>You saw [target]'s [parse_zone(target_zone)] open.</span>")
return 1
+10 -10
View File
@@ -2,13 +2,13 @@
if(!istype(M))
return
var/mob/living/carbon/human/H
var/mob/living/carbon/C
var/obj/item/bodypart/affecting
var/selected_zone = user.zone_selected
if(istype(M, /mob/living/carbon/human))
H = M
affecting = H.get_bodypart(check_zone(selected_zone))
if(istype(M, /mob/living/carbon))
C = M
affecting = C.get_bodypart(check_zone(selected_zone))
if(!M.lying && !isslime(M)) //if they're prone or a slime
return
@@ -29,9 +29,9 @@
if(affecting)
if(!S.requires_bodypart)
continue
if(S.requires_organic_bodypart && affecting.status == ORGAN_ROBOTIC)
if(S.requires_organic_bodypart && affecting.status == BODYPART_ROBOTIC)
continue
else if(H && S.requires_bodypart) //human with no limb in surgery zone when we need a limb
else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb
continue
if(!S.can_start(user, M))
continue
@@ -49,14 +49,14 @@
return //during the input() another surgery was started at the same location.
//we check that the surgery is still doable after the input() wait.
if(H)
affecting = H.get_bodypart(check_zone(selected_zone))
if(C)
affecting = C.get_bodypart(check_zone(selected_zone))
if(affecting)
if(!S.requires_bodypart)
return
if(S.requires_organic_bodypart && affecting.status == ORGAN_ROBOTIC)
if(S.requires_organic_bodypart && affecting.status == BODYPART_ROBOTIC)
return
else if(H && S.requires_bodypart)
else if(C && S.requires_bodypart)
return
if(!S.can_start(user, M))
return
+11 -13
View File
@@ -16,17 +16,17 @@
/datum/surgery_step/add_limb
name = "replace limb"
implements = list(/obj/item/robot_parts = 100)
implements = list(/obj/item/bodypart = 100)
time = 32
var/obj/item/bodypart/L = null // L because "limb"
/datum/surgery_step/add_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/obj/item/robot_parts/aug = tool
if(istype(aug) && aug.body_zone != target_zone)
var/obj/item/bodypart/aug = tool
if(aug.status != BODYPART_ROBOTIC && aug.body_zone != target_zone)
user << "<span class='warning'>[tool] isn't the right type for [parse_zone(target_zone)].</span>"
return -1
L = surgery.organ
L = surgery.operated_bodypart
if(L)
user.visible_message("[user] begins to augment [target]'s [parse_zone(user.zone_selected)].", "<span class ='notice'>You begin to augment [target]'s [parse_zone(user.zone_selected)]...</span>")
else
@@ -45,15 +45,13 @@
/datum/surgery_step/add_limb/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(L)
if(ishuman(target))
var/mob/living/carbon/human/H = target
user.visible_message("[user] successfully augments [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You successfully augment [target]'s [parse_zone(target_zone)].</span>")
L.change_bodypart_status(ORGAN_ROBOTIC, 1)
user.drop_item()
qdel(tool)
H.update_damage_overlays(0)
H.updatehealth()
add_logs(user, target, "augmented", addition="by giving him new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]")
user.visible_message("[user] successfully augments [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You successfully augment [target]'s [parse_zone(target_zone)].</span>")
L.change_bodypart_status(BODYPART_ROBOTIC, 1)
user.drop_item()
qdel(tool)
target.update_damage_overlays()
target.updatehealth()
add_logs(user, target, "augmented", addition="by giving him new [parse_zone(target_zone)] INTENT: [uppertext(user.a_intent)]")
else
user << "<span class='warning'>[target] has no organic [parse_zone(target_zone)] there!</span>"
return 1
+1 -1
View File
@@ -43,7 +43,7 @@
if(prob(10 * severity))
return
owner << "<span class='warning'>Static obfuscates your vision!</span>"
owner.flash_eyes(visual = 1)
owner.flash_act(visual = 1)
/obj/item/organ/cyberimp/eyes/xray
name = "X-ray implant"
+3 -2
View File
@@ -11,7 +11,7 @@ mob/proc/getorganslot(slot)
mob/living/carbon/getorgan(typepath)
return (locate(typepath) in internal_organs)
mob/living/carbon/getorganszone(zone, var/subzones = 0)
mob/living/carbon/getorganszone(zone, subzones = 0)
var/list/returnorg = list()
if(subzones)
// Include subzones - groin for chest, eyes and mouth for head
@@ -20,7 +20,8 @@ mob/living/carbon/getorganszone(zone, var/subzones = 0)
if(zone == "chest")
returnorg = getorganszone("groin")
for(var/obj/item/organ/O in internal_organs)
for(var/X in internal_organs)
var/obj/item/organ/O = X
if(zone == O.zone)
returnorg += O
return returnorg
+22 -24
View File
@@ -1,52 +1,50 @@
/datum/surgery/prosthetic_replacement
name = "prosthetic replacement"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/add_prosthetic)
species = list(/mob/living/carbon/human)
species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list("r_arm", "l_arm", "l_leg", "r_leg", "head")
requires_bodypart = FALSE //need a missing limb
/datum/surgery/prosthetic_replacement/can_start(mob/user, mob/living/carbon/target)
if(!ishuman(target))
if(!iscarbon(target))
return 0
var/mob/living/carbon/human/H = target
if(!H.get_bodypart(user.zone_selected)) //can only start if limb is missing
var/mob/living/carbon/C = target
if(!C.get_bodypart(user.zone_selected)) //can only start if limb is missing
return 1
/datum/surgery_step/add_prosthetic
name = "add prosthetic"
implements = list(/obj/item/robot_parts = 100, /obj/item/bodypart = 100)
implements = list(/obj/item/bodypart = 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)
var/tool_body_zone
if(istype(tool, /obj/item/robot_parts))
var/obj/item/robot_parts/RP = tool
tool_body_zone = RP.body_zone
else if(istype(tool, /obj/item/bodypart))
var/obj/item/bodypart/L = tool
if(L.status != ORGAN_ROBOTIC)
organ_rejection_dam = 10
if(target.dna.species.id != L.species_id)
var/obj/item/bodypart/BP = tool
if(ismonkey(target))// monkey patient only accept organic monkey limbs
if(BP.status == BODYPART_ROBOTIC || BP.animal_origin != MONKEY_BODYPART)
user << "<span class='warning'>[BP] doesn't match the patient's morphology.</span>"
return -1
if(BP.status != BODYPART_ROBOTIC)
organ_rejection_dam = 10
if(ishuman(target))
if(BP.animal_origin)
user << "<span class='warning'>[BP] doesn't match the patient's morphology.</span>"
return -1
var/mob/living/carbon/human/H = target
if(H.dna.species.id != BP.species_id)
organ_rejection_dam = 30
tool_body_zone = L.body_zone
if(target_zone == tool_body_zone) //so we can't replace a leg with an arm.
if(target_zone == BP.body_zone) //so we can't replace a leg with an arm, or a human arm with a monkey arm.
user.visible_message("[user] begins to replace [target]'s [parse_zone(target_zone)].", "<span class ='notice'>You begin to replace [target]'s [parse_zone(target_zone)]...</span>")
else
user << "<span class='warning'>[tool] isn't the right type for [parse_zone(target_zone)].</span>"
return -1
/datum/surgery_step/add_prosthetic/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/obj/item/bodypart/L
if(istype(tool, /obj/item/robot_parts))
L = newBodyPart(target_zone, 1, 1)
user.drop_item()
qdel(tool)
else
L = tool
user.drop_item()
var/obj/item/bodypart/L = tool
user.drop_item()
L.attach_limb(target)
if(organ_rejection_dam)
target.adjustToxLoss(organ_rejection_dam)
@@ -12,7 +12,7 @@
/datum/surgery_step/remove_object/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
L = surgery.organ
L = surgery.operated_bodypart
if(L)
user.visible_message("[user] looks for objects embedded in [target]'s [parse_zone(user.zone_selected)].", "<span class='notice'>You look for objects embedded in [target]'s [parse_zone(user.zone_selected)]...</span>")
else
+5 -5
View File
@@ -10,26 +10,26 @@
var/list/possible_locs = list() //Multiple locations
var/ignore_clothes = 0 //This surgery ignores clothes
var/mob/living/carbon/target //Operation target mob
var/obj/item/organ/organ //Operable body part
var/obj/item/bodypart/operated_bodypart //Operable body part
var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing.
var/success_multiplier = 0 //Step success propability multiplier
/datum/surgery/New(surgery_target, surgery_location, surgery_organ)
/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart)
..()
if(surgery_target)
target = surgery_target
target.surgeries += src
if(surgery_location)
location = surgery_location
if(surgery_organ)
organ = surgery_organ
if(surgery_bodypart)
operated_bodypart = surgery_bodypart
/datum/surgery/Destroy()
if(target)
target.surgeries -= src
target = null
organ = null
operated_bodypart = null
return ..()