Merge pull request #9596 from Linzolle/abductor-update

Bring abductors up-to-date with /tg/.
This commit is contained in:
Ghom
2019-12-21 11:15:29 +01:00
committed by GitHub
44 changed files with 844 additions and 316 deletions

View File

@@ -118,6 +118,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define ismouse(A) (istype(A, /mob/living/simple_animal/mouse))
#define iscow(A) (istype(A, /mob/living/simple_animal/cow))
#define isslime(A) (istype(A, /mob/living/simple_animal/slime))
#define isdrone(A) (istype(A, /mob/living/simple_animal/drone))

View File

@@ -57,6 +57,7 @@
#define MOVESPEED_ID_PRONE_DRAGGING "PRONE_DRAG"
#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
#define MOVESPEED_ID_SHRINK_RAY "SHRUNKEN_SPEED_MODIFIER"
#define MOVESPEED_ID_TASED_STATUS "TASED"

View File

@@ -213,6 +213,16 @@ or something covering your eyes."
desc = "Whoa man, you're tripping balls! Careful you don't get addicted... if you aren't already."
icon_state = "high"
/obj/screen/alert/mind_control
name = "Mind Control"
desc = "Your mind has been hijacked! Click to view the mind control command."
icon_state = "mind_control"
var/command
/obj/screen/alert/mind_control/Click()
var/mob/living/L = usr
to_chat(L, "<span class='mind_control'>[command]</span>")
/obj/screen/alert/hypnosis
name = "Hypnosis"
desc = "Something's hypnotizing you, but you're not really sure about what."

View File

