diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index 2decc918f2..dcdf5aa268 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -17,8 +17,9 @@ #define DIAG_TRACK_HUD "13"// Mech tracking beacon #define DIAG_AIRLOCK_HUD "14"//Airlock shock overlay #define DIAG_PATH_HUD "15"//Bot path indicators +#define GLAND_HUD "16"//Gland indicators for abductors //for antag huds. these are used at the /mob level -#define ANTAG_HUD "16" +#define ANTAG_HUD "17" //by default everything in the hud_list of an atom is an image //a value in hud_list with one of these will change that behavior @@ -32,21 +33,22 @@ #define DATA_HUD_MEDICAL_ADVANCED 4 #define DATA_HUD_DIAGNOSTIC_BASIC 5 #define DATA_HUD_DIAGNOSTIC_ADVANCED 6 +#define DATA_HUD_ABDUCTOR 7 //antag HUD defines -#define ANTAG_HUD_CULT 7 -#define ANTAG_HUD_REV 8 -#define ANTAG_HUD_OPS 9 -#define ANTAG_HUD_WIZ 10 -#define ANTAG_HUD_SHADOW 11 -#define ANTAG_HUD_TRAITOR 12 -#define ANTAG_HUD_NINJA 13 -#define ANTAG_HUD_CHANGELING 14 -#define ANTAG_HUD_ABDUCTOR 15 -#define ANTAG_HUD_DEVIL 16 -#define ANTAG_HUD_SINTOUCHED 17 -#define ANTAG_HUD_SOULLESS 18 -#define ANTAG_HUD_CLOCKWORK 19 -#define ANTAG_HUD_BROTHER 20 +#define ANTAG_HUD_CULT 8 +#define ANTAG_HUD_REV 9 +#define ANTAG_HUD_OPS 10 +#define ANTAG_HUD_WIZ 11 +#define ANTAG_HUD_SHADOW 12 +#define ANTAG_HUD_TRAITOR 13 +#define ANTAG_HUD_NINJA 14 +#define ANTAG_HUD_CHANGELING 15 +#define ANTAG_HUD_ABDUCTOR 16 +#define ANTAG_HUD_DEVIL 17 +#define ANTAG_HUD_SINTOUCHED 18 +#define ANTAG_HUD_SOULLESS 19 +#define ANTAG_HUD_CLOCKWORK 20 +#define ANTAG_HUD_BROTHER 21 // Notification action types #define NOTIFY_JUMP "jump" diff --git a/code/datums/hud.dm b/code/datums/hud.dm index 837e7a6a95..fc6c09be14 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -10,6 +10,7 @@ GLOBAL_LIST_INIT(huds, list( DATA_HUD_MEDICAL_ADVANCED = new/datum/atom_hud/data/human/medical/advanced(), DATA_HUD_DIAGNOSTIC_BASIC = new/datum/atom_hud/data/diagnostic/basic(), DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(), + DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(), ANTAG_HUD_CULT = new/datum/atom_hud/antag(), ANTAG_HUD_REV = new/datum/atom_hud/antag(), ANTAG_HUD_OPS = new/datum/atom_hud/antag(), diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 1afd2953a0..74ac93c023 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -60,6 +60,9 @@ /datum/atom_hud/data/bot_path hud_icons = list(DIAG_PATH_HUD) +/datum/atom_hud/abductor + hud_icons = list(GLAND_HUD) + /* MED/SEC/DIAG HUD HOOKS */ /* diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm index 9128847e16..3e7e5f01ef 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm @@ -2,6 +2,8 @@ #define VEST_COMBAT 2 #define GIZMO_SCAN 1 #define GIZMO_MARK 2 +#define MIND_DEVICE_MESSAGE 1 +#define MIND_DEVICE_CONTROL 2 //AGENT VEST /obj/item/clothing/suit/armor/abductor/vest @@ -278,6 +280,84 @@ if(!istype(I, /obj/item/device/radio/headset)) r.broadcasting = 0 //goddamned headset hacks +/obj/item/device/abductor/mind_device + name = "mental interface device" + desc = "A dual-mode tool for directly communicating with sentient brains. It can be used to send a direct message to a target, \ + 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/device/abductor/mind_device/attack_self(mob/user) + if(!ScientistCheck(user)) + return + + if(mode == MIND_DEVICE_MESSAGE) + mode = MIND_DEVICE_CONTROL + icon_state = "mind_device_control" + else + mode = MIND_DEVICE_MESSAGE + icon_state = "mind_device_message" + to_chat(user, "You switch the device to [mode==MIND_DEVICE_MESSAGE? "TRANSMISSION": "COMMAND"] MODE") + +/obj/item/device/abductor/mind_device/afterattack(atom/target, mob/living/user, flag, params) + if(!ScientistCheck(user)) + return + + switch(mode) + if(MIND_DEVICE_CONTROL) + mind_control(target, user) + if(MIND_DEVICE_MESSAGE) + mind_message(target, user) + +/obj/item/device/abductor/mind_device/proc/mind_control(atom/target, mob/living/user) + if(iscarbon(target)) + var/mob/living/carbon/C = target + var/obj/item/organ/heart/gland/G = C.getorganslot("heart") + if(!istype(G)) + to_chat(user, "Your target does not have an experimental gland!") + return + if(!G.mind_control_uses) + to_chat(user, "Your target's gland is spent!") + return + if(G.active_mind_control) + to_chat(user, "Your target is already under a mind-controlling influence!") + return + + var/command = stripped_input(user, "Enter the command for your target to follow.\ + Uses Left: [G.mind_control_uses], Duration: [G.mind_control_duration / 10] seconds","Enter command") + + if(!command) + return + + if(QDELETED(user) || user.get_active_held_item() != src || loc != user) + return + + if(QDELETED(G)) + return + + G.mind_control(command, user) + to_chat(user, "You send the command to your target.") + +/obj/item/device/abductor/mind_device/proc/mind_message(atom/target, mob/living/user) + if(isliving(target)) + var/mob/living/L = target + if(L.stat == DEAD) + to_chat(user, "Your target is dead!") + return + var/message = stripped_input(user, "Write a message to send to your target's brain.","Enter message") + if(!message) + return + if(QDELETED(L) || L.stat == DEAD) + return + + to_chat(L, "You hear a voice in your head saying: [message]") + to_chat(user, "You send the message to your target.") + log_talk(user,"[key_name(user)] sent an abductor mind message to [L]/[L.ckey]: '[message]'", LOGSAY) + + /obj/item/device/firing_pin/abductor name = "alien firing pin" icon_state = "firing_pin_ayy" diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm index 22edb79c80..508f4e9f13 100644 --- a/code/game/gamemodes/miniantags/abduction/gland.dm +++ b/code/game/gamemodes/miniantags/abduction/gland.dm @@ -12,28 +12,68 @@ var/human_only = 0 var/active = 0 + var/mind_control_uses = 1 + var/mind_control_duration = 1800 + var/active_mind_control = FALSE + /obj/item/organ/heart/gland/proc/ownerCheck() if(ishuman(owner)) - return 1 + return TRUE if(!human_only && iscarbon(owner)) - return 1 - return 0 + return TRUE + return FALSE /obj/item/organ/heart/gland/proc/Start() active = 1 next_activation = world.time + rand(cooldown_low,cooldown_high) +/obj/item/organ/heart/gland/proc/update_gland_hud() + if(!owner) + return + var/image/holder = owner.hud_list[GLAND_HUD] + var/icon/I = icon(owner.icon, owner.icon_state, owner.dir) + holder.pixel_y = I.Height() - world.icon_size + if(active_mind_control) + holder.icon_state = "hudgland_active" + else if(mind_control_uses) + holder.icon_state = "hudgland_ready" + else + holder.icon_state = "hudgland_spent" -/obj/item/organ/heart/gland/Remove(var/mob/living/carbon/M, special = 0) +/obj/item/organ/heart/gland/proc/mind_control(command, mob/living/user) + if(!ownerCheck() || !mind_control_uses || active_mind_control) + return + mind_control_uses-- + to_chat(owner, "You suddenly feel an irresistible compulsion to follow an order...") + to_chat(owner, "[command]") + active_mind_control = TRUE + log_admin("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]") + update_gland_hud() + + addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration) + +/obj/item/organ/heart/gland/proc/clear_mind_control() + if(!ownerCheck() || !active_mind_control) + return + to_chat(owner, "You feel the compulsion fade, and you completely forget about your previous orders.") + active_mind_control = FALSE + +/obj/item/organ/heart/gland/Remove(mob/living/carbon/M, special = 0) active = 0 if(initial(uses) == 1) uses = initial(uses) + var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR] + hud.remove_from_hud(owner) + clear_mind_control() ..() -/obj/item/organ/heart/gland/Insert(var/mob/living/carbon/M, special = 0) +/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0) ..() if(special != 2 && uses) // Special 2 means abductor surgery Start() + var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR] + hud.add_to_hud(owner) + update_gland_hud() /obj/item/organ/heart/gland/on_life() if(!beating) @@ -59,6 +99,8 @@ 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.") @@ -71,6 +113,8 @@ cooldown_high = 1200 uses = -1 icon_state = "slime" + mind_control_uses = 1 + mind_control_duration = 2400 /obj/item/organ/heart/gland/slime/activate() to_chat(owner, "You feel nauseous!") @@ -86,6 +130,8 @@ cooldown_high = 300 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.") @@ -103,6 +149,8 @@ uses = -1 human_only = 1 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.") @@ -114,6 +162,8 @@ 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.") @@ -125,6 +175,8 @@ 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.") @@ -141,6 +193,8 @@ cooldown_high = 1600 uses = 10 icon_state = "emp" + mind_control_uses = 1 + mind_control_duration = 1800 /obj/item/organ/heart/gland/emp/activate() to_chat(owner, "You feel a spike of pain in your head.") @@ -151,6 +205,8 @@ cooldown_high = 900 uses = 10 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.") @@ -164,6 +220,8 @@ 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() to_chat(owner, "You lay an egg!") @@ -175,6 +233,8 @@ cooldown_low = 200 cooldown_high = 400 uses = -1 + mind_control_uses = 1 + mind_control_duration = 450 /obj/item/organ/heart/gland/bloody/activate() owner.blood_volume -= 20 @@ -192,6 +252,8 @@ cooldown_high = 600 human_only = 1 uses = 1 + mind_control_uses = 1 + mind_control_duration = 600 /obj/item/organ/heart/gland/bodysnatch/activate() to_chat(owner, "You feel something moving around inside you...") @@ -233,6 +295,8 @@ 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.") diff --git a/code/game/gamemodes/miniantags/abduction/machinery/console.dm b/code/game/gamemodes/miniantags/abduction/machinery/console.dm index f243f161c3..0b13c359eb 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/console.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/console.dm @@ -48,6 +48,7 @@ dat += "Agent Vest
" dat += "Radio Silencer
" dat += "Science Tool
" + dat += "Mental Interface Device
" else dat += "NO EXPERIMENT MACHINE DETECTED
" @@ -109,6 +110,8 @@ Dispense(/obj/item/device/abductor/gizmo) if("vest") Dispense(/obj/item/clothing/suit/armor/abductor/vest) + if("mind_device") + Dispense(/obj/item/device/abductor/mind_device,cost=2) updateUsrDialog() /obj/machinery/abductor/console/proc/TeleporterRetrieve() diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index 824c86c69d..3403253c07 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -390,6 +390,7 @@ h1.alert, h2.alert {color: #000000;} .memo {color: #638500; text-align: center;} .memoedit {text-align: center; font-size: 16px;} .abductor {color: #800080; font-style: italic;} +.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;} .slime {color: #00CED1;} .drone {color: #848482;} .monkey {color: #975032;} diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 4e409391da..d601fde492 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -2,6 +2,7 @@ gender = MALE pressure_resistance = 15 possible_a_intents = list(INTENT_HELP, INTENT_HARM) + hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,GLAND_HUD) var/list/stomach_contents = list() var/list/internal_organs = list() //List of /obj/item/organ in the mob. They don't go in the contents for some reason I don't want to know. var/list/internal_organs_slot= list() //Same as above, but stores "slot ID" - "organ" pairs for easy access. diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 8e72b26419..716373061d 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -1,5 +1,5 @@ /mob/living/carbon/human - hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD) + hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD,GLAND_HUD) possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM) pressure_resistance = 25 //Hair colour and style diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index cf03d12130..cd273ec98e 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -9,3 +9,13 @@ /datum/species/abductor/copy_properties_from(datum/species/abductor/old_species) scientist = old_species.scientist + +/datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species) + . = ..() + var/datum/atom_hud/abductor_hud = GLOB.huds[DATA_HUD_ABDUCTOR] + abductor_hud.add_hud_to(C) + +/datum/species/abductor/on_species_loss(mob/living/carbon/C) + . = ..() + var/datum/atom_hud/abductor_hud = GLOB.huds[DATA_HUD_ABDUCTOR] + abductor_hud.remove_hud_from(C) diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index 70988dbef5..5e33807ec7 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/obj/abductor.dmi b/icons/obj/abductor.dmi index 38edd8dc7d..5602b03f87 100644 Binary files a/icons/obj/abductor.dmi and b/icons/obj/abductor.dmi differ diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index dd23e1807a..e1505d6088 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -160,6 +160,7 @@ h1.alert, h2.alert {color: #000000;} .memo {color: #638500; text-align: center;} .memoedit {text-align: center; font-size: 2;} .abductor {color: #800080; font-style: italic;} +.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;} .slime {color: #00CED1;} .drone {color: #848482;} .monkey {color: #975032;}