initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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()
|
||||
..()
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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))
|
||||
..()
|
||||
Reference in New Issue
Block a user