@@ -93,7 +93,7 @@ SUBSYSTEM_DEF(traumas)
/obj/item/clothing/under/rank/head_of_security/grey, /obj/item/clothing/under/rank/head_of_security/alt,
/obj/item/clothing/under/rank/research_director/alt, /obj/item/clothing/under/rank/research_director/turtleneck,
/obj/item/clothing/under/captainparade, /obj/item/clothing/under/hosparademale, /obj/item/clothing/under/hosparadefem,
/obj/item/clothing/head/helmet/abductor, /obj/item/clothing/suit/armor/abductor/vest, /obj/item/abductor_baton,
/obj/item/clothing/head/helmet/abductor, /obj/item/clothing/suit/armor/abductor/vest, /obj/item/abductor/baton,
/obj/item/storage/belt/military/abductor, /obj/item/gun/energy/alien, /obj/item/abductor/silencer,
/obj/item/abductor/gizmo, /obj/item/clothing/under/rank/centcom_officer,
/obj/item/clothing/suit/space/hardsuit/ert, /obj/item/clothing/suit/space/hardsuit/ert/sec,
@@ -136,7 +136,7 @@ SUBSYSTEM_DEF(traumas)
"aliens" = typecacheof(list(/obj/item/clothing/mask/facehugger, /obj/item/organ/body_egg/alien_embryo,
/obj/structure/alien, /obj/item/toy/toy_xeno,
/obj/item/clothing/suit/armor/abductor, /obj/item/abductor, /obj/item/gun/energy/alien,
/obj/item/abductor_baton, /obj/item/radio/headset/abductor, /obj/item/scalpel/alien, /obj/item/hemostat/alien,
/obj/item/abductor/baton, /obj/item/radio/headset/abductor, /obj/item/scalpel/alien, /obj/item/hemostat/alien,
/obj/item/retractor/alien, /obj/item/circular_saw/alien, /obj/item/surgicaldrill/alien, /obj/item/cautery/alien,
/obj/item/clothing/head/helmet/abductor, /obj/structure/bed/abductor, /obj/structure/table_frame/abductor,
/obj/structure/table/abductor, /obj/structure/table/optable/abductor, /obj/structure/closet/abductor, /obj/item/organ/heart/gland,

View File

@@ -0,0 +1,42 @@
/datum/component/shrink
var/olddens
var/oldopac
dupe_mode = COMPONENT_DUPE_HIGHLANDER
/datum/component/shrink/Initialize(shrink_time)
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
var/atom/parent_atom = parent
parent_atom.transform = parent_atom.transform.Scale(0.5,0.5)
olddens = parent_atom.density
oldopac = parent_atom.opacity
parent_atom.density = 0
parent_atom.opacity = 0
if(isliving(parent_atom))
var/mob/living/L = parent_atom
L.add_movespeed_modifier(MOVESPEED_ID_SHRINK_RAY, update=TRUE, priority=100, multiplicative_slowdown=4)
if(iscarbon(L))
var/mob/living/carbon/C = L
C.unequip_everything()
C.visible_message("<span class='warning'>[C]'s belongings fall off of [C.p_them()] as they shrink down!</span>",
"<span class='userdanger'>Your belongings fall away as everything grows bigger!</span>")
if(ishuman(C))
var/mob/living/carbon/human/H = C
H.physiology.damage_resistance -= 100//carbons take double damage while shrunk
parent_atom.visible_message("<span class='warning'>[parent_atom] shrinks down to a tiny size!</span>",
"<span class='userdanger'>Everything grows bigger!</span>")
QDEL_IN(src, shrink_time)
/datum/component/shrink/Destroy()
var/atom/parent_atom = parent
parent_atom.transform = parent_atom.transform.Scale(2,2)
parent_atom.density = olddens
parent_atom.opacity = oldopac
if(isliving(parent_atom))
var/mob/living/L = parent_atom
L.remove_movespeed_modifier(MOVESPEED_ID_SHRINK_RAY)
if(ishuman(L))
var/mob/living/carbon/human/H = L
H.physiology.damage_resistance += 100
..()

View File

@@ -165,7 +165,7 @@
/obj/item/organ/heart/gland/chem = 5,
/obj/item/organ/heart/gland/mindshock = 5,
/obj/item/organ/heart/gland/plasma = 7,
/obj/item/organ/heart/gland/pop = 5,
/obj/item/organ/heart/gland/transform = 5,
/obj/item/organ/heart/gland/slime = 4,
/obj/item/organ/heart/gland/spiderman = 5,
/obj/item/organ/heart/gland/ventcrawling = 1,

View File

@@ -349,6 +349,10 @@
icon_state = "impact_laser_purple"
duration = 4
/obj/effect/temp_visual/impact_effect/shrink
icon_state = "m_shield"
duration = 10
/obj/effect/temp_visual/impact_effect/ion
icon_state = "shieldsparkles"
duration = 6

View File

@@ -665,6 +665,13 @@
name = "Booze Dispenser (Machine Board)"
build_path = /obj/machinery/chem_dispenser/drinks/beer
/obj/item/circuitboard/machine/chem_dispenser/abductor
name = "Reagent Synthetizer (Abductor Machine Board)"
icon_state = "abductor_mod"
build_path = /obj/machinery/chem_dispenser/abductor
def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high)
needs_anchored = FALSE
/obj/item/circuitboard/machine/smoke_machine
name = "Smoke Machine (Machine Board)"
build_path = /obj/machinery/smoke_machine

View File

@@ -65,6 +65,8 @@
//Equip
var/mob/living/carbon/human/H = owner.current
H.set_species(/datum/species/abductor)
var/obj/item/organ/tongue/abductor/T = H.getorganslot(ORGAN_SLOT_TONGUE)
T.mothership = "[team.name]"
H.real_name = "[team.name] [sub_role]"
H.equipOutfit(outfit)

View File

@@ -17,7 +17,7 @@
actions_types = list(/datum/action/item_action/hands_free/activate)
allowed = list(
/obj/item/abductor,
/obj/item/abductor_baton,
/obj/item/abductor/baton,
/obj/item/melee/baton,
/obj/item/gun/energy,
/obj/item/restraints/handcuffs
@@ -57,7 +57,7 @@
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_WEAR_SUIT) //we only give the mob the ability to activate the vest if he's actually wearing it.
return 1
return TRUE
/obj/item/clothing/suit/armor/abductor/vest/proc/SetDisguise(datum/icon_snapshot/entry)
disguise = entry
@@ -89,11 +89,9 @@
/obj/item/clothing/suit/armor/abductor/vest/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
DeactivateStealth()
return 0
/obj/item/clothing/suit/armor/abductor/vest/IsReflect()
DeactivateStealth()
return 0
/obj/item/clothing/suit/armor/abductor/vest/ui_action_click()
switch(mode)
@@ -111,7 +109,10 @@
to_chat(loc, "<span class='warning'>Combat injection is still recharging.</span>")
return
var/mob/living/carbon/human/M = loc
M.do_adrenaline(150, FALSE, 0, 0, TRUE, list("inaprovaline" = 3, "synaptizine" = 10, "omnizine" = 10), "<span class='boldnotice'>You feel a sudden surge of energy!</span>")
M.adjustStaminaLoss(-75)
M.SetUnconscious(0)
M.SetStun(0)
M.SetKnockdown(0)
combat_cooldown = 0
START_PROCESSING(SSobj, src)
@@ -131,9 +132,11 @@
/obj/item/abductor
icon = 'icons/obj/abductor.dmi'
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
/obj/item/abductor/proc/AbductorCheck(mob/user)
if(HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING))
if (HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING))
return TRUE
if (istype(user) && user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
return TRUE
@@ -158,8 +161,6 @@
desc = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras."
icon_state = "gizmo_scan"
item_state = "silencer"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
var/mode = GIZMO_SCAN
var/mob/living/marked = null
var/obj/machinery/abductor/console/console
@@ -218,12 +219,9 @@
if(marked == target)
to_chat(user, "<span class='warning'>This specimen is already marked!</span>")
return
if(ishuman(target))
if(isabductor(target))
marked = target
to_chat(user, "<span class='notice'>You mark [target] for future retrieval.</span>")
else
prepare(target,user)
if(isabductor(target) || iscow(target))
marked = target
to_chat(user, "<span class='notice'>You mark [target] for future retrieval.</span>")
else
prepare(target,user)
@@ -247,8 +245,6 @@
desc = "A compact device used to shut down communications equipment."
icon_state = "silencer"
item_state = "gizmo"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
/obj/item/abductor/silencer/attack(mob/living/M, mob/user)
if(!AbductorCheck(user))
@@ -292,8 +288,6 @@
or to send a command to a test subject with a charged gland."
icon_state = "mind_device_message"
item_state = "silencer"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
var/mode = MIND_DEVICE_MESSAGE
/obj/item/abductor/mind_device/attack_self(mob/user)
@@ -389,6 +383,17 @@
item_state = "alienpistol"
trigger_guard = TRIGGER_GUARD_ALLOW_ALL
/obj/item/gun/energy/shrink_ray
name = "shrink ray blaster"
desc = "This is a piece of frightening alien tech that enhances the magnetic pull of atoms in a localized space to temporarily make an object shrink. \
That or it's just space magic. Either way, it shrinks stuff."
ammo_type = list(/obj/item/ammo_casing/energy/shrink)
item_state = "shrink_ray"
icon_state = "shrink_ray"
fire_delay = 30
selfcharge = 1//shot costs 200 energy, has a max capacity of 1000 for 5 shots. self charge returns 25 energy every couple ticks, so about 1 shot charged every 12~ seconds
trigger_guard = TRIGGER_GUARD_ALLOW_ALL// variable-size trigger, get it? (abductors need this to be set so the gun is usable for them)
/obj/item/paper/guides/antag/abductor
name = "Dissection Guide"
icon_state = "alienpaper_words"
@@ -422,21 +427,18 @@
#define BATON_PROBE 3
#define BATON_MODES 4
/obj/item/abductor_baton
/obj/item/abductor/baton
name = "advanced baton"
desc = "A quad-mode baton used for incapacitation and restraining of specimens."
var/mode = BATON_STUN
icon = 'icons/obj/abductor.dmi'
icon_state = "wonderprodStun"
item_state = "wonderprod"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
slot_flags = ITEM_SLOT_BELT
force = 7
w_class = WEIGHT_CLASS_NORMAL
actions_types = list(/datum/action/item_action/toggle_mode)
/obj/item/abductor_baton/proc/toggle(mob/living/user=usr)
/obj/item/abductor/baton/proc/toggle(mob/living/user=usr)
mode = (mode+1)%BATON_MODES
var/txt
switch(mode)
@@ -452,7 +454,7 @@
to_chat(usr, "<span class='notice'>You switch the baton to [txt] mode.</span>")
update_icon()
/obj/item/abductor_baton/update_icon()
/obj/item/abductor/baton/update_icon()
switch(mode)
if(BATON_STUN)
icon_state = "wonderprodStun"
@@ -467,8 +469,8 @@
icon_state = "wonderprodProbe"
item_state = "wonderprodProbe"
/obj/item/abductor_baton/attack(mob/target, mob/living/user)
if(!isabductor(user))
/obj/item/abductor/baton/attack(mob/target, mob/living/user)
if(!AbductorCheck(user))
return
if(iscyborg(target))
@@ -485,8 +487,8 @@
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return 0
playsound(H, 'sound/weapons/genhit.ogg', 50, TRUE)
return FALSE
switch (mode)
if(BATON_STUN)
@@ -498,10 +500,10 @@
if(BATON_PROBE)
ProbeAttack(L,user)
/obj/item/abductor_baton/attack_self(mob/living/user)
/obj/item/abductor/baton/attack_self(mob/living/user)
toggle(user)
/obj/item/abductor_baton/proc/StunAttack(mob/living/L,mob/living/user)
/obj/item/abductor/baton/proc/StunAttack(mob/living/L,mob/living/user)
L.lastattacker = user.real_name
L.lastattackerckey = user.ckey
@@ -513,7 +515,7 @@
L.visible_message("<span class='danger'>[user] has stunned [L] with [src]!</span>", \
"<span class='userdanger'>[user] has stunned you with [src]!</span>")
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
if(ishuman(L))
var/mob/living/carbon/human/H = L
@@ -521,7 +523,7 @@
log_combat(user, L, "stunned")
/obj/item/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
/obj/item/abductor/baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.incapacitated(TRUE, TRUE))
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is interfering with the sleep inducement!</span>")
@@ -531,7 +533,7 @@
return
L.visible_message("<span class='danger'>[user] has induced sleep in [L] with [src]!</span>", \
"<span class='userdanger'>You suddenly feel very drowsy!</span>")
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
L.Sleeping(1200)
log_combat(user, L, "put to sleep")
else
@@ -545,13 +547,13 @@
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src]!</span>", \
"<span class='userdanger'>You suddenly feel drowsy!</span>")
/obj/item/abductor_baton/proc/CuffAttack(mob/living/L,mob/living/user)
/obj/item/abductor/baton/proc/CuffAttack(mob/living/L,mob/living/user)
if(!iscarbon(L))
return
var/mob/living/carbon/C = L
if(!C.handcuffed)
if(C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore())
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2)
C.visible_message("<span class='danger'>[user] begins restraining [C] with [src]!</span>", \
"<span class='userdanger'>[user] begins shaping an energy field around your hands!</span>")
if(do_mob(user, C, 30) && (C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore()))
@@ -565,7 +567,7 @@
else
to_chat(user, "<span class='warning'>[C] doesn't have two hands...</span>")
/obj/item/abductor_baton/proc/ProbeAttack(mob/living/L,mob/living/user)
/obj/item/abductor/baton/proc/ProbeAttack(mob/living/L,mob/living/user)
L.visible_message("<span class='danger'>[user] probes [L] with [src]!</span>", \
"<span class='userdanger'>[user] probes you!</span>")
@@ -610,7 +612,7 @@
S.start()
. = ..()
/obj/item/abductor_baton/examine(mob/user)
/obj/item/abductor/baton/examine(mob/user)
. = ..()
switch(mode)
if(BATON_STUN)
@@ -639,10 +641,44 @@
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
/obj/item/radio/headset/abductor/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
if(W.tool_behaviour == TOOL_SCREWDRIVER)
return // Stops humans from disassembling abductor headsets.
return ..()
/obj/item/abductor_machine_beacon
name = "machine beacon"
desc = "A beacon designed to instantly tele-construct abductor machinery."
icon = 'icons/obj/abductor.dmi'
icon_state = "beacon"
w_class = WEIGHT_CLASS_TINY
var/obj/machinery/spawned_machine
/obj/item/abductor_machine_beacon/attack_self(mob/user)
..()
user.visible_message("<span class='notice'>[user] places down [src] and activates it.</span>", "<span class='notice'>You place down [src] and activate it.</span>")
user.dropItemToGround(src)
playsound(src, 'sound/machines/terminal_alert.ogg', 50)
addtimer(CALLBACK(src, .proc/try_spawn_machine), 30)
/obj/item/abductor_machine_beacon/proc/try_spawn_machine()
var/viable = FALSE
if(isfloorturf(loc))
var/turf/T = loc
viable = TRUE
for(var/obj/thing in T.contents)
if(thing.density || ismachinery(thing) || isstructure(thing))
viable = FALSE
if(viable)
playsound(src, 'sound/effects/phasein.ogg', 50, TRUE)
var/new_machine = new spawned_machine(loc)
visible_message("<span class='notice'>[new_machine] warps on top of the beacon!</span>")
qdel(src)
else
playsound(src, 'sound/machines/buzz-two.ogg', 50)
/obj/item/abductor_machine_beacon/chem_dispenser
name = "beacon - Reagent Synthesizer"
spawned_machine = /obj/machinery/chem_dispenser/abductor
/obj/item/scalpel/alien
name = "alien scalpel"
@@ -706,11 +742,11 @@
framestackamount = 1
/obj/structure/table_frame/abductor/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wrench))
if(I.tool_behaviour == TOOL_WRENCH)
to_chat(user, "<span class='notice'>You start disassembling [src]...</span>")
I.play_tool_sound(src)
if(I.use_tool(src, user, 30))
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
for(var/i = 1, i <= framestackamount, i++)
new framestack(get_turf(src))
qdel(src)
@@ -760,7 +796,6 @@
icon = 'icons/obj/abductor.dmi'
icon_state = "bed"
can_buckle = 1
buckle_lying = 1
var/static/list/injected_reagents = list("corazone")
@@ -798,3 +833,11 @@
airlock_type = /obj/machinery/door/airlock/abductor
material_type = /obj/item/stack/sheet/mineral/abductor
noglass = TRUE
/obj/item/clothing/under/abductor
desc = "The most advanced form of jumpsuit known to reality, looks uncomfortable."
name = "alien jumpsuit"
icon_state = "abductor"
item_state = "bl_suit"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 10, rad = 0, fire = 0, acid = 0)
can_adjust = 0

