diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 1709714904..46226a35a6 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -102,6 +102,8 @@
#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))
diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm
index 12a3c331ec..28e5c53376 100644
--- a/code/__DEFINES/movespeed_modification.dm
+++ b/code/__DEFINES/movespeed_modification.dm
@@ -34,5 +34,6 @@
#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"
\ No newline at end of file
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index cc183dd6d3..dab887412a 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -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, "[command]")
+
/obj/screen/alert/drunk //Not implemented
name = "Drunk"
desc = "All that alcohol you've been drinking is impairing your speech, motor skills, and mental cognition. Make sure to act like it."
diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm
index ee1f5b8c3d..cb9599cb9a 100644
--- a/code/controllers/subsystem/traumas.dm
+++ b/code/controllers/subsystem/traumas.dm
@@ -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,
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index bdb949a570..4540e48ebc 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -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,
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 7d02d9d383..9b2683b040 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -342,6 +342,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
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 639d570462..d04b0c2040 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -656,6 +656,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
diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm
index e8d30e8dbe..92504641a9 100644
--- a/code/modules/antagonists/abductor/abductor.dm
+++ b/code/modules/antagonists/abductor/abductor.dm
@@ -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)
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index ed26b894d9..1cbd09858b 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -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)
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, "Combat injection is still recharging.")
return
var/mob/living/carbon/human/M = loc
- M.do_adrenaline(150, FALSE, 0, 0, TRUE, list("inaprovaline" = 3, "synaptizine" = 10, "omnizine" = 10), "You feel a sudden surge of energy!")
+ 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, "This specimen is already marked!")
return
- if(ishuman(target))
- if(isabductor(target))
- marked = target
- to_chat(user, "You mark [target] for future retrieval.")
- else
- prepare(target,user)
+ if(isabductor(target) || iscow(target))
+ marked = target
+ to_chat(user, "You mark [target] for future retrieval.")
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)
@@ -345,8 +339,8 @@
if(QDELETED(G))
return
- if(istype(C.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "Your target seems to have some sort of protective headgear on, blocking the message from being sent!")
+ if(C.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "Your target seems to have some sort of tinfoil protection on, blocking the message from being sent!")
return
G.mind_control(command, user)
@@ -364,7 +358,7 @@
if(QDELETED(L) || L.stat == DEAD)
return
- to_chat(L, "You hear a voice in your head saying: [message]")
+ to_chat(L, "You hear a voice in your head saying: [message]")
to_chat(user, "You send the message to your target.")
log_directed_talk(user, L, message, LOG_SAY, "abductor whisper")
@@ -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"
@@ -423,21 +428,18 @@ Congratulations! You are now trained for invasive xenobiology research!"}
#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)
@@ -453,7 +455,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
to_chat(usr, "You switch the baton to [txt] mode.")
update_icon()
-/obj/item/abductor_baton/update_icon()
+/obj/item/abductor/baton/update_icon()
switch(mode)
if(BATON_STUN)
icon_state = "wonderprodStun"
@@ -468,8 +470,8 @@ Congratulations! You are now trained for invasive xenobiology research!"}
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))
@@ -486,8 +488,8 @@ Congratulations! You are now trained for invasive xenobiology research!"}
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)
@@ -499,10 +501,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
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
@@ -514,7 +516,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
L.visible_message("[user] has stunned [L] with [src]!", \
"[user] has stunned you with [src]!")
- 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
@@ -522,37 +524,37 @@ Congratulations! You are now trained for invasive xenobiology research!"}
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(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "The specimen's protective headgear is interfering with the sleep inducement!")
- L.visible_message("[user] tried to induced sleep in [L] with [src], but [L.p_their()] headgear protected [L.p_them()]!", \
- "You feel a strange wave of heavy drowsiness wash over you, but your headgear deflects most of it!")
+ if(L.anti_magic_check(FALSE, FALSE, TRUE))
+ to_chat(user, "The specimen's tinfoil protection is interfering with the sleep inducement!")
+ L.visible_message("[user] tried to induced sleep in [L] with [src], but [L.p_their()] tinfoil protection [L.p_them()]!", \
+ "You feel a strange wave of heavy drowsiness wash over you, but your tinfoil protection deflects most of it!")
L.drowsyness += 2
return
L.visible_message("[user] has induced sleep in [L] with [src]!", \
"You suddenly feel very drowsy!")
- 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
- if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "The specimen's protective headgear is completely blocking our sleep inducement methods!")
- L.visible_message("[user] tried to induce sleep in [L] with [src], but [L.p_their()] headgear completely protected [L.p_them()]!", \
- "Any sense of drowsiness is quickly diminished as your headgear deflects the effects!")
+ if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "The specimen's tinfoil protection is completely blocking our sleep inducement methods!")
+ L.visible_message("[user] tried to induce sleep in [L] with [src], but [L.p_their()] tinfoil protection completely protected [L.p_them()]!", \
+ "Any sense of drowsiness is quickly diminished as your tinfoil protection deflects the effects!")
return
L.drowsyness += 1
to_chat(user, "Sleep inducement works fully only on stunned specimens! ")
L.visible_message("[user] tried to induce sleep in [L] with [src]!", \
"You suddenly feel drowsy!")
-/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("[user] begins restraining [C] with [src]!", \
"[user] begins shaping an energy field around your hands!")
if(do_mob(user, C, 30) && (C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore()))
@@ -566,7 +568,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
else
to_chat(user, "[C] doesn't have two hands...")
-/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("[user] probes [L] with [src]!", \
"[user] probes you!")
@@ -611,17 +613,17 @@ Congratulations! You are now trained for invasive xenobiology research!"}
S.start()
. = ..()
-/obj/item/abductor_baton/examine(mob/user)
- ..()
+/obj/item/abductor/baton/examine(mob/user)
+ . = ..()
switch(mode)
if(BATON_STUN)
- to_chat(user, "The baton is in stun mode.")
+ . += "The baton is in stun mode."
if(BATON_SLEEP)
- to_chat(user, "The baton is in sleep inducement mode.")
+ . += "The baton is in sleep inducement mode."
if(BATON_CUFF)
- to_chat(user, "The baton is in restraining mode.")
+ . += "The baton is in restraining mode."
if(BATON_PROBE)
- to_chat(user, "The baton is in probing mode.")
+ . += "The baton is in probing mode."
/obj/item/radio/headset/abductor
name = "alien headset"
@@ -640,10 +642,44 @@ Congratulations! You are now trained for invasive xenobiology research!"}
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("[user] places down [src] and activates it.", "You place down [src] and activate it.")
+ 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("[new_machine] warps on top of the beacon!")
+ 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"
@@ -707,11 +743,11 @@ Congratulations! You are now trained for invasive xenobiology research!"}
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, "You start disassembling [src]...")
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)
@@ -761,9 +797,8 @@ Congratulations! You are now trained for invasive xenobiology research!"}
icon = 'icons/obj/abductor.dmi'
icon_state = "bed"
can_buckle = 1
- buckle_lying = 1
- var/static/list/injected_reagents = list("corazone")
+ var/static/list/injected_reagents = list(/datum/reagent/medicine/corazone)
/obj/structure/table/optable/abductor/Crossed(atom/movable/AM)
. = ..()
@@ -799,3 +834,11 @@ Congratulations! You are now trained for invasive xenobiology research!"}
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
diff --git a/code/modules/antagonists/abductor/equipment/abduction_outfits.dm b/code/modules/antagonists/abductor/equipment/abduction_outfits.dm
index 7e03bbf57a..0ce41beca7 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_outfits.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_outfits.dm
@@ -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(
diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm
index a35cbbf0e4..11134d5e8d 100644
--- a/code/modules/antagonists/abductor/equipment/gland.dm
+++ b/code/modules/antagonists/abductor/equipment/gland.dm
@@ -10,13 +10,17 @@
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 +59,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, "You feel the compulsion fade, and you completely forget about your previous orders.")
+ to_chat(owner, "You feel the compulsion fade, and you completely forget about your previous orders.")
+ 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 +106,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, "You feel curiously revitalized.")
- 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)
- ..()
- owner.faction |= "slime"
- owner.grant_language(/datum/language/slime)
-
-/obj/item/organ/heart/gland/slime/activate()
- to_chat(owner, "You feel nauseated!")
- 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, "You get a headache.")
-
- 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, "You hear a loud buzz in your head, silencing your thoughts!")
- H.Stun(50)
- if(2)
- to_chat(H, "You hear an annoying buzz in your head.")
- 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, "You feel unlike yourself.")
- 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, "You feel very stretchy.")
- 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, "You feel sick.")
- 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, "You feel a spike of pain in your head.")
- 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, "You feel something crawling in your skin.")
- 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("[owner] [pick(EGG_LAYING_MESSAGES)]")
- 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)
- ..()
- 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("[owner]'s skin starts emitting electric arcs!",\
- "You feel electric energy building up inside you!")
- 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, "You feel bloated.")
- addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "A massive stomachache overcomes you."), 150)
- addtimer(CALLBACK(src, .proc/vomit_plasma), 200)
-
-/obj/item/organ/heart/gland/plasma/proc/vomit_plasma()
- if(!owner)
- return
- owner.visible_message("[owner] vomits a cloud of plasma!")
- var/turf/open/T = get_turf(owner)
- if(istype(T))
- T.atmos_spawn_air("plasma=50;TEMP=[T20C]")
- owner.vomit()
+ return
\ No newline at end of file
diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm
index 9a9b1a6ba0..47294bc766 100644
--- a/code/modules/antagonists/abductor/machinery/console.dm
+++ b/code/modules/antagonists/abductor/machinery/console.dm
@@ -43,12 +43,15 @@
dat += "Collected Samples : [points]
"
dat += "Gear Credits: [credits]
"
dat += "Transfer data in exchange for supplies:
"
- dat += "Advanced Baton
"
- dat += "Agent Helmet
"
- dat += "Agent Vest
"
- dat += "Radio Silencer
"
- dat += "Science Tool
"
- dat += "Mental Interface Device
"
+ dat += "Advanced Baton (2 Credits)
"
+ dat += "Mental Interface Device (2 Credits)
"
+ dat += "Reagent Synthesizer (2 Credits)
"
+ dat += "Shrink Ray Blaster (2 Credits)
"
+ dat += "Agent Helmet (1 Credit)
"
+ dat += "Agent Vest (1 Credit)
"
+ dat += "Radio Silencer (1 Credit)
"
+ dat += "Science Tool (1 Credit)
"
+ dat += "Superlingual Matrix (1 Credit)
"
else
dat += "NO EXPERIMENT MACHINE DETECTED
"
@@ -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)))
@@ -178,8 +187,8 @@
c.console = src
/obj/machinery/abductor/console/proc/AddSnapshot(mob/living/carbon/human/target)
- if(istype(target.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- say("Subject wearing specialized protective headgear, unable to get a proper scan!")
+ if(target.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ say("Subject wearing specialized protective tinfoil gear, unable to get a proper scan!")
return
var/datum/icon_snapshot/entry = new
entry.name = target.name
@@ -236,4 +245,4 @@
new item(drop_location)
else
- say("Insufficent data!")
+ say("Insufficent data!")
\ No newline at end of file
diff --git a/code/modules/projectiles/ammunition/energy/special.dm b/code/modules/projectiles/ammunition/energy/special.dm
index 7b4e0bfa97..2f87872710 100644
--- a/code/modules/projectiles/ammunition/energy/special.dm
+++ b/code/modules/projectiles/ammunition/energy/special.dm
@@ -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
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index e43eb5a3bc..ea9c96ee0c 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -190,3 +190,21 @@
var/mob/living/carbon/M = target
M.visible_message("[M] explodes into a shower of gibs!")
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)
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 9a228b28e3..837d107959 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -655,3 +655,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()
\ No newline at end of file
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 5b3a21dd5c..f3bff00508 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -1017,7 +1017,7 @@
prereq_ids = list("biotech","engineering")
boost_item_paths = list(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, /obj/item/retractor/alien, /obj/item/circular_saw/alien,
/obj/item/cautery/alien, /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /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/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/gun/energy/shrink_ray)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
export_price = 20000
hidden = TRUE
@@ -1031,7 +1031,7 @@
design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery")
boost_item_paths = list(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, /obj/item/retractor/alien, /obj/item/circular_saw/alien,
/obj/item/cautery/alien, /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /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/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor, /obj/item/gun/energy/shrink_ray)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 20000
hidden = TRUE
@@ -1043,7 +1043,7 @@
prereq_ids = list("alientech", "adv_engi")
design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool")
boost_item_paths = list(/obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /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/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor, /obj/item/gun/energy/shrink_ray)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 20000
hidden = TRUE
diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm
index cee20dddee..7fb9c6e4bf 100644
--- a/code/modules/surgery/organs/tongue.dm
+++ b/code/modules/surgery/organs/tongue.dm
@@ -124,6 +124,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, "[src] is already attuned to the same channel as your own.")
+ return
+
+ H.visible_message("[H] holds [src] in their hands, and concentrates for a moment.", "You attempt to modify the attunation of [src].")
+ if(do_after(H, delay=15, target=src))
+ to_chat(H, "You attune [src] to your own channel.")
+ 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)
+ . += "It is not attuned to a specific mothership."
+ else
+ . += "It is attuned to [mothership]."
/obj/item/organ/tongue/abductor/handle_speech(datum/source, list/speech_args)
//Hacks
diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi
index 8978d17237..f6a0e82315 100644
Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi
index 3f8a876d43..2ce62a0ae6 100644
Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index 8142e03498..08a5abde3c 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index 072511b444..2b6f56186f 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/abductor.dmi b/icons/obj/abductor.dmi
index 5602b03f87..49d8858b5c 100644
Binary files a/icons/obj/abductor.dmi and b/icons/obj/abductor.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 50f9e0a207..9449ecbe0a 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/guns/energy.dmi b/icons/obj/guns/energy.dmi
index a6d5c8a5e1..6a9c254397 100644
Binary files a/icons/obj/guns/energy.dmi and b/icons/obj/guns/energy.dmi differ
diff --git a/modular_citadel/icons/mob/uniform_digi.dmi b/modular_citadel/icons/mob/uniform_digi.dmi
index 513ebce439..5318ffa586 100644
Binary files a/modular_citadel/icons/mob/uniform_digi.dmi and b/modular_citadel/icons/mob/uniform_digi.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 702f34f80c..d4b3e9a3b8 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -375,6 +375,7 @@
#include "code\datums\components\remote_materials.dm"
#include "code\datums\components\riding.dm"
#include "code\datums\components\rotation.dm"
+#include "code\datums\components\shrink.dm"
#include "code\datums\components\signal_redirect.dm"
#include "code\datums\components\slippery.dm"
#include "code\datums\components\spooky.dm"
@@ -1176,6 +1177,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"