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