View File

@@ -1,6 +1,6 @@
/datum/outfit/abductor
name = "Abductor Basic"
uniform = /obj/item/clothing/under/color/grey //they're greys gettit
uniform = /obj/item/clothing/under/abductor
shoes = /obj/item/clothing/shoes/combat
back = /obj/item/storage/backpack
ears = /obj/item/radio/headset/abductor
@@ -34,7 +34,7 @@
name = "Abductor Agent"
head = /obj/item/clothing/head/helmet/abductor
suit = /obj/item/clothing/suit/armor/abductor/vest
suit_store = /obj/item/abductor_baton
suit_store = /obj/item/abductor/baton
belt = /obj/item/storage/belt/military/abductor/full
backpack_contents = list(

View File

@@ -5,18 +5,23 @@
icon_state = "gland"
status = ORGAN_ROBOTIC
beating = TRUE
organ_flags = ORGAN_NO_SPOIL
var/true_name = "baseline placebo referencer"
var/cooldown_low = 300
var/cooldown_high = 300
var/next_activation = 0
var/uses // -1 For infinite
var/human_only = 0
var/active = 0
var/human_only = FALSE
var/active = FALSE
var/mind_control_uses = 1
var/mind_control_duration = 1800
var/active_mind_control = FALSE
/obj/item/organ/heart/gland/Initialize()
. = ..()
icon_state = pick(list("health", "spider", "slime", "emp", "species", "egg", "vent", "mindshock", "viral"))
/obj/item/organ/heart/gland/examine(mob/user)
. = ..()
if((user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)) || isobserver(user))
@@ -55,14 +60,18 @@
active_mind_control = TRUE
message_admins("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]")
update_gland_hud()
var/obj/screen/alert/mind_control/mind_alert = owner.throw_alert("mind_control", /obj/screen/alert/mind_control)
mind_alert.command = command
addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration)
return TRUE
/obj/item/organ/heart/gland/proc/clear_mind_control()
if(!ownerCheck() || !active_mind_control)
return FALSE
to_chat(owner, "<span class='userdanger'>You feel the compulsion fade, and you completely forget about your previous orders.</span>")
to_chat(owner, "<span class='userdanger'>You feel the compulsion fade, and you <i>completely forget</i> about your previous orders.</span>")
owner.clear_alert("mind_control")
active_mind_control = FALSE
return TRUE
/obj/item/organ/heart/gland/Remove(mob/living/carbon/M, special = 0)
active = 0
@@ -98,257 +107,4 @@
active = 0
/obj/item/organ/heart/gland/proc/activate()
return
/obj/item/organ/heart/gland/heals
true_name = "coherency harmonizer"
cooldown_low = 200
cooldown_high = 400
uses = -1
icon_state = "health"
mind_control_uses = 3
mind_control_duration = 3000
/obj/item/organ/heart/gland/heals/activate()
to_chat(owner, "<span class='notice'>You feel curiously revitalized.</span>")
owner.adjustToxLoss(-20, FALSE, TRUE)
owner.heal_bodypart_damage(20, 20, 0, TRUE)
owner.adjustOxyLoss(-20)
/obj/item/organ/heart/gland/slime
true_name = "gastric animation galvanizer"
cooldown_low = 600
cooldown_high = 1200
uses = -1
icon_state = "slime"
mind_control_uses = 1
mind_control_duration = 2400
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
owner.faction |= "slime"
owner.grant_language(/datum/language/slime)
/obj/item/organ/heart/gland/slime/activate()
to_chat(owner, "<span class='warning'>You feel nauseated!</span>")
owner.vomit(20)
var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey")
Slime.Friends = list(owner)
Slime.Leader = owner
/obj/item/organ/heart/gland/mindshock
true_name = "neural crosstalk uninhibitor"
cooldown_low = 400
cooldown_high = 700
uses = -1
icon_state = "mindshock"
mind_control_uses = 1
mind_control_duration = 6000
/obj/item/organ/heart/gland/mindshock/activate()
to_chat(owner, "<span class='notice'>You get a headache.</span>")
var/turf/T = get_turf(owner)
for(var/mob/living/carbon/H in orange(4,T))
if(H == owner)
continue
switch(pick(1,3))
if(1)
to_chat(H, "<span class='userdanger'>You hear a loud buzz in your head, silencing your thoughts!</span>")
H.Stun(50)
if(2)
to_chat(H, "<span class='warning'>You hear an annoying buzz in your head.</span>")
H.confused += 15
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 160)
if(3)
H.hallucination += 60
/obj/item/organ/heart/gland/pop
true_name = "anthropmorphic translocator"
cooldown_low = 900
cooldown_high = 1800
uses = -1
human_only = TRUE
icon_state = "species"
mind_control_uses = 5
mind_control_duration = 300
/obj/item/organ/heart/gland/pop/activate()
to_chat(owner, "<span class='notice'>You feel unlike yourself.</span>")
randomize_human(owner)
var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/insect, /datum/species/fly))
owner.set_species(species)
/obj/item/organ/heart/gland/ventcrawling
true_name = "pliant cartilage enabler"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "vent"
mind_control_uses = 4
mind_control_duration = 1800
/obj/item/organ/heart/gland/ventcrawling/activate()
to_chat(owner, "<span class='notice'>You feel very stretchy.</span>")
owner.ventcrawler = VENTCRAWLER_ALWAYS
/obj/item/organ/heart/gland/viral
true_name = "contamination incubator"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "viral"
mind_control_uses = 1
mind_control_duration = 1800
/obj/item/organ/heart/gland/viral/activate()
to_chat(owner, "<span class='warning'>You feel sick.</span>")
var/datum/disease/advance/A = random_virus(pick(2,6),6)
A.carrier = TRUE
owner.ForceContractDisease(A, FALSE, TRUE)
/obj/item/organ/heart/gland/viral/proc/random_virus(max_symptoms, max_level)
if(max_symptoms > VIRUS_SYMPTOM_LIMIT)
max_symptoms = VIRUS_SYMPTOM_LIMIT
var/datum/disease/advance/A = new /datum/disease/advance()
var/list/datum/symptom/possible_symptoms = list()
for(var/symptom in subtypesof(/datum/symptom))
var/datum/symptom/S = symptom
if(initial(S.level) > max_level)
continue
if(initial(S.level) <= 0) //unobtainable symptoms
continue
possible_symptoms += S
for(var/i in 1 to max_symptoms)
var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms)
if(chosen_symptom)
var/datum/symptom/S = new chosen_symptom
A.symptoms += S
A.Refresh() //just in case someone already made and named the same disease
return A
/obj/item/organ/heart/gland/trauma
true_name = "white matter randomiser"
cooldown_low = 800
cooldown_high = 1200
uses = 5
icon_state = "emp"
mind_control_uses = 3
mind_control_duration = 1800
/obj/item/organ/heart/gland/trauma/activate()
to_chat(owner, "<span class='warning'>You feel a spike of pain in your head.</span>")
if(prob(33))
owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
else
if(prob(20))
owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
else
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
/obj/item/organ/heart/gland/spiderman
true_name = "araneae cloister accelerator"
cooldown_low = 450
cooldown_high = 900
uses = -1
icon_state = "spider"
mind_control_uses = 2
mind_control_duration = 2400
/obj/item/organ/heart/gland/spiderman/activate()
to_chat(owner, "<span class='warning'>You feel something crawling in your skin.</span>")
owner.faction |= "spiders"
var/obj/structure/spider/spiderling/S = new(owner.drop_location())
S.directive = "Protect your nest inside [owner.real_name]."
/obj/item/organ/heart/gland/egg
true_name = "roe/enzymatic synthesizer"
cooldown_low = 300
cooldown_high = 400
uses = -1
icon_state = "egg"
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
mind_control_uses = 2
mind_control_duration = 1800
/obj/item/organ/heart/gland/egg/activate()
owner.visible_message("<span class='alertalien'>[owner] [pick(EGG_LAYING_MESSAGES)]</span>")
var/turf/T = owner.drop_location()
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
/obj/item/organ/heart/gland/electric
true_name = "electron accumulator/discharger"
cooldown_low = 800
cooldown_high = 1200
uses = -1
mind_control_uses = 2
mind_control_duration = 900
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0)
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
..()
/obj/item/organ/heart/gland/electric/activate()
owner.visible_message("<span class='danger'>[owner]'s skin starts emitting electric arcs!</span>",\
"<span class='warning'>You feel electric energy building up inside you!</span>")
playsound(get_turf(owner), "sparks", 100, 1, -1)
addtimer(CALLBACK(src, .proc/zap), rand(30, 100))
/obj/item/organ/heart/gland/electric/proc/zap()
tesla_zap(owner, 4, 8000, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN)
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1)
/obj/item/organ/heart/gland/chem
true_name = "intrinsic pharma-provider"
cooldown_low = 50
cooldown_high = 50
uses = -1
mind_control_uses = 3
mind_control_duration = 1200
var/list/possible_reagents = list()
/obj/item/organ/heart/gland/chem/Initialize()
..()
for(var/X in subtypesof(/datum/reagent/drug))
var/datum/reagent/R = X
possible_reagents += initial(R.id)
for(var/X in subtypesof(/datum/reagent/medicine))
var/datum/reagent/R = X
possible_reagents += initial(R.id)
for(var/X in typesof(/datum/reagent/toxin))
var/datum/reagent/R = X
possible_reagents += initial(R.id)
/obj/item/organ/heart/gland/chem/activate()
var/chem_to_add = pick(possible_reagents)
owner.reagents.add_reagent(chem_to_add, 2)
owner.adjustToxLoss(-2, TRUE, TRUE)
..()
/obj/item/organ/heart/gland/plasma
true_name = "effluvium sanguine-synonym emitter"
cooldown_low = 1200
cooldown_high = 1800
uses = -1
mind_control_uses = 1
mind_control_duration = 800
/obj/item/organ/heart/gland/plasma/activate()
to_chat(owner, "<span class='warning'>You feel bloated.</span>")
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "<span class='userdanger'>A massive stomachache overcomes you.</span>"), 150)
addtimer(CALLBACK(src, .proc/vomit_plasma), 200)
/obj/item/organ/heart/gland/plasma/proc/vomit_plasma()
if(!owner)
return
owner.visible_message("<span class='danger'>[owner] vomits a cloud of plasma!</span>")
var/turf/open/T = get_turf(owner)
if(istype(T))
T.atmos_spawn_air("plasma=50;TEMP=[T20C]")
owner.vomit()
return

