initial commit - cross reference with 5th port - obviously has compile errors

This commit is contained in:
LetterJay
2016-07-03 02:17:19 -05:00
commit 35a1723e98
4355 changed files with 2221257 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
/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)
possible_locs = list("r_arm", "l_arm", "l_leg", "r_leg", "head")
/datum/surgery_step/sever_limb
name = "sever limb"
implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/energy/sword/cyborg/saw = 100, /obj/item/weapon/melee/arm_blade = 80, /obj/item/weapon/twohanded/required/chainsaw = 80, /obj/item/weapon/mounted_chainsaw = 80, /obj/item/weapon/twohanded/fireaxe = 50, /obj/item/weapon/hatchet = 40, /obj/item/weapon/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)
user.visible_message("[user] begins to sever [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You begin to sever [target]'s [parse_zone(target_zone)]...</span>")
/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()
return 1
+359
View File
@@ -0,0 +1,359 @@
/obj/item/bodypart
name = "limb"
desc = "why is it detached..."
force = 3
throwforce = 3
icon_state = ""
var/mob/living/carbon/human/owner = null
var/status = ORGAN_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
var/burnstate = 0
var/brute_dam = 0
var/burn_dam = 0
var/max_damage = 0
var/list/embedded_objects = list()
//Coloring and proper item icon update
var/skin_tone = ""
var/body_gender = ""
var/species_id = ""
var/should_draw_gender = FALSE
var/should_draw_greyscale = FALSE
var/species_color = ""
var/mutation_color = ""
var/no_update = 0
var/px_x = 0
var/px_y = 0
var/state_flags
/obj/item/bodypart/examine(mob/user)
..()
if(brute_dam > 0)
user << "<span class='warning'>This limb has [brute_dam > 30 ? "severe" : "minor"] bruising.</span>"
if(burn_dam > 0)
user << "<span class='warning'>This limb has [burn_dam > 30 ? "severe" : "minor"] burns.</span>"
/obj/item/bodypart/Destroy()
if(owner)
owner.bodyparts -= src
owner = null
return ..()
/obj/item/bodypart/attack(mob/living/carbon/C, mob/user)
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 == 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>")
else
H.visible_message("<span class='warning'>[user] jams [src] into [H]'s empty socket!</span>",\
"<span class='notice'>[user] forces [src] into your empty socket, and it locks into place!</span>")
user.unEquip(src,1)
attach_limb(C)
return
..()
/obj/item/bodypart/attackby(obj/item/W, mob/user, params)
if(W.sharpness)
add_fingerprint(user)
if(!contents.len)
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>")
if(do_after(user, 54, target = src))
drop_organs(user)
else
return ..()
/obj/item/bodypart/throw_impact(atom/hit_atom)
..()
playsound(get_turf(src), 'sound/misc/splort.ogg', 50, 1, -1)
/obj/item/bodypart/proc/drop_organs(mob/user)
var/turf/T = get_turf(src)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
for(var/obj/item/I in src)
I.loc = 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)
if(owner && (owner.status_flags & GODMODE))
return 0 //godmode
brute = max(brute,0)
burn = max(burn,0)
if(status == ORGAN_ROBOTIC) //This makes robolimbs not damageable by chems and makes it stronger
brute = max(0, brute - 5)
burn = max(0, burn - 4)
var/can_inflict = max_damage - (brute_dam + burn_dam)
if(!can_inflict)
return 0
if((brute + burn) < can_inflict)
brute_dam += brute
burn_dam += burn
else
if(brute > 0)
if(burn > 0)
brute = round( (brute/(brute+burn)) * can_inflict, 1 )
burn = can_inflict - brute //gets whatever damage is left over
brute_dam += brute
burn_dam += burn
else
brute_dam += can_inflict
else
if(burn > 0)
burn_dam += can_inflict
else
return 0
if(owner)
owner.updatehealth()
return update_bodypart_damage_state()
//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)
if(robotic && status != ORGAN_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.
return
brute_dam = max(brute_dam - brute, 0)
burn_dam = max(burn_dam - burn, 0)
if(owner)
owner.updatehealth()
return update_bodypart_damage_state()
//Returns total damage...kinda pointless really
/obj/item/bodypart/proc/get_damage()
return brute_dam + burn_dam
//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
//Change organ status
/obj/item/bodypart/proc/change_bodypart_status(new_limb_status, heal_limb)
status = new_limb_status
if(heal_limb)
burn_dam = 0
brute_dam = 0
brutestate = 0
burnstate = 0
if(owner)
owner.updatehealth()
owner.update_body() //if our head becomes robotic, we remove the lizard horns and human hair.
owner.update_hair()
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
if(source)
H = source
else
H = owner
if(!istype(H))
return
should_draw_greyscale = FALSE
var/datum/species/S = H.dna.species
species_id = S.limbs_id
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
else
species_color = H.dna.features["mcolor"]
should_draw_greyscale = TRUE
else
species_color = ""
if(H.disabilities & HUSK)
species_id = "husk"
should_draw_gender = FALSE
should_draw_greyscale = FALSE
if(!dropping_limb && H.dna.check_mutation(HULK))
mutation_color = "00aa00"
else
mutation_color = ""
if(dropping_limb)
no_update = 1 //when attached, the limb won't be affected by the appearance changes of its mob owner.
//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)
I.pixel_x = px_x
I.pixel_y = px_y
add_overlay(I)
//Gives you a proper icon appearance for the dismembered limb
/obj/item/bodypart/proc/get_limb_icon(dropped)
var/image/I
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)
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)
else
I = image("icon"='icons/mob/human_parts_greyscale.dmi', "icon_state"="[species_id]_[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
else
if(should_draw_gender)
I = image("icon"='icons/mob/human_parts.dmi', "icon_state"="[species_id]_[body_zone]_[icon_gender]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
else
I = image("icon"='icons/mob/human_parts.dmi', "icon_state"="[species_id]_[body_zone]_s", "layer"=-BODYPARTS_LAYER, "dir"=image_dir)
else
if(should_draw_gender)
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
if(!should_draw_greyscale)
return I
//Greyscale Colouring
var/draw_color
if(skin_tone) //Limb has skin color variable defined, use it
draw_color = skintone2hex(skin_tone)
if(species_color)
draw_color = species_color
if(mutation_color)
draw_color = mutation_color
if(draw_color)
I.color = "#[draw_color]"
//End Greyscale Colouring
return I
/obj/item/bodypart/chest
name = "chest"
desc = "It's impolite to stare at a person's chest."
max_damage = 200
body_zone = "chest"
body_part = CHEST
px_x = 0
px_y = 0
var/obj/item/cavity_item
/obj/item/bodypart/chest/Destroy()
if(cavity_item)
qdel(cavity_item)
return ..()
/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."
attack_verb = list("slapped", "punched")
max_damage = 50
body_zone ="l_arm"
body_part = ARM_LEFT
px_x = -6
px_y = 0
/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."
attack_verb = list("slapped", "punched")
max_damage = 50
body_zone = "r_arm"
body_part = ARM_RIGHT
px_x = 6
px_y = 0
/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."
attack_verb = list("kicked", "stomped")
max_damage = 50
body_zone = "l_leg"
body_part = LEG_LEFT
px_x = -2
px_y = 12
/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
attack_verb = list("kicked", "stomped")
max_damage = 50
body_zone = "r_leg"
body_part = LEG_RIGHT
px_x = 2
px_y = 12
/////////////////////////////////////////////////////////////////////////
/obj/item/severedtail
name = "tail"
desc = "A severed tail. Somewhere, no doubt, a lizard hater is very \
pleased with themselves."
icon = 'icons/obj/surgery.dmi'
icon_state = "severedtail"
color = "#161"
var/markings = "Smooth"
@@ -0,0 +1,322 @@
/obj/item/bodypart/proc/can_dismember(obj/item/I)
. = (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
return 0
var/obj/item/bodypart/affecting = H.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")
drop_limb()
if(dam_type == BURN)
burn()
return 1
add_mob_blood(H)
var/turf/location = H.loc
if(istype(location))
H.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)
for(var/i in 1 to t_range-1)
var/turf/new_turf = get_step(target_turf, direction)
target_turf = new_turf
if(new_turf.density)
break
throw_at_fast(target_turf, throw_range, throw_speed)
return 1
/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
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/obj/item/organ/O = X
if(O.zone != "chest")
continue
O.Remove(owner)
O.loc = T
organ_spilled = 1
if(cavity_item)
cavity_item.loc = 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>")
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))
return
var/turf/T = get_turf(owner)
var/mob/living/carbon/human/H = owner
if(!no_update)
update_limb(1)
H.bodyparts -= src
owner = null
for(var/X in H.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
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(!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)
for(var/X in H.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)
update_icon_dropped()
src.loc = T
H.update_health_hud() //update the healthdoll
H.update_body()
H.update_hair()
H.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)
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)
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
loc = LB
LB.brain = src
LB.brainmob = brainmob
brainmob = null
LB.brainmob.loc = LB
LB.brainmob.container = LB
LB.brainmob.stat = DEAD
/obj/item/bodypart/chest/drop_limb(special)
return
/obj/item/bodypart/r_arm/drop_limb(special)
var/mob/living/carbon/human/H = 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/R = H.hud_used.inv_slots[slot_r_hand]
if(R)
R.update_icon()
if(H.r_hand)
H.unEquip(H.r_hand, 1)
if(H.gloves)
H.unEquip(H.gloves, 1)
H.update_inv_gloves() //to remove the bloody hands overlay
/obj/item/bodypart/l_arm/drop_limb(special)
var/mob/living/carbon/human/H = 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/L = H.hud_used.inv_slots[slot_l_hand]
if(L)
L.update_icon()
if(H.l_hand)
H.unEquip(H.l_hand, 1)
if(H.gloves)
H.unEquip(H.gloves, 1)
H.update_inv_gloves() //to remove the bloody hands overlay
/obj/item/bodypart/r_leg/drop_limb(special)
if(owner && !special)
owner.Weaken(2)
if(owner.legcuffed)
owner.legcuffed.loc = owner.loc
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)
..()
/obj/item/bodypart/l_leg/drop_limb(special) //copypasta
if(owner && !special)
owner.Weaken(2)
if(owner.legcuffed)
owner.legcuffed.loc = owner.loc
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)
..()
/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"
..()
//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))
return
var/obj/item/bodypart/O = locate(src.type) in H.bodyparts
if(O)
O.drop_limb(1)
attach_limb(H, special)
/obj/item/bodypart/head/replace_limb(mob/living/carbon/human/H, special)
if(!istype(H))
return
var/obj/item/bodypart/head/O = locate(src.type) in H.bodyparts
if(O)
if(!special)
return
else
O.drop_limb(1)
attach_limb(H, special)
/obj/item/bodypart/proc/attach_limb(mob/living/carbon/human/H, special)
loc = null
owner = H
H.bodyparts += src
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.
var/datum/surgery/S = X
var/surgery_zone = check_zone(S.location)
if(surgery_zone == body_zone)
H.surgeries -= S
qdel(S)
break
update_bodypart_damage_state()
H.updatehealth()
H.update_body()
H.update_hair()
H.update_damage_overlays()
H.update_canmove()
/obj/item/bodypart/r_arm/attach_limb(mob/living/carbon/human/H, special)
..()
if(H.hud_used)
var/obj/screen/inventory/R = H.hud_used.inv_slots[slot_r_hand]
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/L = H.hud_used.inv_slots[slot_l_hand]
if(L)
L.update_icon()
/obj/item/bodypart/head/attach_limb(mob/living/carbon/human/H, 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 = 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(real_name)
H.real_name = real_name
real_name = ""
name = initial(name)
..()
//Regenerates all limbs. Returns amount of limbs regenerated
/mob/living/proc/regenerate_limbs(noheal, excluded_limbs)
return 0
/mob/living/carbon/human/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)
var/obj/item/bodypart/L
if(get_bodypart(limb_zone))
return 0
L = newBodyPart(limb_zone, 0, 0, src)
if(L)
if(!noheal)
L.brute_dam = 0
L.burn_dam = 0
L.burn_state = 0
L.attach_limb(src, 1)
return 1
+165
View File
@@ -0,0 +1,165 @@
/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."
max_damage = 200
body_zone = "head"
body_part = HEAD
layer = ABOVE_MOB_LAYER //so it isn't hidden behind some objects when on the floor
w_class = 4 //Quite a hefty load
slowdown = 1 //Balancing measure
throw_range = 2 //No head bowling
px_x = 0
px_y = -8
var/mob/living/carbon/brain/brainmob = null //The current occupant.
var/obj/item/organ/brain/brain = null //The brain organ
//Limb appearance info:
var/real_name = "" //Replacement name
//Hair colour and style
var/hair_color = "000"
var/hair_style = "Bald"
var/hair_alpha = 255
//Facial hair colour and style
var/facial_hair_color = "000"
var/facial_hair_style = "Shaved"
//Eye Colouring
var/eyes = "eyes"
var/eye_color = ""
var/lip_style = null
var/lip_color = "white"
/obj/item/bodypart/head/drop_organs(mob/user)
var/turf/T = get_turf(src)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
for(var/obj/item/I in src)
if(I == brain)
if(user)
user.visible_message("<span class='warning'>[user] saws [src] open and pulls out a brain!</span>", "<span class='notice'>You saw [src] open and pull out a brain.</span>")
if(brainmob)
brainmob.container = null
brainmob.loc = brain
brain.brainmob = brainmob
brainmob = null
brain.loc = T
brain = null
update_icon_dropped()
else
I.loc = T
/obj/item/bodypart/head/update_limb(dropping_limb, mob/living/carbon/human/source)
var/mob/living/carbon/human/H
if(source)
H = source
else
H = owner
if(!istype(H))
return
var/datum/species/S = H.dna.species
//First of all, name.
real_name = H.real_name
//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)
return
for(var/image/I in standing)
I.pixel_x = px_x
I.pixel_y = px_y
add_overlay(standing)
/obj/item/bodypart/head/get_limb_icon(dropped)
cut_overlays()
var/image/I = ..()
var/list/standing = list()
standing += I
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.
//facial hair
if(facial_hair_style)
S = facial_hair_styles_list[facial_hair_style]
if(S)
var/image/img_facial_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER, "dir"=SOUTH)
img_facial_s.color = "#" + facial_hair_color
img_facial_s.alpha = hair_alpha
standing += img_facial_s
//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)
else
if(hair_style)
S = hair_styles_list[hair_style]
if(S)
var/image/img_hair_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER, "dir"=SOUTH)
img_hair_s.color = "#" + hair_color
img_hair_s.alpha = hair_alpha
standing += img_hair_s
// lipstick
if(lip_style)
var/image/lips = image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[lip_style]_s", "layer" = -BODY_LAYER, "dir"=SOUTH)
lips.color = lip_color
standing += lips
// eyes
if(eye_color)
var/image/img_eyes_s = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "[eyes]_s", "layer" = -BODY_LAYER, "dir"=SOUTH)
img_eyes_s.color = "#" + eye_color
standing += img_eyes_s
if(standing.len)
return standing
/obj/item/bodypart/head/burn()
drop_organs()
..()
+165
View File
@@ -0,0 +1,165 @@
/mob/living/proc/get_bodypart(zone)
return
/mob/living/carbon/get_bodypart(zone)
if(!zone)
zone = "chest"
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
if(L.body_zone == zone)
return L
//Mob has their active hand
/mob/proc/has_active_hand()
return 1
/mob/living/carbon/human/has_active_hand()
var/obj/item/bodypart/L
if(hand)
L = get_bodypart("l_arm")
else
L = get_bodypart("r_arm")
if(!L)
return 0
return 1
/mob/proc/has_left_hand()
return 1
/mob/living/carbon/human/has_left_hand()
var/obj/item/bodypart/L
L = get_bodypart("l_arm")
if(!L)
return 0
return 1
/mob/proc/has_right_hand()
return 1
/mob/living/carbon/human/has_right_hand()
var/obj/item/bodypart/L
L = get_bodypart("r_arm")
if(!L)
return 0
return 1
//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()
. = 0
for(var/X in bodyparts)
var/obj/item/bodypart/affecting = X
if(affecting.body_part == ARM_RIGHT)
.++
if(affecting.body_part == ARM_LEFT)
.++
/mob/living/carbon/human/get_num_legs()
. = 0
for(var/X in bodyparts)
var/obj/item/bodypart/affecting = X
if(affecting.body_part == LEG_RIGHT)
.++
if(affecting.body_part == LEG_LEFT)
.++
/mob/living/proc/get_missing_limbs()
return list()
/mob/living/carbon/human/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
//Remove all embedded objects from all limbs on the human mob
/mob/living/carbon/human/proc/remove_all_embedded_objects()
var/turf/T = get_turf(src)
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
for(var/obj/item/I in L.embedded_objects)
L.embedded_objects -= I
I.loc = T
clear_alert("embeddedobject")
/mob/living/carbon/human/proc/has_embedded_objects()
. = 0
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
for(var/obj/item/I in L.embedded_objects)
return 1
//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)
var/obj/item/bodypart/L
switch(zone)
if("l_arm")
L = new /obj/item/bodypart/l_arm()
if("r_arm")
L = new /obj/item/bodypart/r_arm()
if("head")
L = new /obj/item/bodypart/head()
if("l_leg")
L = new /obj/item/bodypart/l_leg()
if("r_leg")
L = new /obj/item/bodypart/r_leg()
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.
if(robotic)
L.change_bodypart_status(ORGAN_ROBOTIC)
. = L
/proc/skintone2hex(skin_tone)
. = 0
switch(skin_tone)
if("caucasian1")
. = "ffe0d1"
if("caucasian2")
. = "fcccb3"
if("caucasian3")
. = "e8b59b"
if("latino")
. = "d9ae96"
if("mediterranean")
. = "c79b8b"
if("asian1")
. = "ffdeb3"
if("asian2")
. = "e3ba84"
if("arab")
. = "c4915e"
if("indian")
. = "b87840"
if("african1")
. = "754523"
if("african2")
. = "471c18"
if("albino")
. = "fff4e6"
if("orange")
. = "ffc905"
+44
View File
@@ -0,0 +1,44 @@
/datum/surgery/cavity_implant
name = "cavity implant"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/incise, /datum/surgery_step/handle_cavity, /datum/surgery_step/close)
species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list("chest")
//handle cavity
/datum/surgery_step/handle_cavity
name = "implant item"
accept_hand = 1
accept_any_item = 1
time = 32
var/obj/item/IC = null
/datum/surgery_step/handle_cavity/preop(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/obj/item/bodypart/chest/CH = target.get_bodypart("chest")
IC = CH.cavity_item
if(tool)
user.visible_message("[user] begins to insert [tool] into [target]'s [target_zone].", "<span class='notice'>You begin to insert [tool] into [target]'s [target_zone]...</span>")
else
user.visible_message("[user] checks for items in [target]'s [target_zone].", "<span class='notice'>You check for items in [target]'s [target_zone]...</span>")
/datum/surgery_step/handle_cavity/success(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/obj/item/bodypart/chest/CH = target.get_bodypart("chest")
if(tool)
if(IC || tool.w_class > 3 || (NODROP in tool.flags) || istype(tool, /obj/item/organ))
user << "<span class='warning'>You can't seem to fit [tool] in [target]'s [target_zone]!</span>"
return 0
else
user.visible_message("[user] stuffs [tool] into [target]'s [target_zone]!", "<span class='notice'>You stuff [tool] into [target]'s [target_zone].</span>")
user.drop_item()
CH.cavity_item = tool
tool.loc = target
return 1
else
if(IC)
user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "<span class='notice'>You pull [IC] out of [target]'s [target_zone].</span>")
user.put_in_hands(IC)
CH.cavity_item = null
return 1
else
user << "<span class='warning'>You don't find anything in [target]'s [target_zone].</span>"
return 0
+35
View File
@@ -0,0 +1,35 @@
/datum/surgery/core_removal
name = "core removal"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/incise, /datum/surgery_step/extract_core)
species = list(/mob/living/simple_animal/slime)
/datum/surgery/core_removal/can_start(mob/user, mob/living/carbon/target)
if(target.stat == DEAD)
return 1
return 0
//extract brain
/datum/surgery_step/extract_core
name = "extract core"
implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 100)
time = 16
/datum/surgery_step/extract_core/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to extract a core from [target].", "<span class='notice'>You begin to extract a core from [target]...</span>")
/datum/surgery_step/extract_core/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/mob/living/simple_animal/slime/slime = target
if(slime.cores > 0)
slime.cores--
user.visible_message("[user] successfully extracts a core from [target]!", "<span class='notice'>You successfully extract a core from [target]. [slime.cores] core\s remaining.</span>")
new slime.coretype(slime.loc)
if(slime.cores <= 0)
slime.icon_state = "[slime.colour] baby slime dead-nocore"
return 1
else
return 0
else
user << "<span class='warning'>There aren't any cores left in [target]!</span>"
return 1
+43
View File
@@ -0,0 +1,43 @@
/datum/surgery/dental_implant
name = "dental implant"
steps = list(/datum/surgery_step/drill, /datum/surgery_step/insert_pill)
possible_locs = list("mouth")
/datum/surgery_step/insert_pill
name = "insert pill"
implements = list(/obj/item/weapon/reagent_containers/pill = 100)
time = 16
/datum/surgery_step/insert_pill/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to wedge \the [tool] in [target]'s [parse_zone(target_zone)].", "<span class='notice'>You begin to wedge [tool] in [target]'s [parse_zone(target_zone)]...</span>")
/datum/surgery_step/insert_pill/success(mob/user, mob/living/carbon/target, target_zone, var/obj/item/weapon/reagent_containers/pill/tool, datum/surgery/surgery)
if(!istype(tool))
return 0
user.drop_item()
target.internal_organs += tool
tool.loc = target
var/datum/action/item_action/hands_free/activate_pill/P = new
P.button_icon_state = tool.icon_state
P.target = tool
P.Grant(target)
user.visible_message("[user] wedges \the [tool] into [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You wedge [tool] into [target]'s [parse_zone(target_zone)].</span>")
return 1
/datum/action/item_action/hands_free/activate_pill
name = "Activate Pill"
/datum/action/item_action/hands_free/activate_pill/Trigger()
if(!..())
return 0
owner << "<span class='caution'>You grit your teeth and burst the implanted [target]!</span>"
add_logs(owner, null, "swallowed an implanted pill", target)
if(target.reagents.total_volume)
target.reagents.reaction(owner, INGEST)
target.reagents.trans_to(owner, target.reagents.total_volume)
Remove(owner)
qdel(target)
return 1
+32
View File
@@ -0,0 +1,32 @@
/datum/surgery/eye_surgery
name = "eye surgery"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/fix_eyes, /datum/surgery_step/close)
species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list("eyes")
requires_organic_bodypart = 0
//fix eyes
/datum/surgery_step/fix_eyes
name = "fix eyes"
implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/screwdriver = 45, /obj/item/weapon/pen = 25)
time = 64
/datum/surgery_step/fix_eyes/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to fix [target]'s eyes.", "<span class='notice'>You begin to fix [target]'s eyes...</span>")
/datum/surgery_step/fix_eyes/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] successfully fixes [target]'s eyes!", "<span class='notice'>You succeed in fixing [target]'s eyes.</span>")
target.cure_blind()
target.set_blindness(0)
target.cure_nearsighted()
target.blur_eyes(35) //this will fix itself slowly.
target.set_eye_damage(0)
return 1
/datum/surgery_step/fix_eyes/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(target.getorgan(/obj/item/organ/brain))
user.visible_message("<span class='warning'>[user] accidentally stabs [target] right in the brain!</span>", "<span class='warning'>You accidentally stab [target] right in the brain!</span>")
target.adjustBrainLoss(100)
else
user.visible_message("<span class='warning'>[user] accidentally stabs [target] right in the brain! Or would have, if [target] had a brain.</span>", "<span class='warning'>You accidentally stab [target] right in the brain! Or would have, if [target] had a brain.</span>")
return 0
@@ -0,0 +1,38 @@
/datum/surgery/gender_reassignment
name = "gender reassignment"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/reshape_genitals, /datum/surgery_step/close)
species = list(/mob/living/carbon/human)
possible_locs = list("groin")
//reshape_genitals
/datum/surgery_step/reshape_genitals
name = "reshape genitals"
implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/hatchet = 50, /obj/item/weapon/wirecutters = 35)
time = 64
/datum/surgery_step/reshape_genitals/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(target.gender == FEMALE)
user.visible_message("[user] begins to reshape [target]'s genitals to look more masculine.", "<span class='notice'>You begin to reshape [target]'s genitals to look more masculine...</span>")
else
user.visible_message("[user] begins to reshape [target]'s genitals to look more feminine.", "<span class='notice'>You begin to reshape [target]'s genitals to look more feminine...</span>")
/datum/surgery_step/reshape_genitals/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/mob/living/carbon/human/H = target //no type check, as that should be handled by the surgery
H.gender_ambiguous = 0
if(target.gender == FEMALE)
user.visible_message("[user] has made a man of [target]!", "<span class='notice'>You made [target] a man.</span>")
target.gender = MALE
else
user.visible_message("[user] has made a woman of [target]!", "<span class='notice'>You made [target] a woman.</span>")
target.gender = FEMALE
target.regenerate_icons()
return 1
/datum/surgery_step/reshape_genitals/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/mob/living/carbon/human/H = target
H.gender_ambiguous = 1
user.visible_message("<span class='warning'>[user] accidentally mutilates [target]'s genitals beyond the point of recognition!</span>", "<span class='warning'>You accidentally mutilate [target]'s genitals beyond the point of recognition!</span>")
target.gender = pick(MALE, FEMALE)
target.regenerate_icons()
return 1
+105
View File
@@ -0,0 +1,105 @@
//make incision
/datum/surgery_step/incise
name = "make incision"
implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/melee/energy/sword = 75, /obj/item/weapon/kitchen/knife = 65, /obj/item/weapon/shard = 45)
time = 16
/datum/surgery_step/incise/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to make an incision in [target]'s [parse_zone(target_zone)].", "<span class='notice'>You begin to make an incision in [target]'s [parse_zone(target_zone)]...</span>")
//clamp bleeders
/datum/surgery_step/clamp_bleeders
name = "clamp bleeders"
implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/wirecutters = 60, /obj/item/stack/packageWrap = 35, /obj/item/stack/cable_coil = 15)
time = 24
/datum/surgery_step/clamp_bleeders/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to clamp bleeders in [target]'s [parse_zone(target_zone)].", "<span class='notice'>You begin to clamp bleeders in [target]'s [parse_zone(target_zone)]...</span>")
/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)
return ..()
//retract skin
/datum/surgery_step/retract_skin
name = "retract skin"
implements = list(/obj/item/weapon/retractor = 100, /obj/item/weapon/screwdriver = 45, /obj/item/weapon/wirecutters = 35)
time = 24
/datum/surgery_step/retract_skin/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to retract the skin in [target]'s [parse_zone(target_zone)].", "<span class='notice'>You begin to retract the skin in [target]'s [parse_zone(target_zone)]...</span>")
//close incision
/datum/surgery_step/close
name = "mend incision"
implements = list(/obj/item/weapon/cautery = 100, /obj/item/weapon/weldingtool = 70, /obj/item/weapon/lighter = 45, /obj/item/weapon/match = 20)
time = 24
/datum/surgery_step/close/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to mend the incision in [target]'s [parse_zone(target_zone)].", "<span class='notice'>You begin to mend the incision in [target]'s [parse_zone(target_zone)]...</span>")
/datum/surgery_step/close/tool_check(mob/user, obj/item/tool)
if(istype(tool, /obj/item/weapon/cautery))
return 1
if(istype(tool, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = tool
if(WT.isOn())
return 1
else if(istype(tool, /obj/item/weapon/lighter))
var/obj/item/weapon/lighter/L = tool
if(L.lit)
return 1
else if(istype(tool, /obj/item/weapon/match))
var/obj/item/weapon/match/M = tool
if(M.lit)
return 1
return 0
/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)
return ..()
//saw bone
/datum/surgery_step/saw
name = "saw bone"
implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/energy/sword/cyborg/saw = 100, /obj/item/weapon/melee/arm_blade = 75, /obj/item/weapon/mounted_chainsaw = 65, /obj/item/weapon/twohanded/required/chainsaw = 50, /obj/item/weapon/twohanded/fireaxe = 50, /obj/item/weapon/hatchet = 35, /obj/item/weapon/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)
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]")
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
//drill bone
/datum/surgery_step/drill
name = "drill bone"
implements = list(/obj/item/weapon/surgicaldrill = 100, /obj/item/weapon/pickaxe/drill = 60, /obj/item/mecha_parts/mecha_equipment/drill = 60, /obj/item/weapon/screwdriver = 20)
time = 30
/datum/surgery_step/drill/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to drill into the bone in [target]'s [parse_zone(target_zone)].", "<span class='notice'>You begin to drill into the bone in [target]'s [parse_zone(target_zone)]...</span>")
/datum/surgery_step/drill/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] drills into [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You drill into [target]'s [parse_zone(target_zone)].</span>")
return 1
+165
View File
@@ -0,0 +1,165 @@
/proc/attempt_initiate_surgery(obj/item/I, mob/living/M, mob/user)
if(istype(M))
var/mob/living/carbon/human/H
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(M.lying || isslime(M)) //if they're prone or a slime
var/datum/surgery/current_surgery
for(var/datum/surgery/S in M.surgeries)
if(S.location == selected_zone)
current_surgery = S
if(!current_surgery)
var/list/all_surgeries = surgeries_list.Copy()
var/list/available_surgeries = list()
for(var/datum/surgery/S in all_surgeries)
if(!S.possible_locs.Find(selected_zone))
continue
if(affecting)
if(!S.requires_bodypart)
continue
if(S.requires_organic_bodypart && affecting.status == ORGAN_ROBOTIC)
continue
else if(H && S.requires_bodypart) //human with no limb in surgery zone when we need a limb
continue
if(!S.can_start(user, M))
continue
for(var/path in S.species)
if(istype(M, path))
available_surgeries[S.name] = S
break
var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in available_surgeries
if(P && user && user.Adjacent(M) && (I in user))
var/datum/surgery/S = available_surgeries[P]
for(var/datum/surgery/other in M.surgeries)
if(other.location == S.location)
return //during the input() another surgery was started at the same location.
var/datum/surgery/procedure = new S.type
if(procedure)
procedure.location = selected_zone
//we check that the surgery is still doable after the input() wait.
if(H)
affecting = H.get_bodypart(check_zone(selected_zone))
if(affecting)
if(!procedure.requires_bodypart)
return
if(procedure.requires_organic_bodypart && affecting.status == ORGAN_ROBOTIC)
return
else if(H && procedure.requires_bodypart)
return
if(!procedure.can_start(user, M))
return
if(procedure.ignore_clothes || get_location_accessible(M, selected_zone))
M.surgeries += procedure
procedure.organ = affecting
user.visible_message("[user] drapes [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].", \
"<span class='notice'>You drape [I] over [M]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name].</span>")
add_logs(user, M, "operated", addition="Operation type: [procedure.name], location: [selected_zone]")
else
user << "<span class='warning'>You need to expose [M]'s [parse_zone(selected_zone)] first!</span>"
else if(!current_surgery.step_in_progress)
if(current_surgery.status == 1)
M.surgeries -= current_surgery
user.visible_message("[user] removes the drapes from [M]'s [parse_zone(selected_zone)].", \
"<span class='notice'>You remove the drapes from [M]'s [parse_zone(selected_zone)].</span>")
qdel(current_surgery)
else if(istype(user.get_inactive_hand(), /obj/item/weapon/cautery) && current_surgery.can_cancel)
M.surgeries -= current_surgery
user.visible_message("[user] mends the incision and removes the drapes from [M]'s [parse_zone(selected_zone)].", \
"<span class='notice'>You mend the incision and remove the drapes from [M]'s [parse_zone(selected_zone)].</span>")
qdel(current_surgery)
else if(current_surgery.can_cancel)
user << "<span class='warning'>You need to hold a cautery in inactive hand to stop [M]'s surgery!</span>"
return 1
return 0
proc/get_location_modifier(mob/M)
var/turf/T = get_turf(M)
if(locate(/obj/structure/table/optable, T))
return 1
else if(locate(/obj/structure/table, T))
return 0.8
else if(locate(/obj/structure/bed, T))
return 0.7
else
return 0.5
/proc/get_location_accessible(mob/M, location)
var/covered_locations = 0 //based on body_parts_covered
var/face_covered = 0 //based on flags_inv
var/eyesmouth_covered = 0 //based on flags_cover
if(iscarbon(M))
var/mob/living/carbon/C = M
for(var/obj/item/clothing/I in list(C.back, C.wear_mask, C.head))
covered_locations |= I.body_parts_covered
face_covered |= I.flags_inv
eyesmouth_covered |= I.flags_cover
if(ishuman(C))
var/mob/living/carbon/human/H = C
for(var/obj/item/I in list(H.wear_suit, H.w_uniform, H.shoes, H.belt, H.gloves, H.glasses, H.ears))
covered_locations |= I.body_parts_covered
face_covered |= I.flags_inv
eyesmouth_covered |= I.flags_cover
switch(location)
if("head")
if(covered_locations & HEAD)
return 0
if("eyes")
if(covered_locations & HEAD || face_covered & HIDEEYES || eyesmouth_covered & GLASSESCOVERSEYES)
return 0
if("mouth")
if(covered_locations & HEAD || face_covered & HIDEFACE || eyesmouth_covered & MASKCOVERSMOUTH || eyesmouth_covered & HEADCOVERSMOUTH)
return 0
if("chest")
if(covered_locations & CHEST)
return 0
if("groin")
if(covered_locations & GROIN)
return 0
if("l_arm")
if(covered_locations & ARM_LEFT)
return 0
if("r_arm")
if(covered_locations & ARM_RIGHT)
return 0
if("l_leg")
if(covered_locations & LEG_LEFT)
return 0
if("r_leg")
if(covered_locations & LEG_RIGHT)
return 0
if("l_hand")
if(covered_locations & HAND_LEFT)
return 0
if("r_hand")
if(covered_locations & HAND_RIGHT)
return 0
if("l_foot")
if(covered_locations & FOOT_LEFT)
return 0
if("r_foot")
if(covered_locations & FOOT_RIGHT)
return 0
return 1
+47
View File
@@ -0,0 +1,47 @@
/datum/surgery/implant_removal
name = "implant removal"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/extract_implant, /datum/surgery_step/close)
species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list("chest")
requires_organic_bodypart = 0
//extract implant
/datum/surgery_step/extract_implant
name = "extract implant"
implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 65)
time = 64
var/obj/item/weapon/implant/I = null
/datum/surgery_step/extract_implant/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
I = locate(/obj/item/weapon/implant) in target
if(I)
user.visible_message("[user] begins to extract [I] from [target]'s [target_zone].", "<span class='notice'>You begin to extract [I] from [target]'s [target_zone]...</span>")
else
user.visible_message("[user] looks for an implant in [target]'s [target_zone].", "<span class='notice'>You look for an implant in [target]'s [target_zone]...</span>")
/datum/surgery_step/extract_implant/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(I)
user.visible_message("[user] successfully removes [I] from [target]'s [target_zone]!", "<span class='notice'>You successfully remove [I] from [target]'s [target_zone].</span>")
I.removed(target)
var/obj/item/weapon/implantcase/case
if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase))
case = user.get_item_by_slot(slot_l_hand)
else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase))
case = user.get_item_by_slot(slot_r_hand)
else
case = locate(/obj/item/weapon/implantcase) in get_turf(target)
if(case && !case.imp)
case.imp = I
I.loc = case
case.update_icon()
user.visible_message("[user] places [I] into [case]!", "<span class='notice'>You place [I] into [case].</span>")
else
qdel(I)
else
user << "<span class='warning'>You can't find anything in [target]'s [target_zone]!</span>"
return 1
+126
View File
@@ -0,0 +1,126 @@
/////AUGMENTATION SURGERIES//////
//SURGERY STEPS
/datum/surgery_step/replace
name = "sever muscles"
implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/wirecutters = 55)
time = 32
/datum/surgery_step/replace/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to sever the muscles on [target]'s [parse_zone(user.zone_selected)].", "<span class ='notice'>You begin to sever the muscles on [target]'s [parse_zone(user.zone_selected)]...</span>")
/datum/surgery_step/add_limb
name = "replace limb"
implements = list(/obj/item/robot_parts = 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)
L = surgery.organ
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
user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "<span class ='notice'>You look for [target]'s [parse_zone(user.zone_selected)]...</span>")
//ACTUAL SURGERIES
/datum/surgery/augmentation
name = "augmentation"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/replace, /datum/surgery_step/saw, /datum/surgery_step/add_limb)
species = list(/mob/living/carbon/human)
possible_locs = list("r_arm","l_arm","r_leg","l_leg","chest","head")
//SURGERY STEP SUCCESSES
/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)]")
else
user << "<span class='warning'>[target] has no organic [parse_zone(target_zone)] there!</span>"
return 1
/datum/surgery/chainsaw
name = "chainsaw augmentation"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise, /datum/surgery_step/chainsaw)
species = list(/mob/living/carbon/human)
possible_locs = list("r_arm", "l_arm")
requires_organic_bodypart = 0
/datum/surgery_step/chainsaw
time = 64
name = "insert chainsaw"
implements = list(/obj/item/weapon/twohanded/required/chainsaw = 100)
/datum/surgery_step/chainsaw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to install the chainsaw onto [target].", "<span class='notice'>You begin to install the chainsaw onto [target]...</span>")
/datum/surgery_step/chainsaw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(target.l_hand && target.r_hand)
user << "<span class='warning'>You can't fit the chainsaw in while [target]'s hands are full!</span>"
return 0
else
user.visible_message("[user] finishes installing the chainsaw!", "<span class='notice'>You install the chainsaw.</span>")
user.unEquip(tool)
qdel(tool)
var/obj/item/weapon/mounted_chainsaw/sawarms = new(target)
target.put_in_hands(sawarms)
return 1
/datum/surgery/chainsaw_removal
name = "chainsaw removal"
steps = list(/datum/surgery_step/chainsaw_removal)
species = list(/mob/living/carbon/human)
possible_locs = list("r_arm", "l_arm")
requires_organic_bodypart = 0
/datum/surgery/chainsaw_removal/can_start(mob/user, mob/living/carbon/target)
var/list/hands = get_both_hands(target)
var/M = locate(/obj/item/weapon/mounted_chainsaw) in hands
if(M)
return 1//can continue surgery
else
return 0//surgery will never be available
/datum/surgery_step/chainsaw_removal
time = 128
name = "saw off chainsaw"
implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/energy/sword/cyborg/saw = 100, /obj/item/weapon/melee/arm_blade = 75, /obj/item/weapon/mounted_chainsaw = 65, /obj/item/weapon/twohanded/fireaxe = 50, /obj/item/weapon/twohanded/required/chainsaw = 50, /obj/item/weapon/hatchet = 35, /obj/item/weapon/kitchen/knife/butcher = 25)
/datum/surgery_step/chainsaw_removal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins sawing the chainsaw off of [target]'s arms.", "<span class='notice'>You begin removing [target]'s chainsaw...</span>")
/datum/surgery_step/chainsaw_removal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/list/hands = get_both_hands(target)
for(var/obj/item/weapon/mounted_chainsaw/V in hands)
target.unEquip(V, 1)
user.visible_message("[user] carefully saws [target]'s arm free of the chainsaw.", "<span class='notice'>You remove the chainsaw.</span>")
return 1
+53
View File
@@ -0,0 +1,53 @@
/datum/surgery/lipoplasty
name = "lipoplasty"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/cut_fat, /datum/surgery_step/remove_fat, /datum/surgery_step/close)
possible_locs = list("chest")
/datum/surgery/lipoplasty/can_start(mob/user, mob/living/carbon/target)
if(target.disabilities & FAT)
return 1
return 0
//cut fat
/datum/surgery_step/cut_fat
name = "cut excess fat"
implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/energy/sword/cyborg/saw = 100, /obj/item/weapon/hatchet = 35, /obj/item/weapon/kitchen/knife/butcher = 25)
time = 64
/datum/surgery_step/cut_fat/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to cut away [target]'s excess fat.", "<span class='notice'>You begin to cut away [target]'s excess fat...</span>")
/datum/surgery_step/cut_fat/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] cuts [target]'s excess fat loose!", "<span class='notice'>You cut [target]'s excess fat loose.</span>")
return 1
//remove fat
/datum/surgery_step/remove_fat
name = "remove loose fat"
implements = list(/obj/item/weapon/retractor = 100, /obj/item/weapon/screwdriver = 45, /obj/item/weapon/wirecutters = 35)
time = 32
/datum/surgery_step/remove_fat/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to extract [target]'s loose fat!", "<span class='notice'>You begin to extract [target]'s loose fat...</span>")
/datum/surgery_step/remove_fat/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] extracts [target]'s fat!", "<span class='notice'>You extract [target]'s fat.</span>")
target.overeatduration = 0 //patient is unfatted
var/removednutriment = target.nutrition
target.nutrition = NUTRITION_LEVEL_WELL_FED
removednutriment -= 450 //whatever was removed goes into the meat
var/mob/living/carbon/human/H = target
var/typeofmeat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human
if(H.dna && H.dna.species)
typeofmeat = H.dna.species.meat
var/obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/newmeat = new typeofmeat
newmeat.name = "fatty meat"
newmeat.desc = "Extremely fatty tissue taken from a patient."
newmeat.subjectname = H.real_name
newmeat.subjectjob = H.job
newmeat.reagents.add_reagent ("nutriment", (removednutriment / 15)) //To balance with nutriment_factor of nutriment
newmeat.loc = target.loc
return 1
+119
View File
@@ -0,0 +1,119 @@
/datum/surgery/organ_manipulation
name = "organ manipulation"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise, /datum/surgery_step/manipulate_organs)
species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list("chest", "head")
requires_organic_bodypart = 0
/datum/surgery/organ_manipulation/soft
possible_locs = list("groin", "eyes", "mouth", "l_arm", "r_arm")
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise, /datum/surgery_step/manipulate_organs)
/datum/surgery/organ_manipulation/alien
name = "alien organ manipulation"
possible_locs = list("chest", "head", "groin", "eyes", "mouth", "l_arm", "r_arm")
species = list(/mob/living/carbon/alien/humanoid)
steps = list(/datum/surgery_step/saw, /datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/manipulate_organs)
/datum/surgery_step/manipulate_organs
time = 64
name = "manipulate organs"
implements = list(/obj/item/organ = 100, /obj/item/weapon/reagent_containers/food/snacks/organ = 0)
var/implements_extract = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 55)
var/implements_mend = list(/obj/item/weapon/cautery = 100, /obj/item/weapon/weldingtool = 70, /obj/item/weapon/lighter = 45, /obj/item/weapon/match = 20)
var/current_type
var/obj/item/organ/I = null
/datum/surgery_step/manipulate_organs/New()
..()
implements = implements + implements_extract + implements_mend
/datum/surgery_step/manipulate_organs/tool_check(mob/user, obj/item/tool)
if(istype(tool, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = tool
if(!WT.isOn())
return 0
else if(istype(tool, /obj/item/weapon/lighter))
var/obj/item/weapon/lighter/L = tool
if(!L.lit)
return 0
else if(istype(tool, /obj/item/weapon/match))
var/obj/item/weapon/match/M = tool
if(!M.lit)
return 0
return 1
/datum/surgery_step/manipulate_organs/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
I = null
if(isorgan(tool))
current_type = "insert"
I = tool
if(target_zone != I.zone || target.getorganslot(I.slot))
user << "<span class='notice'>There is no room for [I] in [target]'s [parse_zone(target_zone)]!</span>"
return -1
user.visible_message("[user] begins to insert [tool] into [target]'s [parse_zone(target_zone)].",
"<span class='notice'>You begin to insert [tool] into [target]'s [parse_zone(target_zone)]...</span>")
else if(implement_type in implements_extract)
current_type = "extract"
var/list/organs = target.getorganszone(target_zone)
if(!organs.len)
user << "<span class='notice'>There is no removeable organs in [target]'s [parse_zone(target_zone)]!</span>"
return -1
else
for(var/obj/item/organ/O in organs)
O.on_find(user)
organs -= O
organs[O.name] = O
I = input("Remove which organ?", "Surgery", null, null) as null|anything in organs
if(I && user && target && user.Adjacent(target) && user.get_active_hand() == tool)
I = organs[I]
if(!I) return -1
user.visible_message("[user] begins to extract [I] from [target]'s [parse_zone(target_zone)].",
"<span class='notice'>You begin to extract [I] from [target]'s [parse_zone(target_zone)]...</span>")
else
return -1
else if(implement_type in implements_mend)
current_type = "mend"
user.visible_message("[user] begins to mend the incision in [target]'s [parse_zone(target_zone)].",
"<span class='notice'>You begin to mend the incision in [target]'s [parse_zone(target_zone)]...</span>")
else if(istype(tool, /obj/item/weapon/reagent_containers/food/snacks/organ))
user << "<span class='warning'>[tool] was biten 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 == "mend")
user.visible_message("[user] mends the incision in [target]'s [parse_zone(target_zone)].",
"<span class='notice'>You mend the incision in [target]'s [parse_zone(target_zone)].</span>")
return 1
else if(current_type == "insert")
I = tool
user.drop_item()
I.Insert(target)
user.visible_message("[user] inserts [tool] into [target]'s [parse_zone(target_zone)]!",
"<span class='notice'>You insert [tool] into [target]'s [parse_zone(target_zone)].</span>")
else if(current_type == "extract")
if(I && I.owner == target)
user.visible_message("[user] successfully extracts [I] from [target]'s [parse_zone(target_zone)]!",
"<span class='notice'>You successfully extract [I] from [target]'s [parse_zone(target_zone)].</span>")
add_logs(user, target, "surgically removed [I.name] from", addition="INTENT: [uppertext(user.a_intent)]")
I.Remove(target)
I.loc = get_turf(target)
else
user.visible_message("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!",
"<span class='notice'>You can't extract anything from [target]'s [parse_zone(target_zone)]!</span>")
return 0
@@ -0,0 +1,182 @@
/obj/item/organ/cyberimp/arm
name = "arm-mounted implant"
desc = "You shouldn't see this! Adminhelp and report this as an issue on github!"
zone = "r_arm"
slot = "r_arm_device"
icon_state = "implant-toolkit"
w_class = 3
actions_types = list(/datum/action/item_action/organ_action/toggle)
var/list/items_list = list()
// Used to store a list of all items inside, for multi-item implants.
// I would use contents, but they shuffle on every activation/deactivation leading to interface inconsistencies.
var/obj/item/holder = null
// You can use this var for item path, it would be converted into an item on New()
/obj/item/organ/cyberimp/arm/New()
..()
if(ispath(holder))
holder = new holder(src)
update_icon()
slot = zone + "_device"
items_list = contents.Copy()
/obj/item/organ/cyberimp/arm/update_icon()
if(zone == "r_arm")
transform = null
else // Mirroring the icon
transform = matrix(-1, 0, 0, 0, 1, 0)
/obj/item/organ/cyberimp/arm/examine(mob/user)
..()
user << "<span class='info'>[src] is assembled in the [zone == "r_arm" ? "right" : "left"] arm configuration. You can use a screwdriver to reassemble it.</span>"
/obj/item/organ/cyberimp/arm/attackby(obj/item/weapon/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/screwdriver))
if(zone == "r_arm")
zone = "l_arm"
else
zone = "r_arm"
slot = zone + "_device"
user << "<span class='notice'>You modify [src] to be installed on the [zone == "r_arm" ? "right" : "left"] arm.</span>"
update_icon()
else if(istype(W, /obj/item/weapon/card/emag))
emag_act()
/obj/item/organ/cyberimp/arm/Remove(mob/living/carbon/M, special = 0)
Retract()
..()
/obj/item/organ/cyberimp/arm/emag_act()
return 0
/obj/item/organ/cyberimp/arm/gun/emp_act(severity)
if(prob(15/severity) && owner)
owner << "<span class='warning'>[src] is hit by EMP!</span>"
// give the owner an idea about why his implant is glitching
Retract()
..()
/obj/item/organ/cyberimp/arm/proc/Retract()
if(!holder || (holder in src))
return
owner.visible_message("<span class='notice'>[owner] retracts [holder] back into \his [zone == "r_arm" ? "right" : "left"] arm.</span>",
"<span class='notice'>[holder] snaps back into your [zone == "r_arm" ? "right" : "left"] arm.</span>",
"<span class='italics'>You hear a short mechanical noise.</span>")
owner.unEquip(holder, 1)
holder.loc = src
holder = null
playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1)
/obj/item/organ/cyberimp/arm/proc/Extend(var/obj/item/item)
if(!(item in src))
return
holder = item
holder.flags |= NODROP
holder.unacidable = 1
holder.slot_flags = null
holder.w_class = 5
holder.materials = null
var/arm_slot = (zone == "r_arm" ? slot_r_hand : slot_l_hand)
var/obj/item/arm_item = owner.get_item_by_slot(arm_slot)
if(arm_item)
if(!owner.unEquip(arm_item))
owner << "<span class='warning'>Your [arm_item] interferes with [src]!</span>"
return
else
owner << "<span class='notice'>You drop [arm_item] to activate [src]!</span>"
if(zone == "r_arm" ? !owner.put_in_r_hand(holder) : !owner.put_in_l_hand(holder))
owner << "<span class='warning'>Your [src] fails to activate!</span>"
return
// Activate the hand that now holds our item.
if(zone == "r_arm" ? owner.hand : !owner.hand)
owner.swap_hand()
owner.visible_message("<span class='notice'>[owner] extends [holder] from \his [zone == "r_arm" ? "right" : "left"] arm.</span>",
"<span class='notice'>You extend [holder] from your [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)
/obj/item/organ/cyberimp/arm/ui_action_click()
if(crit_fail || (!holder && !contents.len))
owner << "<span class='warning'>The implant doesn't respond. It seems to be broken...</span>"
return
// You can emag the arm-mounted implant by activating it while holding emag in it's hand.
var/arm_slot = (zone == "r_arm" ? slot_r_hand : slot_l_hand)
if(istype(owner.get_item_by_slot(arm_slot), /obj/item/weapon/card/emag) && emag_act())
return
if(!holder || (holder in src))
holder = null
if(contents.len == 1)
Extend(contents[1])
else // TODO: make it similar to borg's storage-like module selection
var/obj/item/choise = input("Activate which item?", "Arm Implant", null, null) as null|anything in items_list
if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && istype(choise) && (choise in contents))
// This monster sanity check is a nice example of how bad input() is.
Extend(choise)
else
Retract()
/obj/item/organ/cyberimp/arm/gun/emp_act(severity)
if(prob(30/severity) && owner && !crit_fail)
Retract()
owner.visible_message("<span class='danger'>A loud bang comes from [owner]\'s [zone == "r_arm" ? "right" : "left"] arm!</span>")
playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1)
owner << "<span class='userdanger'>You feel an explosion erupt inside your [zone == "r_arm" ? "right" : "left"] arm as your implant breaks!</span>"
owner.adjust_fire_stacks(20)
owner.IgniteMob()
owner.adjustFireLoss(25)
crit_fail = 1
else // The gun will still discharge anyway.
..()
/obj/item/organ/cyberimp/arm/gun/laser
name = "arm-mounted laser implant"
desc = "A variant of the arm cannon implant that fires lethal laser beams. The cannon emerges from the subject's arm and remains inside when not in use."
icon_state = "arm_laser"
origin_tech = "materials=4;combat=4;biotech=4;powerstorage=4;syndicate=3"
holder = /obj/item/weapon/gun/energy/laser/mounted
/obj/item/organ/cyberimp/arm/gun/laser/l/zone = "l_arm"
/obj/item/organ/cyberimp/arm/gun/taser
name = "arm-mounted taser implant"
desc = "A variant of the arm cannon implant that fires electrodes and disabler shots. The cannon emerges from the subject's arm and remains inside when not in use."
icon_state = "arm_taser"
origin_tech = "materials=5;combat=5;biotech=4;powerstorage=4"
holder = /obj/item/weapon/gun/energy/gun/advtaser/mounted
/obj/item/organ/cyberimp/arm/gun/taser/l/zone = "l_arm"
/obj/item/organ/cyberimp/arm/toolset
name = "integrated toolset implant"
desc = "A stripped-down version of engineering cyborg toolset, designed to be installed on subject's arm. Contains all neccessary tools."
origin_tech = "materials=3;engineering=4;biotech=3;powerstorage=4"
contents = newlist(/obj/item/weapon/screwdriver/cyborg, /obj/item/weapon/wrench/cyborg, /obj/item/weapon/weldingtool/largetank/cyborg,
/obj/item/weapon/crowbar/cyborg, /obj/item/weapon/wirecutters/cyborg, /obj/item/device/multitool/cyborg)
/obj/item/organ/cyberimp/arm/toolset/l/zone = "l_arm"
/obj/item/organ/cyberimp/arm/toolset/emag_act()
if(!(locate(/obj/item/weapon/kitchen/knife/combat/cyborg) in items_list))
usr << "<span class='notice'>You unlock [src]'s integrated knife!</span>"
items_list += new /obj/item/weapon/kitchen/knife/combat/cyborg(src)
return 1
return 0
@@ -0,0 +1,199 @@
/obj/item/organ/cyberimp/chest
name = "cybernetic torso implant"
desc = "implants for the organs in your torso"
icon_state = "chest_implant"
implant_overlay = "chest_implant_overlay"
zone = "chest"
/obj/item/organ/cyberimp/chest/nutriment
name = "Nutriment pump implant"
desc = "This implant with synthesize and pump into your bloodstream a small amount of nutriment when you are starving."
icon_state = "chest_implant"
implant_color = "#00AA00"
var/hunger_threshold = NUTRITION_LEVEL_STARVING
var/synthesizing = 0
var/poison_amount = 5
slot = "stomach"
origin_tech = "materials=4;powerstorage=5;biotech=4"
/obj/item/organ/cyberimp/chest/nutriment/on_life()
if(synthesizing)
return
if(owner.nutrition <= hunger_threshold)
synthesizing = TRUE
owner << "<span class='notice'>You feel less hungry...</span>"
owner.nutrition += 50
sleep(50)
synthesizing = FALSE
/obj/item/organ/cyberimp/chest/nutriment/emp_act(severity)
if(!owner)
return
owner.reagents.add_reagent("????",poison_amount / severity) //food poisoning
owner << "<span class='warning'>You feel like your insides are burning.</span>"
/obj/item/organ/cyberimp/chest/nutriment/plus
name = "Nutriment pump implant PLUS"
desc = "This implant will synthesize and pump into your bloodstream a small amount of nutriment when you are hungry."
icon_state = "chest_implant"
implant_color = "#006607"
hunger_threshold = NUTRITION_LEVEL_HUNGRY
poison_amount = 10
origin_tech = "materials=4;powerstorage=5;biotech=5"
/obj/item/organ/cyberimp/chest/reviver
name = "Reviver implant"
desc = "This implant will attempt to revive you if you lose consciousness. For the faint of heart!"
icon_state = "chest_implant"
implant_color = "#AD0000"
origin_tech = "materials=5;programming=4;biotech=6"
slot = "heartdrive"
var/revive_cost = 0
var/reviving = 0
var/cooldown = 0
/obj/item/organ/cyberimp/chest/reviver/on_life()
if(reviving)
if(owner.stat == UNCONSCIOUS)
addtimer(src, "heal", 30)
else
cooldown = revive_cost + world.time
reviving = FALSE
return
if(cooldown > world.time)
return
if(owner.stat != UNCONSCIOUS)
return
if(owner.suiciding)
return
revive_cost = 0
reviving = TRUE
/obj/item/organ/cyberimp/chest/reviver/proc/heal()
if(prob(90) && owner.getOxyLoss())
owner.adjustOxyLoss(-3)
revive_cost += 5
if(prob(75) && owner.getBruteLoss())
owner.adjustBruteLoss(-1)
revive_cost += 20
if(prob(75) && owner.getFireLoss())
owner.adjustFireLoss(-1)
revive_cost += 20
if(prob(40) && owner.getToxLoss())
owner.adjustToxLoss(-1)
revive_cost += 50
/obj/item/organ/cyberimp/chest/reviver/emp_act(severity)
if(!owner)
return
if(reviving)
revive_cost += 200
else
cooldown += 200
if(istype(owner, /mob/living/carbon/human))
var/mob/living/carbon/human/H = owner
if(H.stat != DEAD && prob(50 / severity))
H.heart_attack = TRUE
addtimer(src, "undo_heart_attack", 600 / severity)
/obj/item/organ/cyberimp/chest/reviver/proc/undo_heart_attack()
var/mob/living/carbon/human/H = owner
if(!istype(H))
return
H.heart_attack = FALSE
if(H.stat == CONSCIOUS)
H << "<span class='notice'>You feel your heart beating again!</span>"
/obj/item/organ/cyberimp/chest/thrusters
name = "implantable thrusters set"
desc = "An implantable set of thruster ports. They use the gas from environment or subject's internals for propulsion in zero-gravity areas. \
Unlike regular jetpack, this device has no stablilzation system."
slot = "thrusters"
icon_state = "imp_jetpack"
origin_tech = "materials=4;magnets=4;biotech=4;engineering=5"
implant_overlay = null
implant_color = null
actions_types = list(/datum/action/item_action/organ_action/toggle)
w_class = 3
var/on = 0
var/datum/effect_system/trail_follow/ion/ion_trail
/obj/item/organ/cyberimp/chest/thrusters/Insert(mob/living/carbon/M, special = 0)
..()
if(!ion_trail)
ion_trail = new
ion_trail.set_up(M)
/obj/item/organ/cyberimp/chest/thrusters/Remove(mob/living/carbon/M, special = 0)
if(on)
toggle(silent=1)
..()
/obj/item/organ/cyberimp/chest/thrusters/ui_action_click()
toggle()
/obj/item/organ/cyberimp/chest/thrusters/proc/toggle(silent=0)
if(!on)
if(crit_fail)
if(!silent)
owner << "<span class='warning'>Your thrusters set seems to be broken!</span>"
return 0
on = 1
if(allow_thrust(0.01))
ion_trail.start()
if(!silent)
owner << "<span class='notice'>You turn your thrusters set on.</span>"
else
ion_trail.stop()
if(!silent)
owner << "<span class='notice'>You turn your thrusters set off.</span>"
on = 0
update_icon()
/obj/item/organ/cyberimp/chest/thrusters/update_icon()
if(on)
icon_state = "imp_jetpack-on"
else
icon_state = "imp_jetpack"
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
/obj/item/organ/cyberimp/chest/thrusters/proc/allow_thrust(num)
if(!on || !owner)
return 0
var/turf/T = get_turf(owner)
if(!T) // No more runtimes from being stuck in nullspace.
return 0
// Priority 1: use air from environment.
var/datum/gas_mixture/environment = T.return_air()
if(environment && environment.return_pressure() > 30)
return 1
// Priority 2: use plasma from internal plasma storage.
// (just in case someone would ever use this implant system to make cyber-alien ops with jetpacks and taser arms)
if(owner.getPlasma() >= num*100)
owner.adjustPlasma(-num*100)
return 1
// Priority 3: use internals tank.
var/obj/item/weapon/tank/I = owner.internal
if(I && I.air_contents && I.air_contents.total_moles() > num)
var/datum/gas_mixture/removed = I.air_contents.remove(num)
if(removed.total_moles() > 0.005)
T.assume_air(removed)
return 1
else
T.assume_air(removed)
toggle(silent=1)
return 0
@@ -0,0 +1,122 @@
/obj/item/organ/cyberimp/eyes
name = "cybernetic eyes"
desc = "artificial photoreceptors with specialized functionality"
icon_state = "eye_implant"
implant_overlay = "eye_implant_overlay"
slot = "eye_sight"
zone = "eyes"
w_class = 1
var/sight_flags = 0
var/dark_view = 0
var/eye_color = "fff"
var/old_eye_color = "fff"
var/flash_protect = 0
var/see_invisible = 0
var/aug_message = "Your vision is augmented!"
/obj/item/organ/cyberimp/eyes/Insert(var/mob/living/carbon/M, var/special = 0)
..()
if(istype(owner, /mob/living/carbon/human) && eye_color)
var/mob/living/carbon/human/HMN = owner
old_eye_color = HMN.eye_color
HMN.eye_color = eye_color
HMN.regenerate_icons()
if(aug_message && !special)
owner << "<span class='notice'>[aug_message]</span>"
owner.update_sight()
/obj/item/organ/cyberimp/eyes/Remove(var/mob/living/carbon/M, var/special = 0)
M.sight ^= sight_flags
if(istype(M,/mob/living/carbon/human) && eye_color)
var/mob/living/carbon/human/HMN = owner
HMN.eye_color = old_eye_color
HMN.regenerate_icons()
..()
/obj/item/organ/cyberimp/eyes/emp_act(severity)
if(!owner)
return
if(severity > 1)
if(prob(10 * severity))
return
owner << "<span class='warning'>Static obfuscates your vision!</span>"
owner.flash_eyes(visual = 1)
/obj/item/organ/cyberimp/eyes/xray
name = "X-ray implant"
desc = "These cybernetic eye implants will give you X-ray vision. Blinking is futile."
eye_color = "000"
implant_color = "#000000"
origin_tech = "materials=4;programming=4;biotech=6;magnets=4"
dark_view = 8
sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS
/obj/item/organ/cyberimp/eyes/thermals
name = "Thermals implant"
desc = "These cybernetic eye implants will give you Thermal vision. Vertical slit pupil included."
eye_color = "FC0"
implant_color = "#FFCC00"
origin_tech = "materials=5;programming=4;biotech=4;magnets=4;syndicate=1"
sight_flags = SEE_MOBS
see_invisible = SEE_INVISIBLE_MINIMUM
flash_protect = -1
dark_view = 8
aug_message = "You see prey everywhere you look..."
// HUD implants
/obj/item/organ/cyberimp/eyes/hud
name = "HUD implant"
desc = "These cybernetic eyes will display a HUD over everything you see. Maybe."
slot = "eye_hud"
var/HUD_type = 0
/obj/item/organ/cyberimp/eyes/hud/Insert(var/mob/living/carbon/M, var/special = 0)
..()
if(HUD_type)
var/datum/atom_hud/H = huds[HUD_type]
H.add_hud_to(M)
M.permanent_huds |= H
/obj/item/organ/cyberimp/eyes/hud/Remove(var/mob/living/carbon/M, var/special = 0)
if(HUD_type)
var/datum/atom_hud/H = huds[HUD_type]
M.permanent_huds ^= H
H.remove_hud_from(M)
..()
/obj/item/organ/cyberimp/eyes/hud/medical
name = "Medical HUD implant"
desc = "These cybernetic eye implants will display a medical HUD over everything you see."
eye_color = "0ff"
implant_color = "#00FFFF"
origin_tech = "materials=4;programming=4;biotech=4"
aug_message = "You suddenly see health bars floating above people's heads..."
HUD_type = DATA_HUD_MEDICAL_ADVANCED
/obj/item/organ/cyberimp/eyes/hud/security
name = "Security HUD implant"
desc = "These cybernetic eye implants will display a security HUD over everything you see."
eye_color = "d00"
implant_color = "#CC0000"
origin_tech = "materials=4;programming=4;biotech=3;combat=3"
aug_message = "Job indicator icons pop up in your vision. That is not a certified surgeon..."
HUD_type = DATA_HUD_SECURITY_ADVANCED
// Welding shield implant
/obj/item/organ/cyberimp/eyes/shield
name = "welding shield implant"
desc = "These reactive micro-shields will protect you from welders and flashes without obscuring your vision."
slot = "eye_shield"
origin_tech = "materials=4;biotech=3;engineering=4;plasmatech=3"
implant_color = "#101010"
flash_protect = 2
aug_message = null
eye_color = null
/obj/item/organ/cyberimp/eyes/shield/emp_act(severity)
return
@@ -0,0 +1,193 @@
#define STUN_SET_AMOUNT 2
/obj/item/organ/cyberimp
name = "cybernetic implant"
desc = "a state-of-the-art implant that improves a baseline's functionality"
status = ORGAN_ROBOTIC
var/implant_color = "#FFFFFF"
var/implant_overlay
/obj/item/organ/cyberimp/New(var/mob/M = null)
if(iscarbon(M))
src.Insert(M)
if(implant_overlay)
var/image/overlay = new /image(icon, implant_overlay)
overlay.color = implant_color
add_overlay(overlay)
return ..()
//[[[[BRAIN]]]]
/obj/item/organ/cyberimp/brain
name = "cybernetic brain implant"
desc = "injectors of extra sub-routines for the brain"
icon_state = "brain_implant"
implant_overlay = "brain_implant_overlay"
zone = "head"
w_class = 1
/obj/item/organ/cyberimp/brain/emp_act(severity)
if(!owner)
return
var/stun_amount = 5 + (severity-1 ? 0 : 5)
owner.Stun(stun_amount)
owner << "<span class='warning'>Your body seizes up!</span>"
return stun_amount
/obj/item/organ/cyberimp/brain/anti_drop
name = "anti-drop implant"
desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle."
var/active = 0
var/l_hand_ignore = 0
var/r_hand_ignore = 0
var/obj/item/l_hand_obj = null
var/obj/item/r_hand_obj = null
implant_color = "#DE7E00"
slot = "brain_antidrop"
origin_tech = "materials=4;programming=5;biotech=4"
actions_types = list(/datum/action/item_action/organ_action/toggle)
/obj/item/organ/cyberimp/brain/anti_drop/ui_action_click()
active = !active
if(active)
l_hand_obj = owner.l_hand
r_hand_obj = owner.r_hand
if(l_hand_obj)
if(owner.l_hand.flags & NODROP)
l_hand_ignore = 1
else
owner.l_hand.flags |= NODROP
l_hand_ignore = 0
if(r_hand_obj)
if(owner.r_hand.flags & NODROP)
r_hand_ignore = 1
else
owner.r_hand.flags |= NODROP
r_hand_ignore = 0
if(!l_hand_obj && !r_hand_obj)
owner << "<span class='notice'>You are not holding any items, your hands relax...</span>"
active = 0
else
var/msg = 0
msg += !l_hand_ignore && l_hand_obj ? 1 : 0
msg += !r_hand_ignore && r_hand_obj ? 2 : 0
switch(msg)
if(1)
owner << "<span class='notice'>Your left hand's grip tightens.</span>"
if(2)
owner << "<span class='notice'>Your right hand's grip tightens.</span>"
if(3)
owner << "<span class='notice'>Both of your hand's grips tighten.</span>"
else
release_items()
owner << "<span class='notice'>Your hands relax...</span>"
l_hand_obj = null
r_hand_obj = null
/obj/item/organ/cyberimp/brain/anti_drop/emp_act(severity)
if(!owner)
return
var/range = severity ? 10 : 5
var/atom/A
var/obj/item/L_item = owner.l_hand
var/obj/item/R_item = owner.r_hand
release_items()
..()
if(L_item)
A = pick(oview(range))
L_item.throw_at(A, range, 2)
owner << "<span class='warning'>Your left arm spasms and throws the [L_item.name]!</span>"
if(R_item)
A = pick(oview(range))
R_item.throw_at(A, range, 2)
owner << "<span class='warning'>Your right arm spasms and throws the [R_item.name]!</span>"
/obj/item/organ/cyberimp/brain/anti_drop/proc/release_items()
if(!l_hand_ignore && l_hand_obj in owner.contents)
l_hand_obj.flags ^= NODROP
if(!r_hand_ignore && r_hand_obj in owner.contents)
r_hand_obj.flags ^= NODROP
/obj/item/organ/cyberimp/brain/anti_drop/Remove(var/mob/living/carbon/M, special = 0)
if(active)
ui_action_click()
..()
/obj/item/organ/cyberimp/brain/anti_stun
name = "CNS Rebooter implant"
desc = "This implant will automatically give you back control over your central nervous system, reducing downtime when stunned."
implant_color = "#FFFF00"
slot = "brain_antistun"
origin_tech = "materials=5;programming=4;biotech=5"
/obj/item/organ/cyberimp/brain/anti_stun/on_life()
..()
if(crit_fail)
return
if(owner.stunned > STUN_SET_AMOUNT)
owner.stunned = STUN_SET_AMOUNT
if(owner.weakened > STUN_SET_AMOUNT)
owner.weakened = STUN_SET_AMOUNT
/obj/item/organ/cyberimp/brain/anti_stun/emp_act(severity)
if(crit_fail)
return
crit_fail = TRUE
addtimer(src, "reboot", 90 / severity)
/obj/item/organ/cyberimp/brain/anti_stun/proc/reboot()
crit_fail = FALSE
//[[[[MOUTH]]]]
/obj/item/organ/cyberimp/mouth
zone = "mouth"
/obj/item/organ/cyberimp/mouth/breathing_tube
name = "breathing tube implant"
desc = "This simple implant adds an internals connector to your back, allowing you to use internals without a mask and protecting you from being choked."
icon_state = "implant_mask"
slot = "breathing_tube"
w_class = 1
origin_tech = "materials=2;biotech=3"
/obj/item/organ/cyberimp/mouth/breathing_tube/emp_act(severity)
if(prob(60/severity))
owner << "<span class='warning'>Your breathing tube suddenly closes!</span>"
owner.losebreath += 2
//BOX O' IMPLANTS
/obj/item/weapon/storage/box/cyber_implants
name = "boxed cybernetic implant"
desc = "A sleek, sturdy box."
icon_state = "cyber_implants"
/obj/item/weapon/storage/box/cyber_implants/New(loc, implant)
..()
new /obj/item/device/autoimplanter(src)
if(ispath(implant))
new implant(src)
/obj/item/weapon/storage/box/cyber_implants/bundle
name = "boxed cybernetic implants"
var/list/boxed = list(/obj/item/organ/cyberimp/eyes/xray,/obj/item/organ/cyberimp/eyes/thermals,
/obj/item/organ/cyberimp/brain/anti_stun, /obj/item/organ/cyberimp/chest/reviver)
var/amount = 5
/obj/item/weapon/storage/box/cyber_implants/bundle/New()
..()
var/implant
while(contents.len <= amount + 1) // +1 for the autoimplanter.
implant = pick(boxed)
new implant(src)
@@ -0,0 +1,65 @@
#define INFINITE -1
/obj/item/device/autoimplanter
name = "autoimplanter"
desc = "A device that automatically injects a cyber-implant into the user without the hassle of extensive surgery. It has a slot to insert implants and a screwdriver slot for removing accidentally added implants."
icon_state = "autoimplanter"
item_state = "walkietalkie"//left as this so as to intentionally not have inhands
w_class = 2
var/obj/item/organ/storedorgan
var/organ_type = /obj/item/organ/cyberimp
var/uses = INFINITE
/obj/item/device/autoimplanter/New()
..()
if(storedorgan)
storedorgan.loc = src
/obj/item/device/autoimplanter/attack_self(mob/user)//when the object it used...
if(!uses)
user << "<span class='warning'>[src] has already been used. The tools are dull and won't reactivate.</span>"
return
else if(!storedorgan)
user << "<span class='notice'>[src] currently has no implant stored.</span>"
return
storedorgan.Insert(user)//insert stored organ into the user
user.visible_message("<span class='notice'>[user] presses a button on [src], and you hear a short mechanical noise.</span>", "<span class='notice'>You feel a sharp sting as [src] plunges into your body.</span>")
playsound(get_turf(user), 'sound/weapons/circsawhit.ogg', 50, 1)
storedorgan = null
if(uses != INFINITE)
uses--
if(!uses)
desc = "[initial(desc)] Looks like it's been used up."
/obj/item/device/autoimplanter/attackby(obj/item/I, mob/user, params)
if(istype(I, organ_type))
if(storedorgan)
user << "<span class='notice'>[src] already has an implant stored.</span>"
return
else if(!uses)
user << "<span class='notice'>[src] has already been used up.</span>"
return
if(!user.drop_item())
return
I.loc = src
storedorgan = I
user << "<span class='notice'>You insert the [I] into [src].</span>"
else if(istype(I, /obj/item/weapon/screwdriver))
if(!storedorgan)
user << "<span class='notice'>There's no implant in [src] for you to remove.</span>"
else
var/turf/open/floorloc = get_turf(user)
floorloc.contents += contents
user << "<span class='notice'>You remove the [storedorgan] from [src].</span>"
playsound(get_turf(user), 'sound/items/Screwdriver.ogg', 50, 1)
storedorgan = null
if(uses != INFINITE)
uses--
if(!uses)
desc = "[initial(desc)] Looks like it's been used up."
/obj/item/device/autoimplanter/cmo
name = "medical HUD autoimplanter"
desc = "A single use autoimplanter that contains a medical heads-up display augment. A screwdriver can be used to remove it, but implants can't be placed back in."
storedorgan = new/obj/item/organ/cyberimp/eyes/hud/medical()
uses = 1
+33
View File
@@ -0,0 +1,33 @@
mob/proc/getorgan(typepath)
return
mob/proc/getorganszone(zone)
return
mob/proc/getorganslot(slot)
return
mob/living/carbon/getorgan(typepath)
return (locate(typepath) in internal_organs)
mob/living/carbon/getorganszone(zone, var/subzones = 0)
var/list/returnorg = list()
if(subzones)
// Include subzones - groin for chest, eyes and mouth for head
if(zone == "head")
returnorg = getorganszone("eyes") + getorganszone("mouth")
if(zone == "chest")
returnorg = getorganszone("groin")
for(var/obj/item/organ/O in internal_organs)
if(zone == O.zone)
returnorg += O
return returnorg
mob/living/carbon/getorganslot(slot)
return internal_organs_slot[slot]
proc/isorgan(atom/A)
return istype(A, /obj/item/organ)
@@ -0,0 +1,435 @@
/obj/item/organ
name = "organ"
icon = 'icons/obj/surgery.dmi'
var/mob/living/carbon/owner = null
var/status = ORGAN_ORGANIC
origin_tech = "biotech=3"
force = 1
w_class = 2
throwforce = 0
var/zone = "chest"
var/slot
// DO NOT add slots with matching names to different zones - it will break internal_organs_slot list!
var/vital = 0
/obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0)
if(!iscarbon(M) || owner == M)
return
var/obj/item/organ/replaced = M.getorganslot(slot)
if(replaced)
replaced.Remove(M, special = 1)
owner = M
M.internal_organs |= src
M.internal_organs_slot[slot] = src
loc = null
for(var/X in actions)
var/datum/action/A = X
A.Grant(M)
/obj/item/organ/proc/Remove(mob/living/carbon/M, special = 0)
owner = null
if(M)
M.internal_organs -= src
if(M.internal_organs_slot[slot] == src)
M.internal_organs_slot.Remove(slot)
if(vital && !special)
M.death()
for(var/X in actions)
var/datum/action/A = X
A.Remove(M)
/obj/item/organ/proc/on_find(mob/living/finder)
return
/obj/item/organ/proc/on_life()
return
/obj/item/organ/examine(mob/user)
..()
if(status == ORGAN_ROBOTIC && crit_fail)
user << "<span class='warning'>[src] seems to be broken!</span>"
/obj/item/organ/proc/prepare_eat()
var/obj/item/weapon/reagent_containers/food/snacks/organ/S = new
S.name = name
S.desc = desc
S.icon = icon
S.icon_state = icon_state
S.origin_tech = origin_tech
S.w_class = w_class
return S
/obj/item/weapon/reagent_containers/food/snacks/organ
name = "appendix"
icon_state = "appendix"
icon = 'icons/obj/surgery.dmi'
list_reagents = list("nutriment" = 5)
/obj/item/organ/Destroy()
if(owner)
Remove(owner, 1)
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/weapon/reagent_containers/food/snacks/S = prepare_eat()
if(S)
H.drop_item()
H.put_in_active_hand(S)
S.attack(H, H)
qdel(src)
else
..()
/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.
//Looking for brains?
//Try code/modules/mob/living/carbon/brain/brain_item.dm
/obj/item/organ/heart
name = "heart"
icon_state = "heart-on"
zone = "chest"
slot = "heart"
origin_tech = "biotech=5"
var/beating = 1
var/icon_base = "heart"
attack_verb = list("beat", "thumped")
/obj/item/organ/heart/update_icon()
if(beating)
icon_state = "[icon_base]-on"
else
icon_state = "[icon_base]-off"
/obj/item/organ/heart/Remove(mob/living/carbon/M, special = 0)
..()
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.stat == DEAD || H.heart_attack)
Stop()
return
if(!special)
H.heart_attack = 1
addtimer(src, "stop_if_unowned", 120)
/obj/item/organ/heart/proc/stop_if_unowned()
if(!owner)
Stop()
/obj/item/organ/heart/attack_self(mob/user)
..()
if(!beating)
visible_message("<span class='notice'>[user] squeezes [src] to \
make it beat again!</span>")
Restart()
addtimer(src, "stop_if_unowned", 80)
/obj/item/organ/heart/Insert(mob/living/carbon/M, special = 0)
..()
if(ishuman(M) && beating)
var/mob/living/carbon/human/H = M
if(H.heart_attack)
H.heart_attack = 0
return
/obj/item/organ/heart/proc/Stop()
beating = 0
update_icon()
return 1
/obj/item/organ/heart/proc/Restart()
beating = 1
update_icon()
return 1
/obj/item/organ/heart/prepare_eat()
var/obj/S = ..()
S.icon_state = "heart-off"
return S
/obj/item/organ/heart/cursed
name = "cursed heart"
desc = "it needs to be pumped..."
icon_state = "cursedheart-off"
icon_base = "cursedheart"
origin_tech = "biotech=6"
actions_types = list(/datum/action/item_action/organ_action/cursed_heart)
var/last_pump = 0
var/add_colour = TRUE //So we're not constantly recreating colour datums
var/pump_delay = 30 //you can pump 1 second early, for lag, but no more (otherwise you could spam heal)
var/blood_loss = 100 //600 blood is human default, so 5 failures (below 122 blood is where humans die because reasons?)
//How much to heal per pump, negative numbers would HURT the player
var/heal_brute = 0
var/heal_burn = 0
var/heal_oxy = 0
/obj/item/organ/heart/cursed/attack(mob/living/carbon/human/H, mob/living/carbon/human/user, obj/target)
if(H == user && istype(H))
playsound(user,'sound/effects/singlebeat.ogg',40,1)
user.drop_item()
Insert(user)
else
return ..()
/obj/item/organ/heart/cursed/on_life()
if(world.time > (last_pump + pump_delay))
if(ishuman(owner) && owner.client) //While this entire item exists to make people suffer, they can't control disconnects.
var/mob/living/carbon/human/H = owner
if(H.dna && !(NOBLOOD in H.dna.species.specflags))
H.blood_volume = max(H.blood_volume - blood_loss, 0)
H << "<span class = 'userdanger'>You have to keep pumping your blood!</span>"
if(add_colour)
H.add_client_colour(/datum/client_colour/cursed_heart_blood) //bloody screen so real
add_colour = FALSE
else
last_pump = world.time //lets be extra fair *sigh*
/obj/item/organ/heart/cursed/Insert(mob/living/carbon/M, special = 0)
..()
if(owner)
owner << "<span class ='userdanger'>Your heart has been replaced with a cursed one, you have to pump this one manually otherwise you'll die!</span>"
/datum/action/item_action/organ_action/cursed_heart
name = "pump your blood"
//You are now brea- pumping blood manually
/datum/action/item_action/organ_action/cursed_heart/Trigger()
. = ..()
if(. && istype(target,/obj/item/organ/heart/cursed))
var/obj/item/organ/heart/cursed/cursed_heart = target
if(world.time < (cursed_heart.last_pump + (cursed_heart.pump_delay-10))) //no spam
owner << "<span class='userdanger'>Too soon!</span>"
return
cursed_heart.last_pump = world.time
playsound(owner,'sound/effects/singlebeat.ogg',40,1)
owner << "<span class = 'notice'>Your heart beats.</span>"
var/mob/living/carbon/human/H = owner
if(istype(H))
if(H.dna && !(NOBLOOD in H.dna.species.specflags))
H.blood_volume = min(H.blood_volume + cursed_heart.blood_loss*0.5, BLOOD_VOLUME_MAXIMUM)
H.remove_client_colour(/datum/client_colour/cursed_heart_blood)
cursed_heart.add_colour = TRUE
H.adjustBruteLoss(-cursed_heart.heal_brute)
H.adjustFireLoss(-cursed_heart.heal_burn)
H.adjustOxyLoss(-cursed_heart.heal_oxy)
/datum/client_colour/cursed_heart_blood
priority = 100 //it's an indicator you're dieing, so it's very high priority
colour = "red"
/obj/item/organ/lungs
name = "lungs"
icon_state = "lungs"
zone = "chest"
slot = "lungs"
gender = PLURAL
w_class = 3
/obj/item/organ/lungs/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("salbutamol", 5)
return S
/obj/item/organ/tongue
name = "tongue"
desc = "A fleshy muscle mostly used for lying."
icon_state = "tonguenormal"
zone = "mouth"
slot = "tongue"
var/say_mod = null
attack_verb = list("licked", "slobbered", "slapped", "frenched", "tongued")
/obj/item/organ/tongue/get_spans()
return list()
/obj/item/organ/tongue/proc/TongueSpeech(var/message)
return message
/obj/item/organ/tongue/Insert(mob/living/carbon/M, special = 0)
..()
if(say_mod && M.dna && M.dna.species)
M.dna.species.say_mod = say_mod
/obj/item/organ/tongue/Remove(mob/living/carbon/M, special = 0)
..()
if(say_mod && M.dna && M.dna.species)
M.dna.species.say_mod = initial(M.dna.species.say_mod)
/obj/item/organ/tongue/lizard
name = "forked tongue"
desc = "A thin and long muscle typically found in reptilian races, apparently moonlights as a nose."
icon_state = "tonguelizard"
say_mod = "hisses"
/obj/item/organ/tongue/lizard/TongueSpeech(var/message)
var/regex/lizard_hiss = new("s+", "g")
var/regex/lizard_hiSS = new("S+", "g")
if(copytext(message, 1, 2) != "*")
message = lizard_hiss.Replace(message, "sss")
message = lizard_hiSS.Replace(message, "SSS")
return message
/obj/item/organ/tongue/fly
name = "proboscis"
desc = "A freakish looking meat tube that apparently can take in liquids."
icon_state = "tonguefly"
say_mod = "buzzes"
/obj/item/organ/tongue/fly/TongueSpeech(var/message)
var/regex/fly_buzz = new("z+", "g")
var/regex/fly_buZZ = new("Z+", "g")
if(copytext(message, 1, 2) != "*")
message = fly_buzz.Replace(message, "zzz")
message = fly_buZZ.Replace(message, "ZZZ")
return message
/obj/item/organ/tongue/abductor
name = "superlingual matrix"
desc = "A mysterious structure that allows for instant communication between users. Pretty impressive until you need to eat something."
icon_state = "tongueayylmao"
say_mod = "gibbers"
/obj/item/organ/tongue/abductor/TongueSpeech(var/message)
//Hacks
var/mob/living/carbon/human/user = usr
var/rendered = "<span class='abductor'><b>[user.name]:</b> [message]</span>"
for(var/mob/living/carbon/human/H in living_mob_list)
var/obj/item/organ/tongue/T = H.getorganslot("tongue")
if(!T || T.type != type)
continue
else if(H.dna && H.dna.species.id == "abductor" && user.dna && user.dna.species.id == "abductor")
var/datum/species/abductor/Ayy = user.dna.species
var/datum/species/abductor/Byy = H.dna.species
if(Ayy.team != Byy.team)
continue
H << rendered
for(var/mob/M in dead_mob_list)
var/link = FOLLOW_LINK(M, user)
M << "[link] [rendered]"
return ""
/obj/item/organ/tongue/zombie
name = "rotting tongue"
desc = "Between the decay and the fact that it's just lying there you doubt a tongue has ever seemed less sexy."
icon_state = "tonguezombie"
say_mod = "moans"
/obj/item/organ/tongue/zombie/TongueSpeech(var/message)
var/list/message_list = splittext(message, " ")
var/maxchanges = max(round(message_list.len / 1.5), 2)
for(var/i = rand(maxchanges / 2, maxchanges), i > 0, i--)
var/insertpos = rand(1, message_list.len - 1)
var/inserttext = message_list[insertpos]
if(!(copytext(inserttext, length(inserttext) - 2) == "..."))
message_list[insertpos] = inserttext + "..."
if(prob(20) && message_list.len > 3)
message_list.Insert(insertpos, "[pick("BRAINS", "Brains", "Braaaiinnnsss", "BRAAAIIINNSSS")]...")
return jointext(message_list, " ")
/obj/item/organ/tongue/alien
name = "alien tongue"
desc = "According to leading xenobiologists the evolutionary benefit of having a second mouth in your mouth is \"that it looks badass\"."
icon_state = "tonguexeno"
say_mod = "hiss"
/obj/item/organ/tongue/alien/TongueSpeech(var/message)
playsound(owner, "hiss", 25, 1, 1)
return message
/obj/item/organ/tongue/bone
name = "bone \"tongue\""
desc = "Apparently skeletons alter the sounds they produce \
through oscillation of their teeth, hence their characteristic \
rattling."
icon_state = "tonguebone"
say_mod = "rattles"
attack_verb = list("bitten", "chattered", "chomped", "enamelled", "boned")
var/chattering = FALSE
var/phomeme_type = "sans"
var/list/phomeme_types = list("sans", "papyrus")
/obj/item/organ/tongue/bone/New()
. = ..()
phomeme_type = pick(phomeme_types)
/obj/item/organ/tongue/bone/TongueSpeech(var/message)
. = message
if(chattering)
//Annoy everyone nearby with your chattering.
chatter(message, phomeme_type, usr)
/obj/item/organ/tongue/bone/get_spans()
. = ..()
// Feature, if the tongue talks directly, it will speak with its span
switch(phomeme_type)
if("sans")
. |= SPAN_SANS
if("papyrus")
. |= SPAN_PAPYRUS
/obj/item/organ/tongue/bone/chatter
name = "chattering bone \"tongue\""
chattering = TRUE
/obj/item/organ/appendix
name = "appendix"
icon_state = "appendix"
zone = "groin"
slot = "appendix"
var/inflamed = 0
/obj/item/organ/appendix/update_icon()
if(inflamed)
icon_state = "appendixinflamed"
name = "inflamed appendix"
else
icon_state = "appendix"
name = "appendix"
/obj/item/organ/appendix/Remove(mob/living/carbon/M, special = 0)
for(var/datum/disease/appendicitis/A in M.viruses)
A.cure()
inflamed = 1
update_icon()
..()
/obj/item/organ/appendix/Insert(mob/living/carbon/M, special = 0)
..()
if(inflamed)
M.AddDisease(new /datum/disease/appendicitis)
/obj/item/organ/appendix/prepare_eat()
var/obj/S = ..()
if(inflamed)
S.reagents.add_reagent("????", 5)
return S
+27
View File
@@ -0,0 +1,27 @@
/datum/surgery/plastic_surgery
name = "plastic surgery"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/reshape_face, /datum/surgery_step/close)
possible_locs = list("head")
//reshape_face
/datum/surgery_step/reshape_face
name = "reshape face"
implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/kitchen/knife = 50, /obj/item/weapon/wirecutters = 35)
time = 64
/datum/surgery_step/reshape_face/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to alter [target]'s appearance.", "<span class='notice'>You begin to alter [target]'s appearance...</span>")
/datum/surgery_step/reshape_face/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(target.status_flags & DISFIGURED)
target.status_flags &= ~DISFIGURED
user.visible_message("[user] successfully restores [target]'s appearance!", "<span class='notice'>You successfully restore [target]'s appearance.</span>")
else
var/oldname = target.real_name
target.real_name = target.dna.species.random_name(target.gender,1)
var/newname = target.real_name //something about how the code handles names required that I use this instead of target.real_name
user.visible_message("[user] alters [oldname]'s appearance completely, they are now [newname]!", "<span class='notice'>You alter [oldname]'s appearance completely, they are now [newname].</span>")
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.sec_hud_set_ID()
return 1
@@ -0,0 +1,54 @@
/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)
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))
return 0
var/mob/living/carbon/human/H = target
if(!H.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)
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)
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.
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>"
/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()
L.attach_limb(target)
if(organ_rejection_dam)
target.adjustToxLoss(organ_rejection_dam)
user.visible_message("[user] successfully replaces [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You succeed in replacing [target]'s [parse_zone(target_zone)].</span>")
return 1
@@ -0,0 +1,40 @@
/datum/surgery/embedded_removal
name = "removal of embedded objects"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/remove_object)
possible_locs = list("r_arm","l_arm","r_leg","l_leg","chest","head")
/datum/surgery_step/remove_object
name = "remove embedded objects"
time = 32
accept_hand = 1
var/obj/item/bodypart/L = null
/datum/surgery_step/remove_object/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
L = surgery.organ
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
user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "<span class='notice'>You look for [target]'s [parse_zone(user.zone_selected)]...</span>")
/datum/surgery_step/remove_object/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
var/objects = 0
for(var/obj/item/I in L.embedded_objects)
objects++
I.loc = get_turf(H)
L.embedded_objects -= I
if(objects > 0)
user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L]!", "<span class='notice'>You sucessfully remove [objects] objects from [H]'s [L.name].</span>")
else
user << "<span class='warning'>You find no objects embedded in [H]'s [L]!</span>"
else
user << "<span class='warning'>You can't find [target]'s [parse_zone(user.zone_selected)], let alone any objects embedded in it!</span>"
return 1
+63
View File
@@ -0,0 +1,63 @@
/datum/surgery
var/name = "surgery"
var/status = 1
var/list/steps = list() //Steps in a surgery
var/step_in_progress = 0 //Actively performing a Surgery
var/can_cancel = 1 //Can cancel this surgery after step 1 with cautery
var/list/species = list(/mob/living/carbon/human) //Acceptable Species
var/location = "chest" //Surgery location
var/requires_organic_bodypart = 1 //Prevents you from performing an operation on robotic limbs
var/list/possible_locs = list() //Multiple locations -- c0
var/ignore_clothes = 0 //This surgery ignores clothes
var/obj/item/organ/organ //Operable body part
var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing.
/datum/surgery/proc/can_start(mob/user, mob/living/carbon/target)
// if 0 surgery wont show up in list
// put special restrictions here
return 1
/datum/surgery/proc/next_step(mob/user, mob/living/carbon/target)
if(step_in_progress)
return
var/datum/surgery_step/S = get_surgery_step()
if(S)
if(S.try_op(user, target, user.zone_selected, user.get_active_hand(), src))
return 1
return 0
/datum/surgery/proc/get_surgery_step()
var/step_type = steps[status]
return new step_type
/datum/surgery/proc/complete(mob/living/carbon/human/target)
target.surgeries -= src
src = null
//INFO
//Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand.
//As of Feb 21 2013 they are in code/modules/mob/living/carbon/carbon.dm, lines 459 and 51 respectively.
//Other important variables are var/list/surgeries (/mob/living) and var/list/internal_organs (/mob/living/carbon)
// var/list/bodyparts (/mob/living/carbon/human) is the LIMBS of a Mob.
//Surgical procedures are initiated by attempt_initiate_surgery(), which is called by surgical drapes and bedsheets.
// /code/modules/surgery/multiple_location_example.dm contains steps to setup a multiple location operation.
//TODO
//specific steps for some surgeries (fluff text)
//R&D researching new surgeries (especially for non-humans)
//more interesting failure options
//randomised complications
//more surgeries!
//add a probability modifier for the state of the surgeon- health, twitching, etc. blindness, god forbid.
//helper for converting a zone_sel.selecting to body part (for damage)
//RESOLVED ISSUES //"Todo" jobs that have been completed
//combine hands/feet into the arms - Hands/feet were removed - RR
//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see multiple_location_example.dm - RR
+81
View File
@@ -0,0 +1,81 @@
/datum/surgery_step
var/list/implements = list() //format is path = probability of success. alternatively
var/implement_type = null //the current type of implement used. This has to be stored, as the actual typepath of the tool may not match the list type.
var/accept_hand = 0 //does the surgery step require an open hand? If true, ignores implements. Compatible with accept_any_item.
var/accept_any_item = 0 //does the surgery step accept any item? If true, ignores implements. Compatible with require_hand.
var/time = 10 //how long does the step take?
var/name
/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/success = 0
if(accept_hand)
if(!tool)
success = 1
if(accept_any_item)
if(tool && tool_check(user, tool))
success = 1
else
for(var/path in implements)
if(istype(tool, path))
implement_type = path
if(tool_check(user, tool))
success = 1
if(success)
if(target_zone == surgery.location)
if(get_location_accessible(target, target_zone) || surgery.ignore_clothes)
initiate(user, target, target_zone, tool, surgery)
return 1
else
user << "<span class='warning'>You need to expose [target]'s [parse_zone(target_zone)] to perform surgery on it!</span>"
return 1 //returns 1 so we don't stab the guy in the dick or wherever.
if(isrobot(user) && user.a_intent != "harm") //to save asimov borgs a LOT of heartache
return 1
return 0
/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
surgery.step_in_progress = 1
if(preop(user, target, target_zone, tool, surgery) == -1)
surgery.step_in_progress = 0
return
if(do_after(user, time, target = target))
var/advance = 0
var/prob_chance = 100
if(implement_type) //this means it isn't a require hand or any item step.
prob_chance = implements[implement_type]
prob_chance *= get_location_modifier(target)
if(prob(prob_chance) || isrobot(user))
if(success(user, target, target_zone, tool, surgery))
advance = 1
else
if(failure(user, target, target_zone, tool, surgery))
advance = 1
if(advance)
surgery.status++
if(surgery.status > surgery.steps.len)
surgery.complete(target)
surgery.step_in_progress = 0
/datum/surgery_step/proc/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to perform surgery on [target].", "<span class='notice'>You begin to perform surgery on [target]...</span>")
/datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] succeeds!", "<span class='notice'>You succeed.</span>")
return 1
/datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("<span class='warning'>[user] screws up!</span>", "<span class='warning'>You screw up!</span>")
return 0
/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool)
return 1
+73
View File
@@ -0,0 +1,73 @@
// The detachment and attachment of lizard tails
// Dismemberment lite; can/should be generalized aka augs when we get more mutant parts and/or for actual dismemberment
// TAIL REMOVAL
/datum/surgery/tail_removal
name = "tail removal"
steps = list(/datum/surgery_step/sever_tail, /datum/surgery_step/close)
species = list(/mob/living/carbon/human)
possible_locs = list("groin")
/datum/surgery/tail_removal/can_start(mob/user, mob/living/carbon/target)
var/mob/living/carbon/human/L = target
if(("tail_lizard" in L.dna.species.mutant_bodyparts) || ("waggingtail_lizard" in L.dna.species.mutant_bodyparts))
return 1
return 0
/datum/surgery_step/sever_tail
name = "sever tail"
implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/energy/sword/cyborg/saw = 100, /obj/item/weapon/melee/arm_blade = 80, /obj/item/weapon/twohanded/required/chainsaw = 80, /obj/item/weapon/mounted_chainsaw = 80, /obj/item/weapon/twohanded/fireaxe = 50, /obj/item/weapon/hatchet = 40, /obj/item/weapon/kitchen/knife/butcher = 25)
time = 64
/datum/surgery_step/sever_tail/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to sever [target]'s tail!", "<span class='notice'>You begin to sever [target]'s tail...</span>")
/datum/surgery_step/sever_tail/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 tail!", "<span class='notice'>You sever [L]'s tail.</span>")
if("tail_lizard" in L.dna.species.mutant_bodyparts)
L.dna.species.mutant_bodyparts -= "tail_lizard"
else if("waggingtail_lizard" in L.dna.species.mutant_bodyparts)
L.dna.species.mutant_bodyparts -= "waggingtail_lizard"
if("spines" in L.dna.features)
L.dna.features -= "spines"
var/obj/item/severedtail/S = new(get_turf(target))
S.color = "#[L.dna.features["mcolor"]]"
S.markings = "[L.dna.features["tail"]]"
L.update_body()
return 1
// TAIL ATTACHMENT
/datum/surgery/tail_attachment
name = "tail attachment"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/replace, /datum/surgery_step/attach_tail, /datum/surgery_step/close)
species = list(/mob/living/carbon/human)
possible_locs = list("groin")
/datum/surgery/tail_attachment/can_start(mob/user, mob/living/carbon/target)
var/mob/living/carbon/human/L = target
if(!("tail_lizard" in L.dna.species.mutant_bodyparts) && !("waggingtail_lizard" in L.dna.species.mutant_bodyparts))
return 1
return 0
/datum/surgery_step/attach_tail
name = "attach tail"
implements = list(/obj/item/severedtail = 100)
time = 64
/datum/surgery_step/attach_tail/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] begins to attach a tail to [target]!", "<span class='notice'>You begin to attach the tail to [target]...</span>")
/datum/surgery_step/attach_tail/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] gives [L] a tail!", "<span class='notice'>You give [L] a tail. It adjusts to [L]'s melanin.</span>") // fluff for color
if(!(L.dna.features["mcolor"]))
L.dna.features["mcolor"] = tool.color
var/obj/item/severedtail/T = tool
L.dna.features["tail_lizard"] = T.markings
L.dna.species.mutant_bodyparts += "tail_lizard"
qdel(tool)
L.update_body()
return 1
+102
View File
@@ -0,0 +1,102 @@
/obj/item/weapon/retractor
name = "retractor"
desc = "Retracts stuff."
icon = 'icons/obj/surgery.dmi'
icon_state = "retractor"
materials = list(MAT_METAL=6000, MAT_GLASS=3000)
flags = CONDUCT
w_class = 1
origin_tech = "materials=1;biotech=1"
/obj/item/weapon/hemostat
name = "hemostat"
desc = "You think you have seen this before."
icon = 'icons/obj/surgery.dmi'
icon_state = "hemostat"
materials = list(MAT_METAL=5000, MAT_GLASS=2500)
flags = CONDUCT
w_class = 1
origin_tech = "materials=1;biotech=1"
attack_verb = list("attacked", "pinched")
/obj/item/weapon/cautery
name = "cautery"
desc = "This stops bleeding."
icon = 'icons/obj/surgery.dmi'
icon_state = "cautery"
materials = list(MAT_METAL=2500, MAT_GLASS=750)
flags = CONDUCT
w_class = 1
origin_tech = "materials=1;biotech=1"
attack_verb = list("burnt")
/obj/item/weapon/surgicaldrill
name = "surgical drill"
desc = "You can drill using this item. You dig?"
icon = 'icons/obj/surgery.dmi'
icon_state = "drill"
hitsound = 'sound/weapons/circsawhit.ogg'
materials = list(MAT_METAL=10000, MAT_GLASS=6000)
flags = CONDUCT
force = 15
w_class = 3
origin_tech = "materials=1;biotech=1"
attack_verb = list("drilled")
/obj/item/weapon/scalpel
name = "scalpel"
desc = "Cut, cut, and once more cut."
icon = 'icons/obj/surgery.dmi'
icon_state = "scalpel"
flags = CONDUCT
force = 10
w_class = 1
throwforce = 5
throw_speed = 3
throw_range = 5
materials = list(MAT_METAL=4000, MAT_GLASS=1000)
origin_tech = "materials=1;biotech=1"
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP_ACCURATE
/obj/item/weapon/scalpel/suicide_act(mob/user)
user.visible_message(pick("<span class='suicide'>[user] is slitting \his wrists with [src]! It looks like \he's trying to commit suicide.</span>", \
"<span class='suicide'>[user] is slitting \his throat with [src]! It looks like \he's trying to commit suicide.</span>", \
"<span class='suicide'>[user] is slitting \his stomach open with [src]! It looks like \he's trying to commit seppuku.</span>"))
return (BRUTELOSS)
/obj/item/weapon/circular_saw
name = "circular saw"
desc = "For heavy duty cutting."
icon = 'icons/obj/surgery.dmi'
icon_state = "saw"
hitsound = 'sound/weapons/circsawhit.ogg'
throwhitsound = 'sound/weapons/pierce.ogg'
flags = CONDUCT
force = 15
w_class = 3
throwforce = 9
throw_speed = 2
throw_range = 5
materials = list(MAT_METAL=10000, MAT_GLASS=6000)
origin_tech = "biotech=1;combat=1"
attack_verb = list("attacked", "slashed", "sawed", "cut")
sharpness = IS_SHARP
/obj/item/weapon/surgical_drapes
name = "surgical drapes"
desc = "Nanotrasen brand surgical drapes provide optimal safety and infection control."
icon = 'icons/obj/surgery.dmi'
icon_state = "surgical_drapes"
w_class = 1
origin_tech = "biotech=1"
attack_verb = list("slapped")
/obj/item/weapon/surgical_drapes/attack(mob/living/M, mob/user)
if(!attempt_initiate_surgery(src, M, user))
..()