mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
tgui: Abductors (#51920)
* Gland Dispenser * ProbingConsole and Abductor theme * State tweaks, Abductor Console DM side, Abductor Uplink, Abductor orderable gear datum * Line endings * Finished UIs
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
GLOBAL_LIST_INIT(abductor_gear, subtypesof(/datum/abductor_gear))
|
||||
|
||||
/datum/abductor_gear
|
||||
/// Name of the gear
|
||||
var/name = "Generic Abductor Gear"
|
||||
/// Description of the gear
|
||||
var/description = "Generic description."
|
||||
/// Unique ID of the gear
|
||||
var/id = "abductor_generic"
|
||||
/// Credit cost of the gear
|
||||
var/cost = 1
|
||||
/// Build path of the gear itself
|
||||
var/build_path = null
|
||||
/// Category of the gear
|
||||
var/category = "Basic Gear"
|
||||
|
||||
/datum/abductor_gear/agent_helmet
|
||||
name = "Agent Helmet"
|
||||
description = "Abduct with style - spiky style. Prevents digital tracking."
|
||||
id = "agent_helmet"
|
||||
build_path = /obj/item/clothing/head/helmet/abductor
|
||||
|
||||
/datum/abductor_gear/agent_vest
|
||||
name = "Agent Vest"
|
||||
description = "A vest outfitted with advanced stealth technology. It has two modes - combat and stealth."
|
||||
id = "agent_vest"
|
||||
build_path = /obj/item/clothing/suit/armor/abductor/vest
|
||||
|
||||
/datum/abductor_gear/radio_silencer
|
||||
name = "Radio Silencer"
|
||||
description = "A compact device used to shut down communications equipment."
|
||||
id = "radio_silencer"
|
||||
build_path = /obj/item/abductor/silencer
|
||||
|
||||
/datum/abductor_gear/science_tool
|
||||
name = "Science Tool"
|
||||
description = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras."
|
||||
id = "science_tool"
|
||||
build_path = /obj/item/abductor/gizmo
|
||||
|
||||
/datum/abductor_gear/advanced_baton
|
||||
name = "Advanced Baton"
|
||||
description = "A quad-mode baton used for incapacitation and restraining of specimens."
|
||||
id = "advanced_baton"
|
||||
cost = 2
|
||||
build_path = /obj/item/melee/baton/abductor
|
||||
|
||||
/datum/abductor_gear/superlingual_matrix
|
||||
name = "Superlingual Matrix"
|
||||
description = "A mysterious structure that allows for instant communication between users. Pretty impressive until you need to eat something."
|
||||
id = "superlingual_matrix"
|
||||
build_path = /obj/item/organ/tongue/abductor
|
||||
category = "Advanced Gear"
|
||||
|
||||
/datum/abductor_gear/mental_interface
|
||||
name = "Mental Interface Device"
|
||||
description = "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."
|
||||
id = "mental_interface"
|
||||
cost = 2
|
||||
build_path = /obj/item/abductor/mind_device
|
||||
category = "Advanced Gear"
|
||||
|
||||
/datum/abductor_gear/reagent_synthesizer
|
||||
name = "Reagent Synthesizer"
|
||||
description = "Synthesizes a variety of reagents using proto-matter."
|
||||
id = "reagent_synthesizer"
|
||||
cost = 2
|
||||
build_path = /obj/item/abductor_machine_beacon/chem_dispenser
|
||||
category = "Advanced Gear"
|
||||
|
||||
/datum/abductor_gear/shrink_ray
|
||||
name = "Shrink Ray Blaster"
|
||||
description = "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."
|
||||
id = "shrink_ray"
|
||||
cost = 2
|
||||
build_path = /obj/item/gun/energy/shrink_ray
|
||||
category = "Advanced Gear"
|
||||
@@ -17,12 +17,36 @@
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "console"
|
||||
density = TRUE
|
||||
ui_x = 600
|
||||
ui_y = 532
|
||||
var/obj/item/abductor/gizmo/gizmo
|
||||
var/obj/item/clothing/suit/armor/abductor/vest/vest
|
||||
var/obj/machinery/abductor/experiment/experiment
|
||||
var/obj/machinery/abductor/pad/pad
|
||||
var/obj/machinery/computer/camera_advanced/abductor/camera
|
||||
var/list/datum/icon_snapshot/disguises = list()
|
||||
/// Currently selected gear category
|
||||
var/selected_cat
|
||||
/// Dictates if the compact mode of the interface is on or off
|
||||
var/compact_mode = FALSE
|
||||
/// Possible gear to be dispensed
|
||||
var/list/possible_gear
|
||||
|
||||
/obj/machinery/abductor/console/Initialize(mapload)
|
||||
. = ..()
|
||||
possible_gear = get_abductor_gear()
|
||||
|
||||
/**
|
||||
* get_abductor_gear: Returns a list of a filtered abductor gear sorted by categories
|
||||
*/
|
||||
/obj/machinery/abductor/console/proc/get_abductor_gear()
|
||||
var/list/filtered_modules = list()
|
||||
for(var/path in GLOB.abductor_gear)
|
||||
var/datum/abductor_gear/AG = new path
|
||||
if(!filtered_modules[AG.category])
|
||||
filtered_modules[AG.category] = list()
|
||||
filtered_modules[AG.category][AG] = AG
|
||||
return filtered_modules
|
||||
|
||||
/obj/machinery/abductor/console/attack_hand(mob/user)
|
||||
. = ..()
|
||||
@@ -32,96 +56,91 @@
|
||||
to_chat(user, "<span class='warning'>You start mashing alien buttons at random!</span>")
|
||||
if(do_after(user,100, target = src))
|
||||
TeleporterSend()
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat = ""
|
||||
dat += "<H3> Abductsoft 3000 </H3>"
|
||||
|
||||
/obj/machinery/abductor/console/ui_status(mob/user)
|
||||
if(!isabductor(user) && !isobserver(user))
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/abductor/console/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AbductorConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/abductor/console/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["categories"] = list()
|
||||
for(var/category in possible_gear)
|
||||
var/list/cat = list(
|
||||
"name" = category,
|
||||
"items" = (category == selected_cat ? list() : null))
|
||||
for(var/gear in possible_gear[category])
|
||||
var/datum/abductor_gear/AG = possible_gear[category][gear]
|
||||
cat["items"] += list(list(
|
||||
"name" = AG.name,
|
||||
"cost" = AG.cost,
|
||||
"desc" = AG.description,
|
||||
))
|
||||
data["categories"] += list(cat)
|
||||
return data
|
||||
|
||||
/obj/machinery/abductor/console/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["compactMode"] = compact_mode
|
||||
data["experiment"] = experiment ? TRUE : FALSE
|
||||
if(experiment)
|
||||
var/points = experiment.points
|
||||
var/credits = experiment.credits
|
||||
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 (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</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=tongue'>Superlingual Matrix</a><br>"
|
||||
else
|
||||
dat += "<span class='bad'>NO EXPERIMENT MACHINE DETECTED</span> <br>"
|
||||
|
||||
data["points"] = experiment.points
|
||||
data["credits"] = experiment.credits
|
||||
data["pad"] = pad ? TRUE : FALSE
|
||||
if(pad)
|
||||
dat += "<span class='bad'>Emergency Teleporter System.</span>"
|
||||
dat += "<span class='bad'>Consider using primary observation console first.</span>"
|
||||
dat += "<a href='?src=[REF(src)];teleporter_send=1'>Activate Teleporter</A><br>"
|
||||
if(gizmo && gizmo.marked)
|
||||
dat += "<a href='?src=[REF(src)];teleporter_retrieve=1'>Retrieve Mark</A><br>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Retrieve Mark</span><br>"
|
||||
else
|
||||
dat += "<span class='bad'>NO TELEPAD DETECTED</span></br>"
|
||||
|
||||
data["gizmo"] = gizmo && gizmo.marked ? TRUE : FALSE
|
||||
data["vest"] = vest ? TRUE : FALSE
|
||||
if(vest)
|
||||
dat += "<h4> Agent Vest Mode </h4><br>"
|
||||
var/mode = vest.mode
|
||||
if(mode == VEST_STEALTH)
|
||||
dat += "<a href='?src=[REF(src)];flip_vest=1'>Combat</A>"
|
||||
dat += "<span class='linkOff'>Stealth</span>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Combat</span>"
|
||||
dat += "<a href='?src=[REF(src)];flip_vest=1'>Stealth</A>"
|
||||
data["vest_mode"] = vest.mode
|
||||
data["vest_lock"] = HAS_TRAIT_FROM(vest, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT)
|
||||
return data
|
||||
|
||||
dat+="<br>"
|
||||
dat += "<a href='?src=[REF(src)];select_disguise=1'>Select Agent Vest Disguise</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];toggle_vest=1'>[HAS_TRAIT_FROM(vest, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT) ? "Unlock" : "Lock"] Vest</a><br>"
|
||||
else
|
||||
dat += "<span class='bad'>NO AGENT VEST DETECTED</span>"
|
||||
var/datum/browser/popup = new(user, "computer", "Abductor Console", 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/abductor/console/Topic(href, href_list)
|
||||
if(..())
|
||||
/obj/machinery/abductor/console/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
usr.set_machine(src)
|
||||
if(href_list["teleporter_send"])
|
||||
TeleporterSend()
|
||||
else if(href_list["teleporter_retrieve"])
|
||||
TeleporterRetrieve()
|
||||
else if(href_list["flip_vest"])
|
||||
FlipVest()
|
||||
else if(href_list["toggle_vest"])
|
||||
if(vest)
|
||||
switch(action)
|
||||
if("buy")
|
||||
var/item_name = params["name"]
|
||||
var/list/buyable_items = list()
|
||||
for(var/category in possible_gear)
|
||||
buyable_items += possible_gear[category]
|
||||
for(var/key in buyable_items)
|
||||
var/datum/abductor_gear/AG = buyable_items[key]
|
||||
if(AG.name == item_name)
|
||||
Dispense(AG.build_path, AG.cost)
|
||||
return TRUE
|
||||
if("teleporter_send")
|
||||
TeleporterSend()
|
||||
return TRUE
|
||||
if("teleporter_retrieve")
|
||||
TeleporterRetrieve()
|
||||
return TRUE
|
||||
if("flip_vest")
|
||||
FlipVest()
|
||||
return TRUE
|
||||
if("toggle_vest")
|
||||
if(!vest)
|
||||
return
|
||||
vest.toggle_nodrop()
|
||||
else if(href_list["select_disguise"])
|
||||
SelectDisguise()
|
||||
else if(href_list["dispense"])
|
||||
switch(href_list["dispense"])
|
||||
if("baton")
|
||||
Dispense(/obj/item/melee/baton/abductor,cost=2)
|
||||
if("helmet")
|
||||
Dispense(/obj/item/clothing/head/helmet/abductor)
|
||||
if("silencer")
|
||||
Dispense(/obj/item/abductor/silencer)
|
||||
if("tool")
|
||||
Dispense(/obj/item/abductor/gizmo)
|
||||
if("vest")
|
||||
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()
|
||||
return TRUE
|
||||
if("select_disguise")
|
||||
SelectDisguise()
|
||||
return TRUE
|
||||
if("select")
|
||||
selected_cat = params["category"]
|
||||
return TRUE
|
||||
if("compact_toggle")
|
||||
compact_mode = !compact_mode
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/abductor/console/proc/TeleporterRetrieve()
|
||||
if(pad && gizmo && gizmo.marked)
|
||||
@@ -162,7 +181,6 @@
|
||||
pad.teleport_target = location
|
||||
to_chat(user, "<span class='notice'>Location marked as test subject release point.</span>")
|
||||
|
||||
|
||||
/obj/machinery/abductor/console/Initialize(mapload)
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
@@ -232,8 +250,6 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
/obj/machinery/abductor/console/proc/Dispense(item,cost=1)
|
||||
if(experiment && experiment.credits >= cost)
|
||||
experiment.credits -=cost
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "dispenser"
|
||||
density = TRUE
|
||||
ui_x = 300
|
||||
ui_y = 338
|
||||
var/list/gland_types
|
||||
var/list/gland_colors
|
||||
var/list/amounts
|
||||
@@ -22,41 +24,42 @@
|
||||
gland_colors[i] = random_color()
|
||||
amounts[i] = rand(1,5)
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/attack_hand(mob/user)
|
||||
/obj/machinery/abductor/gland_dispenser/ui_status(mob/user)
|
||||
if(!isabductor(user) && !isobserver(user))
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "GlandDispenser", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["glands"] = list()
|
||||
for(var/gland_number=1,gland_number<=gland_colors.len,gland_number++)
|
||||
var/list/gland_information = list(
|
||||
"color" = gland_colors[gland_number],
|
||||
"amount" = amounts[gland_number],
|
||||
"id" = gland_number,
|
||||
)
|
||||
data["glands"] += list(gland_information)
|
||||
return data
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!isabductor(user))
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/box_css = {"
|
||||
<style>
|
||||
a.box.gland {
|
||||
float: left;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: 5px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: rgba(0,0,0,.2);
|
||||
text-align: center;
|
||||
}
|
||||
</style>"}
|
||||
var/dat = ""
|
||||
var/item_count = 0
|
||||
for(var/i=1,i<=gland_colors.len,i++)
|
||||
item_count++
|
||||
var/g_color = gland_colors[i]
|
||||
var/amount = amounts[i]
|
||||
dat += "<a class='box gland' style='background-color:[g_color]' href='?src=[REF(src)];dispense=[i]'>[amount]</a>"
|
||||
if(item_count == 4) // Four boxes per line
|
||||
dat +="</br></br>"
|
||||
item_count = 0
|
||||
var/datum/browser/popup = new(user, "glands", "Gland Dispenser", 200, 200)
|
||||
popup.add_head_content(box_css)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("dispense")
|
||||
var/gland_id = text2num(params["gland_id"])
|
||||
if(!gland_id)
|
||||
return
|
||||
Dispense(gland_id)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/organ/heart/gland))
|
||||
@@ -68,15 +71,6 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["dispense"])
|
||||
Dispense(text2num(href_list["dispense"]))
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/abductor/gland_dispenser/proc/Dispense(count)
|
||||
if(amounts[count]>0)
|
||||
amounts[count]--
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
icon_state = "experiment-open"
|
||||
density = FALSE
|
||||
state_open = TRUE
|
||||
ui_x = 330
|
||||
ui_y = 207
|
||||
var/points = 0
|
||||
var/credits = 0
|
||||
var/list/history
|
||||
var/list/abductee_minds
|
||||
var/flash = " - || - "
|
||||
/// Machine feedback message
|
||||
var/flash = "Awaiting subject."
|
||||
var/obj/machinery/abductor/console/console
|
||||
var/message_cooldown = 0
|
||||
var/breakout_time = 450
|
||||
@@ -22,13 +25,6 @@
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
/obj/machinery/abductor/experiment/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
experimentUI(user)
|
||||
|
||||
/obj/machinery/abductor/experiment/open_machine()
|
||||
if(!state_open && !panel_open)
|
||||
..()
|
||||
@@ -60,121 +56,81 @@
|
||||
"<span class='notice'>You successfully break out of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H)
|
||||
var/icon/photo = null
|
||||
var/g = (H.gender == FEMALE) ? "f" : "m"
|
||||
if(H.dna.species.use_skintones)
|
||||
photo = icon("icon" = 'icons/mob/human.dmi', "icon_state" = "[H.skin_tone]_[g]")
|
||||
else
|
||||
photo = icon("icon" = 'icons/mob/human.dmi', "icon_state" = "[H.dna.species.id]_[g]")
|
||||
photo.Blend("#[H.dna.features["mcolor"]]", ICON_MULTIPLY)
|
||||
/obj/machinery/abductor/experiment/ui_status(mob/user)
|
||||
if(user == occupant)
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
var/icon/eyes
|
||||
if(EYECOLOR in H.dna.species.species_traits)
|
||||
eyes = icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "eyes")
|
||||
eyes.Blend("#[H.eye_color]", ICON_MULTIPLY)
|
||||
/obj/machinery/abductor/experiment/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ProbingConsole", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
var/datum/sprite_accessory/S
|
||||
S = GLOB.hairstyles_list[H.hairstyle]
|
||||
if(S && (HAIR in H.dna.species.species_traits))
|
||||
var/icon/hair = icon("icon" = S.icon, "icon_state" = "[S.icon_state]")
|
||||
hair.Blend("#[H.hair_color]", ICON_MULTIPLY)
|
||||
eyes.Blend(hair, ICON_OVERLAY)
|
||||
|
||||
S = GLOB.facial_hairstyles_list[H.facial_hairstyle]
|
||||
if(S && (FACEHAIR in H.dna.species.species_traits))
|
||||
var/icon/facial = icon("icon" = S.icon, "icon_state" = "[S.icon_state]")
|
||||
facial.Blend("#[H.facial_hair_color]", ICON_MULTIPLY)
|
||||
eyes.Blend(facial, ICON_OVERLAY)
|
||||
|
||||
if(eyes)
|
||||
photo.Blend(eyes, ICON_OVERLAY)
|
||||
|
||||
var/icon/splat = icon("icon" = 'icons/mob/dam_mob.dmi',"icon_state" = "chest30")
|
||||
photo.Blend(splat,ICON_OVERLAY)
|
||||
|
||||
return photo
|
||||
|
||||
/obj/machinery/abductor/experiment/proc/experimentUI(mob/user)
|
||||
var/dat
|
||||
dat += "<h3> Experiment </h3>"
|
||||
if(occupant)
|
||||
var/obj/item/photo/P = new
|
||||
P.picture = new
|
||||
P.picture.picture_image = icon(dissection_icon(occupant), dir = SOUTH)
|
||||
user << browse_rsc(P.picture.picture_image, "dissection_img")
|
||||
dat += "<table><tr><td>"
|
||||
dat += "<img src=dissection_img height=80 width=80>" //Avert your eyes
|
||||
dat += "</td><td>"
|
||||
dat += "<a href='?src=[REF(src)];experiment=1'>Probe</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];experiment=2'>Dissect</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];experiment=3'>Analyze</a><br>"
|
||||
dat += "</td></tr></table>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Experiment </span>"
|
||||
|
||||
if(!occupant)
|
||||
dat += "<h3>Machine Unoccupied</h3>"
|
||||
else
|
||||
dat += "<h3>Subject Status : </h3>"
|
||||
dat += "[occupant.name] => "
|
||||
var/mob/living/mob_occupant = occupant
|
||||
switch(mob_occupant.stat)
|
||||
if(CONSCIOUS)
|
||||
dat += "<span class='good'>Conscious</span>"
|
||||
if(UNCONSCIOUS)
|
||||
dat += "<span class='average'>Unconscious</span>"
|
||||
else // DEAD
|
||||
dat += "<span class='bad'>Deceased</span>"
|
||||
dat += "<br>"
|
||||
dat += "[flash]"
|
||||
dat += "<br>"
|
||||
dat += "<a href='?src=[REF(src)];refresh=1'>Scan</a>"
|
||||
dat += "<a href='?src=[REF(src)];[state_open ? "close=1'>Close</a>" : "open=1'>Open</a>"]"
|
||||
var/datum/browser/popup = new(user, "experiment", "Probing Console", 300, 300)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/abductor/experiment/Topic(href, href_list)
|
||||
if(..() || usr == occupant)
|
||||
return
|
||||
usr.set_machine(src)
|
||||
if(href_list["refresh"])
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(href_list["open"])
|
||||
open_machine()
|
||||
return
|
||||
if(href_list["close"])
|
||||
close_machine()
|
||||
return
|
||||
/obj/machinery/abductor/experiment/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["open"] = state_open
|
||||
data["feedback"] = flash
|
||||
data["occupant"] = occupant ? TRUE : FALSE
|
||||
data["occupant_name"] = null
|
||||
data["occupant_status"] = null
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant.stat != DEAD)
|
||||
if(href_list["experiment"])
|
||||
flash = Experiment(occupant,href_list["experiment"],usr)
|
||||
updateUsrDialog()
|
||||
add_fingerprint(usr)
|
||||
data["occupant_name"] = mob_occupant.name
|
||||
data["occupant_status"] = mob_occupant.stat
|
||||
return data
|
||||
|
||||
/obj/machinery/abductor/experiment/proc/Experiment(mob/occupant,type,mob/user)
|
||||
/obj/machinery/abductor/experiment/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("door")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
return TRUE
|
||||
else
|
||||
open_machine()
|
||||
return TRUE
|
||||
if("experiment")
|
||||
if(!occupant)
|
||||
return
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant.stat == DEAD)
|
||||
return
|
||||
flash = experiment(occupant, params["experiment_type"], usr)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* experiment: Performs selected experiment on occupant mob, resulting in a point reward on success
|
||||
*
|
||||
* Arguments:
|
||||
* * occupant The mob inside the machine
|
||||
* * type The type of experiment to be performed
|
||||
* * user The mob starting the experiment
|
||||
*/
|
||||
/obj/machinery/abductor/experiment/proc/experiment(mob/occupant, type, mob/user)
|
||||
LAZYINITLIST(history)
|
||||
var/mob/living/carbon/human/H = occupant
|
||||
|
||||
var/datum/antagonist/abductor/user_abductor = user.mind.has_antag_datum(/datum/antagonist/abductor)
|
||||
if(!user_abductor)
|
||||
return "<span class='bad'>Authorization failure. Contact mothership immidiately.</span>"
|
||||
return "Authorization failure. Contact mothership immediately."
|
||||
|
||||
var/point_reward = 0
|
||||
if(!H)
|
||||
return "Invalid or missing specimen."
|
||||
if(H in history)
|
||||
return "<span class='bad'>Specimen already in database.</span>"
|
||||
return "Specimen already in database."
|
||||
if(H.stat == DEAD)
|
||||
say("Specimen deceased - please provide fresh sample.")
|
||||
return "<span class='bad'>Specimen deceased.</span>"
|
||||
return "Specimen deceased."
|
||||
var/obj/item/organ/heart/gland/GlandTest = locate() in H.internal_organs
|
||||
if(!GlandTest)
|
||||
say("Experimental dissection not detected!")
|
||||
return "<span class='bad'>No glands detected!</span>"
|
||||
return "No glands detected!"
|
||||
if(H.mind != null && H.ckey != null)
|
||||
LAZYINITLIST(abductee_minds)
|
||||
LAZYADD(history, H)
|
||||
@@ -197,22 +153,27 @@
|
||||
point_reward++
|
||||
if(point_reward > 0)
|
||||
open_machine()
|
||||
SendBack(H)
|
||||
send_back(H)
|
||||
playsound(src.loc, 'sound/machines/ding.ogg', 50, TRUE)
|
||||
points += point_reward
|
||||
credits += point_reward
|
||||
return "<span class='good'>Experiment successful! [point_reward] new data-points collected.</span>"
|
||||
return "Experiment successful! [point_reward] new data-points collected."
|
||||
else
|
||||
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
|
||||
return "<span class='bad'>Experiment failed! No replacement organ detected.</span>"
|
||||
return "Experiment failed! No replacement organ detected."
|
||||
else
|
||||
say("Brain activity nonexistent - disposing sample...")
|
||||
open_machine()
|
||||
SendBack(H)
|
||||
return "<span class='bad'>Specimen braindead - disposed.</span>"
|
||||
send_back(H)
|
||||
return "Specimen braindead - disposed."
|
||||
|
||||
|
||||
/obj/machinery/abductor/experiment/proc/SendBack(mob/living/carbon/human/H)
|
||||
/**
|
||||
* send_back: Sends a mob back to a selected teleport location if safe
|
||||
*
|
||||
* Arguments:
|
||||
* * H The human mob to be sent back
|
||||
*/
|
||||
/obj/machinery/abductor/experiment/proc/send_back(mob/living/carbon/human/H)
|
||||
H.Sleeping(160)
|
||||
H.uncuff()
|
||||
if(console && console.pad && console.pad.teleport_target)
|
||||
@@ -222,7 +183,6 @@
|
||||
SSjob.SendToLateJoin(H, FALSE)
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/abductor/experiment/update_icon_state()
|
||||
if(state_open)
|
||||
icon_state = "experiment-open"
|
||||
|
||||
@@ -1373,6 +1373,7 @@
|
||||
#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\orderable_gear.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"
|
||||
|
||||
@@ -18,6 +18,7 @@ import './polyfills/inferno';
|
||||
|
||||
// Themes
|
||||
import './styles/main.scss';
|
||||
import './styles/themes/abductor.scss';
|
||||
import './styles/themes/cardtable.scss';
|
||||
import './styles/themes/malfunction.scss';
|
||||
import './styles/themes/ntos.scss';
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import { GenericUplink } from './Uplink';
|
||||
import { useBackend, useSharedState } from '../backend';
|
||||
import { Button, LabeledList, NoticeBox, Section, Tabs } from '../components';
|
||||
import { Fragment } from 'inferno';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const AbductorConsole = (props, context) => {
|
||||
const [tab, setTab] = useSharedState(context, 'tab', 1);
|
||||
return (
|
||||
<Window
|
||||
theme="abductor"
|
||||
resizable>
|
||||
<Window.Content scrollable>
|
||||
<Tabs>
|
||||
<Tabs.Tab
|
||||
icon="list"
|
||||
lineHeight="23px"
|
||||
selected={tab === 1}
|
||||
onClick={() => setTab(1)}>
|
||||
Abductsoft 3000
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
icon="list"
|
||||
lineHeight="23px"
|
||||
selected={tab === 2}
|
||||
onClick={() => setTab(2)}>
|
||||
Mission Settings
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
{tab === 1 && (
|
||||
<Abductsoft />
|
||||
)}
|
||||
{tab === 2 && (
|
||||
<Fragment>
|
||||
<EmergencyTeleporter />
|
||||
<VestSettings />
|
||||
</Fragment>
|
||||
)}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const Abductsoft = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
experiment,
|
||||
points,
|
||||
credits,
|
||||
} = data;
|
||||
|
||||
if (!experiment) {
|
||||
return (
|
||||
<NoticeBox danger>
|
||||
No Experiment Machine Detected
|
||||
</NoticeBox>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Collected Samples">
|
||||
{points}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<GenericUplink
|
||||
currencyAmount={credits}
|
||||
currencySymbol="Credits" />
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const EmergencyTeleporter = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
pad,
|
||||
gizmo,
|
||||
} = data;
|
||||
|
||||
if (!pad) {
|
||||
return (
|
||||
<NoticeBox danger>
|
||||
No Telepad Detected
|
||||
</NoticeBox>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Emergency Teleport"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="exclamation-circle"
|
||||
content="Activate"
|
||||
color="bad"
|
||||
onClick={() => act('teleporter_send')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Mark Retrieval">
|
||||
<Button
|
||||
icon={gizmo ? "user-plus" : "user-slash"}
|
||||
content={gizmo ? "Retrieve" : "No Mark"}
|
||||
disabled={!gizmo}
|
||||
onClick={() => act('teleporter_retrieve')} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const VestSettings = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
vest,
|
||||
vest_mode,
|
||||
vest_lock,
|
||||
} = data;
|
||||
|
||||
if (!vest) {
|
||||
return (
|
||||
<NoticeBox danger>
|
||||
No Agent Vest Detected
|
||||
</NoticeBox>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Agent Vest Settings"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={vest_lock ? 'lock' : 'unlock'}
|
||||
content={vest_lock ? 'Locked' : 'Unlocked'}
|
||||
onClick={() => act('toggle_vest')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Mode">
|
||||
<Button
|
||||
icon={vest_mode === 1 ? 'eye-slash' : 'fist-raised'}
|
||||
content={vest_mode === 1 ? "Stealth" : "Combat"}
|
||||
onClick={() => act('flip_vest')} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Disguise">
|
||||
<Button
|
||||
icon="user-secret"
|
||||
content="Select"
|
||||
onClick={() => act('select_disguise')} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const GlandDispenser = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
glands = [],
|
||||
} = data;
|
||||
return (
|
||||
<Window theme="abductor">
|
||||
<Window.Content>
|
||||
<Section>
|
||||
{glands.map(gland => (
|
||||
<Button
|
||||
key={gland.id}
|
||||
width="60px"
|
||||
height="60px"
|
||||
m={0.75}
|
||||
textAlign="center"
|
||||
lineHeight="55px"
|
||||
icon="eject"
|
||||
backgroundColor={gland.color}
|
||||
content={gland.amount || "0"}
|
||||
disabled={!gland.amount}
|
||||
onClick={() => act('dispense', {
|
||||
gland_id: gland.id,
|
||||
})} />
|
||||
))}
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, Section, LabeledList, NoticeBox } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const ProbingConsole = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
open,
|
||||
feedback,
|
||||
occupant,
|
||||
occupant_name,
|
||||
occupant_status,
|
||||
} = data;
|
||||
return (
|
||||
<Window theme="abductor">
|
||||
<Window.Content>
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Machine Report">
|
||||
{feedback}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section
|
||||
title="Scanner"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={open ? 'sign-out-alt' : 'sign-in-alt'}
|
||||
content={open ? 'Close' : 'Open'}
|
||||
onClick={() => act('door')} />
|
||||
)}>
|
||||
{occupant && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Name">
|
||||
{occupant_name}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Status"
|
||||
color={occupant_status === 3
|
||||
? 'bad'
|
||||
: occupant_status === 2
|
||||
? 'average'
|
||||
: 'good'}>
|
||||
{occupant_status === 3
|
||||
? 'Deceased'
|
||||
: occupant_status === 2
|
||||
? 'Unconcious'
|
||||
: 'Concious'}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Experiments">
|
||||
<Button
|
||||
icon="thermometer"
|
||||
content="Probe"
|
||||
onClick={() => act('experiment', {
|
||||
experiment_type: 1,
|
||||
})} />
|
||||
<Button
|
||||
icon="brain"
|
||||
content="Dissect"
|
||||
onClick={() => act('experiment', {
|
||||
experiment_type: 2,
|
||||
})} />
|
||||
<Button
|
||||
icon="search"
|
||||
content="Analyze"
|
||||
onClick={() => act('experiment', {
|
||||
experiment_type: 3,
|
||||
})} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) || (
|
||||
<NoticeBox>
|
||||
No Subject
|
||||
</NoticeBox>
|
||||
)}
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Aleksej Komarov
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
@use 'sass:color';
|
||||
@use 'sass:meta';
|
||||
|
||||
@use '../colors.scss' with (
|
||||
$primary: #ad2350,
|
||||
$fg-map-keys: (),
|
||||
$bg-map-keys: (),
|
||||
);
|
||||
@use '../base.scss' with (
|
||||
$color-bg: #2a314a,
|
||||
$color-bg-grad-spread: 6%,
|
||||
$border-radius: 2px,
|
||||
);
|
||||
|
||||
.theme-abductor {
|
||||
// Atomic classes
|
||||
@include meta.load-css('../atomic/color.scss');
|
||||
|
||||
// Components
|
||||
@include meta.load-css('../components/Button.scss', $with: (
|
||||
'color-default': colors.$primary,
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #465899,
|
||||
'color-caution': #be6209,
|
||||
'color-danger': #9a9d00,
|
||||
));
|
||||
@include meta.load-css('../components/Input.scss', $with: (
|
||||
'border-color': #404b6e,
|
||||
));
|
||||
@include meta.load-css('../components/NoticeBox.scss', $with: (
|
||||
'color-background': #a82d55,
|
||||
));
|
||||
@include meta.load-css('../components/NumberInput.scss', $with: (
|
||||
'border-color': #404b6e,
|
||||
));
|
||||
@include meta.load-css('../components/ProgressBar.scss', $with: (
|
||||
'color-background': rgba(0, 0, 0, 0.5),
|
||||
));
|
||||
@include meta.load-css('../components/Section.scss');
|
||||
@include meta.load-css('../components/Tooltip.scss', $with: (
|
||||
'color-background': #a82d55,
|
||||
));
|
||||
|
||||
// Layouts
|
||||
@include meta.load-css('../layouts/Layout.scss');
|
||||
@include meta.load-css('../layouts/Window.scss');
|
||||
@include meta.load-css('../layouts/TitleBar.scss', $with: (
|
||||
'color-background': #9e1b46,
|
||||
));
|
||||
|
||||
.Layout__content {
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user