View File

@@ -0,0 +1,19 @@
/obj/item/organ/heart/gland/access
true_name = "anagraphic electro-scrambler"
cooldown_low = 600
cooldown_high = 1200
uses = 1
icon_state = "mindshock"
mind_control_uses = 3
mind_control_duration = 900
/obj/item/organ/heart/gland/access/activate()
to_chat(owner, "<span class='notice'>You feel like a VIP for some reason.</span>")
RegisterSignal(owner, COMSIG_MOB_ALLOWED, .proc/free_access)
/obj/item/organ/heart/gland/access/proc/free_access(datum/source, obj/O)
return TRUE
/obj/item/organ/heart/gland/access/Remove(mob/living/carbon/M, special = 0)
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
..()

View File

@@ -0,0 +1,18 @@
/obj/item/organ/heart/gland/blood
true_name = "pseudonuclear hemo-destabilizer"
cooldown_low = 1200
cooldown_high = 1800
uses = -1
icon_state = "egg"
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
mind_control_uses = 3
mind_control_duration = 1500
/obj/item/organ/heart/gland/blood/activate()
if(!ishuman(owner) || !owner.dna.species)
return
var/mob/living/carbon/human/H = owner
var/datum/species/species = H.dna.species
to_chat(H, "<span class='warning'>You feel your blood heat up for a moment.</span>")
species.exotic_blood = get_random_reagent_id()

View File

@@ -0,0 +1,20 @@
/obj/item/organ/heart/gland/chem
true_name = "intrinsic pharma-provider"
cooldown_low = 50
cooldown_high = 50
uses = -1
icon_state = "viral"
mind_control_uses = 3
mind_control_duration = 1200
var/list/possible_reagents = list()
/obj/item/organ/heart/gland/chem/Initialize()
. = ..()
for(var/R in subtypesof(/datum/reagent/drug) + subtypesof(/datum/reagent/medicine) + typesof(/datum/reagent/toxin))
possible_reagents += R
/obj/item/organ/heart/gland/chem/activate()
var/chem_to_add = pick(possible_reagents)
owner.reagents.add_reagent(chem_to_add, 2)
owner.adjustToxLoss(-5, TRUE, TRUE)
..()

View File

@@ -0,0 +1,15 @@
/obj/item/organ/heart/gland/egg
true_name = "roe/enzymatic synthesizer"
cooldown_low = 300
cooldown_high = 400
uses = -1
icon_state = "egg"
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
mind_control_uses = 2
mind_control_duration = 1800
/obj/item/organ/heart/gland/egg/activate()
owner.visible_message("<span class='alertalien'>[owner] [pick(EGG_LAYING_MESSAGES)]</span>")
var/turf/T = owner.drop_location()
new /obj/item/reagent_containers/food/snacks/egg/gland(T)

View File

@@ -0,0 +1,26 @@
/obj/item/organ/heart/gland/electric
true_name = "electron accumulator/discharger"
cooldown_low = 800
cooldown_high = 1200
icon_state = "species"
uses = -1
mind_control_uses = 2
mind_control_duration = 900
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0)
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
..()
/obj/item/organ/heart/gland/electric/activate()
owner.visible_message("<span class='danger'>[owner]'s skin starts emitting electric arcs!</span>",\
"<span class='warning'>You feel electric energy building up inside you!</span>")
playsound(get_turf(owner), "sparks", 100, TRUE, -1)
addtimer(CALLBACK(src, .proc/zap), rand(30, 100))
/obj/item/organ/heart/gland/electric/proc/zap()
tesla_zap(owner, 4, 8000, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN)
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, TRUE)

View File

@@ -0,0 +1,178 @@
/obj/item/organ/heart/gland/heal
true_name = "organic replicator"
cooldown_low = 200
cooldown_high = 400
uses = -1
human_only = TRUE
icon_state = "health"
mind_control_uses = 3
mind_control_duration = 3000
/obj/item/organ/heart/gland/heal/activate()
if(!(owner.mob_biotypes & MOB_ORGANIC))
return
for(var/organ in owner.internal_organs)
if(istype(organ, /obj/item/organ/cyberimp))
reject_implant(organ)
return
var/obj/item/organ/liver/liver = owner.getorganslot(ORGAN_SLOT_LIVER)
if((!liver/* && !HAS_TRAIT(owner, TRAIT_NOMETABOLISM)*/) || (liver && ((liver.damage > (liver.maxHealth / 2)) || (istype(liver, /obj/item/organ/liver/cybernetic)))))
replace_liver(liver)
return
var/obj/item/organ/lungs/lungs = owner.getorganslot(ORGAN_SLOT_LUNGS)
if((!lungs && !HAS_TRAIT(owner, TRAIT_NOBREATH)) || (lungs && (istype(lungs, /obj/item/organ/lungs/cybernetic))))
replace_lungs(lungs)
return
var/obj/item/organ/eyes/eyes = owner.getorganslot(ORGAN_SLOT_EYES)
if(!eyes || (eyes && ((HAS_TRAIT_FROM(owner, TRAIT_NEARSIGHT, EYE_DAMAGE)) || (HAS_TRAIT_FROM(owner, TRAIT_BLIND, EYE_DAMAGE)) || (istype(eyes, /obj/item/organ/eyes/robotic)))))
replace_eyes(eyes)
return
var/obj/item/bodypart/limb
var/list/limb_list = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
for(var/zone in limb_list)
limb = owner.get_bodypart(zone)
if(!limb)
replace_limb(zone)
return
if((limb.get_damage() >= (limb.max_damage / 2)) || (limb.status == BODYPART_ROBOTIC))
replace_limb(zone, limb)
return
if(owner.getToxLoss() > 40)
replace_blood()
return
var/tox_amount = 0
for(var/datum/reagent/toxin/T in owner.reagents.reagent_list)
tox_amount += owner.reagents.get_reagent_amount(T.type)
if(tox_amount > 10)
replace_blood()
return
if(owner.blood_volume < BLOOD_VOLUME_OKAY)
owner.blood_volume = BLOOD_VOLUME_NORMAL
to_chat(owner, "<span class='warning'>You feel your blood pulsing within you.</span>")
return
var/obj/item/bodypart/chest/chest = owner.get_bodypart(BODY_ZONE_CHEST)
if((chest.get_damage() >= (chest.max_damage / 4)) || (chest.status == BODYPART_ROBOTIC))
replace_chest(chest)
return
/obj/item/organ/heart/gland/heal/proc/reject_implant(obj/item/organ/cyberimp/implant)
owner.visible_message("<span class='warning'>[owner] vomits up his [implant.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [implant.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
implant.Remove(owner)
implant.forceMove(owner.drop_location())
/obj/item/organ/heart/gland/heal/proc/replace_liver(obj/item/organ/liver/liver)
if(liver)
owner.visible_message("<span class='warning'>[owner] vomits up his [liver.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [liver.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
liver.Remove(owner)
liver.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble in your bowels...</span>")
var/liver_type = /obj/item/organ/liver
if(owner?.dna?.species?.mutantliver)
liver_type = owner.dna.species.mutantliver
var/obj/item/organ/liver/new_liver = new liver_type()
new_liver.Insert(owner)
/obj/item/organ/heart/gland/heal/proc/replace_lungs(obj/item/organ/lungs/lungs)
if(lungs)
owner.visible_message("<span class='warning'>[owner] vomits up his [lungs.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [lungs.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
lungs.Remove(owner)
lungs.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble inside your chest...</span>")
var/lung_type = /obj/item/organ/lungs
if(owner.dna.species && owner.dna.species.mutantlungs)
lung_type = owner.dna.species.mutantlungs
var/obj/item/organ/lungs/new_lungs = new lung_type()
new_lungs.Insert(owner)
/obj/item/organ/heart/gland/heal/proc/replace_eyes(obj/item/organ/eyes/eyes)
if(eyes)
owner.visible_message("<span class='warning'>[owner]'s [eyes.name] fall out of their sockets!</span>", "<span class='userdanger'>Your [eyes.name] fall out of their sockets!</span>")
playsound(owner, 'sound/effects/splat.ogg', 50, TRUE)
eyes.Remove(owner)
eyes.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble behind your eye sockets...</span>")
addtimer(CALLBACK(src, .proc/finish_replace_eyes), rand(100, 200))
/obj/item/organ/heart/gland/heal/proc/finish_replace_eyes()
var/eye_type = /obj/item/organ/eyes
if(owner.dna.species && owner.dna.species.mutanteyes)
eye_type = owner.dna.species.mutanteyes
var/obj/item/organ/eyes/new_eyes = new eye_type()
new_eyes.Insert(owner)
owner.visible_message("<span class='warning'>A pair of new eyes suddenly inflates into [owner]'s eye sockets!</span>", "<span class='userdanger'>A pair of new eyes suddenly inflates into your eye sockets!</span>")
/obj/item/organ/heart/gland/heal/proc/replace_limb(body_zone, obj/item/bodypart/limb)
if(limb)
owner.visible_message("<span class='warning'>[owner]'s [limb.name] suddenly detaches from [owner.p_their()] body!</span>", "<span class='userdanger'>Your [limb.name] suddenly detaches from your body!</span>")
playsound(owner, "desceration", 50, TRUE, -1)
limb.drop_limb()
else
to_chat(owner, "<span class='warning'>You feel a weird tingle in your [parse_zone(body_zone)]... even if you don't have one.</span>")
addtimer(CALLBACK(src, .proc/finish_replace_limb, body_zone), rand(150, 300))
/obj/item/organ/heart/gland/heal/proc/finish_replace_limb(body_zone)
owner.visible_message("<span class='warning'>With a loud snap, [owner]'s [parse_zone(body_zone)] rapidly grows back from [owner.p_their()] body!</span>",
"<span class='userdanger'>With a loud snap, your [parse_zone(body_zone)] rapidly grows back from your body!</span>",
"<span class='warning'>Your hear a loud snap.</span>")
playsound(owner, 'sound/magic/demon_consume.ogg', 50, TRUE)
owner.regenerate_limb(body_zone)
/obj/item/organ/heart/gland/heal/proc/replace_blood()
owner.visible_message("<span class='warning'>[owner] starts vomiting huge amounts of blood!</span>", "<span class='userdanger'>You suddenly start vomiting huge amounts of blood!</span>")
keep_replacing_blood()
/obj/item/organ/heart/gland/heal/proc/keep_replacing_blood()
var/keep_going = FALSE
owner.vomit(0, TRUE, FALSE, 3, FALSE, FALSE, FALSE, TRUE)
owner.Stun(15)
owner.adjustToxLoss(-15, TRUE, TRUE)
owner.blood_volume = min(BLOOD_VOLUME_NORMAL, owner.blood_volume + 20)
if(owner.blood_volume < BLOOD_VOLUME_NORMAL)
keep_going = TRUE
if(owner.getToxLoss())
keep_going = TRUE
for(var/datum/reagent/toxin/R in owner.reagents.reagent_list)
owner.reagents.remove_reagent(R.type, 4)
if(owner.reagents.has_reagent(R.type))
keep_going = TRUE
if(keep_going)
addtimer(CALLBACK(src, .proc/keep_replacing_blood), 30)
/obj/item/organ/heart/gland/heal/proc/replace_chest(obj/item/bodypart/chest/chest)
if(chest.status == BODYPART_ROBOTIC)
owner.visible_message("<span class='warning'>[owner]'s [chest.name] rapidly expels its mechanical components, replacing them with flesh!</span>", "<span class='userdanger'>Your [chest.name] rapidly expels its mechanical components, replacing them with flesh!</span>")
playsound(owner, 'sound/magic/clockwork/anima_fragment_attack.ogg', 50, TRUE)
var/list/dirs = GLOB.alldirs.Copy()
for(var/i in 1 to 3)
var/obj/effect/decal/cleanable/robot_debris/debris = new(get_turf(owner))
debris.streak(dirs)
else
owner.visible_message("<span class='warning'>[owner]'s [chest.name] sheds off its damaged flesh, rapidly replacing it!</span>", "<span class='warning'>Your [chest.name] sheds off its damaged flesh, rapidly replacing it!</span>")
playsound(owner, 'sound/effects/splat.ogg', 50, TRUE)
var/list/dirs = GLOB.alldirs.Copy()
for(var/i in 1 to 3)
var/obj/effect/decal/cleanable/blood/gibs/gibs = new(get_turf(owner))
gibs.streak(dirs)
var/obj/item/bodypart/chest/new_chest = new(null)
new_chest.replace_limb(owner, TRUE)
qdel(chest)

View File

@@ -0,0 +1,64 @@
/obj/item/organ/heart/gland/mindshock
true_name = "neural crosstalk uninhibitor"
cooldown_low = 400
cooldown_high = 700
uses = -1
icon_state = "mindshock"
mind_control_uses = 1
mind_control_duration = 6000
var/list/mob/living/carbon/human/broadcasted_mobs = list()
/obj/item/organ/heart/gland/mindshock/activate()
to_chat(owner, "<span class='notice'>You get a headache.</span>")
var/turf/T = get_turf(owner)
for(var/mob/living/carbon/H in orange(4,T))
if(H == owner)
continue
switch(pick(1,3))
if(1)
to_chat(H, "<span class='userdanger'>You hear a loud buzz in your head, silencing your thoughts!</span>")
H.Stun(50)
if(2)
to_chat(H, "<span class='warning'>You hear an annoying buzz in your head.</span>")
H.confused += 15
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 160)
if(3)
H.hallucination += 60
/obj/item/organ/heart/gland/mindshock/mind_control(command, mob/living/user)
if(!ownerCheck() || !mind_control_uses || active_mind_control)
return FALSE
mind_control_uses--
for(var/mob/M in oview(7, owner))
if(!ishuman(M))
continue
var/mob/living/carbon/human/H = M
if(H.stat)
continue
broadcasted_mobs += H
to_chat(H, "<span class='userdanger'>You suddenly feel an irresistible compulsion to follow an order...</span>")
to_chat(H, "<span class='mind_control'>[command]</span>")
message_admins("[key_name(user)] broadcasted an abductor mind control message from [key_name(owner)] to [key_name(H)]: [command]")
var/obj/screen/alert/mind_control/mind_alert = H.throw_alert("mind_control", /obj/screen/alert/mind_control)
mind_alert.command = command
if(LAZYLEN(broadcasted_mobs))
active_mind_control = TRUE
addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration)
update_gland_hud()
return TRUE
/obj/item/organ/heart/gland/mindshock/clear_mind_control()
if(!active_mind_control || !LAZYLEN(broadcasted_mobs))
return FALSE
for(var/M in broadcasted_mobs)
var/mob/living/carbon/human/H = M
to_chat(H, "<span class='userdanger'>You feel the compulsion fade, and you <i>completely forget</i> about your previous orders.</span>")
H.clear_alert("mind_control")
active_mind_control = FALSE
return TRUE

View File

@@ -0,0 +1,22 @@
/obj/item/organ/heart/gland/plasma
true_name = "effluvium sanguine-synonym emitter"
cooldown_low = 1200
cooldown_high = 1800
icon_state = "slime"
uses = -1
mind_control_uses = 1
mind_control_duration = 800
/obj/item/organ/heart/gland/plasma/activate()
to_chat(owner, "<span class='warning'>You feel bloated.</span>")
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "<span class='userdanger'>A massive stomachache overcomes you.</span>"), 150)
addtimer(CALLBACK(src, .proc/vomit_plasma), 200)
/obj/item/organ/heart/gland/plasma/proc/vomit_plasma()
if(!owner)
return
owner.visible_message("<span class='danger'>[owner] vomits a cloud of plasma!</span>")
var/turf/open/T = get_turf(owner)
if(istype(T))
T.atmos_spawn_air("plasma=50;TEMP=[T20C]")
owner.vomit()

View File

@@ -0,0 +1,47 @@
/obj/item/organ/heart/gland/quantum
true_name = "quantic de-observation matrix"
cooldown_low = 150
cooldown_high = 150
uses = -1
icon_state = "emp"
mind_control_uses = 2
mind_control_duration = 1200
var/mob/living/carbon/entangled_mob
/obj/item/organ/heart/gland/quantum/activate()
if(entangled_mob)
return
for(var/mob/M in oview(owner, 7))
if(!iscarbon(M))
continue
entangled_mob = M
addtimer(CALLBACK(src, .proc/quantum_swap), rand(600, 2400))
return
/obj/item/organ/heart/gland/quantum/proc/quantum_swap()
if(QDELETED(entangled_mob))
entangled_mob = null
return
var/turf/T = get_turf(owner)
do_teleport(owner, get_turf(entangled_mob),null,TRUE,channel = TELEPORT_CHANNEL_QUANTUM)
do_teleport(entangled_mob, T,null,TRUE,channel = TELEPORT_CHANNEL_QUANTUM)
to_chat(owner, "<span class='warning'>You suddenly find yourself somewhere else!</span>")
to_chat(entangled_mob, "<span class='warning'>You suddenly find yourself somewhere else!</span>")
if(!active_mind_control) //Do not reset entangled mob while mind control is active
entangled_mob = null
/obj/item/organ/heart/gland/quantum/mind_control(command, mob/living/user)
if(..())
if(entangled_mob && ishuman(entangled_mob) && (entangled_mob.stat < DEAD))
to_chat(entangled_mob, "<span class='userdanger'>You suddenly feel an irresistible compulsion to follow an order...</span>")
to_chat(entangled_mob, "<span class='mind_control'>[command]</span>")
var/obj/screen/alert/mind_control/mind_alert = entangled_mob.throw_alert("mind_control", /obj/screen/alert/mind_control)
mind_alert.command = command
message_admins("[key_name(owner)] mirrored an abductor mind control message to [key_name(entangled_mob)]: [command]")
update_gland_hud()
/obj/item/organ/heart/gland/quantum/clear_mind_control()
if(active_mind_control)
to_chat(entangled_mob, "<span class='userdanger'>You feel the compulsion fade, and you completely forget about your previous orders.</span>")
entangled_mob.clear_alert("mind_control")
..()

View File

@@ -0,0 +1,21 @@
/obj/item/organ/heart/gland/slime
true_name = "gastric animation galvanizer"
cooldown_low = 600
cooldown_high = 1200
uses = -1
icon_state = "slime"
mind_control_uses = 1
mind_control_duration = 2400
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
owner.faction |= "slime"
owner.grant_language(/datum/language/slime)
/obj/item/organ/heart/gland/slime/activate()
to_chat(owner, "<span class='warning'>You feel nauseated!</span>")
owner.vomit(20)
var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey")
Slime.Friends = list(owner)
Slime.Leader = owner

View File

@@ -0,0 +1,14 @@
/obj/item/organ/heart/gland/spiderman
true_name = "araneae cloister accelerator"
cooldown_low = 450
cooldown_high = 900
uses = -1
icon_state = "spider"
mind_control_uses = 2
mind_control_duration = 2400
/obj/item/organ/heart/gland/spiderman/activate()
to_chat(owner, "<span class='warning'>You feel something crawling in your skin.</span>")
owner.faction |= "spiders"
var/obj/structure/spider/spiderling/S = new(owner.drop_location())
S.directive = "Protect your nest inside [owner.real_name]."

View File

@@ -0,0 +1,15 @@
/obj/item/organ/heart/gland/transform
true_name = "anthropmorphic transmorphosizer"
cooldown_low = 900
cooldown_high = 1800
uses = -1
human_only = TRUE
icon_state = "species"
mind_control_uses = 7
mind_control_duration = 300
/obj/item/organ/heart/gland/transform/activate()
to_chat(owner, "<span class='notice'>You feel unlike yourself.</span>")
randomize_human(owner)
var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/insect, /datum/species/fly))
owner.set_species(species)

View File

@@ -0,0 +1,18 @@
/obj/item/organ/heart/gland/trauma
true_name = "white matter randomiser"
cooldown_low = 800
cooldown_high = 1200
uses = 5
icon_state = "emp"
mind_control_uses = 3
mind_control_duration = 1800
/obj/item/organ/heart/gland/trauma/activate()
to_chat(owner, "<span class='warning'>You feel a spike of pain in your head.</span>")
if(prob(33))
owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
else
if(prob(20))
owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
else
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))

View File

@@ -0,0 +1,12 @@
/obj/item/organ/heart/gland/ventcrawling
true_name = "pliant cartilage enabler"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "vent"
mind_control_uses = 4
mind_control_duration = 1800
/obj/item/organ/heart/gland/ventcrawling/activate()
to_chat(owner, "<span class='notice'>You feel very stretchy.</span>")
owner.ventcrawler = VENTCRAWLER_ALWAYS

View File

@@ -0,0 +1,34 @@
/obj/item/organ/heart/gland/viral
true_name = "contamination incubator"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "viral"
mind_control_uses = 1
mind_control_duration = 1800
/obj/item/organ/heart/gland/viral/activate()
to_chat(owner, "<span class='warning'>You feel sick.</span>")
var/datum/disease/advance/A = random_virus(pick(2,6),6)
A.carrier = TRUE
owner.ForceContractDisease(A, FALSE, TRUE)
/obj/item/organ/heart/gland/viral/proc/random_virus(max_symptoms, max_level)
if(max_symptoms > VIRUS_SYMPTOM_LIMIT)
max_symptoms = VIRUS_SYMPTOM_LIMIT
var/datum/disease/advance/A = new /datum/disease/advance()
var/list/datum/symptom/possible_symptoms = list()
for(var/symptom in subtypesof(/datum/symptom))
var/datum/symptom/S = symptom
if(initial(S.level) > max_level)
continue
if(initial(S.level) <= 0) //unobtainable symptoms
continue
possible_symptoms += S
for(var/i in 1 to max_symptoms)
var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms)
if(chosen_symptom)
var/datum/symptom/S = new chosen_symptom
A.symptoms += S
A.Refresh() //just in case someone already made and named the same disease
return A

View File

@@ -43,12 +43,15 @@
dat += "Collected Samples : [points] <br>"
dat += "Gear Credits: [credits] <br>"
dat += "<b>Transfer data in exchange for supplies:</b><br>"
dat += "<a href='?src=[REF(src)];dispense=baton'>Advanced Baton</A><br>"
dat += "<a href='?src=[REF(src)];dispense=helmet'>Agent Helmet</A><br>"
dat += "<a href='?src=[REF(src)];dispense=vest'>Agent Vest</A><br>"
dat += "<a href='?src=[REF(src)];dispense=silencer'>Radio Silencer</A><br>"
dat += "<a href='?src=[REF(src)];dispense=tool'>Science Tool</A><br>"
dat += "<a href='?src=[REF(src)];dispense=mind_device'>Mental Interface Device</A><br>"
dat += "<a href='?src=[REF(src)];dispense=baton'>Advanced Baton (2 Credits)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=mind_device'>Mental Interface Device (2 Credits)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=chem_dispenser'>Reagent Synthesizer (2 Credits)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=shrink_ray'>Shrink Ray Blaster (2 Credits)</a><br>"
dat += "<a href='?src=[REF(src)];dispense=helmet'>Agent Helmet (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=vest'>Agent Vest (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=silencer'>Radio Silencer (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=tool'>Science Tool (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=tongue'>Superlingual Matrix (1 Credit)</a><br>"
else
dat += "<span class='bad'>NO EXPERIMENT MACHINE DETECTED</span> <br>"
@@ -101,7 +104,7 @@
else if(href_list["dispense"])
switch(href_list["dispense"])
if("baton")
Dispense(/obj/item/abductor_baton,cost=2)
Dispense(/obj/item/abductor/baton,cost=2)
if("helmet")
Dispense(/obj/item/clothing/head/helmet/abductor)
if("silencer")
@@ -112,6 +115,12 @@
Dispense(/obj/item/clothing/suit/armor/abductor/vest)
if("mind_device")
Dispense(/obj/item/abductor/mind_device,cost=2)
if("chem_dispenser")
Dispense(/obj/item/abductor_machine_beacon/chem_dispenser,cost=2)
if("tongue")
Dispense(/obj/item/organ/tongue/abductor)
if("shrink_ray")
Dispense(/obj/item/gun/energy/shrink_ray,cost=2)
updateUsrDialog()
/obj/machinery/abductor/console/proc/TeleporterRetrieve()
@@ -136,9 +145,9 @@
var/entry_name
if(remote)
entry_name = show_radial_menu(usr, camera.eyeobj, disguises2)
entry_name = show_radial_menu(usr, camera.eyeobj, disguises2, tooltips = TRUE)
else
entry_name = show_radial_menu(usr, src, disguises2)
entry_name = show_radial_menu(usr, src, disguises2, require_near = TRUE, tooltips = TRUE)
var/datum/icon_snapshot/chosen = disguises[entry_name]
if(chosen && vest && (remote || in_range(usr,src)))
@@ -236,4 +245,4 @@
new item(drop_location)
else
say("Insufficent data!")
say("Insufficent data!")

View File

@@ -309,4 +309,4 @@
//The "pocket" for the M1 helmet so you can tuck things into the elastic band
/datum/component/storage/concrete/pockets/tiny/spacenam
attack_hand_interact = TRUE //So you can actually see what you stuff in there
attack_hand_interact = TRUE //So you can actually see what you stuff in there

View File

@@ -67,3 +67,8 @@
fire_sound = 'sound/weapons/emitter.ogg'
e_cost = 2000 //20,000 is in the cell making this 10 shots before reload
projectile_type = /obj/item/projectile/beam/emitter
/obj/item/ammo_casing/energy/shrink
projectile_type = /obj/item/projectile/beam/shrink
select_name = "shrink ray"
e_cost = 200

View File

@@ -190,3 +190,21 @@
var/mob/living/carbon/M = target
M.visible_message("<span class='danger'>[M] explodes into a shower of gibs!</span>")
M.gib()
//a shrink ray that shrinks stuff, which grows back after a short while.
/obj/item/projectile/beam/shrink
name = "shrink ray"
icon_state = "blue_laser"
hitsound = 'sound/weapons/shrink_hit.ogg'
damage = 0
damage_type = STAMINA
flag = "energy"
impact_effect_type = /obj/effect/temp_visual/impact_effect/shrink
light_color = LIGHT_COLOR_BLUE
var/shrink_time = 90
/obj/item/projectile/beam/shrink/on_hit(atom/target, blocked = FALSE)
. = ..()
if(isopenturf(target) || istype(target, /turf/closed/indestructible))//shrunk floors wouldnt do anything except look weird, i-walls shouldnt be bypassable
return
target.AddComponent(/datum/component/shrink, shrink_time)

View File

@@ -656,3 +656,67 @@
component_parts += new /obj/item/stack/sheet/glass(null)
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
RefreshParts()
/obj/machinery/chem_dispenser/abductor
name = "reagent synthesizer"
desc = "Synthesizes a variety of reagents using proto-matter."
icon = 'icons/obj/abductor.dmi'
icon_state = "chem_dispenser"
has_panel_overlay = FALSE
circuit = /obj/item/circuitboard/machine/chem_dispenser/abductor
working_state = null
nopower_state = null
dispensable_reagents = list(
"hydrogen",
"lithium",
"carbon",
"nitrogen",
"oxygen",
"fluorine",
"sodium",
"aluminium",
"silicon",
"phosphorus",
"sulfur",
"chlorine",
"potassium",
"iron",
"copper",
"mercury",
"radium",
"water",
"ethanol",
"sugar",
"sacid",
"welding_fuel",
"silver",
"iodine",
"bromine",
"stable_plasma",
"oil",
"ammonia",
"ash",
"acetone",
"phenol",
"diethylamine",
"mine_salve",
"toxin",
"space_drugs",
"plasma",
"frostoil",
"uranium",
"histamine",
"morphine"
)
/obj/machinery/chem_dispenser/abductor/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/chem_dispenser(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
component_parts += new /obj/item/stack/sheet/glass(null)
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
RefreshParts()

View File

@@ -1056,7 +1056,7 @@
/obj/item/crowbar/abductor, /obj/item/multitool/abductor,
/obj/item/stock_parts/cell/infinite/abductor, /obj/item/weldingtool/abductor,
/obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor,
/obj/item/abductor_baton, /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor)
/obj/item/abductor, /obj/item/stack/sheet/mineral/abductor)
/datum/techweb_node/alien_bio
id = "alien_bio"

View File

@@ -125,6 +125,32 @@
taste_sensitivity = 101 // ayys cannot taste anything.
maxHealth = 120 //Ayys probe a lot
modifies_speech = TRUE
var/mothership
/obj/item/organ/tongue/abductor/attack_self(mob/living/carbon/human/H)
if(!istype(H))
return
var/obj/item/organ/tongue/abductor/T = H.getorganslot(ORGAN_SLOT_TONGUE)
if(!istype(T))
return
if(T.mothership == mothership)
to_chat(H, "<span class='notice'>[src] is already attuned to the same channel as your own.</span>")
return
H.visible_message("<span class='notice'>[H] holds [src] in their hands, and concentrates for a moment.</span>", "<span class='notice'>You attempt to modify the attunation of [src].</span>")
if(do_after(H, delay=15, target=src))
to_chat(H, "<span class='notice'>You attune [src] to your own channel.</span>")
mothership = T.mothership
/obj/item/organ/tongue/abductor/examine(mob/M)
. = ..()
if(HAS_TRAIT(M, TRAIT_ABDUCTOR_TRAINING) || HAS_TRAIT(M.mind, TRAIT_ABDUCTOR_TRAINING) || isobserver(M))
if(!mothership)
. += "<span class='notice'>It is not attuned to a specific mothership.</span>"
else
. += "<span class='notice'>It is attuned to [mothership].</span>"
/obj/item/organ/tongue/abductor/handle_speech(datum/source, list/speech_args)
//Hacks

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 KiB

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 KiB

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

View File

@@ -384,6 +384,7 @@
#include "code\datums\components\riding.dm"
#include "code\datums\components\rotation.dm"
#include "code\datums\components\shrapnel.dm"
#include "code\datums\components\shrink.dm"
#include "code\datums\components\slippery.dm"
#include "code\datums\components\spooky.dm"
#include "code\datums\components\squeak.dm"
@@ -1211,6 +1212,21 @@
#include "code\modules\antagonists\abductor\equipment\abduction_outfits.dm"
#include "code\modules\antagonists\abductor\equipment\abduction_surgery.dm"
#include "code\modules\antagonists\abductor\equipment\gland.dm"
#include "code\modules\antagonists\abductor\equipment\glands\access.dm"
#include "code\modules\antagonists\abductor\equipment\glands\blood.dm"
#include "code\modules\antagonists\abductor\equipment\glands\chem.dm"
#include "code\modules\antagonists\abductor\equipment\glands\egg.dm"
#include "code\modules\antagonists\abductor\equipment\glands\electric.dm"
#include "code\modules\antagonists\abductor\equipment\glands\heal.dm"
#include "code\modules\antagonists\abductor\equipment\glands\mindshock.dm"
#include "code\modules\antagonists\abductor\equipment\glands\plasma.dm"
#include "code\modules\antagonists\abductor\equipment\glands\quantum.dm"
#include "code\modules\antagonists\abductor\equipment\glands\slime.dm"
#include "code\modules\antagonists\abductor\equipment\glands\spider.dm"
#include "code\modules\antagonists\abductor\equipment\glands\transform.dm"
#include "code\modules\antagonists\abductor\equipment\glands\trauma.dm"
#include "code\modules\antagonists\abductor\equipment\glands\ventcrawl.dm"
#include "code\modules\antagonists\abductor\equipment\glands\viral.dm"
#include "code\modules\antagonists\abductor\machinery\camera.dm"
#include "code\modules\antagonists\abductor\machinery\console.dm"
#include "code\modules\antagonists\abductor\machinery\dispenser.dm"