Merge pull request #12853 from LetterN/TGUI-4

TGUI4 port
This commit is contained in:
silicons
2020-08-09 05:46:21 -07:00
committed by GitHub
539 changed files with 15719 additions and 8963 deletions
@@ -18,9 +18,7 @@
/obj/item/mining_scanner,
/obj/item/flashlight/lantern,
/obj/item/card/id/mining,
/obj/item/gps/mining{
tracking = 0
},
/obj/item/gps/mining,
/turf/open/floor/plating,
/area/ruin/powered/golem_ship)
"d" = (
@@ -34,9 +32,7 @@
/obj/item/mining_scanner,
/obj/item/flashlight/lantern,
/obj/item/card/id/mining,
/obj/item/gps/mining{
tracking = 0
},
/obj/item/gps/mining,
/turf/open/floor/plating,
/area/ruin/powered/golem_ship)
"e" = (
@@ -156,9 +152,7 @@
"x" = (
/obj/structure/table/wood,
/obj/machinery/reagentgrinder,
/obj/item/gps/mining{
tracking = 0
},
/obj/item/gps/mining,
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
"z" = (
+35
View File
@@ -0,0 +1,35 @@
/// Module is compatible with Security Cyborg models
#define BORG_MODULE_SECURITY (1<<0)
/// Module is compatible with Miner Cyborg models
#define BORG_MODULE_MINER (1<<1)
/// Module is compatible with Janitor Cyborg models
#define BORG_MODULE_JANITOR (1<<2)
/// Module is compatible with Medical Cyborg models
#define BORG_MODULE_MEDICAL (1<<3)
/// Module is compatible with Engineering Cyborg models
#define BORG_MODULE_ENGINEERING (1<<4)
/// Module is compatible with Ripley Exosuit models
#define EXOSUIT_MODULE_RIPLEY (1<<0)
/// Module is compatible with Odyseeus Exosuit models
#define EXOSUIT_MODULE_ODYSSEUS (1<<1)
/// Module is compatible with Clarke Exosuit models. Rebranded to firefighter because tg nerfed it to this.
#define EXOSUIT_MODULE_FIREFIGHTER (1<<2)
// #define EXOSUIT_MODULE_CLARKE (1<<2)
/// Module is compatible with Gygax Exosuit models
#define EXOSUIT_MODULE_GYGAX (1<<3)
/// Module is compatible with Durand Exosuit models
#define EXOSUIT_MODULE_DURAND (1<<4)
/// Module is compatible with H.O.N.K Exosuit models
#define EXOSUIT_MODULE_HONK (1<<5)
/// Module is compatible with Phazon Exosuit models
#define EXOSUIT_MODULE_PHAZON (1<<6)
/// Module is compatable with N models
#define EXOSUIT_MODULE_GYGAX_MED (1<<7)
/// Module is compatible with "Working" Exosuit models - Ripley and Clarke
#define EXOSUIT_MODULE_WORKING EXOSUIT_MODULE_RIPLEY | EXOSUIT_MODULE_FIREFIGHTER // | EXOSUIT_MODULE_CLARKE
/// Module is compatible with "Combat" Exosuit models - Gygax, H.O.N.K, Durand and Phazon
#define EXOSUIT_MODULE_COMBAT EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON
/// Module is compatible with "Medical" Exosuit modelsm - Odysseus
#define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS | EXOSUIT_MODULE_GYGAX_MED
+5 -4
View File
@@ -341,10 +341,11 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are.
//Endgame Results
#define NUKE_MISS_STATION 1
#define NUKE_SYNDICATE_BASE 2
#define STATION_DESTROYED_NUKE 3
#define STATION_EVACUATED 4
#define NUKE_NEAR_MISS 1
#define NUKE_MISS_STATION 2
#define NUKE_SYNDICATE_BASE 3
#define STATION_DESTROYED_NUKE 4
#define STATION_EVACUATED 5
#define BLOB_WIN 8
#define BLOB_NUKE 9
#define BLOB_DESTROYED 10
+28 -4
View File
@@ -1,4 +1,28 @@
#define UI_INTERACTIVE 2 // Green/Interactive
#define UI_UPDATE 1 // Orange/Updates Only
#define UI_DISABLED 0 // Red/Disabled
#define UI_CLOSE -1 // Closed
/// Green eye; fully interactive
#define UI_INTERACTIVE 2
/// Orange eye; updates but is not interactive
#define UI_UPDATE 1
/// Red eye; disabled, does not update
#define UI_DISABLED 0
/// UI Should close
#define UI_CLOSE -1
/// Maximum number of windows that can be suspended/reused
#define TGUI_WINDOW_SOFT_LIMIT 5
/// Maximum number of open windows
#define TGUI_WINDOW_HARD_LIMIT 9
/// Maximum ping timeout allowed to detect zombie windows
#define TGUI_PING_TIMEOUT 4 SECONDS
/// Window does not exist
#define TGUI_WINDOW_CLOSED 0
/// Window was just opened, but is still not ready to be sent data
#define TGUI_WINDOW_LOADING 1
/// Window is free and ready to receive data
#define TGUI_WINDOW_READY 2
/// Get a window id based on the provided pool index
#define TGUI_WINDOW_ID(index) "tgui-window-[index]"
/// Get a pool index of the provided window id
#define TGUI_WINDOW_INDEX(window_id) text2num(copytext(window_id, 13))
+12 -3
View File
@@ -201,9 +201,18 @@
WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------")
/* ui logging */
/proc/log_tgui(text)
WRITE_LOG(GLOB.tgui_log, text)
/proc/log_tgui(user_or_client, text)
var/entry = ""
if(!user_or_client)
entry += "no user"
else if(istype(user_or_client, /mob))
var/mob/user = user_or_client
entry += "[user.ckey] (as [user])"
else if(istype(user_or_client, /client))
var/client/client = user_or_client
entry += "[client.ckey]"
entry += ":\n[text]"
WRITE_LOG(GLOB.tgui_log, entry)
/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */
/proc/shutdown_logging()
+9 -6
View File
@@ -85,9 +85,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_advdisease_resistance_asc(datum/disease/advance/A, datum/disease/advance/B)
return A.totalResistance() - B.totalResistance()
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
return A.display_order - B.display_order
/proc/cmp_uplink_items_dsc(datum/uplink_item/A, datum/uplink_item/B)
return sorttext(initial(B.name), initial(A.name))
@@ -97,9 +94,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_numbered_displays_name_dsc(datum/numbered_display/A, datum/numbered_display/B)
return sorttext(B.sample_object.name, A.sample_object.name)
/proc/cmp_reagents_asc(datum/reagent/a, datum/reagent/b)
return sorttext(initial(b.name),initial(a.name))
/proc/cmp_quirk_asc(datum/quirk/A, datum/quirk/B)
var/a_sign = num2sign(initial(A.value) * -1)
var/b_sign = num2sign(initial(B.value) * -1)
@@ -133,3 +127,12 @@ GLOBAL_VAR_INIT(cmp_field, "name")
return A.required_temp - B.required_temp //return coldest
else
return B.required_temp - A.required_temp //return hottest
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
return A.display_order - B.display_order
/proc/cmp_reagents_asc(datum/reagent/a, datum/reagent/b)
return sorttext(initial(b.name),initial(a.name))
/proc/cmp_typepaths_asc(A, B)
return sorttext("[B]","[A]")
+7 -5
View File
@@ -775,12 +775,14 @@ SUBSYSTEM_DEF(shuttle)
preview_shuttle = null
/datum/controller/subsystem/shuttle/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ShuttleManipulator", name, 800, 600, master_ui, state)
ui.open()
/datum/controller/subsystem/shuttle/ui_state(mob/user)
return GLOB.admin_state
/datum/controller/subsystem/shuttle/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ShuttleManipulator")
ui.open()
/datum/controller/subsystem/shuttle/ui_data(mob/user)
var/list/data = list()
+330 -16
View File
@@ -1,3 +1,12 @@
/**
* tgui subsystem
*
* Contains all tgui state and subsystem code.
*
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
SUBSYSTEM_DEF(tgui)
name = "tgui"
wait = 9
@@ -5,33 +14,338 @@ SUBSYSTEM_DEF(tgui)
priority = FIRE_PRIORITY_TGUI
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun = list()
var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
var/list/processing_uis = list() // A list of processing UIs, ungrouped.
var/basehtml // The HTML base used for all UIs.
/// A list of UIs scheduled to process
var/list/current_run = list()
/// A list of open UIs
var/list/open_uis = list()
/// A list of open UIs, grouped by src_object.
var/list/open_uis_by_src = list()
/// The HTML base used for all UIs.
var/basehtml
/datum/controller/subsystem/tgui/PreInit()
basehtml = file2text('tgui/packages/tgui/public/tgui.html')
basehtml = file2text('tgui/packages/tgui/public/tgui.html')
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()
/datum/controller/subsystem/tgui/stat_entry()
..("P:[processing_uis.len]")
..("P:[open_uis.len]")
/datum/controller/subsystem/tgui/fire(resumed = 0)
if (!resumed)
src.currentrun = processing_uis.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/datum/tgui/ui = currentrun[currentrun.len]
currentrun.len--
if(!resumed)
src.current_run = open_uis.Copy()
// Cache for sanic speed (lists are references anyways)
var/list/current_run = src.current_run
while(current_run.len)
var/datum/tgui/ui = current_run[current_run.len]
current_run.len--
// TODO: Move user/src_object check to process()
if(ui && ui.user && ui.src_object)
ui.process()
else
processing_uis.Remove(ui)
if (MC_TICK_CHECK)
open_uis.Remove(ui)
if(MC_TICK_CHECK)
return
/**
* public
*
* Requests a usable tgui window from the pool.
* Returns null if pool was exhausted.
*
* required user mob
* return datum/tgui
*/
/datum/controller/subsystem/tgui/proc/request_pooled_window(mob/user)
if(!user.client)
return null
var/list/windows = user.client.tgui_windows
var/window_id
var/datum/tgui_window/window
var/window_found = FALSE
// Find a usable window
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
window_id = TGUI_WINDOW_ID(i)
window = windows[window_id]
// As we are looping, create missing window datums
if(!window)
window = new(user.client, window_id, pooled = TRUE)
// Skip windows with acquired locks
if(window.locked)
continue
if(window.status == TGUI_WINDOW_READY)
return window
if(window.status == TGUI_WINDOW_CLOSED)
window.status = TGUI_WINDOW_LOADING
window_found = TRUE
break
if(!window_found)
log_tgui(user, "Error: Pool exhausted")
return null
return window
/**
* public
*
* Force closes all tgui windows.
*
* required user mob
*/
/datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user)
log_tgui(user, "force_close_all_windows")
if(user.client)
user.client.tgui_windows = list()
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
var/window_id = TGUI_WINDOW_ID(i)
user << browse(null, "window=[window_id]")
/**
* public
*
* Force closes the tgui window by window_id.
*
* required user mob
* required window_id string
*/
/datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id)
log_tgui(user, "force_close_window")
// Close all tgui datums based on window_id.
for(var/datum/tgui/ui in user.tgui_open_uis)
if(ui.window && ui.window.id == window_id)
ui.close(can_be_suspended = FALSE)
// Unset machine just to be sure.
user.unset_machine()
// Close window directly just to be sure.
user << browse(null, "window=[window_id]")
/**
* public
*
* Try to find an instance of a UI, and push an update to it.
*
* required user mob The mob who opened/is using the UI.
* required src_object datum The object/datum which owns the UI.
* optional ui datum/tgui The UI to be updated, if it exists.
* optional force_open bool If the UI should be re-opened instead of updated.
*
* return datum/tgui The found UI.
*/
/datum/controller/subsystem/tgui/proc/try_update_ui(
mob/user,
datum/src_object,
datum/tgui/ui)
// Look up a UI if it wasn't passed
if(isnull(ui))
ui = get_open_ui(user, src_object)
// Couldn't find a UI.
if(isnull(ui))
return null
ui.process_status()
// UI ended up with the closed status
// or is actively trying to close itself.
// FIXME: Doesn't actually fix the paper bug.
if(ui.status <= UI_CLOSE)
ui.close()
return null
ui.send_update()
return ui
/**
* public
*
* Get a open UI given a user and src_object.
*
* required user mob The mob who opened/is using the UI.
* required src_object datum The object/datum which owns the UI.
*
* return datum/tgui The found UI.
*/
/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object)
var/key = "[REF(src_object)]"
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return null
for(var/datum/tgui/ui in open_uis_by_src[key])
// Make sure we have the right user
if(ui.user == user)
return ui
return null
/**
* public
*
* Update all UIs attached to src_object.
*
* required src_object datum The object/datum which owns the UIs.
*
* return int The number of UIs updated.
*/
/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
var/count = 0
var/key = "[REF(src_object)]"
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return count
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.process(force = 1)
count++
return count
/**
* public
*
* Close all UIs attached to src_object.
*
* required src_object datum The object/datum which owns the UIs.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object)
var/count = 0
var/key = "[REF(src_object)]"
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return count
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
count++
return count
/**
* public
*
* Close all UIs regardless of their attachment to src_object.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/close_all_uis()
var/count = 0
for(var/key in open_uis_by_src)
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
count++
return count
/**
* public
*
* Update all UIs belonging to a user.
*
* required user mob The mob who opened/is using the UI.
* optional src_object datum If provided, only update UIs belonging this src_object.
*
* return int The number of UIs updated.
*/
/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object)
var/count = 0
if(length(user?.tgui_open_uis) == 0)
return count
for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object)
ui.process(force = 1)
count++
return count
/**
* public
*
* Close all UIs belonging to a user.
*
* required user mob The mob who opened/is using the UI.
* optional src_object datum If provided, only close UIs belonging this src_object.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object)
var/count = 0
if(length(user?.tgui_open_uis) == 0)
return count
for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object)
ui.close()
count++
return count
/**
* private
*
* Add a UI to the list of open UIs.
*
* required ui datum/tgui The UI to be added.
*/
/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui)
var/key = "[REF(ui.src_object)]"
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
open_uis_by_src[key] = list()
ui.user.tgui_open_uis |= ui
var/list/uis = open_uis_by_src[key]
uis |= ui
open_uis |= ui
/**
* private
*
* Remove a UI from the list of open UIs.
*
* required ui datum/tgui The UI to be removed.
*
* return bool If the UI was removed or not.
*/
/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui)
var/key = "[REF(ui.src_object)]"
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return FALSE
// Remove it from the list of processing UIs.
open_uis.Remove(ui)
// If the user exists, remove it from them too.
if(ui.user)
ui.user.tgui_open_uis.Remove(ui)
var/list/uis = open_uis_by_src[key]
uis.Remove(ui)
if(length(uis) == 0)
open_uis_by_src.Remove(key)
return TRUE
/**
* private
*
* Handle client logout, by closing all their UIs.
*
* required user mob The mob which logged out.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/on_logout(mob/user)
close_user_uis(user)
/**
* private
*
* Handle clients switching mobs, by transferring their UIs.
*
* required user source The client's original mob.
* required user target The client's new mob.
*
* return bool If the UIs were transferred.
*/
/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target)
// The old mob had no open UIs.
if(length(source?.tgui_open_uis) == 0)
return FALSE
if(isnull(target.tgui_open_uis) || !istype(target.tgui_open_uis, /list))
target.tgui_open_uis = list()
// Transfer all the UIs.
for(var/datum/tgui/ui in source.tgui_open_uis)
// Inform the UIs of their new owner.
ui.user = target
target.tgui_open_uis.Add(ui)
// Clear the old list.
source.tgui_open_uis.Cut()
return TRUE
+17 -10
View File
@@ -431,25 +431,31 @@
if(!owner)
owner = M
/datum/ai_laws/proc/get_law_list(include_zeroth = 0, show_numbers = 1)
/**
* Generates a list of all laws on this datum, including rendered HTML tags if required
*
* Arguments:
* * include_zeroth - Operator that controls if law 0 or law 666 is returned in the set
* * show_numbers - Operator that controls if law numbers are prepended to the returned laws
* * render_html - Operator controlling if HTML tags are rendered on the returned laws
*/
/datum/ai_laws/proc/get_law_list(include_zeroth = FALSE, show_numbers = TRUE, render_html = TRUE)
var/list/data = list()
if (include_zeroth && devillaws && devillaws.len)
for(var/i in devillaws)
data += "[show_numbers ? "666:" : ""] <font color='#cc5500'>[i]</font>"
if (include_zeroth && devillaws)
for(var/law in devillaws)
data += "[show_numbers ? "666:" : ""] [render_html ? "<font color='#cc5500'>[law]</font>" : law]"
if (include_zeroth && zeroth)
data += "[show_numbers ? "0:" : ""] <font color='#ff0000'><b>[zeroth]</b></font>"
data += "[show_numbers ? "0:" : ""] [render_html ? "<font color='#ff0000'><b>[zeroth]</b></font>" : zeroth]"
for(var/law in hacked)
if (length(law) > 0)
var/num = ionnum()
data += "[show_numbers ? "[num]:" : ""] <font color='#660000'>[law]</font>"
data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "<font color='#660000'>[law]</font>" : law]"
for(var/law in ion)
if (length(law) > 0)
var/num = ionnum()
data += "[show_numbers ? "[num]:" : ""] <font color='#547DFE'>[law]</font>"
data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "<font color='#547DFE'>[law]</font>" : law]"
var/number = 1
for(var/law in inherent)
@@ -459,6 +465,7 @@
for(var/law in supplied)
if (length(law) > 0)
data += "[show_numbers ? "[number]:" : ""] <font color='#990099'>[law]</font>"
data += "[show_numbers ? "[number]:" : ""] [render_html ? "<font color='#990099'>[law]</font>" : law]"
number++
return data
+11 -13
View File
@@ -203,9 +203,9 @@
Set var amt to the value current cycle req is pointing to, its amount of type we need to delete
Get var/surroundings list of things accessable to crafting by get_environment()
Check the type of the current cycle req
If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isnt remove thing from surroundings
If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isn't remove thing from surroundings
If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list
If there isnt enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
If there isn't enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one
If its stack check if it has enough amount
If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack
@@ -216,7 +216,7 @@
Then do a loop over parts var of the recipe
Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return
After its done loop over deletion list and delete all the shit that wasnt taken by parts loop
After its done loop over deletion list and delete all the shit that wasn't taken by parts loop
del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
*/
@@ -323,9 +323,12 @@
if(user == parent)
ui_interact(user)
/datum/component/personal_crafting/ui_state(mob/user)
return GLOB.not_incapacitated_turf_state
//For the UI related things we're going to assume the user is a mob rather than typesetting it to an atom as the UI isn't generated if the parent is an atom
/datum/component/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_turf_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/datum/component/personal_crafting/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
cur_category = categories[1]
if(islist(categories[cur_category]))
@@ -333,7 +336,7 @@
cur_subcategory = subcats[1]
else
cur_subcategory = CAT_NONE
ui = new(user, src, ui_key, "PersonalCrafting", "Crafting Menu", 700, 800, master_ui, state)
ui = new(user, src, "PersonalCrafting")
ui.open()
/datum/component/personal_crafting/ui_data(mob/user)
@@ -413,13 +416,8 @@
display_compact = !display_compact
. = TRUE
if("set_category")
if(!isnull(params["category"]))
cur_category = params["category"]
if(!isnull(params["subcategory"]))
if(params["subcategory"] == "0")
cur_subcategory = ""
else
cur_subcategory = params["subcategory"]
cur_category = params["category"]
cur_subcategory = params["subcategory"] || ""
. = TRUE
/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
+4 -8
View File
@@ -80,19 +80,15 @@ GLOBAL_LIST_EMPTY(GPS_list)
to_chat(user, "<span class='notice'>[parent] is now tracking, and visible to other GPS devices.</span>")
tracking = TRUE
/datum/component/gps/item/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
/datum/component/gps/item/ui_interact(mob/user, datum/tgui/ui)
if(emped)
to_chat(user, "<span class='hear'>[parent] fizzles weakly.</span>")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
// Variable window height, depending on how many GPS units there are
// to show, clamped to relatively safe range.
var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "Gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui = new(user, src, "Gps")
ui.open()
ui.set_autoupdate(state = updating)
ui.set_autoupdate(updating)
/datum/component/gps/item/ui_data(mob/user)
var/list/data = list()
+16 -10
View File
@@ -143,23 +143,19 @@ GLOBAL_LIST_EMPTY(uplinks)
// an unlocked uplink blocks also opening the PDA or headset menu
return COMPONENT_NO_INTERACT
/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
/datum/component/uplink/ui_state(mob/user)
return GLOB.inventory_state
/datum/component/uplink/ui_interact(mob/user, datum/tgui/ui)
active = TRUE
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Uplink", name, 620, 580, master_ui, state)
ui = new(user, src, "Uplink", name)
// This UI is only ever opened by one person,
// and never is updated outside of user input.
ui.set_autoupdate(FALSE)
ui.open()
/datum/component/uplink/ui_host(mob/user)
if(istype(parent, /obj/item/implant)) //implants are like organs, not really located inside mobs codewise.
var/obj/item/implant/I = parent
return I.imp_in
return ..()
/datum/component/uplink/ui_data(mob/user)
if(!user.mind)
return
@@ -187,8 +183,18 @@ GLOBAL_LIST_EMPTY(uplinks)
is_inaccessible = FALSE
if(is_inaccessible)
continue
/*
if(I.restricted_species) //catpeople specfic gloves.
if(ishuman(user))
var/is_inaccessible = TRUE
var/mob/living/carbon/human/H = user
for(var/F in I.restricted_species)
if(F == H.dna.species.id || debug)
is_inaccessible = FALSE
break
if(is_inaccessible)
continue
*/
cat["items"] += list(list(
"name" = I.name,
"cost" = I.cost,
+42 -6
View File
@@ -1,13 +1,13 @@
//TODO: someone please get rid of this shit
/datum/datacore
var/medical[] = list()
var/list/medical = list()
var/medicalPrintCount = 0
var/general[] = list()
var/security[] = list()
var/list/general = list()
var/list/security = list()
var/securityPrintCount = 0
var/securityCrimeCounter = 0
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
var/locked[] = list()
///This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
var/list/locked = list()
/datum/data
var/name = "data"
@@ -91,6 +91,42 @@
if(foundrecord)
foundrecord.fields["rank"] = assignment
/datum/datacore/proc/get_manifest_tg() //copypasted from tg, renamed to avoid namespace conflicts
var/list/manifest_out = list()
var/list/departments = list(
"Command" = GLOB.command_positions,
"Security" = GLOB.security_positions,
"Engineering" = GLOB.engineering_positions,
"Medical" = GLOB.medical_positions,
"Science" = GLOB.science_positions,
"Supply" = GLOB.supply_positions,
"Service" = GLOB.civilian_positions,
"Silicon" = GLOB.nonhuman_positions
)
for(var/datum/data/record/t in GLOB.data_core.general)
var/name = t.fields["name"]
var/rank = t.fields["rank"]
var/has_department = FALSE
for(var/department in departments)
var/list/jobs = departments[department]
if(rank in jobs)
if(!manifest_out[department])
manifest_out[department] = list()
manifest_out[department] += list(list(
"name" = name,
"rank" = rank
))
has_department = TRUE
break
if(!has_department)
if(!manifest_out["Misc"])
manifest_out["Misc"] = list()
manifest_out["Misc"] += list(list(
"name" = name,
"rank" = rank
))
return manifest_out
/datum/datacore/proc/get_manifest(monochrome, OOC)
var/list/heads = list()
var/list/sec = list()
+119 -5
View File
@@ -32,20 +32,29 @@
var/datum/action/innate/end_holocall/hangup //hangup action
var/call_start_time
var/head_call = FALSE //calls from a head of staff autoconnect, if the receiving pad is not secure.
//creates a holocall made by `caller` from `calling_pad` to `callees`
/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees)
/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees, elevated_access = FALSE)
call_start_time = world.time
user = caller
calling_pad.outgoing_call = src
calling_holopad = calling_pad
head_call = elevated_access
dialed_holopads = list()
for(var/I in callees)
var/obj/machinery/holopad/H = I
if(!QDELETED(H) && H.is_operational())
dialed_holopads += H
H.say("Incoming call.")
if(head_call)
if(H.secure)
calling_pad.say("Auto-connection refused, falling back to call mode.")
H.say("Incoming call.")
else
H.say("Incoming connection.")
else
H.say("Incoming call.")
LAZYADD(H.holo_calls, src)
if(!dialed_holopads.len)
@@ -79,6 +88,7 @@
dialed_holopads.Cut()
if(calling_holopad)
calling_holopad.calling = FALSE
calling_holopad.outgoing_call = null
calling_holopad.SetLightsAndPower()
calling_holopad = null
@@ -145,6 +155,7 @@
if(!Check())
return
calling_holopad.calling = FALSE
hologram = H.activate_holo(user)
hologram.HC = src
@@ -160,6 +171,8 @@
hangup = new(eye, src)
hangup.Grant(user)
playsound(H, 'sound/machines/ping.ogg', 100)
H.say("Connection established.")
//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise
/datum/holocall/proc/Check()
@@ -178,7 +191,6 @@
. = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME)
if(!.)
calling_holopad.say("No answer received.")
calling_holopad.temp = ""
if(!.)
testing("Holocall Check fail")
@@ -241,10 +253,10 @@
record.caller_image = holodiskOriginal.record.caller_image
record.entries = holodiskOriginal.record.entries.Copy()
record.language = holodiskOriginal.record.language
to_chat(user, "You copy the record from [holodiskOriginal] to [src] by connecting the ports!")
to_chat(user, "<span class='notice'>You copy the record from [holodiskOriginal] to [src] by connecting the ports!</span>")
name = holodiskOriginal.name
else
to_chat(user, "[holodiskOriginal] has no record on it!")
to_chat(user, "<span class='warning'>[holodiskOriginal] has no record on it!</span>")
..()
/obj/item/disk/holodisk/proc/build_record()
@@ -331,6 +343,21 @@
DELAY 20"}
/datum/preset_holoimage/engineer
outfit_type = /datum/outfit/job/engineer
/datum/preset_holoimage/engineer/rig
outfit_type = /datum/outfit/job/engineer/gloved/rig
/datum/preset_holoimage/engineer/ce
outfit_type = /datum/outfit/job/ce
/datum/preset_holoimage/engineer/ce/rig
outfit_type = /datum/outfit/job/engineer/gloved/rig
/datum/preset_holoimage/engineer/atmos
outfit_type = /datum/outfit/job/atmos
/datum/preset_holoimage/engineer/atmos/rig
outfit_type = /datum/outfit/job/engineer/gloved/rig
/datum/preset_holoimage/researcher
@@ -350,3 +377,90 @@
/datum/preset_holoimage/clown
outfit_type = /datum/outfit/job/clown
/obj/item/disk/holodisk/donutstation/whiteship
name = "Blackbox Print-out #DS024"
desc = "A holodisk containing the last viable recording of DS024's blackbox."
preset_image_type = /datum/preset_holoimage/engineer/ce
preset_record_text = {"
NAME Geysr Shorthalt
SAY Engine renovations complete and the ships been loaded. We all ready?
DELAY 25
PRESET /datum/preset_holoimage/engineer
NAME Jacob Ullman
SAY Lets blow this popsicle stand of a station.
DELAY 20
PRESET /datum/preset_holoimage/engineer/atmos
NAME Lindsey Cuffler
SAY Uh, sir? Shouldn't we call for a secondary shuttle? The bluespace drive on this thing made an awfully weird noise when we jumped here..
DELAY 30
PRESET /datum/preset_holoimage/engineer/ce
NAME Geysr Shorthalt
SAY Pah! Ship techie at the dock said to give it a good few kicks if it started acting up, let me just..
DELAY 25
SOUND punch
SOUND sparks
DELAY 10
SOUND punch
SOUND sparks
DELAY 10
SOUND punch
SOUND sparks
SOUND warpspeed
DELAY 15
PRESET /datum/preset_holoimage/engineer/atmos
NAME Lindsey Cuffler
SAY Uhh.. is it supposed to be doing that??
DELAY 15
PRESET /datum/preset_holoimage/engineer/ce
NAME Geysr Shorthalt
SAY See? Working as intended. Now, are we all ready?
DELAY 10
PRESET /datum/preset_holoimage/engineer
NAME Jacob Ullman
SAY Is it supposed to be glowing like that?
DELAY 20
SOUND explosion
"}
/obj/item/disk/holodisk/ruin/snowengieruin
name = "Blackbox Print-out #EB412"
desc = "A holodisk containing the last moments of EB412. There's a bloody fingerprint on it."
preset_image_type = /datum/preset_holoimage/engineer
preset_record_text = {"
NAME Dave Tundrale
SAY Maria, how's Build?
DELAY 10
NAME Maria Dell
PRESET /datum/preset_holoimage/engineer/atmos
SAY It's fine, don't worry. I've got Plastic on it. And frankly, i'm kinda busy with, the, uhhm, incinerator.
DELAY 30
NAME Dave Tundrale
PRESET /datum/preset_holoimage/engineer
SAY Aight, wonderful. The science mans been kinda shit though. No RCDs-
DELAY 20
NAME Maria Dell
PRESET /datum/preset_holoimage/engineer/atmos
SAY Enough about your RCDs. They're not even that important, just bui-
DELAY 15
SOUND explosion
DELAY 10
SAY Oh, shit!
DELAY 10
PRESET /datum/preset_holoimage/engineer/atmos/rig
LANGUAGE /datum/language/narsie
NAME Unknown
SAY RISE, MY LORD!!
DELAY 10
LANGUAGE /datum/language/common
NAME Plastic
PRESET /datum/preset_holoimage/engineer/rig
SAY Fuck, fuck, fuck!
DELAY 20
SAY It's loose! CALL THE FUCKING SHUTT-
DELAY 10
PRESET /datum/preset_holoimage/corgi
NAME Blackbox Automated Message
SAY Connection lost. Dumping audio logs to disk.
DELAY 50"}
+7 -4
View File
@@ -14,11 +14,14 @@
mind.skill_holder.ui_interact(src)
/datum/skill_holder/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/datum/skill_holder/ui_state(mob/user)
return GLOB.always_state
/datum/skill_holder/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "SkillPanel", "[owner.name]'s Skills", 620, 580, master_ui, state)
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
ui = new(user, src, "SkillPanel", "[owner.name]'s Skills")
ui.set_autoupdate(FALSE)
ui.open()
else if(need_static_data_update)
update_static_data(user)
+15 -8
View File
@@ -6,10 +6,13 @@
qdel(src)
owner = new_owner
/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/datum/spawners_menu/ui_state(mob/user)
return GLOB.observer_state
/datum/spawners_menu/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "SpawnersMenu", "Spawners Menu", 700, 600, master_ui, state)
ui = new(user, src, "SpawnersMenu")
ui.open()
/datum/spawners_menu/ui_data(mob/user)
@@ -42,11 +45,15 @@
if(..())
return
var/spawner_ref = pick(GLOB.mob_spawners[params["name"]])
var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list
if(!MS)
var/group_name = params["name"]
if(!group_name || !(group_name in GLOB.mob_spawners))
return
var/list/spawnerlist = GLOB.mob_spawners[group_name]
if(!spawnerlist.len)
return
var/obj/effect/mob_spawn/MS = pick(spawnerlist)
if(!istype(MS) || !(MS in GLOB.poi_list))
return
switch(action)
if("jump")
if(MS)
@@ -55,4 +62,4 @@
if("spawn")
if(MS)
MS.attack_ghost(owner)
. = TRUE
. = TRUE
+14 -5
View File
@@ -97,6 +97,12 @@
/datum/wires/proc/get_wire(color)
return colors[color]
/datum/wires/proc/get_color_of_wire(wire_type)
for(var/color in colors)
var/other_type = colors[color]
if(wire_type == other_type)
return color
/datum/wires/proc/get_attached(color)
if(assemblies[color])
return assemblies[color]
@@ -117,7 +123,7 @@
return TRUE
/datum/wires/proc/is_dud(wire)
return findtext(wire, WIRE_DUD_PREFIX)
return findtext(wire, WIRE_DUD_PREFIX, 1, length(WIRE_DUD_PREFIX) + 1)
/datum/wires/proc/is_dud_color(color)
return is_dud(get_wire(color))
@@ -197,6 +203,7 @@
S.forceMove(holder.drop_location())
return S
/// Called from [/atom/proc/emp_act]
/datum/wires/proc/emp_pulse()
var/list/possible_wires = shuffle(wires)
var/remaining_pulses = MAXIMUM_EMP_WIRES
@@ -239,11 +246,13 @@
return ..()
return UI_CLOSE
/datum/wires/ui_interact(mob/user, ui_key = "wires", 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)
/datum/wires/ui_state(mob/user)
return GLOB.physical_state
/datum/wires/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, ui_key, "Wires", "[holder.name] Wires", 350, 150 + wires.len * 30, master_ui, state)
ui = new(user, src, "Wires", "[holder.name] Wires")
ui.open()
/datum/wires/ui_data(mob/user)
+10 -21
View File
@@ -53,11 +53,10 @@
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
if(!A.panel_open)
return FALSE
if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100))
return FALSE
return TRUE
if(A.panel_open)
return TRUE
/datum/wires/airlock/get_status()
var/obj/machinery/door/airlock/A = holder
@@ -115,10 +114,7 @@
A.aiControlDisabled = -1
if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks.
if(!A.secondsElectrified)
A.set_electrified(30)
if(usr)
LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]"))
log_combat(usr, A, "electrified")
A.set_electrified(30, usr)
if(WIRE_SAFETY)
A.safe = !A.safe
if(!A.density)
@@ -135,21 +131,17 @@
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
A.regainMainPower()
if(usr)
A.shock(usr, 50)
else
A.loseMainPower()
if(usr)
A.shock(usr, 50)
if(isliving(usr))
A.shock(usr, 50)
if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power.
if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2))
A.regainBackupPower()
if(usr)
A.shock(usr, 50)
else
A.loseBackupPower()
if(usr)
A.shock(usr, 50)
if(isliving(usr))
A.shock(usr, 50)
if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing.
if(!mend)
A.bolt()
@@ -170,10 +162,7 @@
A.set_electrified(0)
else
if(A.secondsElectrified != -1)
A.set_electrified(-1)
if(usr)
LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]"))
log_combat(usr, A, "electrified")
A.set_electrified(-1, usr)
if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable.
A.safe = mend
if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable.
@@ -184,5 +173,5 @@
A.lights = mend
A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
if(usr)
A.shock(usr, 50)
if(isliving(usr))
A.shock(usr, 50)
+10 -9
View File
@@ -962,15 +962,16 @@
if(source != target)
target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE)
/*
Proc for attack log creation, because really why not
1 argument is the actor performing the action
2 argument is the target of the action
3 is a verb describing the action (e.g. punched, throwed, kicked, etc.)
4 is a tool with which the action was made (usually an item)
5 is any additional text, which will be appended to the rest of the log line
*/
/**
* Log a combat message in the attack log
*
* Arguments:
* * atom/user - argument is the actor performing the action
* * atom/target - argument is the target of the action
* * what_done - is a verb describing the action (e.g. punched, throwed, kicked, etc.)
* * atom/object - is a tool with which the action was made (usually an item)
* * addition - is any additional text, which will be appended to the rest of the log line
*/
/proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null)
var/ssource = key_name(user)
var/starget = key_name(target)
+7 -7
View File
@@ -201,15 +201,15 @@
. = ..()
. += "<span class='notice'>Alt-click [src] to [state_open ? "close" : "open"] it.</span>"
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
/obj/machinery/sleeper/ui_state(mob/user)
if(controls_inside)
return GLOB.notcontained_state
return GLOB.default_state
if(controls_inside && state == GLOB.notcontained_state)
state = GLOB.default_state // If it has a set of controls on the inside, make it actually controllable by the mob in it.
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/sleeper/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Sleeper", name, 550, 700, master_ui, state)
ui = new(user, src, "Sleeper", name)
ui.open()
/obj/machinery/sleeper/process()
+3 -6
View File
@@ -93,13 +93,10 @@ GLOBAL_LIST_EMPTY(announcement_systems)
for(var/channel in channels)
radio.talk_into(src, message, channel)
//config stuff
/obj/machinery/announcement_system/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
. = ..()
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/announcement_system/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AutomatedAnnouncement", "Automated Announcement System", 500, 225, master_ui, state)
ui = new(user, src, "AutomatedAnnouncement")
ui.open()
/obj/machinery/announcement_system/ui_data()
+10 -7
View File
@@ -3,6 +3,7 @@
desc = "A machine used to deposit and withdraw station funds."
icon = 'goon/icons/obj/goon_terminals.dmi'
idle_power_usage = 100
var/siphoning = FALSE
var/next_warning = 0
var/obj/item/radio/radio
@@ -38,7 +39,6 @@
return
return ..()
/obj/machinery/computer/bank_machine/process()
..()
if(siphoning)
@@ -51,7 +51,7 @@
end_syphon()
return
playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1)
playsound(src, 'sound/items/poster_being_created.ogg', 100, TRUE)
syphoning_credits += 200
D.adjust_money(-200)
if(next_warning < world.time && prob(15))
@@ -60,17 +60,20 @@
radio.talk_into(src, message, radio_channel)
next_warning = world.time + minimum_time_between_warnings
/obj/machinery/computer/bank_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/bank_machine/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "BankMachine", name, 320, 165, master_ui, state)
ui = new(user, src, "BankMachine", name)
ui.open()
/obj/machinery/computer/bank_machine/ui_data(mob/user)
var/list/data = list()
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
data["current_balance"] = D.account_balance
if(D)
data["current_balance"] = D.account_balance
else
data["current_balance"] = 0
data["siphoning"] = siphoning
data["station_name"] = station_name()
+8 -3
View File
@@ -43,10 +43,13 @@
table.computer = src
break
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/operating/ui_state(mob/user)
return GLOB.not_incapacitated_state
/obj/machinery/computer/operating/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "OperatingComputer", name, 350, 470, master_ui, state)
ui = new(user, src, "OperatingComputer", name)
ui.open()
/obj/machinery/computer/operating/ui_data(mob/user)
@@ -153,6 +156,8 @@
))
return data
/obj/machinery/computer/operating/ui_act(action, params)
if(..())
return
+36 -67
View File
@@ -2,14 +2,13 @@
name = "\improper AI system integrity restorer"
desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order."
req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS)
var/mob/living/silicon/ai/occupier = null
var/active = 0
circuit = /obj/item/circuitboard/computer/aifixer
icon_keyboard = "tech_key"
icon_screen = "ai-fixer"
light_color = LIGHT_COLOR_PINK
ui_x = 370
ui_y = 360
circuit = /obj/item/circuitboard/computer/aifixer
var/mob/living/silicon/ai/occupier = null
var/active = FALSE
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
if(occupier && istype(I, /obj/item/screwdriver))
@@ -20,64 +19,45 @@
else
return ..()
/obj/machinery/computer/aifixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/aifixer/ui_interact(mob/user, datum/tgui/ui) //artur didn't port this correctly
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AiRestorer", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "AiRestorer", name)
ui.open()
var/dat = ""
/obj/machinery/computer/aifixer/ui_data(mob/user)
var/list/data = list()
if (src.occupier)
var/laws
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
data["ejectable"] = FALSE
data["AI_present"] = FALSE
data["error"] = null
if(!occupier)
data["error"] = "Please transfer an AI unit."
else
data["AI_present"] = TRUE
data["name"] = occupier.name
data["restoring"] = active
data["health"] = (occupier.health + 100) / 2
data["isDead"] = occupier.stat == DEAD
data["laws"] = occupier.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
if (src.occupier.laws.zeroth)
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
return data
for (var/index = 1, index <= src.occupier.laws.hacked.len, index++)
var/law = src.occupier.laws.hacked[index]
if (length(law) > 0)
var/num = ionnum()
laws += "<b>[num]:</b> [law]<BR>"
/obj/machinery/computer/aifixer/ui_act(action, params)
if(..())
return
if(!occupier)
active = FALSE
for (var/index = 1, index <= src.occupier.laws.ion.len, index++)
var/law = src.occupier.laws.ion[index]
if (length(law) > 0)
var/num = ionnum()
laws += "<b>[num]:</b> [law]<BR>"
var/number = 1
for (var/index = 1, index <= src.occupier.laws.inherent.len, index++)
var/law = src.occupier.laws.inherent[index]
if (length(law) > 0)
laws += "<b>[number]:</b> [law]<BR>"
number++
for (var/index = 1, index <= src.occupier.laws.supplied.len, index++)
var/law = src.occupier.laws.supplied[index]
if (length(law) > 0)
laws += "<b>[number]:</b> [law]<BR>"
number++
dat += "<b>Laws:</b><br>[laws]<br>"
if (src.occupier.stat == DEAD)
dat += "<span class='bad'>AI non-functional</span>"
else
dat += "<span class='good'>AI functional</span>"
if (!src.active)
dat += {"<br><br><A href='byond://?src=[REF(src)];fix=1'>Begin Reconstruction</A>"}
else
dat += "<br><br>Reconstruction in process, please wait.<br>"
dat += {"<br><A href='?src=[REF(user)];mach_close=computer'>Close</A>"}
var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
return
switch(action)
if("PRG_beginReconstruction")
if(occupier?.health < 100)
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
active = TRUE
occupier.notify_ghost_cloning("Your core files are being restored!", source = src)
. = TRUE
/obj/machinery/computer/aifixer/proc/Fix()
use_power(1000)
@@ -97,17 +77,6 @@
active = Fix()
if(oldstat != occupier.stat)
update_icon()
updateDialog()
/obj/machinery/computer/aifixer/Topic(href, href_list)
if(..())
return
if(href_list["fix"])
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
active = TRUE
add_fingerprint(usr)
updateUsrDialog()
/obj/machinery/computer/aifixer/update_overlays()
. = ..()
+153 -161
View File
@@ -3,19 +3,19 @@
desc = "Used to remotely control the flow of power to different parts of the station."
icon_screen = "solar"
icon_keyboard = "power_key"
req_access = list(ACCESS_ENGINE)
req_access = list(ACCESS_CE)
circuit = /obj/item/circuitboard/computer/apc_control
light_color = LIGHT_COLOR_YELLOW
var/mob/living/operator //Who's operating the computer right now
var/obj/machinery/power/apc/active_apc //The APC we're using right now
var/list/result_filters //For sorting the results
var/checking_logs = 0
var/should_log = TRUE
var/restoring = FALSE
var/list/logs
var/auth_id = "\[NULL\]"
var/auth_id = "\[NULL\]:"
/obj/machinery/computer/apc_control/Initialize()
/obj/machinery/computer/apc_control/Initialize(mapload, obj/item/circuitboard/C)
. = ..()
result_filters = list("Name" = null, "Charge Above" = null, "Charge Below" = null, "Responsive" = null)
logs = list()
/obj/machinery/computer/apc_control/process()
if(operator && (!operator.Adjacent(src) || stat))
@@ -23,8 +23,8 @@
if(active_apc)
if(!active_apc.locked)
active_apc.say("Remote access canceled. Interface locked.")
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0)
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0)
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE)
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE)
active_apc.locked = TRUE
active_apc.update_icon()
active_apc.remote_control = null
@@ -34,171 +34,163 @@
if(!IsAdminGhost(user))
to_chat(user,"<span class='warning'>[src] does not support AI control.</span>") //You already have APC access, cheater!
return
..(user)
..()
/obj/machinery/computer/apc_control/proc/check_apc(obj/machinery/power/apc/APC)
return APC.z == z && !APC.malfhack && !APC.aidisabled && !(APC.obj_flags & EMAGGED) && !APC.stat && !istype(APC.area, /area/ai_monitored) && !APC.area.outdoors
/obj/machinery/computer/apc_control/ui_interact(mob/living/user)
. = ..()
var/dat
if(authenticated)
if(!checking_logs)
dat += "Logged in as [auth_id].<br><br>"
dat += "<i>Filters</i><br>"
dat += "<b>Name:</b> <a href='?src=[REF(src)];name_filter=1'>[result_filters["Name"] ? result_filters["Name"] : "None set"]</a><br>"
dat += "<b>Charge:</b> <a href='?src=[REF(src)];above_filter=1'>\>[result_filters["Charge Above"] ? result_filters["Charge Above"] : "NaN"]%</a> and <a href='?src=[REF(src)];below_filter=1'>\<[result_filters["Charge Below"] ? result_filters["Charge Below"] : "NaN"]%</a><br>"
dat += "<b>Accessible:</b> <a href='?src=[REF(src)];access_filter=1'>[result_filters["Responsive"] ? "Non-Responsive Only" : "All"]</a><br><br>"
for(var/A in GLOB.apcs_list)
if(check_apc(A))
var/obj/machinery/power/apc/APC = A
if(result_filters["Name"] && !findtext(APC.name, result_filters["Name"]) && !findtext(APC.area.name, result_filters["Name"]))
continue
if(result_filters["Charge Above"] && (!APC.cell || (APC.cell && (APC.cell.charge / APC.cell.maxcharge) < result_filters["Charge Above"] / 100)))
continue
if(result_filters["Charge Below"] && APC.cell && (APC.cell.charge / APC.cell.maxcharge) > result_filters["Charge Below"] / 100)
continue
if(result_filters["Responsive"] && !APC.aidisabled)
continue
dat += "<a href='?src=[REF(src)];access_apc=[REF(APC)]'>[A]</a><br>\
<b>Charge:</b> [APC.cell ? "[DisplayEnergy(APC.cell.charge)] / [DisplayEnergy(APC.cell.maxcharge)] ([round((APC.cell.charge / APC.cell.maxcharge) * 100)]%)" : "No Powercell Installed"]<br>\
<b>Area:</b> [APC.area]<br>\
[APC.aidisabled || APC.panel_open ? "<font color='#FF0000'>APC does not respond to interface query.</font>" : "<font color='#00FF00'>APC responds to interface query.</font>"]<br><br>"
dat += "<a href='?src=[REF(src)];check_logs=1'>Check Logs</a><br>"
dat += "<a href='?src=[REF(src)];log_out=1'>Log Out</a><br>"
if(obj_flags & EMAGGED)
dat += "<font color='#FF0000'>WARNING: Logging functionality partially disabled from outside source.</font><br>"
dat += "<a href='?src=[REF(src)];restore_logging=1'>Restore logging functionality?</a><br>"
else
if(logs.len)
for(var/entry in logs)
dat += "[entry]<br>"
else
dat += "<i>No activity has been recorded at this time.</i><br>"
if(obj_flags & EMAGGED)
dat += "<a href='?src=[REF(src)];clear_logs=1'><font color='#FF0000'>@#%! CLEAR LOGS</a>"
dat += "<a href='?src=[REF(src)];check_apcs=1'>Return</a>"
operator = user
else
dat = "<a href='?src=[REF(src)];authenticate=1'>Please swipe a valid ID to log in...</a>"
var/datum/browser/popup = new(user, "apc_control", name, 600, 400)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
/obj/machinery/computer/apc_control/ui_interact(mob/user, datum/tgui/ui)
operator = user
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ApcControl")
ui.open()
/obj/machinery/computer/apc_control/Topic(href, href_list)
/obj/machinery/computer/apc_control/ui_data(mob/user)
var/list/data = list()
data["auth_id"] = auth_id
data["authenticated"] = authenticated
data["emagged"] = obj_flags & EMAGGED
data["logging"] = should_log
data["restoring"] = restoring
data["logs"] = list()
data["apcs"] = list()
for(var/entry in logs)
data["logs"] += list(list("entry" = entry))
for(var/apc in GLOB.apcs_list)
if(check_apc(apc))
var/obj/machinery/power/apc/A = apc
var/has_cell = (A.cell) ? TRUE : FALSE
data["apcs"] += list(list(
"name" = A.area.name,
"operating" = A.operating,
"charge" = (has_cell) ? A.cell.percent() : "NOCELL",
"load" = DisplayPower(A.lastused_total),
"charging" = A.charging,
"chargeMode" = A.chargemode,
"eqp" = A.equipment,
"lgt" = A.lighting,
"env" = A.environ,
"responds" = A.aidisabled || A.panel_open,
"ref" = REF(A)
)
)
return data
/obj/machinery/computer/apc_control/ui_act(action, params)
if(..())
return
if(!usr || !usr.canUseTopic(src) || stat || QDELETED(src))
return
if(href_list["authenticate"])
var/obj/item/card/id/ID = usr.get_idcard(TRUE)
if(ID && istype(ID))
if(check_access(ID))
switch(action)
if("log-in")
if(obj_flags & EMAGGED)
authenticated = TRUE
auth_id = "[ID.registered_name] ([ID.assignment])"
log_activity("logged in")
if(href_list["log_out"])
log_activity("logged out")
authenticated = FALSE
auth_id = "\[NULL\]"
if(href_list["restore_logging"])
to_chat(usr, "<span class='robot notice'>[icon2html(src, usr)] Logging functionality restored from backup data.</span>")
obj_flags &= ~EMAGGED
LAZYADD(logs, "<b>-=- Logging restored to full functionality at this point -=-</b>")
if(href_list["access_apc"])
playsound(src, "terminal_type", 50, 0)
var/obj/machinery/power/apc/APC = locate(href_list["access_apc"]) in GLOB.apcs_list
if(!APC || APC.aidisabled || APC.panel_open || QDELETED(APC))
to_chat(usr, "<span class='robot danger'>[icon2html(src, usr)] APC does not return interface request. Remote access may be disabled.</span>")
return
if(active_apc)
to_chat(usr, "<span class='robot danger'>[icon2html(src, usr)] Disconnected from [active_apc].</span>")
active_apc.say("Remote access canceled. Interface locked.")
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0)
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0)
active_apc.locked = TRUE
active_apc.update_icon()
active_apc.remote_control = null
active_apc = null
to_chat(usr, "<span class='robot notice'>[icon2html(src, usr)] Connected to APC in [get_area_name(APC.area, TRUE)]. Interface request sent.</span>")
log_activity("remotely accessed APC in [get_area_name(APC.area, TRUE)]")
APC.remote_control = src
APC.ui_interact(usr)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
message_admins("[ADMIN_LOOKUPFLW(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
log_game("[key_name(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
if(APC.locked)
APC.say("Remote access detected. Interface unlocked.")
playsound(APC, 'sound/machines/boltsup.ogg', 25, 0)
playsound(APC, 'sound/machines/terminal_alert.ogg', 50, 0)
APC.locked = FALSE
APC.update_icon()
active_apc = APC
if(href_list["name_filter"])
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
var/new_filter = stripped_input(usr, "What name are you looking for?", name)
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
return
log_activity("changed name filter to \"[new_filter]\"")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
result_filters["Name"] = new_filter
if(href_list["above_filter"])
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (greater than).", name) as null|num
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
return
log_activity("changed greater than charge filter to \"[new_filter]\"")
if(new_filter)
new_filter = clamp(new_filter, 0, 100)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
result_filters["Charge Above"] = new_filter
if(href_list["below_filter"])
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (lesser than).", name) as null|num
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
return
log_activity("changed lesser than charge filter to \"[new_filter]\"")
if(new_filter)
new_filter = clamp(new_filter, 0, 100)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
result_filters["Charge Below"] = new_filter
if(href_list["access_filter"])
if(isnull(result_filters["Responsive"]))
result_filters["Responsive"] = 1
log_activity("sorted by non-responsive APCs only")
else
result_filters["Responsive"] = !result_filters["Responsive"]
log_activity("sorted by all APCs")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
if(href_list["check_logs"])
checking_logs = TRUE
log_activity("checked logs")
if(href_list["check_apcs"])
checking_logs = FALSE
log_activity("checked APCs")
if(href_list["clear_logs"])
logs = list()
ui_interact(usr) //Refresh the UI after a filter changes
auth_id = "Unknown (Unknown):"
log_activity("[auth_id] logged in to the terminal")
return
var/obj/item/card/id/ID = operator.get_idcard(TRUE)
if(ID && istype(ID))
if(check_access(ID))
authenticated = TRUE
auth_id = "[ID.registered_name] ([ID.assignment]):"
log_activity("[auth_id] logged in to the terminal")
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
else
auth_id = "[ID.registered_name] ([ID.assignment]):"
log_activity("[auth_id] attempted to log into the terminal")
return
auth_id = "Unknown (Unknown):"
log_activity("[auth_id] attempted to log into the terminal")
if("log-out")
log_activity("[auth_id] logged out of the terminal")
playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
authenticated = FALSE
auth_id = "\[NULL\]"
if("toggle-logs")
should_log = !should_log
log_game("[key_name(operator)] set the logs of [src] in [AREACOORD(src)] [should_log ? "On" : "Off"]")
if("restore-console")
restoring = TRUE
addtimer(CALLBACK(src, .proc/restore_comp), rand(3,5) * 9)
if("access-apc")
var/ref = params["ref"]
playsound(src, "terminal_type", 50, FALSE)
var/obj/machinery/power/apc/APC = locate(ref) in GLOB.apcs_list
if(!APC)
return
if(active_apc)
to_chat(operator, "<span class='robot danger'>[icon2html(src, auth_id)] Disconnected from [active_apc].</span>")
active_apc.say("Remote access canceled. Interface locked.")
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE)
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE)
active_apc.locked = TRUE
active_apc.update_icon()
active_apc.remote_control = null
active_apc = null
APC.remote_control = src
APC.ui_interact(operator)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
log_game("[key_name(operator)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
log_activity("[auth_id] remotely accessed APC in [get_area_name(APC.area, TRUE)]")
if(APC.locked)
APC.say("Remote access detected. Interface unlocked.")
playsound(APC, 'sound/machines/boltsup.ogg', 25, FALSE)
playsound(APC, 'sound/machines/terminal_alert.ogg', 50, FALSE)
APC.locked = FALSE
APC.update_icon()
active_apc = APC
if("check-logs")
log_activity("Checked Logs")
if("check-apcs")
log_activity("Checked APCs")
if("toggle-minor")
var/ref = params["ref"]
var/type = params["type"]
var/value = params["value"]
var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
if(!target)
return
target.vars[type] = target.setsubsystem(text2num(value))
target.update_icon()
target.update()
var/setTo = ""
switch(target.vars[type])
if(0)
setTo = "Off"
if(1)
setTo = "Auto Off"
if(2)
setTo = "On"
if(3)
setTo = "Auto On"
log_activity("Set APC [target.area.name] [type] to [setTo]")
log_game("[key_name(operator)] Set APC [target.area.name] [type] to [setTo]]")
if("breaker")
var/ref = params["ref"]
var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
target.toggle_breaker()
var/setTo = target.operating ? "On" : "Off"
log_activity("Turned APC [target.area.name]'s breaker [setTo]")
/obj/machinery/computer/apc_control/emag_act(mob/user)
. = ..()
if(!authenticated)
to_chat(user, "<span class='warning'>You bypass [src]'s access requirements using your emag.</span>")
authenticated = TRUE
log_activity("logged in")
else
if(obj_flags & EMAGGED)
return
user.visible_message("<span class='warning'>You emag [src], disabling precise logging and allowing you to clear logs.</span>")
log_game("[key_name(user)] emagged [src] at [AREACOORD(src)], disabling operator tracking.")
obj_flags |= EMAGGED
playsound(src, "sparks", 50, 1)
return TRUE
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
log_game("[key_name(user)] emagged [src] at [AREACOORD(src)]")
playsound(src, "sparks", 50, TRUE)
/obj/machinery/computer/apc_control/proc/log_activity(log_text)
var/op_string = operator && !(obj_flags & EMAGGED) ? operator : "\[NULL OPERATOR\]"
LAZYADD(logs, "<b>([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)])</b> [op_string] [log_text]")
if(!should_log)
return
LAZYADD(logs, "([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]): [auth_id] [log_text]")
/obj/machinery/computer/apc_control/proc/restore_comp()
obj_flags &= ~EMAGGED
should_log = TRUE
log_game("[key_name(operator)] restored the logs of [src] in [AREACOORD(src)]")
log_activity("-=- Logging restored to full functionality at this point -=-")
restoring = FALSE
/mob/proc/using_power_flow_console()
for(var/obj/machinery/computer/apc_control/A in range(1, src))
+5 -6
View File
@@ -19,11 +19,10 @@
SSradio.remove_object(src, receive_frequency)
return ..()
/obj/machinery/computer/atmos_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/atmos_alert/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AtmosAlertConsole", name, 350, 300, master_ui, state)
ui = new(user, src, "AtmosAlertConsole", name)
ui.open()
/obj/machinery/computer/atmos_alert/ui_data(mob/user)
@@ -45,11 +44,11 @@
if("clear")
var/zone = params["zone"]
if(zone in priority_alarms)
to_chat(usr, "Priority alarm for [zone] cleared.")
to_chat(usr, "<span class='notice'>Priority alarm for [zone] cleared.</span>")
priority_alarms -= zone
. = TRUE
if(zone in minor_alarms)
to_chat(usr, "Minor alarm for [zone] cleared.")
to_chat(usr, "<span class='notice'>Minor alarm for [zone] cleared.</span>")
minor_alarms -= zone
. = TRUE
update_icon()
+3 -13
View File
@@ -91,8 +91,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
icon_screen = "tank"
icon_keyboard = "atmos_key"
circuit = /obj/item/circuitboard/computer/atmos_control
ui_x = 400
ui_y = 925
var/frequency = FREQ_ATMOS_STORAGE
var/list/sensors = list(
@@ -123,11 +121,10 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
SSradio.remove_object(src, frequency)
return ..()
/obj/machinery/computer/atmos_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/atmos_control/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "AtmosControlConsole", name)
ui.open()
/obj/machinery/computer/atmos_control/ui_data(mob/user)
@@ -265,13 +262,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
U.broadcast_status()
/obj/machinery/computer/atmos_control/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/atmos_control/tank/ui_data(mob/user)
var/list/data = ..()
data["tank"] = TRUE
+5 -8
View File
@@ -5,8 +5,6 @@
icon_keyboard = "security_key"
circuit = /obj/item/circuitboard/computer/security
light_color = LIGHT_COLOR_RED
ui_x = 870
ui_y = 708
var/list/network = list("ss13")
var/obj/machinery/camera/active_camera
@@ -55,11 +53,9 @@
network -= i
network += "[idnum][i]"
/obj/machinery/computer/security/ui_interact(\
mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui)
// Update UI
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
ui = SStgui.try_update_ui(user, src, ui)
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
@@ -76,10 +72,11 @@
use_power(active_power_usage)
// Register map objects
user.client.register_map_obj(cam_screen)
user.client.register_map_obj(cam_plane_master)
for(var/plane in cam_plane_master)
user.client.register_map_obj(plane)
user.client.register_map_obj(cam_background)
// Open UI
ui = new(user, src, ui_key, "CameraConsole", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "CameraConsole", name)
ui.open()
/obj/machinery/computer/security/ui_data()
+3 -4
View File
@@ -76,11 +76,10 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
/datum/crewmonitor/Destroy()
return ..()
/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/datum/crewmonitor/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, ui_key, "CrewConsole", "crew monitor", 800, 600 , master_ui, state)
ui = new(user, src, "CrewConsole")
ui.open()
/datum/crewmonitor/proc/show(mob/M, source)
+3 -6
View File
@@ -220,9 +220,7 @@
/obj/machinery/computer/scan_consolenew/examine(mob/user)
. = ..()
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
. = ..()
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, datum/tgui/ui)
// Most of ui_interact is spent setting variables for passing to the tgui
// interface.
// We can also do some general state processing here too as it's a good
@@ -264,10 +262,9 @@
time_to_pulse = round((rad_pulse_timer - world.time)/10)
// Attempt to update tgui ui, open and update if needed.
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "DnaConsole", name, 539, 710, master_ui, state)
ui = new(user, src, "DnaConsole")
ui.open()
/obj/machinery/computer/scan_consolenew/ui_data(mob/user)
@@ -53,10 +53,10 @@
var/obj/machinery/launchpad/pad = launchpads[number]
return pad
/obj/machinery/computer/launchpad/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/launchpad/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "LaunchpadConsole", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "LaunchpadConsole", name)
ui.open()
/obj/machinery/computer/launchpad/ui_data(mob/user)
@@ -128,4 +128,4 @@
if("pull")
teleport(usr, current_pad, FALSE)
. = TRUE
. = TRUE
. = TRUE
@@ -6,8 +6,6 @@
icon_keyboard = "security_key"
req_access = list(ACCESS_ARMORY)
circuit = /obj/item/circuitboard/computer/gulag_teleporter_console
ui_x = 350
ui_y = 295
var/default_goal = 200
var/obj/machinery/gulag_teleporter/teleporter = null
@@ -21,11 +19,10 @@
. = ..()
scan_machinery()
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "GulagTeleporterConsole", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "GulagTeleporterConsole", name)
ui.open()
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user)
+4 -5
View File
@@ -23,11 +23,10 @@
return
return TRUE
/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/robotics/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "RoboticsControlConsole", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "RoboticsControlConsole", name)
ui.open()
/obj/machinery/computer/robotics/ui_data(mob/user)
@@ -123,5 +122,5 @@
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, TRUE, D)
s.start()
D.visible_message("<span class='danger'>\the [D] self destructs!</span>")
D.visible_message("<span class='danger'>\the [D] self-destructs!</span>")
D.gib()
@@ -16,11 +16,10 @@
GLOB.alert_consoles -= src
return ..()
/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/station_alert/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "StationAlertConsole", name, 325, 500, master_ui, state)
ui = new(user, src, "StationAlertConsole", name)
ui.open()
/obj/machinery/computer/station_alert/ui_data(mob/user)
@@ -31,6 +30,7 @@
data["alarms"][class] = list()
for(var/area in alarms[class])
data["alarms"][class] += area
return data
/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
+13 -13
View File
@@ -34,11 +34,10 @@
break
return power_station
obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/teleporter/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Teleporter", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "Teleporter", name)
ui.open()
/obj/machinery/computer/teleporter/ui_data(mob/user)
@@ -56,7 +55,6 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
return data
/obj/machinery/computer/teleporter/ui_act(action, params)
if(..())
return
@@ -92,16 +90,18 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
say("Processing hub calibration to target...")
calibrating = TRUE
power_station.update_icon()
spawn(50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration
calibrating = FALSE
if(check_hub_connection())
power_station.teleporter_hub.calibrated = TRUE
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
power_station.update_icon()
addtimer(CALLBACK(src, .proc/finish_calibration), 50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration
. = TRUE
/obj/machinery/computer/teleporter/proc/finish_calibration()
calibrating = FALSE
if(check_hub_connection())
power_station.teleporter_hub.calibrated = TRUE
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
power_station.update_icon()
/obj/machinery/computer/teleporter/proc/check_hub_connection()
if(!power_station)
return FALSE
+64 -46
View File
@@ -9,6 +9,7 @@
var/active = FALSE
var/list/rangers = list()
var/stop = 0
var/volume = 70
var/datum/track/selection = null
/obj/machinery/jukebox/disco
@@ -51,74 +52,91 @@
else
icon_state = "[initial(icon_state)]"
/obj/machinery/jukebox/ui_interact(mob/user)
. = ..()
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if (!anchored)
/obj/machinery/jukebox/ui_status(mob/user)
if(!anchored)
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
return
if(!allowed(user))
return UI_CLOSE
if(!allowed(user) && !isobserver(user))
to_chat(user,"<span class='warning'>Error: Access Denied.</span>")
user.playsound_local(src,'sound/misc/compiler-failure.ogg', 25, 1)
return
if(!SSjukeboxes.songs.len)
user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
return UI_CLOSE
if(!SSjukeboxes.songs.len && !isobserver(user))
to_chat(user,"<span class='warning'>Error: No music tracks have been authorized for your station. Petition Central Command to resolve this issue.</span>")
playsound(src,'sound/misc/compiler-failure.ogg', 25, 1)
return
var/list/dat = list()
dat +="<div class='statusDisplay' style='text-align:center'>"
dat += "<b><A href='?src=[REF(src)];action=toggle'>[!active ? "BREAK IT DOWN" : "SHUT IT DOWN"]<b></A><br>"
dat += "</div><br>"
dat += "<A href='?src=[REF(src)];action=select'> Select Track</A><br>"
if(istype(selection))
dat += "Track Selected: [selection.song_name]<br>"
dat += "Track Length: [DisplayTimeText(selection.song_length)]<br><br>"
else
dat += "Track Selected: None!<br><br>"
var/datum/browser/popup = new(user, "vending", "[name]", 400, 350)
popup.set_content(dat.Join())
popup.open()
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
return UI_CLOSE
return ..()
/obj/machinery/jukebox/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Jukebox", name)
ui.open()
/obj/machinery/jukebox/Topic(href, href_list)
if(..())
/obj/machinery/jukebox/ui_data(mob/user)
var/list/data = list()
data["active"] = active
data["songs"] = list()
for(var/datum/track/S in SSjukeboxes.songs)
var/list/track_data = list(
name = S.song_name
)
data["songs"] += list(track_data)
data["track_selected"] = null
data["track_length"] = null
data["track_beat"] = null
if(selection)
data["track_selected"] = selection.song_name
data["track_length"] = DisplayTimeText(selection.song_length)
data["track_beat"] = selection.song_beat
data["volume"] = volume
return data
/obj/machinery/jukebox/ui_act(action, list/params)
. = ..()
if(.)
return
add_fingerprint(usr)
switch(href_list["action"])
switch(action)
if("toggle")
if (QDELETED(src))
if(QDELETED(src))
return
if(!active)
if(stop > world.time)
to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].</span>")
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE)
return
if(!istype(selection))
to_chat(usr, "<span class='warning'>Error: Severe user incompetence detected.</span>")
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
return
if(!activate_music())
to_chat(usr, "<span class='warning'>Error: Generic hardware failure.</span>")
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
return
updateUsrDialog()
else if(active)
activate_music()
START_PROCESSING(SSobj, src)
return TRUE
else
stop = 0
updateUsrDialog()
if("select")
return TRUE
if("select_track")
if(active)
to_chat(usr, "<span class='warning'>Error: You cannot change the song until the current one is over.</span>")
return
var/list/available = list()
for(var/datum/track/S in SSjukeboxes.songs)
available[S.song_name] = S
var/selected = input(usr, "Choose your song", "Track:") as null|anything in available
var/selected = params["track"]
if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
return
selection = available[selected]
updateUsrDialog()
return TRUE
if("set_volume")
var/new_volume = params["volume"]
if(new_volume == "reset")
volume = initial(volume)
return TRUE
else if(new_volume == "min")
volume = 0
return TRUE
else if(new_volume == "max")
volume = 100
return TRUE
else if(text2num(new_volume) != null)
volume = text2num(new_volume)
return TRUE
/obj/machinery/jukebox/proc/activate_music()
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
+39 -29
View File
@@ -50,7 +50,7 @@
integrity_failure = 0.25
damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N
autoclose = TRUE
secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
secondsElectrified = NOT_ELECTRIFIED //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
assemblytype = /obj/structure/door_assembly
normalspeed = 1
explosion_block = 1
@@ -298,10 +298,10 @@
/obj/machinery/door/airlock/Destroy()
QDEL_NULL(wires)
QDEL_NULL(electronics)
if(charge)
qdel(charge)
charge = null
QDEL_NULL(electronics)
if (cyclelinkedairlock)
if (cyclelinkedairlock.cyclelinkedairlock == src)
cyclelinkedairlock.cyclelinkedairlock = null
@@ -309,7 +309,7 @@
if(id_tag)
for(var/obj/machinery/doorButtons/D in GLOB.machines)
D.removeMe(src)
qdel(note)
QDEL_NULL(note)
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.remove_from_hud(src)
return ..()
@@ -765,8 +765,8 @@
/obj/machinery/door/airlock/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!(issilicon(user) || IsAdminGhost(user)))
if(src.isElectrified())
if(src.shock(user, 100))
if(isElectrified())
if(shock(user, 100))
return
if(ishuman(user) && prob(40) && src.density)
@@ -790,15 +790,15 @@
return ..()
/obj/machinery/door/airlock/proc/electrified_loop()
while (secondsElectrified > 0)
while (secondsElectrified > NOT_ELECTRIFIED)
sleep(10)
if(QDELETED(src))
return
secondsElectrified -= 1
secondsElectrified--
updateDialog()
// This is to protect against changing to permanent, mid loop.
if(secondsElectrified==0)
if(secondsElectrified == NOT_ELECTRIFIED)
set_electrified(NOT_ELECTRIFIED)
else
set_electrified(ELECTRIFIED_PERMANENT)
@@ -825,8 +825,8 @@
/obj/machinery/door/airlock/attackby(obj/item/C, mob/user, params)
if(!issilicon(user) && !IsAdminGhost(user))
if(src.isElectrified())
if(src.shock(user, 75))
if(isElectrified())
if(shock(user, 75))
return
add_fingerprint(user)
@@ -839,7 +839,7 @@
to_chat(user, "<span class='warning'>You need at least 2 metal sheets to reinforce [src].</span>")
return
to_chat(user, "<span class='notice'>You start reinforcing [src].</span>")
if(do_after(user, 20, 1, target = src))
if(do_after(user, 20, TRUE, target = src))
if(!panel_open || !S.use(2))
return
user.visible_message("<span class='notice'>[user] reinforces \the [src] with metal.</span>",
@@ -1070,7 +1070,7 @@
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
if(istype(I, /obj/item/crowbar/power))
if(isElectrified())
if(hasPower() && isElectrified())
shock(user,100)//it's like sticking a forck in a power socket
return
@@ -1090,12 +1090,11 @@
time_to_open = 50
playsound(src, 'sound/machines/airlock_alien_prying.ogg',100,1) //is it aliens or just the CE being a dick?
prying_so_hard = TRUE
var/result = do_after(user, time_to_open,target = src)
prying_so_hard = FALSE
if(result)
if(do_after(user, time_to_open,target = src))
open(2)
if(density && !open(2))
to_chat(user, "<span class='warning'>Despite your attempts, [src] refuses to open.</span>")
prying_so_hard = FALSE
/obj/machinery/door/airlock/open(forced=0)
if( operating || welded || locked )
@@ -1359,12 +1358,25 @@
wires.cut_all()
update_icon()
/obj/machinery/door/airlock/proc/set_electrified(seconds)
/obj/machinery/door/airlock/proc/set_electrified(seconds, mob/user)
secondsElectrified = seconds
diag_hud_set_electrified()
if(secondsElectrified > 0)
if(secondsElectrified > NOT_ELECTRIFIED)
INVOKE_ASYNC(src, .proc/electrified_loop)
if(user)
var/message
switch(secondsElectrified)
if(ELECTRIFIED_PERMANENT)
message = "permanently shocked"
if(NOT_ELECTRIFIED)
message = "unshocked"
else
message = "temp shocked for [secondsElectrified] seconds"
LAZYADD(shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(user)] - ([uppertext(message)])"))
log_combat(user, src, message)
//add_hiddenprint(user)
/obj/machinery/door/airlock/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..()
if(obj_integrity < (0.75 * max_integrity))
@@ -1438,11 +1450,10 @@
else if(istype(note, /obj/item/photo))
return "photo"
/obj/machinery/door/airlock/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/door/airlock/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AiAirlock", name, 500, 390, master_ui, state)
ui = new(user, src, "AiAirlock", name)
ui.open()
return TRUE
@@ -1450,13 +1461,13 @@
var/list/data = list()
var/list/power = list()
power["main"] = src.secondsMainPowerLost ? 0 : 2 // boolean
power["main_timeleft"] = src.secondsMainPowerLost
power["backup"] = src.secondsBackupPowerLost ? 0 : 2 // boolean
power["backup_timeleft"] = src.secondsBackupPowerLost
power["main"] = secondsMainPowerLost ? 0 : 2 // boolean
power["main_timeleft"] = secondsMainPowerLost
power["backup"] = secondsBackupPowerLost ? 0 : 2 // boolean
power["backup_timeleft"] = secondsBackupPowerLost
data["power"] = power
data["shock"] = secondsElectrified == 0 ? 2 : 0
data["shock"] = secondsElectrified == NOT_ELECTRIFIED ? 2 : 0
data["shock_timeleft"] = secondsElectrified
data["id_scanner"] = !aiDisabledIdScanner
data["emergency"] = emergency // access
@@ -1493,14 +1504,14 @@
loseMainPower()
update_icon()
else
to_chat(usr, "Main power is already offline.")
to_chat(usr, "<span class='warning'>Main power is already offline.</span>")
. = TRUE
if("disrupt-backup")
if(!secondsBackupPowerLost)
loseBackupPower()
update_icon()
else
to_chat(usr, "Backup power is already offline.")
to_chat(usr, "<span class='warning'>Backup power is already offline.</span>")
. = TRUE
if("shock-restore")
shock_restore(usr)
@@ -1529,7 +1540,6 @@
. = TRUE
if("speed-toggle")
normalspeed = !normalspeed
. = TRUE
if("open-close")
user_toggle_open(usr)
@@ -15,11 +15,13 @@
. = ..()
. += "<span class='notice'>Has a neat <i>selection menu</i> for modifying airlock access levels.</span>"
/obj/item/electronics/airlock/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/electronics/airlock/ui_state(mob/user)
return GLOB.hands_state
/obj/item/electronics/airlock/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AirlockElectronics", name, 420, 485, master_ui, state)
ui = new(user, src, "AirlockElectronics", name)
ui.open()
/obj/item/electronics/airlock/ui_static_data(mob/user)
+4 -5
View File
@@ -140,11 +140,10 @@
. = new_time == timer_duration //return 1 on no change
timer_duration = new_time
/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/door_timer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "BrigTimer", name, 300, 138, master_ui, state)
ui = new(user, src, "BrigTimer", name)
ui.open()
//icon update function
@@ -235,7 +234,7 @@
preset_time = PRESET_LONG
. = set_timer(preset_time)
if(timing)
activation_time = REALTIMEOFDAY
activation_time = world.time
else
. = FALSE
+13 -14
View File
@@ -20,18 +20,15 @@
return ..()
/obj/machinery/gulag_item_reclaimer/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items
return
req_access = list()
obj_flags |= EMAGGED
return TRUE
/obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "GulagItemReclaimer", name, 300, 400, master_ui, state)
ui = new(user, src, "GulagItemReclaimer", name)
ui.open()
/obj/machinery/gulag_item_reclaimer/ui_data(mob/user)
@@ -60,20 +57,22 @@
mobs += list(mob_info)
data["mobs"] = mobs
data["can_reclaim"] = can_reclaim
return data
/obj/machinery/gulag_item_reclaimer/ui_act(action, list/params)
/obj/machinery/gulag_item_reclaimer/ui_act(action, params)
if(..())
return
switch(action)
if("release_items")
var/mob/M = locate(params["mobref"])
if(M == usr || allowed(usr))
drop_items(M)
else
to_chat(usr, "Access denied.")
var/mob/living/carbon/human/H = locate(params["mobref"]) in stored_items
if(H != usr && !allowed(usr))
to_chat(usr, "<span class='warning'>Access denied.</span>")
return
drop_items(H)
. = TRUE
/obj/machinery/gulag_item_reclaimer/proc/drop_items(mob/user)
if(!stored_items[user])
+182 -187
View File
@@ -25,7 +25,6 @@ Possible to do for anyone motivated enough:
*/
GLOBAL_LIST_EMPTY(network_holopads)
#define HOLOPAD_PASSIVE_POWER_USAGE 1
#define HOLOGRAM_POWER_USAGE 2
@@ -34,34 +33,64 @@ GLOBAL_LIST_EMPTY(network_holopads)
desc = "It's a floor-mounted device for projecting holographic images."
icon_state = "holopad0"
layer = LOW_OBJ_LAYER
plane = ABOVE_WALL_PLANE
plane = FLOOR_PLANE
flags_1 = HEAR_1
req_access = list(ACCESS_KEYCARD_AUTH) //Used to allow for forced connecting to other (not secure) holopads. Anyone can make a call, though.
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 100
max_integrity = 300
armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0)
circuit = /obj/item/circuitboard/machine/holopad
var/list/masters //List of living mobs that use the holopad
var/list/holorays //Holoray-mob link.
var/last_request = 0 //to prevent request spam. ~Carn
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
var/temp = ""
var/list/holo_calls //array of /datum/holocalls
var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
var/obj/item/disk/holodisk/disk //Record disk
var/replay_mode = FALSE //currently replaying a recording
var/loop_mode = FALSE //currently looping a recording
var/record_mode = FALSE //currently recording
var/record_start = 0 //recording start time
var/record_user //user that inititiated the recording
var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
/// List of living mobs that use the holopad
var/list/masters
/// Holoray-mob link
var/list/holorays
/// To prevent request spam. ~Carn
var/last_request = 0
/// Change to change how far the AI can move away from the holopad before deactivating
var/holo_range = 5
/// Array of /datum/holocalls
var/list/holo_calls
/// Currently outgoing holocall, do not modify the datums only check and call the public procs
var/datum/holocall/outgoing_call
/// Record disk
var/obj/item/disk/holodisk/disk
/// Currently replaying a recording
var/replay_mode = FALSE
/// Currently looping a recording
var/loop_mode = FALSE
/// Currently recording
var/record_mode = FALSE
/// Recording start time
var/record_start = 0
/// User that inititiated the recording
var/record_user
/// Replay hologram
var/obj/effect/overlay/holo_pad_hologram/replay_holo
/// Calls will be automatically answered after a couple rings, here for debugging
var/static/force_answer_call = FALSE
// var/static/list/holopads = list()
var/obj/effect/overlay/holoray/ray
var/ringing = FALSE
var/offset = FALSE
var/on_network = TRUE
/// For pads in secure areas; do not allow forced connecting
var/secure = FALSE
/// If we are currently calling another holopad
var/calling = FALSE
/*
/obj/machinery/holopad/secure
name = "secure holopad"
desc = "It's a floor-mounted device for projecting holographic images. This one will refuse to auto-connect incoming calls."
secure = TRUE
/obj/machinery/holopad/secure/Initialize()
. = ..()
var/obj/item/circuitboard/machine/holopad/board = circuit
board.secure = TRUE
board.build_path = /obj/machinery/holopad/secure
*/
/obj/machinery/holopad/tutorial
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
flags_1 = NODECONSTRUCT_1
@@ -121,10 +150,8 @@ GLOBAL_LIST_EMPTY(network_holopads)
return ..()
/obj/machinery/holopad/power_change()
if (powered())
stat &= ~NOPOWER
else
stat |= NOPOWER
. = ..()
if (!powered())
if(replay_mode)
replay_stop()
if(record_mode)
@@ -163,171 +190,150 @@ GLOBAL_LIST_EMPTY(network_holopads)
if(istype(P,/obj/item/disk/holodisk))
if(disk)
to_chat(user,"<span class='notice'>There's already a disk inside [src]</span>")
to_chat(user,"<span class='warning'>There's already a disk inside [src]!</span>")
return
if (!user.transferItemToLoc(P,src))
return
to_chat(user,"<span class='notice'>You insert [P] into [src]</span>")
to_chat(user,"<span class='notice'>You insert [P] into [src].</span>")
disk = P
updateDialog()
return
return ..()
/obj/machinery/holopad/ui_status(mob/user)
if(!is_operational())
return UI_CLOSE
if(outgoing_call && !calling)
return UI_CLOSE
return ..()
/obj/machinery/holopad/ui_interact(mob/living/carbon/human/user) //Carn: Hologram requests.
/obj/machinery/holopad/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Holopad", name)
ui.open()
/obj/machinery/holopad/ui_data(mob/user)
var/list/data = list()
data["calling"] = calling
data["on_network"] = on_network
data["on_cooldown"] = last_request + 200 < world.time ? FALSE : TRUE
data["allowed"] = allowed(user)
data["disk"] = disk ? TRUE : FALSE
data["disk_record"] = disk?.record ? TRUE : FALSE
data["replay_mode"] = replay_mode
data["loop_mode"] = loop_mode
data["record_mode"] = record_mode
data["holo_calls"] = list()
for(var/I in holo_calls)
var/datum/holocall/HC = I
var/list/call_data = list(
caller = HC.user,
connected = HC.connected_holopad == src ? TRUE : FALSE,
ref = REF(HC)
)
data["holo_calls"] += list(call_data)
return data
/obj/machinery/holopad/ui_act(action, list/params)
. = ..()
if(!istype(user))
if(.)
return
if(outgoing_call || user.incapacitated() || !is_operational())
return
user.set_machine(src)
var/dat
if(temp)
dat = temp
else
if(on_network)
dat += "<a href='?src=[REF(src)];AIrequest=1'>Request an AI's presence</a><br>"
dat += "<a href='?src=[REF(src)];Holocall=1'>Call another holopad</a><br>"
if(disk)
if(disk.record)
//Replay
dat += "<a href='?src=[REF(src)];replay_start=1'>Replay disk recording</a><br>"
dat += "<a href='?src=[REF(src)];loop_start=1'>Loop disk recording</a><br>"
//Clear
dat += "<a href='?src=[REF(src)];record_clear=1'>Clear disk recording</a><br>"
switch(action)
if("AIrequest")
if(last_request + 200 < world.time)
last_request = world.time
to_chat(usr, "<span class='info'>You requested an AI's presence.</span>")
var/area/area = get_area(src)
for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
if(!AI.client)
continue
to_chat(AI, "<span class='info'>Your presence is requested at <a href='?src=[REF(AI)];jumptoholopad=[REF(src)]'>\the [area]</a>.</span>")
return TRUE
else
//Record
dat += "<a href='?src=[REF(src)];record_start=1'>Start new recording</a><br>"
//Eject
dat += "<a href='?src=[REF(src)];disk_eject=1'>Eject disk</a><br>"
to_chat(usr, "<span class='info'>A request for AI presence was already sent recently.</span>")
return
if("holocall")
if(outgoing_call)
return
if(usr.loc == loc)
var/list/callnames = list()
for(var/I in GLOB.network_holopads)
var/area/A = get_area(I)
if(A)
LAZYADD(callnames[A], I)
callnames -= get_area(src)
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in sortNames(callnames)
if(QDELETED(usr) || !result || outgoing_call)
return
if(usr.loc == loc)
var/input = text2num(params["headcall"])
var/headcall = input == 1 ? TRUE : FALSE
new /datum/holocall(usr, src, callnames[result], headcall)
calling = TRUE
return TRUE
else
to_chat(usr, "<span class='warning'>You must stand on the holopad to make a call!</span>")
if("connectcall")
var/datum/holocall/call_to_connect = locate(params["holopad"]) in holo_calls
if(!QDELETED(call_to_connect))
call_to_connect.Answer(src)
return TRUE
if("disconnectcall")
var/datum/holocall/call_to_disconnect = locate(params["holopad"]) in holo_calls
if(!QDELETED(call_to_disconnect))
call_to_disconnect.Disconnect(src)
return TRUE
if("disk_eject")
if(disk && !replay_mode)
disk.forceMove(drop_location())
disk = null
return TRUE
if("replay_mode")
if(replay_mode)
replay_stop()
return TRUE
else
replay_start()
return TRUE
if("loop_mode")
loop_mode = !loop_mode
return TRUE
if("record_mode")
if(record_mode)
record_stop()
return TRUE
else
record_start(usr)
return TRUE
if("record_clear")
record_clear()
return TRUE
if("offset")
offset++
if(offset > 4)
offset = FALSE
var/turf/new_turf
if(!offset)
new_turf = get_turf(src)
else
new_turf = get_step(src, GLOB.cardinals[offset])
replay_holo.forceMove(new_turf)
return TRUE
if("hang_up")
if(outgoing_call)
outgoing_call.Disconnect(src)
return TRUE
if(LAZYLEN(holo_calls))
dat += "=====================================================<br>"
if(on_network)
var/one_answered_call = FALSE
var/one_unanswered_call = FALSE
for(var/I in holo_calls)
var/datum/holocall/HC = I
if(HC.connected_holopad != src)
dat += "<a href='?src=[REF(src)];connectcall=[REF(HC)]'>Answer call from [get_area(HC.calling_holopad)]</a><br>"
one_unanswered_call = TRUE
else
one_answered_call = TRUE
if(one_answered_call && one_unanswered_call)
dat += "=====================================================<br>"
//we loop twice for formatting
for(var/I in holo_calls)
var/datum/holocall/HC = I
if(HC.connected_holopad == src)
dat += "<a href='?src=[REF(src)];disconnectcall=[REF(HC)]'>Disconnect call from [HC.user]</a><br>"
var/datum/browser/popup = new(user, "holopad", name, 300, 175)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
//Stop ringing the AI!!
/**
* hangup_all_calls: Disconnects all current holocalls from the holopad
*/
/obj/machinery/holopad/proc/hangup_all_calls()
for(var/I in holo_calls)
var/datum/holocall/HC = I
HC.Disconnect(src)
/obj/machinery/holopad/Topic(href, href_list)
if(..() || isAI(usr))
return
add_fingerprint(usr)
if(!is_operational())
return
if (href_list["AIrequest"])
if(last_request + 200 < world.time)
last_request = world.time
temp = "You requested an AI's presence.<BR>"
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
var/area/area = get_area(src)
for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
if(!AI.client)
continue
to_chat(AI, "<span class='info'>Your presence is requested at <a href='?src=[REF(AI)];jumptoholopad=[REF(src)]'>\the [area]</a>.</span>")
else
temp = "A request for AI presence was already sent recently.<BR>"
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
else if(href_list["Holocall"])
if(outgoing_call)
return
temp = "You must stand on the holopad to make a call!<br>"
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
if(usr.loc == loc)
var/list/callnames = list()
for(var/I in GLOB.network_holopads)
var/area/A = get_area(I)
if(A)
LAZYADD(callnames[A], I)
callnames -= get_area(src)
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
if(QDELETED(usr) || !result || outgoing_call)
return
if(usr.loc == loc)
temp = "Dialing...<br>"
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
new /datum/holocall(usr, src, callnames[result])
else if(href_list["connectcall"])
var/datum/holocall/call_to_connect = locate(href_list["connectcall"])
if(!QDELETED(call_to_connect))
call_to_connect.Answer(src)
temp = ""
else if(href_list["disconnectcall"])
var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"])
if(!QDELETED(call_to_disconnect))
call_to_disconnect.Disconnect(src)
temp = ""
else if(href_list["mainmenu"])
temp = ""
if(outgoing_call)
outgoing_call.Disconnect()
else if(href_list["disk_eject"])
if(disk && !replay_mode)
disk.forceMove(drop_location())
disk = null
else if(href_list["replay_stop"])
replay_stop()
else if(href_list["replay_start"])
replay_start()
else if(href_list["loop_start"])
loop_mode = TRUE
replay_start()
else if(href_list["record_start"])
record_start(usr)
else if(href_list["record_stop"])
record_stop()
else if(href_list["record_clear"])
record_clear()
else if(href_list["offset"])
offset++
if (offset > 4)
offset = FALSE
var/turf/new_turf
if (!offset)
new_turf = get_turf(src)
else
new_turf = get_step(src, GLOB.cardinals[offset])
replay_holo.forceMove(new_turf)
updateDialog()
//do not allow AIs to answer calls or people will use it to meta the AI sattelite
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user)
if (!istype(user))
@@ -366,6 +372,9 @@ GLOBAL_LIST_EMPTY(network_holopads)
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
HC.Answer(src)
break
if(!secure) //HC.head_call &&
HC.Answer(src)
break
if(outgoing_call)
HC.Disconnect(src)//can't answer calls while calling
else
@@ -412,17 +421,17 @@ GLOBAL_LIST_EMPTY(network_holopads)
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
. = ..()
if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios.
for(var/mob/living/silicon/ai/master in masters)
if(masters[master] && speaker != master)
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
for(var/I in holo_calls)
var/datum/holocall/HC = I
if(HC.connected_holopad == src && speaker != HC.hologram)
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode, source)
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
if(outgoing_call && speaker == outgoing_call.user)
outgoing_call.hologram.say(raw_message)
@@ -449,7 +458,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
else
icon_state = "holopad0"
/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h)
/obj/machinery/holopad/proc/set_holo(mob/living/user, obj/effect/overlay/holo_pad_hologram/h)
LAZYSET(masters, user, h)
LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc))
var/mob/living/silicon/ai/AI = user
@@ -504,7 +513,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
else
return FALSE
/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf, direction)
/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf)
if(LAZYLEN(masters) && masters[user])
var/obj/effect/overlay/holo_pad_hologram/holo = masters[user]
var/transfered = FALSE
@@ -516,8 +525,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
transfered = TRUE
//All is good.
holo.forceMove(new_turf)
if(direction)
holo.setDir(direction)
if(!transfered)
update_holoray(user,new_turf)
return TRUE
@@ -568,22 +575,15 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(!replay_mode)
replay_mode = TRUE
replay_holo = setup_replay_holo(disk.record)
temp = "Replaying...<br>"
temp += "<A href='?src=[REF(src)];offset=1'>Change offset</A><br>"
temp += "<A href='?src=[REF(src)];replay_stop=1'>End replay</A>"
SetLightsAndPower()
replay_entry(1)
return
/obj/machinery/holopad/proc/replay_stop()
if(replay_mode)
replay_mode = FALSE
loop_mode = FALSE
offset = FALSE
temp = null
QDEL_NULL(replay_holo)
SetLightsAndPower()
updateDialog()
/obj/machinery/holopad/proc/record_start(mob/living/user)
if(!user || !disk || disk.record)
@@ -593,8 +593,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
record_start = world.time
record_user = user
disk.record.set_caller_image(user)
temp = "Recording...<br>"
temp += "<A href='?src=[REF(src)];record_stop=1'>End recording.</A>"
/obj/machinery/holopad/proc/record_message(mob/living/speaker,message,language)
if(!record_mode)
@@ -641,7 +639,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(replay_holo)
replay_holo.say(message)
if(HOLORECORD_SOUND)
playsound(src,entry[2],50,1)
playsound(src,entry[2],50,TRUE)
if(HOLORECORD_DELAY)
addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2])
return
@@ -660,14 +658,11 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/holopad/proc/record_stop()
if(record_mode)
record_mode = FALSE
temp = null
record_user = null
updateDialog()
/obj/machinery/holopad/proc/record_clear()
if(disk && disk.record)
QDEL_NULL(disk.record)
updateDialog()
/obj/effect/overlay/holo_pad_hologram
initial_language_holder = /datum/language_holder/universal
+9 -10
View File
@@ -6,14 +6,12 @@
circuit = /obj/item/circuitboard/machine/hypnochair
density = TRUE
opacity = 0
ui_x = 375
ui_y = 480
var/mob/living/carbon/victim = null ///Keeps track of the victim to apply effects if it teleports away
var/interrogating = FALSE ///Is the device currently interrogating someone?
var/start_time = 0 ///Time when the interrogation was started, to calculate effect in case of interruption
var/trigger_phrase = "" ///Trigger phrase to implant
var/timerid = 0 ///Timer ID for interrogations
var/message_cooldown = 0 ///Cooldown for breakout message
/obj/machinery/hypnochair/Initialize()
@@ -25,24 +23,24 @@
if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))
update_icon()
return
if(default_pry_open(I))
return
if(default_deconstruction_crowbar(I))
return
return ..()
/obj/machinery/hypnochair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/hypnochair/ui_state(mob/user)
return GLOB.notcontained_state
/obj/machinery/hypnochair/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "HypnoChair", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "HypnoChair", name)
ui.open()
/obj/machinery/hypnochair/ui_data()
var/list/data = list()
data["occupied"] = occupant ? TRUE : FALSE
data["occupied"] = occupant ? 1 : 0
data["open"] = state_open
data["interrogating"] = interrogating
@@ -201,3 +199,4 @@
if(!(L.mobility_flags & MOBILITY_STAND))
return
close_machine(target)
+7 -5
View File
@@ -282,12 +282,14 @@
ui_interact(user)
to_chat(user, "<span class='notice'>[src] projects a display onto your retina.</span>")
/obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "LaunchpadRemote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
ui.open()
/obj/item/launchpad_remote/ui_state(mob/user)
return GLOB.inventory_state
/obj/item/launchpad_remote/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "LaunchpadRemote")
ui.open()
ui.set_autoupdate(TRUE)
/obj/item/launchpad_remote/ui_data(mob/user)
@@ -4,6 +4,15 @@
#define POPUP_ANIM_TIME 5
#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad
#define TURRET_FLAG_SHOOT_ALL_REACT (1<<0) // The turret gets pissed off and shoots at people nearby (unless they have sec access!)
#define TURRET_FLAG_AUTH_WEAPONS (1<<1) // Checks if it can shoot people that have a weapon they aren't authorized to have
#define TURRET_FLAG_SHOOT_CRIMINALS (1<<2) // Checks if it can shoot people that are wanted
#define TURRET_FLAG_SHOOT_ALL (1<<3) // The turret gets pissed off and shoots at people nearby (unless they have sec access!)
#define TURRET_FLAG_SHOOT_ANOMALOUS (1<<4) // Checks if it can shoot at unidentified lifeforms (ie xenos)
#define TURRET_FLAG_SHOOT_UNSHIELDED (1<<5) // Checks if it can shoot people that aren't mindshielded and who arent heads
#define TURRET_FLAG_SHOOT_BORGS (1<<6) // checks if it can shoot cyborgs
#define TURRET_FLAG_SHOOT_HEADS (1<<7) // checks if it can shoot at heads of staff
/obj/machinery/porta_turret
name = "turret"
icon = 'icons/obj/turrets.dmi'
@@ -15,70 +24,79 @@
use_power = IDLE_POWER_USE //this turret uses and requires power
idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power
active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power
req_access = list(ACCESS_SEC_DOORS)
req_access = list(ACCESS_SECURITY) /// Only people with Security access
power_channel = EQUIP //drains power from the EQUIPMENT channel
speed_process = TRUE
var/base_icon_state = "standard"
var/scan_range = 7
var/atom/base = null //for turrets inside other objects
var/raised = 0 //if the turret cover is "open" and the turret is raised
var/raising= 0 //if the turret is currently opening or closing its cover
max_integrity = 160 //the turret's health
integrity_failure = 0.5
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
var/locked = TRUE //if the turret's behaviour control access is locked
var/controllock = FALSE //if the turret responds to control panels
var/installation = /obj/item/gun/energy/e_gun/turret //the type of weapon installed by default
/// Base turret icon state
var/base_icon_state = "standard"
/// Scan range of the turret for locating targets
var/scan_range = 7
/// For turrets inside other objects
var/atom/base = null
/// If the turret cover is "open" and the turret is raised
var/raised = FALSE
/// If the turret is currently opening or closing its cover
var/raising = FALSE
/// If the turret's behaviour control access is locked
var/locked = TRUE
/// If the turret responds to control panels
var/controllock = FALSE
/// The type of weapon installed by default
var/installation = /obj/item/gun/energy/e_gun/turret
/// What stored gun is in the turret
var/obj/item/gun/stored_gun = null
var/gun_charge = 0 //the charge of the gun when retrieved from wreckage
/// The charge of the gun when retrieved from wreckage
var/gun_charge = 0
/// In which mode is turret in, stun or lethal
var/mode = TURRET_STUN
var/stun_projectile = null //stun mode projectile type
/// Stun mode projectile type
var/stun_projectile = null
/// Sound of stun projectile
var/stun_projectile_sound
var/nonlethal_projectile //projectile to use in stun mode when the target is resting, if any
/// Projectile to use in stun mode when the target is resting, if any
var/nonlethal_projectile
/// Sound of stun projectile wen the target is resting, optional
var/nonlethal_projectile_sound
var/lethal_projectile = null //lethal mode projectile type
/// Lethal mode projectile type
var/lethal_projectile = null
/// Sound of lethal projectile
var/lethal_projectile_sound
var/reqpower = 500 //power needed per shot
var/always_up = 0 //Will stay active
var/has_cover = 1 //Hides the cover
var/obj/machinery/porta_turret_cover/cover = null //the cover that is covering this turret
var/last_fired = 0 //world.time the turret last fired
var/shot_delay = 15 //ticks until next shot (1.5 ?)
var/shot_stagger = 0 // sleep() shots to stagger attacks
var/check_records = 1 //checks if it can use the security records
var/criminals = 1 //checks if it can shoot people on arrest
var/auth_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have
var/stun_all = 0 //if this is active, the turret shoots everything that isn't security or head of staff
var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos)
var/shoot_unloyal = 0 //checks if it can shoot people that aren't loyalty implantd
var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)
var/on = TRUE //determines if the turret is on
var/list/faction = list("turret") // Same faction mobs will never be shot at, no matter the other settings
var/datum/effect_system/spark_spread/spark_system //the spark system, used for generating... sparks?
/// Power needed per shot
var/reqpower = 500
/// Will stay active
var/always_up = FALSE
/// Hides the cover
var/has_cover = TRUE
/// The cover that is covering this turret
var/obj/machinery/porta_turret_cover/cover = null
/// World.time the turret last fired
var/last_fired = 0
/// Ticks until next shot (1.5 ?)
var/shot_delay = 15
/// Turret flags about who is turret allowed to shoot
var/turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS
/// Determines if the turret is on
var/on = TRUE
/// Same faction mobs will never be shot at, no matter the other settings
var/list/faction = list("turret")
/// The spark system, used for generating... sparks?
var/datum/effect_system/spark_spread/spark_system
/// Linked turret control panel of the turret
var/obj/machinery/turretid/cp = null
var/wall_turret_direction //The turret will try to shoot from a turf in that direction when in a wall
var/manual_control = FALSE //
/// The turret will try to shoot from a turf in that direction when in a wall
var/wall_turret_direction
/// If the turret is manually controlled
var/manual_control = FALSE
/// Action button holder for quitting manual control
var/datum/action/turret_quit/quit_action
/// Action button holder for switching between turret modes when manually controlling
var/datum/action/turret_toggle/toggle_action
/// Mob that is remotely controlling the turret
var/mob/remote_controller
/// MISSING:
var/shot_stagger = 0
/obj/machinery/porta_turret/Initialize()
. = ..()
@@ -100,6 +118,27 @@
if(!has_cover)
INVOKE_ASYNC(src, .proc/popUp)
/obj/machinery/porta_turret/proc/toggle_on(var/set_to)
var/current = on
if (!isnull(set_to))
on = set_to
else
on = !on
if (current != on)
check_should_process()
if (!on)
popDown()
/obj/machinery/porta_turret/proc/check_should_process()
if (datum_flags & DF_ISPROCESSING)
if (!on || !anchored || (stat & BROKEN) || !powered())
//end_processing()
STOP_PROCESSING(SSmachines, src)
else
if (on && anchored && !(stat & BROKEN) && powered())
START_PROCESSING(SSmachines, src)
//begin_processing()
/obj/machinery/porta_turret/update_icon_state()
if(!anchored)
icon_state = "turretCover"
@@ -119,7 +158,6 @@
else
icon_state = "[base_icon_state]_unpowered"
/obj/machinery/porta_turret/proc/setup(obj/item/gun/turret_gun)
if(stored_gun)
qdel(stored_gun)
@@ -160,83 +198,88 @@
remove_control()
return ..()
/obj/machinery/porta_turret/ui_interact(mob/user)
. = ..()
var/dat
dat += "Status: <a href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</a><br>"
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<br>"
/obj/machinery/porta_turret/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PortableTurret", name)
ui.open()
if(!locked)
dat += "Check for Weapon Authorization: <A href='?src=[REF(src)];operation=authweapon'>[auth_weapons ? "Yes" : "No"]</A><BR>"
dat += "Check Security Records: <A href='?src=[REF(src)];operation=checkrecords'>[check_records ? "Yes" : "No"]</A><BR>"
dat += "Neutralize Identified Criminals: <A href='?src=[REF(src)];operation=shootcrooks'>[criminals ? "Yes" : "No"]</A><BR>"
dat += "Neutralize All Non-Security and Non-Command Personnel: <A href='?src=[REF(src)];operation=shootall'>[stun_all ? "Yes" : "No"]</A><BR>"
dat += "Neutralize All Unidentified Life Signs: <A href='?src=[REF(src)];operation=checkxenos'>[check_anomalies ? "Yes" : "No"]</A><BR>"
dat += "Neutralize All Non-Loyalty Implanted Personnel: <A href='?src=[REF(src)];operation=checkloyal'>[shoot_unloyal ? "Yes" : "No"]</A><BR>"
/obj/machinery/porta_turret/ui_data(mob/user)
var/list/data = list(
"locked" = locked,
"on" = on,
"check_weapons" = turret_flags & TURRET_FLAG_AUTH_WEAPONS,
"neutralize_criminals" = turret_flags & TURRET_FLAG_SHOOT_CRIMINALS,
"neutralize_all" = turret_flags & TURRET_FLAG_SHOOT_ALL,
"neutralize_unidentified" = turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS,
"neutralize_nonmindshielded" = turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED,
"neutralize_cyborgs" = turret_flags & TURRET_FLAG_SHOOT_BORGS,
"ignore_heads" = turret_flags & TURRET_FLAG_SHOOT_HEADS,
"manual_control" = manual_control,
"silicon_user" = FALSE,
"allow_manual_control" = FALSE,
"lasertag_turret" = istype(src, /obj/machinery/porta_turret/lasertag),
)
if(issilicon(user))
data["silicon_user"] = TRUE
if(!manual_control)
var/mob/living/silicon/S = user
if(S.hack_software)
dat += "Assume direct control : <a href='?src=[REF(src)];operation=manual'>Manual Control</a><br>"
else
dat += "Warning! Remote control protocol enabled.<br>"
data["allow_manual_control"] = TRUE
return data
var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300)
popup.set_content(dat)
popup.open()
/obj/machinery/porta_turret/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
if(href_list["power"] && !locked)
if(anchored) //you can't turn a turret on/off if it's not anchored/secured
on = !on //toggle on/off
else
to_chat(usr, "<span class='notice'>It has to be secured first!</span>")
interact(usr)
/obj/machinery/porta_turret/ui_act(action, list/params)
. = ..()
if(.)
return
if(href_list["operation"])
switch(href_list["operation"]) //toggles customizable behavioural protocols
if("authweapon")
auth_weapons = !auth_weapons
if("checkrecords")
check_records = !check_records
if("shootcrooks")
criminals = !criminals
if("shootall")
stun_all = !stun_all
if("checkxenos")
check_anomalies = !check_anomalies
if("checkloyal")
shoot_unloyal = !shoot_unloyal
if("manual")
if(issilicon(usr) && !manual_control)
give_control(usr)
interact(usr)
switch(action)
if("power")
if(anchored)
toggle_on()
return TRUE
else
to_chat(usr, "<span class='warning'>It has to be secured first!</span>")
if("authweapon")
turret_flags ^= TURRET_FLAG_AUTH_WEAPONS
return TRUE
if("shootcriminals")
turret_flags ^= TURRET_FLAG_SHOOT_CRIMINALS
return TRUE
if("shootall")
turret_flags ^= TURRET_FLAG_SHOOT_ALL
return TRUE
if("checkxenos")
turret_flags ^= TURRET_FLAG_SHOOT_ANOMALOUS
return TRUE
if("checkloyal")
turret_flags ^= TURRET_FLAG_SHOOT_UNSHIELDED
return TRUE
if("shootborgs")
turret_flags ^= TURRET_FLAG_SHOOT_BORGS
return TRUE
if("shootheads")
turret_flags ^= TURRET_FLAG_SHOOT_HEADS
return TRUE
if("manual")
if(!issilicon(usr))
return
give_control(usr)
return TRUE
/obj/machinery/porta_turret/ui_host(mob/user)
if(has_cover && cover)
return cover
if(base)
return base
return src
/obj/machinery/porta_turret/power_change()
if(!anchored)
. = ..()
if(!anchored || (stat & BROKEN) || !powered())
update_icon()
remove_control()
return
if(stat & BROKEN)
update_icon()
remove_control()
else
if( powered() )
stat &= ~NOPOWER
update_icon()
else
spawn(rand(0, 15))
stat |= NOPOWER
remove_control()
update_icon()
check_should_process()
/obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params)
if(stat & BROKEN)
@@ -284,8 +327,10 @@
locked = !locked
to_chat(user, "<span class='notice'>Controls are now [locked ? "locked" : "unlocked"].</span>")
else
to_chat(user, "<span class='notice'>Access denied.</span>")
to_chat(user, "<span class='alert'>Access denied.</span>")
else if(istype(I, /obj/item/multitool) && !locked)
if(!multitool_check_buffer(user, I))
return
var/obj/item/multitool/M = I
M.buffer = src
to_chat(user, "<span class='notice'>You add [src] to multitool buffer.</span>")
@@ -293,19 +338,17 @@
return ..()
/obj/machinery/porta_turret/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
to_chat(user, "<span class='warning'>You short out [src]'s threat assessment circuits.</span>")
visible_message("[src] hums oddly...")
audible_message("<span class='hear'>[src] hums oddly...</span>")
obj_flags |= EMAGGED
controllock = TRUE
on = FALSE //turns off the turret temporarily
toggle_on(FALSE) //turns off the turret temporarily
update_icon()
sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
on = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
return TRUE
//6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 6 SECONDS)
//turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
/obj/machinery/porta_turret/emp_act(severity)
. = ..()
@@ -314,63 +357,41 @@
if(on)
//if the turret is on, the EMP no matter how severe disables the turret for a while
//and scrambles its settings, with a slight chance of having an emag effect
check_records = pick(0, 1)
criminals = pick(0, 1)
auth_weapons = pick(0, 1)
stun_all = pick(0, 0, 0, 0, 1) //stun_all is a pretty big deal, so it's least likely to get turned on
if(prob(50))
turret_flags |= TURRET_FLAG_SHOOT_CRIMINALS
if(prob(50))
turret_flags |= TURRET_FLAG_AUTH_WEAPONS
if(prob(20))
turret_flags |= TURRET_FLAG_SHOOT_ALL // Shooting everyone is a pretty big deal, so it's least likely to get turned on
on = FALSE
toggle_on(FALSE)
remove_control()
spawn(rand(60,600))
if(!on)
on = TRUE
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), rand(60,600))
/obj/machinery/porta_turret/take_damage(damage, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
. = ..()
if(.) //damage received
if(. && obj_integrity > 0) //damage received
if(prob(30))
spark_system.start()
if(on && !attacked && !(obj_flags & EMAGGED))
attacked = TRUE
if(on && !(turret_flags & TURRET_FLAG_SHOOT_ALL_REACT) && !(obj_flags & EMAGGED))
turret_flags |= TURRET_FLAG_SHOOT_ALL_REACT
addtimer(CALLBACK(src, .proc/reset_attacked), 60)
/obj/machinery/porta_turret/proc/reset_attacked()
attacked = FALSE
turret_flags &= ~TURRET_FLAG_SHOOT_ALL_REACT
/obj/machinery/porta_turret/deconstruct(disassembled = TRUE)
qdel(src)
/obj/machinery/porta_turret/obj_break(damage_flag)
if(!(flags_1 & NODECONSTRUCT_1) && !(stat & BROKEN))
stat |= BROKEN //enables the BROKEN bit
. = ..()
if(.)
power_change()
invisibility = 0
spark_system.start() //creates some sparks because they look cool
qdel(cover) //deletes the cover - no need on keeping it there!
//turret healing
/obj/machinery/porta_turret/examine(mob/user)
. = ..()
if(obj_integrity < max_integrity)
. += "<span class='notice'>Use a welder to fix it.</span>"
/obj/machinery/porta_turret/welder_act(mob/living/user, obj/item/I)
. = TRUE
if(obj_integrity < max_integrity)
if(!I.tool_start_check(user, amount=0))
return
user.visible_message("[user] is welding the turret.", \
"<span class='notice'>You begin repairing the turret...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 40, volume=50))
obj_integrity = max_integrity
user.visible_message("[user.name] has repaired [src].", \
"<span class='notice'>You finish repairing the turret.</span>")
else
to_chat(user, "<span class='notice'>The turret doesn't need repairing.</span>")
/obj/machinery/porta_turret/process()
//the main machinery process
if(cover == null && anchored) //if it has no cover and is anchored
@@ -382,35 +403,43 @@
cover.parent_turret = src //assign the cover its parent_turret, which would be this (src)
if(!on || (stat & (NOPOWER|BROKEN)) || manual_control)
return
return PROCESS_KILL
var/list/targets = list()
for(var/mob/A in view(scan_range, base))
if(A.invisibility > SEE_INVISIBLE_LIVING)
continue
if(check_anomalies)//if it's set to check for simple animals
if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS)//if it's set to check for simple animals
if(isanimal(A))
var/mob/living/simple_animal/SA = A
if(SA.stat || in_faction(SA)) //don't target if dead or in faction
continue
targets += SA
if(issilicon(A))
var/mob/living/silicon/sillycone = A
if(sillycone.stat || in_faction(sillycone))
continue
if(issilicon(A))
var/mob/living/silicon/sillycone = A
if(ispAI(A))
continue
if((turret_flags & TURRET_FLAG_SHOOT_BORGS) && sillycone.stat != DEAD && iscyborg(sillycone))
targets += sillycone
continue
if(sillycone.stat || in_faction(sillycone))
continue
if(iscyborg(sillycone))
var/mob/living/silicon/robot/sillyconerobot = A
if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE)
continue
if(iscyborg(sillycone))
var/mob/living/silicon/robot/sillyconerobot = A
if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE)
continue
targets += sillycone
if(iscarbon(A))
else if(iscarbon(A))
var/mob/living/carbon/C = A
//If not emagged, only target non downed carbons
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || (C.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)))//CIT CHANGE - replaces check for lying with check for recoveringstam
//If not emagged, only target carbons that can use items
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || !(C.mobility_flags & MOBILITY_USE)))
continue
//If emagged, target all but dead carbons
@@ -419,12 +448,13 @@
//if the target is a human and not in our faction, analyze threat level
if(ishuman(C) && !in_faction(C))
if(assess_perp(C) >= 4)
targets += C
else if(check_anomalies) //non humans who are not simple animals (xenos etc)
else if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) //non humans who are not simple animals (xenos etc)
if(!in_faction(C))
targets += C
for(var/A in GLOB.mechas_list)
if((get_dist(A, base) < scan_range) && can_see(base, A, scan_range))
var/obj/mecha/Mech = A
@@ -432,6 +462,10 @@
if(assess_perp(Mech.occupant) >= 4)
targets += Mech
if((turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) && GLOB.blobs.len && (mode == TURRET_LETHAL))
for(var/obj/structure/blob/B in view(scan_range, base))
targets += B
if(targets.len)
tryToShootAt(targets)
else if(!always_up)
@@ -488,36 +522,37 @@
if(obj_flags & EMAGGED)
return 10 //if emagged, always return 10.
if((stun_all || attacked) && !allowed(perp))
if((turret_flags & (TURRET_FLAG_SHOOT_ALL | TURRET_FLAG_SHOOT_ALL_REACT)) && !allowed(perp))
//if the turret has been attacked or is angry, target all non-sec people
if(!allowed(perp))
return 10
if(auth_weapons) //check for weapon authorization
if(turret_flags & TURRET_FLAG_AUTH_WEAPONS) //check for weapon authorization
if(isnull(perp.wear_id) || istype(perp.wear_id.GetID(), /obj/item/card/id/syndicate))
if(allowed(perp)) //if the perp has security access, return 0
return 0
if(perp.is_holding_item_of_type(/obj/item/gun) || perp.is_holding_item_of_type(/obj/item/melee/baton))
threatcount += 4
if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee/baton))
threatcount += 2
if(check_records) //if the turret can check the records, check if they are set to *Arrest* on records
if(turret_flags & TURRET_FLAG_SHOOT_CRIMINALS) //if the turret can check the records, check if they are set to *Arrest* on records
var/perpname = perp.get_face_name(perp.get_id_name())
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
if(!R || (R.fields["criminal"] == "*Arrest*"))
threatcount += 4
if(shoot_unloyal)
if (!HAS_TRAIT(perp, TRAIT_MINDSHIELD))
threatcount += 4
if((turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED) && (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)))
threatcount += 4
// If we aren't shooting heads then return a threatcount of 0
if (!(turret_flags & TURRET_FLAG_SHOOT_HEADS) && (perp.get_assignment() in GLOB.command_positions))
return 0
return threatcount
/obj/machinery/porta_turret/proc/in_faction(mob/target)
for(var/faction1 in faction)
if(faction1 in target.faction)
@@ -563,15 +598,14 @@
T = closer
break
var/mob/living/carbon/C
if(iscarbon(target))
C = target
update_icon()
var/obj/item/projectile/A
//any emagged turrets drains 2x power and uses a different projectile?
if(mode == TURRET_STUN)
if(nonlethal_projectile && C && C.resting)
var/mob/living/carbon/C = null
if(iscarbon(target))
C = target
if(nonlethal_projectile && C?.resting)
use_power(reqpower*0.5)
A = new nonlethal_projectile(T)
playsound(loc, nonlethal_projectile_sound, 75, 1)
@@ -582,7 +616,7 @@
else
use_power(reqpower * 2)
A = new lethal_projectile(T)
playsound(loc, lethal_projectile_sound, 75, 1)
playsound(loc, lethal_projectile_sound, 75, TRUE)
//Shooting Code:
@@ -592,16 +626,15 @@
A.fire()
return A
/obj/machinery/porta_turret/proc/setState(on, mode)
/obj/machinery/porta_turret/proc/setState(on, mode, shoot_cyborgs)
if(controllock)
return
src.on = on
if(!on)
popDown()
shoot_cyborgs ? (turret_flags |= TURRET_FLAG_SHOOT_BORGS) : (turret_flags &= ~TURRET_FLAG_SHOOT_BORGS)
toggle_on(on)
src.mode = mode
power_change()
/datum/action/turret_toggle
name = "Toggle Mode"
icon_icon = 'icons/mob/actions/actions_mecha.dmi'
@@ -685,7 +718,15 @@
/obj/machinery/porta_turret/syndicate/ComponentInitialize()
. = ..()
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
// AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) //this one or ^ one?
/obj/machinery/porta_turret/syndicate/setup()
return
/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp)
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/energy
icon_state = "standard_stun"
@@ -698,7 +739,6 @@
lethal_projectile_sound = 'sound/weapons/laser.ogg'
desc = "An energy blaster auto-turret."
/obj/machinery/porta_turret/syndicate/energy/heavy
icon_state = "standard_stun"
base_icon_state = "standard"
@@ -715,14 +755,13 @@
integrity_failure = 0.08
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
/obj/machinery/porta_turret/syndicate/setup()
return
/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp)
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/energy/raven
stun_projectile = /obj/item/projectile/beam/laser
stun_projectile_sound = 'sound/weapons/laser.ogg'
faction = list("neutral","silicon","turret")
/obj/machinery/porta_turret/syndicate/pod
integrity_failure = 0.5
max_integrity = 40
stun_projectile = /obj/item/projectile/bullet/syndicate_turret
lethal_projectile = /obj/item/projectile/bullet/syndicate_turret
@@ -749,6 +788,7 @@
faction = list("silicon")
nonlethal_projectile = /obj/item/projectile/beam/disabler
nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS | TURRET_FLAG_SHOOT_HEADS
/obj/machinery/porta_turret/ai/assess_perp(mob/living/carbon/human/perp)
return 10 //AI turrets shoot at everything not in their faction
@@ -804,6 +844,7 @@
/obj/machinery/porta_turret/centcom_shuttle/weak
max_integrity = 120
integrity_failure = 0.5
name = "Old Laser Turret"
desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else."
stun_projectile = /obj/item/projectile/beam/weak/penetrator
@@ -817,7 +858,6 @@
stun_projectile_sound = 'sound/weapons/gunshot.ogg'
desc = "A ballistic machine gun auto-turret."
////////////////////////
//Turret Control Panel//
////////////////////////
@@ -828,14 +868,22 @@
icon = 'icons/obj/machines/turret_control.dmi'
icon_state = "control_standby"
density = FALSE
var/enabled = 1
var/lethal = 0
var/locked = TRUE
var/control_area = null //can be area name, path or nothing.
var/ailock = 0 // AI cannot use this
req_access = list(ACCESS_AI_UPLOAD)
var/list/obj/machinery/porta_turret/turrets = list()
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/// Variable dictating if linked turrets are active and will shoot targets
var/enabled = TRUE
/// Variable dictating if linked turrets will shoot lethal projectiles
var/lethal = FALSE
/// Variable dictating if the panel is locked, preventing changes to turret settings
var/locked = TRUE
/// An area in which linked turrets are located, it can be an area name, path or nothing
var/control_area = null
/// AI is unable to use this machine if set to TRUE
var/ailock = FALSE
/// Variable dictating if linked turrets will shoot cyborgs
var/shoot_cyborgs = FALSE
/// List of all linked turrets
var/list/turrets = list()
/obj/machinery/turretid/Initialize(mapload, ndir = 0, built = 0)
. = ..()
@@ -868,112 +916,111 @@
T.cp = src
/obj/machinery/turretid/examine(mob/user)
. = ..()
if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
. += "<span class='notice'>Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets.</span>"
. += "<span class='notice'>Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"].</span>"
. += ..()
if(issilicon(user) && !(stat & BROKEN))
. += {"<span class='notice'>Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets.</span>
<span class='notice'>Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"].</span>"}
/obj/machinery/turretid/attackby(obj/item/I, mob/user, params)
if(stat & BROKEN)
return
if (istype(I, /obj/item/multitool))
if(!multitool_check_buffer(user, I))
return
var/obj/item/multitool/M = I
if(M.buffer && istype(M.buffer, /obj/machinery/porta_turret))
turrets |= M.buffer
to_chat(user, "You link \the [M.buffer] with \the [src]")
to_chat(user, "<span class='notice'>You link \the [M.buffer] with \the [src].</span>")
return
if (hasSiliconAccessInArea(user))
if (issilicon(user))
return attack_hand(user)
if ( get_dist(src, user) == 0 ) // trying to unlock the interface
if (allowed(usr))
if(obj_flags & EMAGGED)
to_chat(user, "<span class='notice'>The turret control is unresponsive.</span>")
to_chat(user, "<span class='warning'>The turret control is unresponsive!</span>")
return
locked = !locked
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] the panel.</span>")
if (locked)
if (user.machine==src)
user.unset_machine()
user << browse(null, "window=turretid")
else
if (user.machine==src)
attack_hand(user)
else
to_chat(user, "<span class='warning'>Access denied.</span>")
to_chat(user, "<span class='alert'>Access denied.</span>")
/obj/machinery/turretid/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
to_chat(user, "<span class='danger'>You short out the turret controls' access analysis module.</span>")
to_chat(user, "<span class='notice'>You short out the turret controls' access analysis module.</span>")
obj_flags |= EMAGGED
locked = FALSE
if(user && user.machine == src)
attack_hand(user)
return TRUE
/obj/machinery/turretid/attack_ai(mob/user)
if(!ailock || IsAdminGhost(user))
return attack_hand(user)
else
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>")
to_chat(user, "<span class='warning'>There seems to be a firewall preventing you from accessing this device!</span>")
/obj/machinery/turretid/ui_interact(mob/user)
/obj/machinery/turretid/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TurretControl", name)
ui.open()
/obj/machinery/turretid/ui_data(mob/user)
var/list/data = list()
data["locked"] = locked
data["siliconUser"] = hasSiliconAccessInArea(user) || IsAdminGhost(user)
data["enabled"] = enabled
data["lethal"] = lethal
data["shootCyborgs"] = shoot_cyborgs
return data
/obj/machinery/turretid/ui_act(action, list/params)
. = ..()
if ( get_dist(src, user) > 0 )
if ( !(hasSiliconAccessInArea(user) || IsAdminGhost(user)) )
to_chat(user, "<span class='notice'>You are too far away.</span>")
user.unset_machine()
user << browse(null, "window=turretid")
return
var/t = ""
if(locked && !(hasSiliconAccessInArea(user) || IsAdminGhost(user)))
t += "<div class='notice icon'>Swipe ID card to unlock interface</div>"
else
if(!hasSiliconAccessInArea(user) && !IsAdminGhost(user))
t += "<div class='notice icon'>Swipe ID card to lock interface</div>"
t += "Turrets [enabled?"activated":"deactivated"] - <A href='?src=[REF(src)];toggleOn=1'>[enabled?"Disable":"Enable"]?</a><br>"
t += "Currently set for [lethal?"lethal":"stun repeatedly"] - <A href='?src=[REF(src)];toggleLethal=1'>Change to [lethal?"Stun repeatedly":"Lethal"]?</a><br>"
var/datum/browser/popup = new(user, "turretid", "Turret Control Panel ([get_area_name(src, TRUE)])")
popup.set_content(t)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
/obj/machinery/turretid/Topic(href, href_list)
if(..())
if(.)
return
if (locked)
if(!(hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
to_chat(usr, "Control panel is locked!")
return
if (href_list["toggleOn"])
toggle_on()
else if (href_list["toggleLethal"])
toggle_lethal()
attack_hand(usr)
/obj/machinery/turretid/proc/toggle_lethal()
switch(action)
if("lock")
if(!hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
return
if((obj_flags & EMAGGED) || (stat & BROKEN))
to_chat(usr, "<span class='warning'>The turret control is unresponsive!</span>")
return
locked = !locked
return TRUE
if("power")
toggle_on(usr)
return TRUE
if("mode")
toggle_lethal(usr)
return TRUE
if("shoot_silicons")
shoot_silicons(usr)
return TRUE
/obj/machinery/turretid/proc/toggle_lethal(mob/user)
lethal = !lethal
add_hiddenprint(user)
log_combat(user, src, "[lethal ? "enabled" : "disabled"] lethals on")
updateTurrets()
/obj/machinery/turretid/proc/toggle_on()
/obj/machinery/turretid/proc/toggle_on(mob/user)
enabled = !enabled
add_hiddenprint(user)
log_combat(user, src, "[enabled ? "enabled" : "disabled"]")
updateTurrets()
/obj/machinery/turretid/proc/shoot_silicons(mob/user)
shoot_cyborgs = !shoot_cyborgs
add_hiddenprint(user)
log_combat(user, src, "[shoot_cyborgs ? "Shooting Borgs" : "Not Shooting Borgs"]")
updateTurrets()
/obj/machinery/turretid/proc/updateTurrets()
for (var/obj/machinery/porta_turret/aTurret in turrets)
aTurret.setState(enabled, lethal)
update_icon()
/obj/machinery/turretid/power_change()
..()
aTurret.setState(enabled, lethal, shoot_cyborgs)
update_icon()
/obj/machinery/turretid/update_icon_state()
@@ -1051,11 +1098,7 @@
/obj/machinery/porta_turret/lasertag
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
check_records = 0
criminals = 0
auth_weapons = 1
stun_all = 0
check_anomalies = 0
turret_flags = TURRET_FLAG_AUTH_WEAPONS
var/team_color
/obj/machinery/porta_turret/lasertag/assess_perp(mob/living/carbon/human/perp)
@@ -1083,20 +1126,14 @@
if(properties["team_color"])
team_color = properties["team_color"]
/obj/machinery/porta_turret/lasertag/ui_interact(mob/user)
. = ..()
/obj/machinery/porta_turret/lasertag/ui_status(mob/user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(team_color == "blue" && istype(H.wear_suit, /obj/item/clothing/suit/redtag))
return
return UI_CLOSE
if(team_color == "red" && istype(H.wear_suit, /obj/item/clothing/suit/bluetag))
return
var/dat = "Status: <a href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</a>"
var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300)
popup.set_content(dat)
popup.open()
return UI_CLOSE
return ..()
//lasertag presets
/obj/machinery/porta_turret/lasertag/red
@@ -1112,11 +1149,9 @@
if(on)
if(team_color == "blue")
if(istype(P, /obj/item/projectile/beam/lasertag/redtag))
on = FALSE
spawn(100)
on = TRUE
toggle_on(FALSE)
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS)
else if(team_color == "red")
if(istype(P, /obj/item/projectile/beam/lasertag/bluetag))
on = FALSE
spawn(100)
on = TRUE
toggle_on(FALSE)
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS)
+5 -16
View File
@@ -170,12 +170,10 @@
..()
default_unfasten_wrench(user, I, 5)
return TRUE
/obj/machinery/space_heater/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)
/obj/machinery/space_heater/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "SpaceHeater", name, 400, 305, master_ui, state)
ui = new(user, src, "SpaceHeater", name)
ui.open()
/obj/machinery/space_heater/ui_data()
@@ -210,7 +208,7 @@
if("power")
on = !on
mode = HEATER_MODE_STANDBY
usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>")
usr.visible_message("<span class='notice'>[usr] switches [on ? "on" : "off"] \the [src].</span>", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>")
update_icon()
if (on)
START_PROCESSING(SSmachines, src)
@@ -222,16 +220,7 @@
if(!panel_open)
return
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "input")
target = input("New target temperature:", name, round(targetTemperature - T0C, 1)) as num|null
if(!isnull(target) && !..())
target += T0C
. = TRUE
else if(adjust)
target = targetTemperature + adjust
. = TRUE
else if(text2num(target) != null)
if(text2num(target) != null)
target= text2num(target) + T0C
. = TRUE
if(.)
+6 -4
View File
@@ -377,11 +377,13 @@
return ..()
/obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/suit_storage_unit/ui_state(mob/user)
return GLOB.notcontained_state
/obj/machinery/suit_storage_unit/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "SuitStorageUnit", name, 400, 305, master_ui, state)
ui = new(user, src, "SuitStorageUnit", name)
ui.open()
/obj/machinery/suit_storage_unit/ui_data()
@@ -17,11 +17,10 @@
var/notice = ""
var/universal_translate = FALSE // set to TRUE(1) if it can translate nonhuman speech
/obj/machinery/computer/telecomms/server/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/telecomms/server/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "TelecommsLogBrowser", "Telecomms Server Monitor", 575, 400, master_ui, state)
ui = new(user, src, "TelecommsLogBrowser", "Telecomms Server Monitor")
ui.open()
/obj/machinery/computer/telecomms/server/ui_data(mob/user)
@@ -36,12 +36,11 @@
light_color = LIGHT_COLOR_GREEN
/obj/machinery/computer/message_monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/message_monitor/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "TelecommsPDALog", name, 727, 510, master_ui, state)
ui = new(user, src, "TelecommsPDALog", name)
ui.open()
/obj/machinery/computer/message_monitor/ui_static_data(mob/user)
@@ -17,12 +17,11 @@
circuit = /obj/item/circuitboard/computer/comm_monitor
/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "TelecommsMonitor", name, 575, 400, master_ui, state)
ui = new(user, src, "TelecommsMonitor", name)
ui.open()
/obj/machinery/computer/telecomms/monitor/ui_data(mob/user)
@@ -27,16 +27,15 @@
else
return ..()
/obj/machinery/telecomms/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
/obj/machinery/telecomms/ui_interact(mob/user, datum/tgui/ui)
if(!canInteract(user))
if(ui)
ui.close() //haha no.
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "TelecommsInteraction", "[name] Access", 520, 500, master_ui, state)
ui = new(user, src, "TelecommsInteraction", "[name] Access")
ui.open()
/obj/machinery/telecomms/ui_data(mob/user)
+17 -9
View File
@@ -11,10 +11,15 @@
var/equip_ready = 1 //whether the equipment is ready for use. (or deactivated/activated for static stuff)
var/energy_drain = 0
var/obj/mecha/chassis = null
var/range = MELEE //bitFflags
/// Bitflag. Determines the range of the equipment.
var/range = MELEE
/// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this.
var/mech_flags = NONE
var/salvageable = 1
//var/detachable = TRUE // Set to FALSE for built-in equipment that cannot be removed
var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates
var/harmful = FALSE //Controls if equipment can be used to attack by a pacifist.
//var/destroy_sound = 'sound/mecha/critdestr.ogg'
/obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page()
if(chassis)
@@ -35,9 +40,14 @@
if(chassis.selected == src)
chassis.selected = null
src.update_chassis_page()
chassis.occupant_message("<span class='danger'>[src] is destroyed!</span>")
//log_message("[src] is destroyed.", LOG_MECHA)
chassis.log_append_to_last("[src] is destroyed.",1)
SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50))
if(chassis.occupant)
chassis.occupant_message("<span class='danger'>[src] is destroyed!</span>")
SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50))
//chassis.occupant.playsound_local(chassis, destroy_sound, 50)
//if(!detachable) //If we're a built-in nondetachable equipment, let's lock up the slot that we were in.
// chassis.max_equip--
chassis = null
return ..()
@@ -59,7 +69,7 @@
return txt
/obj/item/mecha_parts/mecha_equipment/proc/is_ranged()//add a distance restricted equipment. Why not?
return range&RANGED
return range&RANGED //rename to MECHA_RANGE and MECHA_MELEE
/obj/item/mecha_parts/mecha_equipment/proc/is_melee()
return range&MELEE
@@ -72,10 +82,10 @@
return 0
if(!equip_ready)
return 0
if(crit_fail)
return 0
if(energy_drain && !chassis.has_charge(energy_drain))
return 0
if(crit_fail)
return 0
if(chassis.equipment_disabled)
to_chat(chassis.occupant, "<span=warn>Error -- Equipment control unit is unresponsive.</span>")
return 0
@@ -117,8 +127,6 @@
chassis = M
forceMove(M)
M.mecha_log_message("[src] initialized.")
if(!M.selected && selectable)
M.selected = src
src.update_chassis_page()
return
@@ -150,7 +158,7 @@
chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]")
return
/obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color)
/obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color) //on tg this just overrides log_message
log_message(message, LOG_GAME, color) //pass to default admin logging too
if(chassis)
chassis.mecha_log_message(message, color) //and pass to our chassis
@@ -1,6 +1,7 @@
// Sleeper, Medical Beam, and Syringe gun
/obj/item/mecha_parts/mecha_equipment/medical
mech_flags = EXOSUIT_MODULE_MEDICAL
/obj/item/mecha_parts/mecha_equipment/medical/Initialize()
. = ..()
@@ -17,6 +17,7 @@
toolspeed = 0.9
var/drill_delay = 7
var/drill_level = DRILL_BASIC
mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT
/obj/item/mecha_parts/mecha_equipment/drill/Initialize()
. = ..()
@@ -153,6 +154,7 @@
selectable = 0
equip_cooldown = 15
var/scanning_time = 0
mech_flags = EXOSUIT_MODULE_WORKING
/obj/item/mecha_parts/mecha_equipment/mining_scanner/Initialize()
. = ..()
@@ -8,11 +8,12 @@
icon_state = "mecha_clamp"
equip_cooldown = 15
energy_drain = 10
tool_behaviour = TOOL_RETRACTOR
toolspeed = 0.8
var/dam_force = 20
var/obj/mecha/working/ripley/cargo_holder
harmful = TRUE
tool_behaviour = TOOL_RETRACTOR
toolspeed = 0.8
mech_flags = EXOSUIT_MODULE_RIPLEY
/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj)
if(..())
@@ -180,6 +181,7 @@
equip_cooldown = 5
energy_drain = 0
range = MELEE|RANGED
mech_flags = EXOSUIT_MODULE_WORKING
/obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize()
. = ..()
@@ -9,6 +9,7 @@
var/projectile_delay = 0
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired.
var/kickback = TRUE //Will using this weapon in no grav push mecha back.
mech_flags = EXOSUIT_MODULE_COMBAT
/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/combat/M)
if(..())
+3 -4
View File
@@ -81,10 +81,10 @@
var/obj/machinery/mech_bay_recharge_port/recharge_port
light_color = LIGHT_COLOR_PINK
/obj/machinery/computer/mech_bay_power_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.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "MechBayPowerConsole", "Mech Bay Power Control Console", 400, 200, master_ui, state)
ui = new(user, src, "MechBayPowerConsole", name)
ui.open()
/obj/machinery/computer/mech_bay_power_console/ui_act(action, params)
@@ -104,7 +104,6 @@
data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "maxhealth" = recharge_port.recharging_mech.max_integrity, "cell" = null, "name" = recharge_port.recharging_mech.name,)
if(recharge_port.recharging_mech.cell && !QDELETED(recharge_port.recharging_mech.cell))
data["recharge_port"]["mech"]["cell"] = list(
"critfail" = recharge_port.recharging_mech.cell.crit_fail,
"charge" = recharge_port.recharging_mech.cell.charge,
"maxcharge" = recharge_port.recharging_mech.cell.maxcharge
)
+546 -335
View File
@@ -9,17 +9,41 @@
active_power_usage = 5000
req_access = list(ACCESS_ROBOTICS)
circuit = /obj/item/circuitboard/machine/mechfab
var/time_coeff = 1
var/component_coeff = 1
var/datum/techweb/specialized/autounlocking/exofab/stored_research
var/sync = 0
var/part_set
var/datum/design/being_built
// processing_flags = START_PROCESSING_MANUALLY
// subsystem_type = /datum/controller/subsystem/processing/fastprocess
/// Current items in the build queue.
var/list/queue = list()
var/processing_queue = 0
var/screen = "main"
var/temp
var/offstation_security_levels = TRUE
/// Whether or not the machine is building the entire queue automagically.
var/process_queue = FALSE
/// The current design datum that the machine is building.
var/datum/design/being_built
/// World time when the build will finish.
var/build_finish = 0
/// World time when the build started.
var/build_start = 0
/// Reference to all materials used in the creation of the item being_built.
var/list/build_materials
/// Part currently stored in the Exofab.
var/obj/item/stored_part
/// Coefficient for the speed of item building. Based on the installed parts.
var/time_coeff = 1
/// Coefficient for the efficiency of material usage in item building. Based on the installed parts.
var/component_coeff = 1
/// Copy of the currently synced techweb.
var/datum/techweb/specialized/autounlocking/exofab/stored_research
/// Whether the Exofab links to the ore silo on init. Special derelict or maintanance variants should set this to FALSE.
var/link_on_init = TRUE
/// Reference to a remote material inventory, such as an ore silo.
var/datum/component/remote_materials/rmat
/// A list of categories that valid MECHFAB design datums will broadly categorise themselves under.
var/list/part_sets = list(
"Cyborg",
"Ripley",
@@ -33,25 +57,17 @@
"Exosuit Equipment",
"Exosuit Ammunition",
"Cyborg Upgrade Modules",
"Cybernetics",
"Implants",
"Control Interfaces",
"Misc"
)
/obj/machinery/mecha_part_fabricator/Initialize()
var/static/list/allowed_types = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/silver,
/datum/material/gold,
/datum/material/diamond,
/datum/material/plasma,
/datum/material/uranium,
/datum/material/bananium,
/datum/material/titanium,
/datum/material/bluespace
)
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, allowed_types, 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
materials.precise_insertion = TRUE
/obj/machinery/mecha_part_fabricator/Initialize(mapload)
stored_research = new
rmat = AddComponent(/datum/component/remote_materials, "mechfab", mapload && link_on_init)
RefreshParts() //Recalculating local material sizes if the fab isn't linked
return ..()
/obj/machinery/mecha_part_fabricator/RefreshParts()
@@ -60,8 +76,7 @@
//maximum stocking amount (default 300000, 600000 at T4)
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
T += M.rating
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = (200000 + (T*50000))
rmat.set_local_size((200000 + (T*50000)))
//resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55)
T = 1.15
@@ -74,89 +89,157 @@
for(var/obj/item/stock_parts/manipulator/Ml in component_parts)
T += Ml.rating
time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01)
var/obj/item/circuitboard/machine/mechfab/C = circuit
offstation_security_levels = C.offstation_security_levels
// Adjust the build time of any item currently being built.
if(being_built)
var/last_const_time = build_finish - build_start
var/new_const_time = get_construction_time_w_coeff(initial(being_built.construction_time))
var/const_time_left = build_finish - world.time
var/new_build_time = (new_const_time / last_const_time) * const_time_left
build_finish = world.time + new_build_time
update_static_data(usr)
/obj/machinery/mecha_part_fabricator/examine(mob/user)
. = ..()
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Storing up to <b>[materials.max_amount]</b> material units.<br>Material consumption at <b>[component_coeff*100]%</b>.<br>Build time reduced by <b>[100-time_coeff*100]%</b>.</span>"
. += "<span class='notice'>The status display reads: Storing up to <b>[rmat.local_size]</b> material units.<br>Material consumption at <b>[component_coeff*100]%</b>.<br>Build time reduced by <b>[100-time_coeff*100]%</b>.</span>"
/obj/machinery/mecha_part_fabricator/emag_act()
. = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
req_access = list()
INVOKE_ASYNC(src, .proc/error_action_sucessful)
return TRUE
/obj/machinery/mecha_part_fabricator/proc/error_action_sucessful()
say("DB error \[Code 0x00F1\]")
sleep(10)
say("Attempting auto-repair...")
sleep(15)
say("User DB corrupted \[Code 0x00FA\]. Truncating data structure...")
sleep(30)
say("User DB truncated. Please contact your Nanotrasen system operator for future assistance.")
/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name)
var/output = ""
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(!(set_name in D.category))
continue
output += "<div class='part'>[output_part_info(D)]<br>\["
if(check_clearance(D) && check_resources(D))
output += "<a href='?src=[REF(src)];part=[D.id]'>Build</a> | "
output += "<a href='?src=[REF(src)];add_to_queue=[D.id]'>Add to queue</a>\]\[<a href='?src=[REF(src)];part_desc=[D.id]'>?</a>\]</div>"
return output
/obj/machinery/mecha_part_fabricator/proc/check_clearance(datum/design/D)
if(!(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z)) && !ISINRANGE(GLOB.security_level, D.min_security_level, D.max_security_level))
return FALSE
return TRUE
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D)
var/clearance = !(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z))
var/sec_text = ""
if(clearance && (D.min_security_level > SEC_LEVEL_GREEN || D.max_security_level < SEC_LEVEL_DELTA))
sec_text = " (Allowed security levels: "
for(var/n in D.min_security_level to D.max_security_level)
sec_text += NUM2SECLEVEL(n)
if(n + 1 <= D.max_security_level)
sec_text += ", "
sec_text += ") "
var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [sec_text][get_construction_time_w_coeff(D)/10]sec"
return output
/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D)
var/i = 0
var/output
/**
* Generates an info list for a given part.
*
* Returns a list of part information.
* * D - Design datum to get information on.
* * categories - Boolean, whether or not to parse snowflake categories into the part information list.
*/
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, categories = FALSE)
var/cost = list()
for(var/c in D.materials)
var/datum/material/M = c
output += "[i?" | ":null][get_resource_cost_w_coeff(D, M)] [M.name]"
i++
return output
cost[M.name] = get_resource_cost_w_coeff(D, M)
var/obj/built_item = D.build_path
var/list/category_override = null
var/list/sub_category = null
if(categories)
// Handle some special cases to build up sub-categories for the fab interface.
// Start with checking if this design builds a cyborg module.
if(built_item in typesof(/obj/item/borg/upgrade))
var/obj/item/borg/upgrade/U = built_item
var/module_types = initial(U.module_flags)
sub_category = list()
if(module_types)
if(module_types & BORG_MODULE_SECURITY)
sub_category += "Security"
if(module_types & BORG_MODULE_MINER)
sub_category += "Mining"
if(module_types & BORG_MODULE_JANITOR)
sub_category += "Janitor"
if(module_types & BORG_MODULE_MEDICAL)
sub_category += "Medical"
if(module_types & BORG_MODULE_ENGINEERING)
sub_category += "Engineering"
else
sub_category += "All Cyborgs"
// Else check if this design builds a piece of exosuit equipment.
else if(built_item in typesof(/obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/E = built_item
var/mech_types = initial(E.mech_flags)
sub_category = "Equipment"
if(mech_types)
category_override = list()
if(mech_types & EXOSUIT_MODULE_RIPLEY)
category_override += "Ripley"
if(mech_types & EXOSUIT_MODULE_FIREFIGHTER)
category_override += "Firefighter"
if(mech_types & EXOSUIT_MODULE_ODYSSEUS)
category_override += "Odysseus"
// if(mech_types & EXOSUIT_MODULE_CLARKE)
// category_override += "Clarke"
if(mech_types & EXOSUIT_MODULE_GYGAX_MED)
category_override += "Medical-Spec Gygax"
if(mech_types & EXOSUIT_MODULE_GYGAX)
category_override += "Gygax"
if(mech_types & EXOSUIT_MODULE_DURAND)
category_override += "Durand"
if(mech_types & EXOSUIT_MODULE_HONK)
category_override += "H.O.N.K"
if(mech_types & EXOSUIT_MODULE_PHAZON)
category_override += "Phazon"
var/list/part = list(
"name" = D.name,
"desc" = initial(built_item.desc),
"printTime" = get_construction_time_w_coeff(initial(D.construction_time))/10,
"cost" = cost,
"id" = D.id,
"subCategory" = sub_category,
"categoryOverride" = category_override,
"searchMeta" = "UNKNOWN"//D.search_metadata
)
return part
/**
* Generates a list of resources / materials available to this Exosuit Fab
*
* Returns null if there is no material container available.
* List format is list(material_name = list(amount = ..., ref = ..., etc.))
*/
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/output
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = mat_id
var/amount = materials.materials[mat_id]
output += "<span class=\"res_name\">[M.name]: </span>[amount] cm&sup3;"
if(amount >= MINERAL_MATERIAL_AMOUNT)
output += "<span style='font-size:80%;'>- Remove \[<a href='?src=[REF(src)];remove_mat=1;material=[REF(mat_id)]'>1</a>\]"
if(amount >= (MINERAL_MATERIAL_AMOUNT * 10))
output += " | \[<a href='?src=[REF(src)];remove_mat=10;material=[REF(M)]'>10</a>\]"
output += " | \[<a href='?src=[REF(src)];remove_mat=50;material=[REF(M)]'>All</a>\]</span>"
output += "<br/>"
return output
var/datum/component/material_container/materials = rmat.mat_container
var/list/material_data = list()
if(materials)
for(var/mat_id in materials.materials)
var/datum/material/M = mat_id
var/list/material_info = list()
var/amount = materials.materials[mat_id]
material_info = list(
"name" = M.name,
"ref" = REF(M),
"amount" = amount,
"sheets" = round(amount / MINERAL_MATERIAL_AMOUNT),
"removable" = amount >= MINERAL_MATERIAL_AMOUNT
)
material_data += list(material_info)
return material_data
return null
/**
* Intended to be called when an item starts printing.
*
* Adds the overlay to show the fab working and sets active power usage settings.
*/
/obj/machinery/mecha_part_fabricator/proc/on_start_printing()
add_overlay("fab-active")
use_power = ACTIVE_POWER_USE
/**
* Intended to be called when the exofab has stopped working and is no longer printing items.
*
* Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing.
*/
/obj/machinery/mecha_part_fabricator/proc/on_finish_printing()
cut_overlay("fab-active")
use_power = IDLE_POWER_USE
desc = initial(desc)
process_queue = FALSE
/**
* Calculates resource/material costs for printing an item based on the machine's resource coefficient.
*
* Returns a list of k,v resources with their amounts.
* * D - Design datum to calculate the modified resource cost of.
*/
/obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D)
var/list/resources = list()
for(var/R in D.materials)
@@ -164,294 +247,419 @@
resources[M] = get_resource_cost_w_coeff(D, M)
return resources
/**
* Checks if the Exofab has enough resources to print a given item.
*
* Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources.
* Returns TRUE if there are sufficient resources to print the item.
* * D - Design datum to calculate the modified resource cost of.
*/
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
if(D.reagents_list.len) // No reagents storage - no reagent designs.
if(length(D.reagents_list)) // No reagents storage - no reagent designs.
return FALSE
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/datum/component/material_container/materials = rmat.mat_container
if(materials.has_materials(get_resources_w_coeff(D)))
return TRUE
return FALSE
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D)
/**
* Attempts to build the next item in the build queue.
*
* Returns FALSE if either there are no more parts to build or the next part is not buildable.
* Returns TRUE if the next part has started building.
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
*/
/obj/machinery/mecha_part_fabricator/proc/build_next_in_queue(verbose = TRUE)
if(!length(queue))
return FALSE
var/datum/design/D = queue[1]
if(build_part(D, verbose))
remove_from_queue(1)
return TRUE
return FALSE
/**
* Starts the build process for a given design datum.
*
* Returns FALSE if the procedure fails. Returns TRUE when being_built is set.
* Uses materials.
* * D - Design datum to attempt to print.
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
*/
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE)
if(!D)
return FALSE
var/datum/component/material_container/materials = rmat.mat_container
if (!materials)
if(verbose)
say("No access to material storage, please contact the quartermaster.")
return FALSE
if (rmat.on_hold())
if(verbose)
say("Mineral access is on hold, please contact the quartermaster.")
return FALSE
if(!check_resources(D))
if(verbose)
say("Not enough resources. Processing stopped.")
return FALSE
build_materials = get_resources_w_coeff(D)
materials.use_materials(build_materials)
being_built = D
desc = "It's building \a [initial(D.name)]."
var/list/res_coef = get_resources_w_coeff(D)
build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time))
build_start = world.time
desc = "It's building \a [D.name]."
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.use_materials(res_coef)
add_overlay("fab-active")
use_power = ACTIVE_POWER_USE
updateUsrDialog()
sleep(get_construction_time_w_coeff(D))
use_power = IDLE_POWER_USE
cut_overlay("fab-active")
desc = initial(desc)
rmat.silo_log(src, "built", -1, "[D.name]", build_materials)
var/location = get_step(src,(dir))
var/obj/item/I = new D.build_path(location)
I.set_custom_materials(res_coef)
say("\The [I] is complete.")
being_built = null
updateUsrDialog()
return TRUE
/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page()
send_byjax(usr,"mecha_fabricator.browser","queue",list_queue())
return
/obj/machinery/mecha_part_fabricator/process()
// If there's a stored part to dispense due to an obstruction, try to dispense it.
if(stored_part)
var/turf/exit = get_step(src,(dir))
if(exit.density)
return TRUE
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name)
if(set_name in part_sets)
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(set_name in D.category)
add_to_queue(D)
say("Obstruction cleared. \The [stored_part] is complete.")
stored_part.forceMove(exit)
stored_part = null
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(D)
// If there's nothing being built, try to build something
if(!being_built)
// If we're not processing the queue anymore or there's nothing to build, end processing.
if(!process_queue || !build_next_in_queue())
on_finish_printing()
STOP_PROCESSING(SSfastprocess, src)
//end_processing()
return TRUE
on_start_printing()
// If there's an item being built, check if it is complete.
if(being_built && (build_finish < world.time))
// Then attempt to dispense it and if appropriate build the next item.
dispense_built_part(being_built)
if(process_queue)
build_next_in_queue(FALSE)
return TRUE
/**
* Dispenses a part to the tile infront of the Exosuit Fab.
*
* Returns FALSE is the machine cannot dispense the part on the appropriate turf.
* Return TRUE if the part was successfully dispensed.
* * D - Design datum to attempt to dispense.
*/
/obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/D)
var/obj/item/I = new D.build_path(src)
// I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this.
I.set_custom_materials(build_materials)
being_built = null
var/turf/exit = get_step(src,(dir))
if(exit.density)
say("Error! Part outlet is obstructed.")
desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed."
stored_part = I
return FALSE
say("\The [I] is complete.")
I.forceMove(exit)
return TRUE
/**
* Adds a list of datum designs to the build queue.
*
* Will only add designs that are in this machine's stored techweb.
* Does final checks for datum IDs and makes sure this machine can build the designs.
* * part_list - List of datum design ids for designs to add to the queue.
*/
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(list/part_list)
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if((D.build_type & MECHFAB) && (D.id in part_list))
add_to_queue(D)
/**
* Adds a datum design to the build queue.
*
* Returns TRUE if successful and FALSE if the design was not added to the queue.
* * D - Datum design to add to the queue.
*/
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D)
if(!istype(queue))
queue = list()
if(D)
queue[++queue.len] = D
return queue.len
return TRUE
return FALSE
/**
* Removes datum design from the build queue based on index.
*
* Returns TRUE if successful and FALSE if a design was not removed from the queue.
* * index - Index in the build queue of the element to remove.
*/
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index)
if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>queue.len))
if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue)))
return FALSE
queue.Cut(index,++index)
return TRUE
/obj/machinery/mecha_part_fabricator/proc/process_queue()
var/datum/design/D = queue[1]
if(!D)
remove_from_queue(1)
if(queue.len)
return process_queue()
else
return
temp = null
while(D)
if(stat&(NOPOWER|BROKEN))
return FALSE
if(!check_clearance(D))
say("Security level not met. Queue processing stopped.")
temp = {"<span class='alert'>Security level not met to build next part.</span><br>
<a href='?src=[REF(src)];process_queue=1'>Try again</a> | <a href='?src=[REF(src)];clear_temp=1'>Return</a><a>"}
return FALSE
if(!check_resources(D))
say("Not enough resources. Queue processing stopped.")
temp = {"<span class='alert'>Not enough resources to build next part.</span><br>
<a href='?src=[REF(src)];process_queue=1'>Try again</a> | <a href='?src=[REF(src)];clear_temp=1'>Return</a><a>"}
return FALSE
remove_from_queue(1)
build_part(D)
D = listgetindex(queue, 1)
say("Queue processing finished successfully.")
/**
* Generates a list of parts formatted for tgui based on the current build queue.
*
* Returns a formatted list of lists containing formatted part information for every part in the build queue.
*/
/obj/machinery/mecha_part_fabricator/proc/list_queue()
var/output = "<b>Queue contains:</b>"
if(!istype(queue) || !queue.len)
output += "<br>Nothing"
else
output += "<ol>"
var/i = 0
for(var/datum/design/D in queue)
i++
var/obj/part = D.build_path
output += "<li[(!check_clearance(D) ||!check_resources(D))?" style='color: #f00;'":null]>"
output += initial(part.name) + " - "
output += "[i>1?"<a href='?src=[REF(src)];queue_move=-1;index=[i]' class='arrow'>&uarr;</a>":null] "
output += "[i<queue.len?"<a href='?src=[REF(src)];queue_move=+1;index=[i]' class='arrow'>&darr;</a>":null] "
output += "<a href='?src=[REF(src)];remove_from_queue=[i]'>Remove</a></li>"
if(!istype(queue) || !length(queue))
return null
output += "</ol>"
output += "\[<a href='?src=[REF(src)];process_queue=1'>Process queue</a> | <a href='?src=[REF(src)];clear_queue=1'>Clear queue</a>\]"
return output
var/list/queued_parts = list()
for(var/datum/design/D in queue)
var/list/part = output_part_info(D)
queued_parts += list(part)
return queued_parts
/**
* Syncs machine with R&D servers.
*
* Requires an R&D Console visible within 7 tiles. Copies techweb research. Updates tgui's state data.
*/
/obj/machinery/mecha_part_fabricator/proc/sync()
temp = "Updating local R&D database..."
updateUsrDialog()
sleep(30) //only sleep if called by user
for(var/obj/machinery/computer/rdconsole/RDC in oview(7,src))
for(var/obj/machinery/computer/rdconsole/RDC in orange(7,src))
RDC.stored_research.copy_research_to(stored_research)
temp = "Processed equipment designs.<br>"
//check if the tech coefficients have changed
temp += "<a href='?src=[REF(src)];clear_temp=1'>Return</a>"
updateUsrDialog()
update_static_data(usr)
say("Successfully synchronized with R&D server.")
return
temp = "Unable to connect to local R&D Database.<br>Please check your connections and try again.<br><a href='?src=[REF(src)];clear_temp=1'>Return</a>"
updateUsrDialog()
say("Unable to connect to local R&D server.")
return
/**
* Calculates the coefficient-modified resource cost of a single material component of a design's recipe.
*
* Returns coefficient-modified resource cost for the given material component.
* * D - Design datum to pull the resource cost from.
* * resource - Material datum reference to the resource to calculate the cost of.
* * roundto - Rounding value for round() proc
*/
/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/datum/material/resource, roundto = 1)
return round(D.materials[resource]*component_coeff, roundto)
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran
return round(initial(D.construction_time)*time_coeff, roundto)
/**
* Calculates the coefficient-modified build time of a design.
*
* Returns coefficient-modified build time of a given design.
* * D - Design datum to calculate the modified build time of.
* * roundto - Rounding value for round() proc
*/
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran
return round(construction_time*time_coeff, roundto)
/obj/machinery/mecha_part_fabricator/ui_interact(mob/user as mob)
. = ..()
var/dat, left_part
user.set_machine(src)
var/turf/exit = get_step(src,(dir))
if(exit.density)
say("Error! Part outlet is obstructed.")
return
if(temp)
left_part = temp
else if(being_built)
var/obj/I = being_built.build_path
left_part = {"<TT>Building [initial(I.name)].<BR>
Please wait until completion...</TT>"}
/obj/machinery/mecha_part_fabricator/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
)
/obj/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ExosuitFabricator")
ui.open()
/obj/machinery/mecha_part_fabricator/ui_static_data(mob/user)
var/list/data = list()
var/list/final_sets = list()
var/list/buildable_parts = list()
for(var/part_set in part_sets)
final_sets += part_set
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
// This is for us.
var/list/part = output_part_info(D, TRUE)
if(part["category_override"])
for(var/cat in part["category_override"])
buildable_parts[cat] += list(part)
if(!(cat in part_sets))
final_sets += cat
continue
for(var/cat in part_sets)
// Find all matching categories.
if(!(cat in D.category))
continue
buildable_parts[cat] += list(part)
data["partSets"] = final_sets
data["buildableParts"] = buildable_parts
return data
/obj/machinery/mecha_part_fabricator/ui_data(mob/user)
var/list/data = list()
data["materials"] = output_available_resources()
if(being_built)
var/list/part = list(
"name" = being_built.name,
"duration" = build_finish - world.time,
"printTime" = get_construction_time_w_coeff(initial(being_built.construction_time))
)
data["buildingPart"] = part
else
switch(screen)
if("main")
left_part = output_available_resources()+"<hr>"
left_part += "<a href='?src=[REF(src)];sync=1'>Sync with R&D servers</a><hr>"
for(var/part_set in part_sets)
left_part += "<a href='?src=[REF(src)];part_set=[part_set]'>[part_set]</a> - \[<a href='?src=[REF(src)];partset_to_queue=[part_set]'>Add all parts to queue</a>\]<br>"
if("parts")
left_part += output_parts_list(part_set)
left_part += "<hr><a href='?src=[REF(src)];screen=main'>Return</a>"
dat = {"<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>[name] data</title>
<style>
.res_name {font-weight: bold; text-transform: capitalize;}
.red {color: #f00;}
.part {margin-bottom: 10px;}
.arrow {text-decoration: none; font-size: 10px;}
body, table {height: 100%;}
td {vertical-align: top; padding: 5px;}
html, body {padding: 0px; margin: 0px;}
h1 {font-size: 18px; margin: 5px 0px;}
</style>
<script language='javascript' type='text/javascript'>
[js_byjax]
</script>
</head><body>
<body>
<table style='width: 100%;'>
<tr>
<td style='width: 65%; padding-right: 10px;'>
[left_part]
</td>
<td style='width: 35%; background: #ccc;' id='queue'>
[list_queue()]
</td>
<tr>
</table>
</body>
</html>"}
user << browse(dat, "window=mecha_fabricator;size=1000x430")
onclose(user, "mecha_fabricator")
return
data["buildingPart"] = null
/obj/machinery/mecha_part_fabricator/Topic(href, href_list)
data["queue"] = list_queue()
if(stored_part)
data["storedPart"] = stored_part.name
else
data["storedPart"] = null
data["isProcessingQueue"] = process_queue
return data
/obj/machinery/mecha_part_fabricator/ui_act(action, var/list/params)
if(..())
return
if(href_list["part_set"])
var/tpart_set = href_list["part_set"]
if(tpart_set)
if(tpart_set=="clear")
part_set = null
else
part_set = tpart_set
screen = "parts"
if(href_list["part"])
var/T = href_list["part"]
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(D.id == T)
if(!processing_queue)
build_part(D)
else
add_to_queue(D)
break
if(href_list["add_to_queue"])
var/T = href_list["add_to_queue"]
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(D.id == T)
return TRUE
. = TRUE
add_fingerprint(usr)
usr.set_machine(src)
switch(action)
if("sync_rnd")
// Sync with R&D Servers
sync()
return
if("add_queue_set")
// Add all parts of a set to queue
var/part_list = params["part_list"]
add_part_set_to_queue(part_list)
return
if("add_queue_part")
// Add a specific part to queue
var/T = params["id"]
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if((D.build_type & MECHFAB) && (D.id == T))
add_to_queue(D)
break
return update_queue_on_page()
if(href_list["remove_from_queue"])
remove_from_queue(text2num(href_list["remove_from_queue"]))
return update_queue_on_page()
if(href_list["partset_to_queue"])
add_part_set_to_queue(href_list["partset_to_queue"])
return update_queue_on_page()
if(href_list["process_queue"])
spawn(0)
if(processing_queue || being_built)
return FALSE
processing_queue = 1
process_queue()
processing_queue = 0
if(href_list["clear_temp"])
temp = null
if(href_list["screen"])
screen = href_list["screen"]
if(href_list["queue_move"] && href_list["index"])
var/index = text2num(href_list["index"])
var/new_index = index + text2num(href_list["queue_move"])
if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index))
if(ISINRANGE(new_index,1,queue.len))
queue.Swap(index,new_index)
return update_queue_on_page()
if(href_list["clear_queue"])
queue = list()
return update_queue_on_page()
if(href_list["sync"])
sync()
if(href_list["part_desc"])
var/T = href_list["part_desc"]
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(D.id == T)
var/obj/part = D.build_path
temp = {"<h1>[initial(part.name)] description:</h1>
[initial(part.desc)]<br>
<a href='?src=[REF(src)];clear_temp=1'>Return</a>
"}
break
return
if("del_queue_part")
// Delete a specific from from the queue
var/index = text2num(params["index"])
remove_from_queue(index)
return
if("clear_queue")
// Delete everything from queue
queue.Cut()
return
if("build_queue")
// Build everything in queue
if(process_queue)
return
process_queue = TRUE
if(href_list["remove_mat"] && href_list["material"])
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/datum/material/Mat = locate(href_list["material"])
materials.retrieve_sheets(text2num(href_list["remove_mat"]), Mat)
if(!being_built)
START_PROCESSING(SSfastprocess, src)
//begin_processing()
return
if("stop_queue")
// Pause queue building. Also known as stop.
process_queue = FALSE
return
if("build_part")
// Build a single part
if(being_built || process_queue)
return
updateUsrDialog()
return
var/id = params["id"]
var/datum/design/D = SSresearch.techweb_design_by_id(id)
/obj/machinery/mecha_part_fabricator/on_deconstruction()
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
..()
if(!(D.build_type & MECHFAB) || !(D.id == id))
return
if(build_part(D))
on_start_printing()
START_PROCESSING(SSfastprocess, src)
//begin_processing() teege has this as a helper proc. please port it!
return
if("move_queue_part")
// Moves a part up or down in the queue.
var/index = text2num(params["index"])
var/new_index = index + text2num(params["newindex"])
if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index))
if(ISINRANGE(new_index,1,length(queue)))
queue.Swap(index,new_index)
return
if("remove_mat")
// Remove a material from the fab
var/mat_ref = params["ref"]
var/amount = text2num(params["amount"])
var/datum/material/mat = locate(mat_ref)
eject_sheets(mat, amount)
return
return FALSE
/**
* Eject material sheets.
*
* Returns the number of sheets successfully ejected.
* eject_sheet - Byond REF of the material to eject.
* eject_amt - Number of sheets to attempt to eject.
*/
/obj/machinery/mecha_part_fabricator/proc/eject_sheets(eject_sheet, eject_amt)
var/datum/component/material_container/mat_container = rmat.mat_container
if (!mat_container)
say("No access to material storage, please contact the quartermaster.")
return 0
if (rmat.on_hold())
say("Mineral access is on hold, please contact the quartermaster.")
return 0
var/count = mat_container.retrieve_sheets(text2num(eject_amt), eject_sheet, drop_location())
var/list/matlist = list()
matlist[eject_sheet] = text2num(eject_amt)
rmat.silo_log(src, "ejected", -count, "sheets", matlist)
return count
/obj/machinery/mecha_part_fabricator/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
var/datum/material/M = id_inserted
add_overlay("fab-load-[M.name]")
addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[M.name]"), 10)
updateUsrDialog()
/obj/machinery/mecha_part_fabricator/attackby(obj/item/W, mob/user, params)
if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W))
/obj/machinery/mecha_part_fabricator/screwdriver_act(mob/living/user, obj/item/I)
if(..())
return TRUE
if(being_built)
to_chat(user, "<span class='warning'>\The [src] is currently processing! Please wait until completion.</span>")
return FALSE
return default_deconstruction_screwdriver(user, "fab-o", "fab-idle", I)
if(default_deconstruction_crowbar(W))
/obj/machinery/mecha_part_fabricator/crowbar_act(mob/living/user, obj/item/I)
if(..())
return TRUE
return ..()
if(being_built)
to_chat(user, "<span class='warning'>\The [src] is currently processing! Please wait until completion.</span>")
return FALSE
return default_deconstruction_crowbar(I)
/obj/machinery/mecha_part_fabricator/proc/is_insertion_ready(mob/user)
if(panel_open)
@@ -463,6 +671,9 @@
return TRUE
/obj/machinery/mecha_part_fabricator/maint
link_on_init = FALSE
/obj/machinery/mecha_part_fabricator/offstation
offstation_security_levels = FALSE
link_on_init = FALSE
circuit = /obj/item/circuitboard/machine/mechfab/offstation
+3 -6
View File
@@ -5,14 +5,11 @@
icon_keyboard = "tech_key"
req_access = list(ACCESS_ROBOTICS)
circuit = /obj/item/circuitboard/computer/mecha_control
ui_x = 500
ui_y = 500
/obj/machinery/computer/mecha/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/computer/mecha/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "ExosuitControlConsole", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "ExosuitControlConsole", name)
ui.open()
/obj/machinery/computer/mecha/ui_data(mob/user)
+45 -29
View File
@@ -8,7 +8,7 @@
anchored = TRUE
light_range = 3
var/movechance = 70
var/obj/item/assembly/signaler/anomaly/aSignal
var/obj/item/assembly/signaler/anomaly/aSignal = /obj/item/assembly/signaler/anomaly
var/area/impact_area
var/lifespan = 990
@@ -23,8 +23,10 @@
START_PROCESSING(SSobj, src)
impact_area = get_area(src)
aSignal = new(src)
aSignal.name = "[name] core"
if (!impact_area)
return INITIALIZE_HINT_QDEL
aSignal = new aSignal(src)
aSignal.code = rand(1,100)
aSignal.anomaly_type = type
@@ -75,7 +77,7 @@
/obj/effect/anomaly/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/analyzer))
if(I.tool_behaviour == TOOL_ANALYZER) //revert if runtimed
to_chat(user, "<span class='notice'>Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].</span>")
///////////////////////
@@ -85,6 +87,7 @@
icon_state = "shield2"
density = FALSE
var/boing = 0
aSignal = /obj/item/assembly/signaler/anomaly/grav
/obj/effect/anomaly/grav/anomalyEffect()
..()
@@ -95,17 +98,23 @@
for(var/mob/living/M in range(0, src))
gravShock(M)
for(var/mob/living/M in orange(4, src))
step_towards(M,src)
if(!M.mob_negates_gravity()) //delete when runtimed
step_towards(M,src)
for(var/obj/O in range(0,src))
if(!O.anchored)
//if(isturf(O.loc))
// var/turf/T = O.loc
// if(T.intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
// continue
var/mob/living/target = locate() in view(4,src)
if(target && !target.stat)
O.throw_at(target, 5, 10)
/obj/effect/anomaly/grav/Crossed(mob/A)
gravShock(A)
/obj/effect/anomaly/grav/Crossed(atom/movable/AM)
. = ..()
gravShock(AM)
/obj/effect/anomaly/grav/Bump(mob/A)
/obj/effect/anomaly/grav/Bump(atom/A)
gravShock(A)
/obj/effect/anomaly/grav/Bumped(atom/movable/AM)
@@ -138,6 +147,7 @@
name = "flux wave anomaly"
icon_state = "electricity2"
density = TRUE
aSignal = /obj/item/assembly/signaler/anomaly/flux
var/canshock = FALSE
var/shockdamage = 20
var/explosive = TRUE
@@ -148,11 +158,12 @@
for(var/mob/living/M in range(0, src))
mobShock(M)
/obj/effect/anomaly/flux/Crossed(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/Crossed(atom/movable/AM)
. = ..()
mobShock(AM)
/obj/effect/anomaly/flux/Bump(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/Bump(atom/A)
mobShock(A)
/obj/effect/anomaly/flux/Bumped(atom/movable/AM)
mobShock(AM)
@@ -160,7 +171,7 @@
/obj/effect/anomaly/flux/proc/mobShock(mob/living/M)
if(canshock && istype(M))
canshock = FALSE //Just so you don't instakill yourself if you slam into the anomaly five times in a second.
M.electrocute_act(shockdamage, "[name]", flags = SHOCK_NOGLOVES)
M.electrocute_act(shockdamage, name, flags = SHOCK_NOGLOVES)
/obj/effect/anomaly/flux/detonate()
if(explosive)
@@ -176,6 +187,7 @@
icon = 'icons/obj/projectiles.dmi'
icon_state = "bluespace"
density = TRUE
aSignal = /obj/item/assembly/signaler/anomaly/bluespace
/obj/effect/anomaly/bluespace/anomalyEffect()
..()
@@ -187,7 +199,7 @@
do_teleport(AM, locate(AM.x, AM.y, AM.z), 8, channel = TELEPORT_CHANNEL_BLUESPACE)
/obj/effect/anomaly/bluespace/detonate()
var/turf/T = safepick(get_area_turfs(impact_area))
var/turf/T = pick(get_area_turfs(impact_area))
if(T)
// Calculate new position (searches through beacons in world)
var/obj/item/beacon/chosen
@@ -224,21 +236,23 @@
if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving
A.forceMove(newloc)
spawn()
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
var/mob/M = A
if(M.client)
var/obj/blueeffect = new /obj(src)
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
blueeffect.icon = 'icons/effects/effects.dmi'
blueeffect.icon_state = "shieldsparkles"
blueeffect.layer = FLASH_LAYER
blueeffect.plane = FULLSCREEN_PLANE
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
M.client.screen += blueeffect
sleep(20)
M.client.screen -= blueeffect
qdel(blueeffect)
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
var/mob/M = A
if(M.client)
INVOKE_ASYNC(src, .proc/blue_effect, M)
/obj/effect/anomaly/bluespace/proc/blue_effect(mob/M)
var/obj/blueeffect = new /obj(src)
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
blueeffect.icon = 'icons/effects/effects.dmi'
blueeffect.icon_state = "shieldsparkles"
blueeffect.layer = FLASH_LAYER
blueeffect.plane = FULLSCREEN_PLANE
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
M.client.screen += blueeffect
sleep(20)
M.client.screen -= blueeffect
qdel(blueeffect)
/////////////////////
@@ -246,6 +260,7 @@
name = "pyroclastic anomaly"
icon_state = "mustard"
var/ticks = 0
aSignal = /obj/item/assembly/signaler/anomaly/pyro
/obj/effect/anomaly/pyro/anomalyEffect()
..()
@@ -278,6 +293,7 @@
name = "vortex anomaly"
icon_state = "bhole3"
desc = "That's a nice station you have there. It'd be a shame if something happened to it."
aSignal = /obj/item/assembly/signaler/anomaly/vortex
/obj/effect/anomaly/bhole/anomalyEffect()
..()
+9 -13
View File
@@ -1,10 +1,10 @@
/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override)
/proc/create_portal_pair(turf/source, turf/destination, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override)
if(!istype(source) || !istype(destination))
return
var/turf/actual_destination = get_teleport_turf(destination, accuracy)
var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE, null, atmos_link_override)
var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE, null, atmos_link_override)
var/obj/effect/portal/P1 = new newtype(source, _lifespan, null, FALSE, null, atmos_link_override)
var/obj/effect/portal/P2 = new newtype(actual_destination, _lifespan, P1, TRUE, null, atmos_link_override)
if(!istype(P1)||!istype(P2))
return
P1.link_portal(P2)
@@ -21,7 +21,6 @@
var/obj/effect/portal/linked
var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted.
var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE
var/creator
var/turf/hard_target //For when a portal needs a hard target and isn't to be linked.
var/atmos_link = FALSE //Link source/destination atmos.
var/turf/open/atmos_source //Atmos link source
@@ -35,6 +34,7 @@
name = "wormhole"
icon = 'icons/obj/objects.dmi'
icon_state = "anom"
layer = RIPPLE_LAYER
mech_sized = TRUE
teleport_channel = TELEPORT_CHANNEL_WORMHOLE
@@ -49,7 +49,9 @@
user.forceMove(get_turf(src))
return TRUE
/obj/effect/portal/Crossed(atom/movable/AM, oldloc)
/obj/effect/portal/Crossed(atom/movable/AM, oldloc, force_stop = 0)
if(force_stop)
return ..()
if(isobserver(AM))
return ..()
if(linked && (get_turf(oldloc) == get_turf(linked)))
@@ -66,7 +68,7 @@
if(Adjacent(user))
user.forceMove(get_turf(src))
/obj/effect/portal/Initialize(mapload, _creator, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override)
/obj/effect/portal/Initialize(mapload, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override)
. = ..()
GLOB.portals += src
if(!istype(_linked) && automatic_link)
@@ -78,7 +80,6 @@
atmos_link = atmos_link_override
link_portal(_linked)
hardlinked = automatic_link
creator = _creator
if(isturf(hard_target_override))
hard_target = hard_target_override
@@ -129,10 +130,7 @@
LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source)
atmos_destination = null
/obj/effect/portal/Destroy() //Calls on_portal_destroy(destroyed portal, location of destroyed portal) on creator if creator has such call.
if(creator && hascall(creator, "on_portal_destroy"))
call(creator, "on_portal_destroy")(src, src.loc)
creator = null
/obj/effect/portal/Destroy()
GLOB.portals -= src
unlink_atmos()
if(hardlinked && !QDELETED(linked))
@@ -153,8 +151,6 @@
return FALSE
if(!force && (!ismecha(M) && !istype(M, /obj/item/projectile) && M.anchored && !allow_anchored))
return
if(ismegafauna(M))
message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].")
var/no_effect = FALSE
if(last_effect == world.time)
no_effect = TRUE
+14 -15
View File
@@ -238,24 +238,22 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1)
return(BRUTELOSS)
/obj/item/pipe_dispenser/ui_base_html(html)
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
/obj/item/pipe_dispenser/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/pipes),
)
/obj/item/pipe_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.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/pipe_dispenser/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
assets.send(user)
ui = new(user, src, ui_key, "RapidPipeDispenser", name, 425, 515, master_ui, state)
ui = new(user, src, "RapidPipeDispenser", name)
ui.open()
/obj/item/pipe_dispenser/ui_data(mob/user)
var/list/data = list(
"category" = category,
"piping_layer" = piping_layer,
// "ducting_layer" = ducting_layer, //uhh is this for chem thing?
"preview_rows" = recipe.get_preview(p_dir),
"categories" = list(),
"selected_color" = paint_color,
@@ -284,7 +282,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
/obj/item/pipe_dispenser/ui_act(action, params)
if(..())
return
if(!usr.canUseTopic(src))
if(!usr.canUseTopic(src, BE_CLOSE))
return
var/playeffect = TRUE
switch(action)
@@ -304,6 +302,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
if("piping_layer")
piping_layer = text2num(params["piping_layer"])
playeffect = FALSE
// if("ducting_layer")
// ducting_layer = text2num(params["ducting_layer"])
// playeffect = FALSE
if("pipe_type")
var/static/list/recipes
if(!recipes)
@@ -320,11 +321,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
mode &= ~n
else
mode |= n
if(playeffect && world.time >= effectcooldown)
if(playeffect)
spark_system.start()
effectcooldown = world.time + 100
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE)
return TRUE
/obj/item/pipe_dispenser/pre_attack(atom/A, mob/user)
+3 -3
View File
@@ -180,10 +180,10 @@
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
return
/obj/item/airlock_painter/decal/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "DecalPainter", name, 500, 400, master_ui, state)
ui = new(user, src, "DecalPainter", name)
ui.open()
/obj/item/airlock_painter/decal/ui_data(mob/user)
+7 -7
View File
@@ -147,23 +147,23 @@
to_chat(user, "<span class='warning'>There is not enough of [src] left!</span>")
. = TRUE
/obj/item/toy/crayon/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
// tgui is a plague upon this codebase
/obj/item/toy/crayon/ui_state(mob/user)
return GLOB.hands_state
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/toy/crayon/ui_interact(mob/user, datum/tgui/ui)
// tgui is a plague upon this codebase
// no u
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Crayon", name, 600, 600,
master_ui, state)
ui = new(user, src, "Crayon", name)
ui.open()
/obj/item/toy/crayon/spraycan/AltClick(mob/user)
. = ..()
if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
if(has_cap)
is_capped = !is_capped
to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>")
update_icon()
return TRUE
/obj/item/toy/crayon/CtrlClick(mob/user)
if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+11 -9
View File
@@ -54,18 +54,20 @@
name = initial(name)
icon_state = initial(icon_state)
/obj/item/aicard/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/aicard/ui_state(mob/user)
return GLOB.hands_state
/obj/item/aicard/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Intellicard", name, 500, 500, master_ui, state)
ui = new(user, src, "Intellicard", name)
ui.open()
/obj/item/aicard/ui_data()
var/list/data = list()
if(AI)
data["name"] = AI.name
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
data["health"] = (AI.health + 100) / 2
data["wireless"] = !AI.control_disabled //todo disabled->enabled
data["radio"] = AI.radio_enabled
@@ -86,19 +88,19 @@
if(confirm == "Yes" && !..())
flush = TRUE
if(AI && AI.loc == src)
to_chat(AI, "Your core files are being wiped!")
to_chat(AI, "<span class='userdanger'>Your core files are being wiped!</span>")
while(AI.stat != DEAD && flush)
AI.adjustOxyLoss(1)
AI.adjustOxyLoss(5)
AI.updatehealth()
sleep(5)
flush = FALSE
. = TRUE
if("wireless")
AI.control_disabled = !AI.control_disabled
to_chat(AI, "[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!")
to_chat(AI, "<span class='warning'>[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!</span>")
. = TRUE
if("radio")
AI.radio_enabled = !AI.radio_enabled
to_chat(AI, "Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!")
to_chat(AI, "<span class='warning'>Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!</span>")
. = TRUE
update_icon()
@@ -163,12 +163,13 @@
return
ui_interact(user)
/obj/item/dogborg/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
/obj/item/dogborg/sleeper/ui_state(mob/user)
return GLOB.notcontained_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/dogborg/sleeper/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "dogborg_sleeper", name, 375, 550, master_ui, state)
ui = new(user, src, "dogborg_sleeper", name, 375, 550) //UI DOES NOT EXIST
ui.open()
/obj/item/dogborg/sleeper/ui_data()
+2 -130
View File
@@ -1,4 +1,4 @@
GLOBAL_LIST_EMPTY(GPS_list)
/obj/item/gps
name = "global positioning system"
desc = "Helping lost spacemen find their way through the planets since 2016."
@@ -8,138 +8,10 @@ GLOBAL_LIST_EMPTY(GPS_list)
slot_flags = ITEM_SLOT_BELT
obj_flags = UNIQUE_RENAME
var/gpstag = "COM0"
var/emped = FALSE
var/tracking = TRUE
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
/obj/item/gps/examine(mob/user)
. = ..()
var/turf/curr = get_turf(src)
. += "The screen says: [get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
. += "<span class='notice'>Alt-click to switch it [tracking ? "off":"on"].</span>"
/obj/item/gps/Initialize()
. = ..()
GLOB.GPS_list += src
name = "global positioning system ([gpstag])"
add_overlay("working")
/obj/item/gps/Destroy()
GLOB.GPS_list -= src
return ..()
/obj/item/gps/emp_act(severity)
. = ..()
if (. & EMP_PROTECT_SELF)
return
emped = TRUE
cut_overlay("working")
add_overlay("emp")
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
SStgui.close_uis(src) //Close the UI control if it is open.
/obj/item/gps/proc/reboot()
emped = FALSE
cut_overlay("emp")
add_overlay("working")
/obj/item/gps/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, BE_CLOSE))
return
toggletracking(user)
return TRUE
/obj/item/gps/proc/toggletracking(mob/user)
if(!user.canUseTopic(src, BE_CLOSE))
return //user not valid to use gps
if(emped)
to_chat(user, "It's busted!")
return
if(tracking)
cut_overlay("working")
to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.")
tracking = FALSE
else
add_overlay("working")
to_chat(user, "[src] is now tracking, and visible to other GPS devices.")
tracking = TRUE
/obj/item/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
if(emped)
to_chat(user, "[src] fizzles weakly.")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
// Variable window height, depending on how many GPS units there are
// to show, clamped to relatively safe range.
var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "Gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
/obj/item/gps/ui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gpstag
data["updating"] = updating
data["globalmode"] = global_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(src)
data["current"] = "[get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = "[curr.x], [curr.y], [curr.z]"
var/list/signals = list()
data["signals"] = list()
for(var/gps in GLOB.GPS_list)
var/obj/item/gps/G = gps
if(G.emped || !G.tracking || G == src)
continue
var/turf/pos = get_turf(G)
if(!global_mode && pos.z != curr.z)
continue
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
signal["coords"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/obj/item/gps/ui_act(action, params)
if(..())
return
switch(action)
if("rename")
var/a = input("Please enter desired tag.", name, gpstag) as text
a = copytext(sanitize(a), 1, 20)
gpstag = a
. = TRUE
name = "global positioning system ([gpstag])"
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
global_mode = !global_mode
. = TRUE
AddComponent(/datum/component/gps/item, gpstag)
/obj/item/gps/science
icon_state = "gps-s"
@@ -29,7 +29,7 @@
/obj/item/electropack/Destroy()
SSradio.remove_object(src, frequency)
. = ..()
return ..()
/obj/item/electropack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
@@ -39,7 +39,7 @@
return
return ..()
/obj/item/electropack/attackby(obj/item/W, mob/living/user, params)
/obj/item/electropack/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/clothing/head/helmet))
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit(user)
A.icon = 'icons/obj/assemblies.dmi'
@@ -59,56 +59,12 @@
else
return ..()
/obj/item/electropack/Topic(href, href_list)
var/mob/living/carbon/C = usr
if(usr.stat || usr.restrained() || C.back == src)
return
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=radio")
onclose(usr, "radio")
return
if(href_list["set"])
if(href_list["set"] == "freq")
var/new_freq = input(usr, "Input a new receiving frequency", "Electropack Frequency", format_frequency(frequency)) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_freq = unformat_frequency(new_freq)
new_freq = sanitize_frequency(new_freq, TRUE)
set_frequency(new_freq)
if(href_list["set"] == "code")
var/new_code = input(usr, "Input a new receiving code", "Electropack Code", code) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_code = round(new_code)
new_code = clamp(new_code, 1, 100)
code = new_code
if(href_list["set"] == "power")
if(!usr.canUseTopic(src, BE_CLOSE))
return
on = !(on)
icon_state = "electropack[on]"
if(usr)
attack_self(usr)
return
/obj/item/electropack/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
SSradio.add_object(src, frequency, RADIO_SIGNALER)
return
/obj/item/electropack/receive_signal(datum/signal/signal)
if(!signal || signal.data["code"] != code)
return
if(isliving(loc) && on)
if(shock_cooldown == TRUE)
if(shock_cooldown)
return
shock_cooldown = TRUE
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
@@ -124,18 +80,59 @@
if(master)
master.receive_signal()
return
/obj/item/electropack/ui_interact(mob/user)
if(!ishuman(user))
/obj/item/electropack/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
SSradio.add_object(src, frequency, RADIO_SIGNALER)
/obj/item/electropack/ui_state(mob/user)
return GLOB.hands_state
/obj/item/electropack/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Electropack", name)
ui.open()
/obj/item/electropack/ui_data(mob/user)
var/list/data = list()
data["power"] = on
data["frequency"] = frequency
data["code"] = code
data["minFrequency"] = MIN_FREE_FREQ
data["maxFrequency"] = MAX_FREE_FREQ
return data
/obj/item/electropack/ui_act(action, params)
if(..())
return
/obj/item/electropack/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Electropack", name, ui_x, ui_y, master_ui, state)
ui.open()
switch(action)
if("power")
on = !on
icon_state = "electropack[on]"
. = TRUE
if("freq")
var/value = unformat_frequency(params["freq"])
if(value)
frequency = sanitize_frequency(value, TRUE)
set_frequency(frequency)
. = TRUE
if("code")
var/value = text2num(params["code"])
if(value)
value = round(value)
code = clamp(value, 1, 100)
. = TRUE
if("reset")
if(params["reset"] == "freq")
frequency = initial(frequency)
. = TRUE
else if(params["reset"] == "code")
code = initial(code)
. = TRUE
/obj/item/electropack/shockcollar
name = "shock collar"
@@ -145,7 +142,7 @@
icon_state = "shockcollar"
item_state = "shockcollar"
body_parts_covered = NECK
slot_flags = ITEM_SLOT_NECK | ITEM_SLOT_DENYPOCKET //no more pocket shockers
slot_flags = ITEM_SLOT_NECK //no more pocket shockers. Now done without lazyness
w_class = WEIGHT_CLASS_SMALL
strip_delay = 60
equip_delay_other = 60
@@ -167,16 +164,18 @@
return
return ..()
/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal)
/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal) //we have to override this because of text
if(!signal || signal.data["code"] != code)
return
if(isliving(loc) && on)
if(isliving(loc) && on) //the "on" arg is currently useless
var/mob/living/L = loc
if(!L.get_item_by_slot(SLOT_NECK)) //**properly** stops pocket shockers
return
if(shock_cooldown == TRUE)
return
shock_cooldown = TRUE
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
var/mob/living/L = loc
step(L, pick(GLOB.cardinals))
to_chat(L, "<span class='danger'>You feel a sharp shock from the collar!</span>")
@@ -196,10 +195,13 @@
if(t)
tagname = t
name = "[initial(name)] - [t]"
return
if(istype(W, /obj/item/clothing/head/helmet)) //lazy method of denying this
return
else
return ..()
/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this
/obj/item/electropack/shockcollar/ui_interact(mob/user) //note to src: use tgooey
var/dat = {"
<TT>
<B>Frequency/Code</B> for shock collar:<BR>
+8 -12
View File
@@ -107,19 +107,15 @@
else
..()
/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
. = ..()
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/radio/ui_state(mob/user)
return GLOB.inventory_state
/obj/item/radio/ui_interact(mob/user, datum/tgui/ui, datum/ui_state/state)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
var/ui_width = 360
var/ui_height = 106
if(subspace_transmission)
if(channels.len > 0)
ui_height += 6 + channels.len * 21
else
ui_height += 24
ui = new(user, src, ui_key, "Radio", name, ui_width, ui_height, master_ui, state)
ui = new(user, src, "Radio", name)
if(state)
ui.set_state(state)
ui.open()
/obj/item/radio/ui_data(mob/user)
@@ -86,98 +86,102 @@ effective or pretty fucking useless.
return
if(!used)
log_combat(user, M, "irradiated", src)
var/cooldown = GetCooldown()
used = 1
var/cooldown = get_cooldown()
used = TRUE
icon_state = "health1"
handle_cooldown(cooldown) // splits off to handle the cooldown while handling wavelength
addtimer(VARSET_CALLBACK(src, used, FALSE), cooldown)
addtimer(VARSET_CALLBACK(src, icon_state, "health"), cooldown)
to_chat(user, "<span class='warning'>Successfully irradiated [M].</span>")
spawn((wavelength+(intensity*4))*5)
if(M)
if(intensity >= 5)
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
M.rad_act(intensity*10)
addtimer(CALLBACK(src, .proc/radiation_aftereffect, M), (wavelength+(intensity*4))*5)
else
to_chat(user, "<span class='warning'>The radioactive microlaser is still recharging.</span>")
/obj/item/healthanalyzer/rad_laser/proc/handle_cooldown(cooldown)
spawn(cooldown)
used = 0
icon_state = "health"
/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M)
if(QDELETED(M))
return
if(intensity >= 5)
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
M.rad_act(intensity*10)
/obj/item/healthanalyzer/rad_laser/proc/get_cooldown()
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
/obj/item/healthanalyzer/rad_laser/attack_self(mob/user)
interact(user)
/obj/item/healthanalyzer/rad_laser/proc/GetCooldown()
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
/obj/item/healthanalyzer/rad_laser/interact(mob/user)
ui_interact(user)
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user)
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/healthanalyzer/rad_laser/ui_state(mob/user)
return GLOB.hands_state
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "RadioactiveMicrolaser", "Radioactive Microlaser", ui_x, ui_y, master_ui, state)
ui = new(user, src, "RadioactiveMicrolaser")
ui.open()
var/dat = "Irradiation: <A href='?src=[REF(src)];rad=1'>[irradiate ? "On" : "Off"]</A><br>"
dat += "Stealth Mode (NOTE: Deactivates automatically while Irradiation is off): <A href='?src=[REF(src)];stealthy=[TRUE]'>[stealth ? "On" : "Off"]</A><br>"
dat += "Scan Mode: <a href='?src=[REF(src)];mode=1'>"
if(!scanmode)
dat += "Scan Health"
else if(scanmode == 1)
dat += "Scan Reagents"
else
dat += "Disabled"
dat += "</a><br><br>"
/obj/item/healthanalyzer/rad_laser/ui_data(mob/user)
var/list/data = list()
data["irradiate"] = irradiate
data["stealth"] = stealth
data["scanmode"] = scanmode
data["intensity"] = intensity
data["wavelength"] = wavelength
data["on_cooldown"] = used
data["cooldown"] = DisplayTimeText(get_cooldown())
return data
dat += {"
Radiation Intensity:
<A href='?src=[REF(src)];radint=-5'>-</A><A href='?src=[REF(src)];radint=-1'>-</A>
[intensity]
<A href='?src=[REF(src)];radint=1'>+</A><A href='?src=[REF(src)];radint=5'>+</A><BR>
/obj/item/healthanalyzer/rad_laser/ui_act(action, params)
if(..())
return
Radiation Wavelength:
<A href='?src=[REF(src)];radwav=-5'>-</A><A href='?src=[REF(src)];radwav=-1'>-</A>
[(wavelength+(intensity*4))]
<A href='?src=[REF(src)];radwav=1'>+</A><A href='?src=[REF(src)];radwav=5'>+</A><BR>
Laser Cooldown: [DisplayTimeText(GetCooldown())]<BR>
"}
var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240)
popup.set_content(dat)
popup.open()
/obj/item/healthanalyzer/rad_laser/Topic(href, href_list)
if(!usr.canUseTopic(src))
return 1
usr.set_machine(src)
if(href_list["rad"])
irradiate = !irradiate
else if(href_list["stealthy"])
stealth = !stealth
else if(href_list["mode"])
scanmode += 1
if(scanmode > 2)
scanmode = 0
else if(href_list["radint"])
var/amount = text2num(href_list["radint"])
amount += intensity
intensity = max(1,(min(20,amount)))
else if(href_list["radwav"])
var/amount = text2num(href_list["radwav"])
amount += wavelength
wavelength = max(0,(min(120,amount)))
attack_self(usr)
add_fingerprint(usr)
return
switch(action)
if("irradiate")
irradiate = !irradiate
. = TRUE
if("stealth")
stealth = !stealth
. = TRUE
if("scanmode")
scanmode = !scanmode
. = TRUE
if("radintensity")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "min")
target = 1
. = TRUE
else if(target == "max")
target = 20
. = TRUE
else if(adjust)
target = intensity + adjust
. = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
target = round(target)
intensity = clamp(target, 1, 20)
if("radwavelength")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "min")
target = 0
. = TRUE
else if(target == "max")
target = 120
. = TRUE
else if(adjust)
target = wavelength + adjust
. = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
target = round(target)
wavelength = clamp(target, 0, 120)
/obj/item/shadowcloak
name = "cloaker belt"
@@ -188,11 +188,10 @@
tank_one.air_contents.merge(temp)
tank_two.air_contents.set_volume(tank_two.air_contents.return_volume() - tank_one.air_contents.return_volume())
/*
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
it explodes properly when it gets a signal (and it does).
*/
*/
/obj/item/transfer_valve/proc/toggle_valve()
if(!valve_open && tank_one && tank_two)
valve_open = TRUE
@@ -233,16 +232,20 @@
valve_open = FALSE
update_icon()
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
/*
This doesn't do anything but the timer etc. expects it to be here
eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
*/
/obj/item/transfer_valve/proc/c_state()
return
/obj/item/transfer_valve/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/transfer_valve/ui_state(mob/user)
return GLOB.hands_state
/obj/item/transfer_valve/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "TransferValve", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "TransferValve", name)
ui.open()
/obj/item/transfer_valve/ui_data(mob/user)
+5 -3
View File
@@ -192,11 +192,13 @@
return top_vote
/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.always_state)
/obj/item/toy/eightball/haunted/ui_state(mob/user)
return GLOB.observer_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/toy/eightball/haunted/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "EightBallVote", name, 400, 600, master_ui, state)
ui = new(user, src, "EightBallVote", name)
ui.open()
/obj/item/toy/eightball/haunted/ui_data(mob/user)
@@ -10,7 +10,7 @@
/obj/item/implant/radio/activate()
. = ..()
// needs to be GLOB.deep_inventory_state otherwise it won't open
radio.ui_interact(usr, "main", null, FALSE, null, GLOB.deep_inventory_state)
radio.ui_interact(usr, state = GLOB.deep_inventory_state)
/obj/item/implant/radio/implant(mob/living/target, mob/user, silent = FALSE)
. = ..()
@@ -26,14 +26,15 @@
open_machine()
update_icon()
/obj/machinery/implantchair/ui_state(mob/user)
return GLOB.notcontained_state
/obj/machinery/implantchair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/implantchair/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "implantchair", name, 375, 280, master_ui, state)
ui = new(user, src, "ImplantChair", name)
ui.open()
/obj/machinery/implantchair/ui_data()
var/list/data = list()
data["occupied"] = occupant ? 1 : 0
@@ -6,21 +6,24 @@
desc = "Protected by FRM."
icon = 'icons/obj/module.dmi'
icon_state = "cyborg_upgrade"
w_class = WEIGHT_CLASS_SMALL
var/locked = FALSE
var/installed = 0
var/require_module = 0
var/list/module_type
/// Bitflags listing module compatibility. Used in the exosuit fabricator for creating sub-categories.
var/module_flags = NONE
// if true, is not stored in the robot to be ejected
// if module is reset
var/one_use = FALSE
/obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R, user = usr)
if(R.stat == DEAD)
to_chat(user, "<span class='notice'>[src] will not function on a deceased cyborg.</span>")
to_chat(user, "<span class='warning'>[src] will not function on a deceased cyborg.</span>")
return FALSE
if(module_type && !is_type_in_list(R.module, module_type))
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
to_chat(user, "There's no mounting point for the module!")
to_chat(R, "<span class='alert'>Upgrade mounting error! No suitable hardpoint detected.</span>")
to_chat(user, "<span class='warning'>There's no mounting point for the module!</span>")
return FALSE
return TRUE
@@ -37,7 +40,7 @@
one_use = TRUE
/obj/item/borg/upgrade/rename/attack_self(mob/user)
heldname = stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN)
heldname = sanitize_name(stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN))
/obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R)
. = ..()
@@ -95,6 +98,7 @@
desc = "Used to cool a mounted energy-based firearm, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
require_module = 1
module_flags = BORG_MODULE_SECURITY
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -147,6 +151,7 @@
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/miner)
module_flags = BORG_MODULE_MINER
/obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -207,6 +212,7 @@
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/butler)
module_flags = BORG_MODULE_JANITOR
/obj/item/borg/upgrade/tboh/action(mob/living/silicon/robot/R)
. = ..()
@@ -234,6 +240,7 @@
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/butler)
module_flags = BORG_MODULE_JANITOR
/obj/item/borg/upgrade/amop/action(mob/living/silicon/robot/R)
. = ..()
@@ -283,6 +290,7 @@
resistance_flags = LAVA_PROOF | FIRE_PROOF
require_module = 1
module_type = list(/obj/item/robot_module/miner)
module_flags = BORG_MODULE_MINER
/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -402,6 +410,7 @@
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical)
var/list/additional_reagents = list()
module_flags = BORG_MODULE_MEDICAL
/obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -471,6 +480,7 @@
require_module = 1
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical)
module_flags = BORG_MODULE_MEDICAL
/obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -578,6 +588,7 @@
icon_state = "borg_BS_RPED"
require_module = TRUE
module_type = list(/obj/item/robot_module/engineering, /obj/item/robot_module/saboteur)
module_flags = BORG_MODULE_ENGINEERING
/obj/item/borg/upgrade/rped/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -612,8 +623,8 @@
icon = 'icons/obj/device.dmi'
icon_state = "pinpointer_crew"
require_module = TRUE
module_type = list(/obj/item/robot_module/medical,
/obj/item/robot_module/syndicate_medical)
module_type = list(/obj/item/robot_module/medical, /obj/item/robot_module/syndicate_medical)
module_flags = BORG_MODULE_MEDICAL
/obj/item/borg/upgrade/pinpointer/action(mob/living/silicon/robot/R, user = usr)
. = ..()
+6 -8
View File
@@ -164,11 +164,13 @@
else
. = ..()
/obj/item/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/tank/ui_state(mob/user)
return GLOB.hands_state
/obj/item/tank/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Tank", name, 400, 120, master_ui, state)
ui = new(user, src, "Tank", name)
ui.open()
/obj/item/tank/ui_data(mob/user)
@@ -205,10 +207,6 @@
else if(pressure == "max")
pressure = TANK_MAX_RELEASE_PRESSURE
. = TRUE
else if(pressure == "input")
pressure = input("New release pressure ([TANK_MIN_RELEASE_PRESSURE]-[TANK_MAX_RELEASE_PRESSURE] kPa):", name, distribute_pressure) as num|null
if(!isnull(pressure) && !..())
. = TRUE
else if(text2num(pressure) != null)
pressure = text2num(pressure)
. = TRUE
+65 -90
View File
@@ -1,4 +1,3 @@
#define SOURCE_PORTAL 1
#define DESTINATION_PORTAL 2
@@ -25,90 +24,72 @@
throw_speed = 3
throw_range = 7
custom_materials = list(/datum/material/iron=400)
var/tracking_range = 20
/obj/item/locator/attack_self(mob/user)
user.set_machine(src)
var/dat
if (temp)
dat = "[temp]<BR><BR><A href='byond://?src=[REF(src)];temp=1'>Clear</A>"
else
dat = {"
<B>Persistent Signal Locator</B><HR>
<A href='?src=[REF(src)];refresh=1'>Refresh</A>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
/obj/item/locator/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BluespaceLocator", name)
ui.open()
/obj/item/locator/Topic(href, href_list)
..()
if (usr.stat || usr.restrained())
return
var/turf/current_location = get_turf(usr)//What turf is the user on?
if(!current_location || is_centcom_level(current_location.z))//If turf was not found or they're on CentCom
to_chat(usr, "[src] is malfunctioning.")
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)))
usr.set_machine(src)
if (href_list["refresh"])
temp = "<B>Persistent Signal Locator</B><HR>"
var/turf/sr = get_turf(src)
/obj/item/locator/ui_data(mob/user)
var/list/data = list()
if (sr)
temp += "<B>Beacon Signals:</B><BR>"
for(var/obj/item/beacon/W in GLOB.teleportbeacons)
if (!W.renamed)
continue
var/turf/tr = get_turf(W)
if (tr.z == sr.z && tr)
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if (direct < 5)
direct = "very strong"
else
if (direct < 10)
direct = "strong"
else
if (direct < 20)
direct = "weak"
else
direct = "very weak"
temp += "[W.name]-[dir2text(get_dir(sr, tr))]-[direct]<BR>"
data["trackingrange"] = tracking_range
temp += "<B>Implant Signals:</B><BR>"
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
if (!isliving(W.imp_in))
continue
var/mob/living/M = W.imp_in
if (M.stat == DEAD)
if (M.timeofdeath + W.lifespan_postmortem < world.time)
continue
// Get our current turf location.
var/turf/sr = get_turf(src)
var/turf/tr = get_turf(M)
if (tr.z == sr.z && tr)
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if (direct < 20)
if (direct < 5)
direct = "very strong"
else
if (direct < 10)
direct = "strong"
else
direct = "weak"
temp += "[W.imp_in.name]-[dir2text(get_dir(sr, tr))]-[direct]<BR>"
if (sr)
// Check every teleport beacon.
var/list/tele_beacons = list()
for(var/obj/item/beacon/W in GLOB.teleportbeacons)
temp += "<B>You are at \[[sr.x],[sr.y],[sr.z]\]</B> in orbital coordinates.<BR><BR><A href='byond://?src=[REF(src)];refresh=1'>Refresh</A><BR>"
// Get the tracking beacon's turf location.
var/turf/tr = get_turf(W)
// Make sure it's on a turf and that its Z-level matches the tracker's Z-level
if (tr && tr.z == sr.z)
// Get the distance between the beacon's turf and our turf
var/distance = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
// If the target is too far away, skip over this beacon.
if(distance > tracking_range)
continue
var/beacon_name
if(W.renamed)
beacon_name = W.name
else
var/area/A = get_area(W)
beacon_name = A.name
var/D = dir2text(get_dir(sr, tr))
tele_beacons += list(list(name = beacon_name, direction = D, distance = distance))
data["telebeacons"] = tele_beacons
var/list/track_implants = list()
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
if (!W.imp_in || !isliving(W.loc))
continue
else
temp += "<B><FONT color='red'>Processing Error:</FONT></B> Unable to locate orbital position.<BR>"
else
if (href_list["temp"])
temp = null
if (ismob(src.loc))
attack_self(src.loc)
else
for(var/mob/M in fov_viewers(1, src))
if (M.client)
src.attack_self(M)
return
var/mob/living/M = W.loc
if (M.stat == DEAD)
if (M.timeofdeath + W.lifespan_postmortem < world.time)
continue
var/turf/tr = get_turf(W)
var/distance = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if(distance > tracking_range)
continue
var/D = dir2text(get_dir(sr, tr))
track_implants += list(list(name = W.imp_in.name, direction = D, distance = distance))
data["trackimplants"] = track_implants
return data
/*
* Hand-tele
@@ -141,14 +122,11 @@
return TRUE
return ..()
/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user, delay = 30)
var/datum/beam/B = user.Beam(target, icon_state = "rped_upgrade", maxdistance = 50)
if(is_parent_of_portal(target) && (!delay || do_after(user, delay, target = target)))
/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user)
if(is_parent_of_portal(target))
qdel(target)
to_chat(user, "<span class='notice'>You dispel [target] with \the [src]!</span>")
qdel(B)
return TRUE
qdel(B)
return FALSE
/obj/item/hand_tele/afterattack(atom/target, mob/user)
@@ -190,13 +168,8 @@
user.show_message("<span class='notice'>\The [src] is recharging!</span>")
return
var/atom/T = L[t1]
var/implantcheckmate = FALSE
if(isliving(T))
var/mob/living/M = T
if(!locate(/obj/item/implant/tracking) in M.implants) //The user was too slow and let the target mob's tracking implant expire or get removed.
implantcheckmate = TRUE
var/area/A = get_area(T)
if(A.noteleport || implantcheckmate)
if(A.noteleport)
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
current_location = get_turf(user) //Recheck.
@@ -205,10 +178,12 @@
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
user.show_message("<span class='notice'>Locked In.</span>", MSG_AUDIBLE)
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1, null, atmos_link_override)
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), 300, 1, null, atmos_link_override)
if(!(LAZYLEN(created) == 2))
return
try_move_adjacent(created[1])
RegisterSignal(created[1], COMSIG_PARENT_QDELETING, .proc/on_portal_destroy) //Gosh darn it kevinz.
RegisterSignal(created[2], COMSIG_PARENT_QDELETING, .proc/on_portal_destroy)
try_move_adjacent(created[1], user.dir)
active_portal_pairs[created[1]] = created[2]
var/obj/effect/portal/c1 = created[1]
var/obj/effect/portal/c2 = created[2]
+9 -13
View File
@@ -45,8 +45,6 @@
var/height = 11
var/list/grid
var/canvas_color = "#ffffff" //empty canvas color
var/ui_x = 400
var/ui_y = 400
var/used = FALSE
var/painting_name //Painting name, this is set after framing.
var/finalized = FALSE //Blocks edits
@@ -75,12 +73,16 @@
. = ..()
ui_interact(user)
/obj/item/canvas/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
/obj/item/canvas/ui_state(mob/user)
if(finalized)
return GLOB.physical_obscured_state
else
return GLOB.default_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/canvas/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Canvas", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "Canvas", name)
ui.set_autoupdate(FALSE)
ui.open()
@@ -190,8 +192,6 @@
icon_state = "19x19"
width = 19
height = 19
ui_x = 600
ui_y = 600
pixel_x = 6
pixel_y = 9
framed_offset_x = 8
@@ -201,8 +201,6 @@
icon_state = "23x19"
width = 23
height = 19
ui_x = 800
ui_y = 600
pixel_x = 4
pixel_y = 10
framed_offset_x = 6
@@ -212,8 +210,6 @@
icon_state = "23x23"
width = 23
height = 23
ui_x = 800
ui_y = 800
pixel_x = 5
pixel_y = 9
framed_offset_x = 5
@@ -262,7 +258,7 @@
/obj/structure/sign/painting/examine(mob/user)
. = ..()
if(C)
C.ui_interact(user,state = GLOB.physical_obscured_state)
C.ui_interact(user)
/obj/structure/sign/painting/wirecutter_act(mob/living/user, obj/item/I)
. = ..()
+209
View File
@@ -345,3 +345,212 @@
name = initial(I.name)
icon = initial(I.icon)
icon_state = initial(I.icon_state)
/* Selling people in jars is currently disabled.
/obj/structure/displaycase/forsale
name = "vend-a-tray"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "laserbox0"
desc = "A display case with an ID-card swiper. Use your ID to purchase the contents."
density = FALSE
max_integrity = 100
req_access = null
showpiece_type = /obj/item/reagent_containers/food
alert = FALSE //No, we're not calling the fire department because someone stole your cookie.
glass_fix = FALSE //Fixable with tools instead.
///The price of the item being sold. Altered by grab intent ID use.
var/sale_price = 20
///The Account which will receive payment for purchases. Set by the first ID to swipe the tray.
var/datum/bank_account/payments_acc = null
///We're using the same trick as paper does in order to cache the image, and only load the UI when messed with.
var/list/viewing_ui = list()
/obj/structure/displaycase/forsale/update_icon() //remind me to fix my shitcode later
var/icon/I
if(open)
I = icon('icons/obj/stationobjs.dmi',"laserboxb0")
else
I = icon('icons/obj/stationobjs.dmi',"laserbox0")
if(!showpiece && !open)
I = icon('icons/obj/stationobjs.dmi',"laserbox_open")
if(broken)
I = icon('icons/obj/stationobjs.dmi',"laserbox_broken")
if(showpiece)
var/icon/S = getFlatIcon(showpiece)
S.Scale(17,17)
I.Blend(S,ICON_UNDERLAY,8,12)
src.icon = I
return
/obj/structure/displaycase/forsale/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Vendatray", name)
ui.set_autoupdate(FALSE)
viewing_ui[user] = ui
ui.open()
/obj/structure/displaycase/forsale/ui_data(mob/user)
var/list/data = list()
var/register = FALSE
if(payments_acc)
register = TRUE
data["owner_name"] = payments_acc.account_holder
if(showpiece)
data["product_name"] = capitalize(showpiece.name)
var/base64 = icon2base64(icon(showpiece.icon, showpiece.icon_state))
data["product_icon"] = base64
data["registered"] = register
data["product_cost"] = sale_price
data["tray_open"] = open
return data
/obj/structure/displaycase/forsale/ui_act(action, params)
if(..())
return
var/obj/item/card/id/potential_acc = usr.get_idcard(hand_first = TRUE)
switch(action)
if("Buy")
if(!showpiece)
to_chat(usr, "<span class='notice'>There's nothing for sale.</span>")
return TRUE
if(broken)
to_chat(usr, "<span class='notice'>[src] appears to be broken.</span>")
return TRUE
if(!payments_acc)
to_chat(usr, "<span class='notice'>[src] hasn't been registered yet.</span>")
return TRUE
if(!usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return TRUE
if(!potential_acc)
to_chat(usr, "<span class='notice'>No ID card detected.</span>")
return
var/datum/bank_account/account = potential_acc.registered_account
if(!account)
to_chat(usr, "<span class='notice'>[potential_acc] has no account registered!</span>")
return
if(!account.has_money(sale_price))
to_chat(usr, "<span class='notice'>You do not possess the funds to purchase this.</span>")
return TRUE
else
account.adjust_money(-sale_price)
if(payments_acc)
payments_acc.adjust_money(sale_price)
usr.put_in_hands(showpiece)
to_chat(usr, "<span class='notice'>You purchase [showpiece] for [sale_price] credits.</span>")
playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE)
icon = 'icons/obj/stationobjs.dmi'
flick("laserbox_vend", src)
showpiece = null
update_icon()
SStgui.update_uis(src)
return TRUE
if("Open")
if(!payments_acc)
to_chat(usr, "<span class='notice'>[src] hasn't been registered yet.</span>")
return TRUE
if(!potential_acc || !potential_acc.registered_account)
return
if(!check_access(potential_acc))
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
return
toggle_lock()
SStgui.update_uis(src)
if("Register")
if(payments_acc)
return
if(!potential_acc || !potential_acc.registered_account)
return
if(!check_access(potential_acc))
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
return
payments_acc = potential_acc.registered_account
playsound(src, 'sound/machines/click.ogg', 20, TRUE)
if("Adjust")
if(!check_access(potential_acc) || potential_acc.registered_account != payments_acc)
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
return
var/new_price_input = input(usr,"Set the sale price for this vend-a-tray.","new price",0) as num|null
if(isnull(new_price_input) || (payments_acc != potential_acc.registered_account))
to_chat(usr, "<span class='warning'>[src] rejects your new price.</span>")
return
if(!usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK) )
to_chat(usr, "<span class='warning'>You need to get closer!</span>")
return
new_price_input = clamp(round(new_price_input, 1), 10, 1000)
sale_price = new_price_input
to_chat(usr, "<span class='notice'>The cost is now set to [sale_price].</span>")
SStgui.update_uis(src)
return TRUE
. = TRUE
/obj/structure/displaycase/forsale/attackby(obj/item/I, mob/living/user, params)
if(isidcard(I))
//Card Registration
var/obj/item/card/id/potential_acc = I
if(!potential_acc.registered_account)
to_chat(user, "<span class='warning'>This ID card has no account registered!</span>")
return
if(payments_acc == potential_acc.registered_account)
playsound(src, 'sound/machines/click.ogg', 20, TRUE)
toggle_lock()
return
if(istype(I, /obj/item/pda))
return TRUE
SStgui.update_uis(src)
. = ..()
/obj/structure/displaycase/forsale/multitool_act(mob/living/user, obj/item/I)
. = ..()
if(obj_integrity <= (integrity_failure * max_integrity))
to_chat(user, "<span class='notice'>You start recalibrating [src]'s hover field...</span>")
if(do_after(user, 20, target = src))
broken = 0
obj_integrity = max_integrity
update_icon()
return TRUE
/obj/structure/displaycase/forsale/wrench_act(mob/living/user, obj/item/I)
. = ..()
if(open && user.a_intent == INTENT_HELP )
if(anchored)
to_chat(user, "<span class='notice'>You start unsecuring [src]...</span>")
else
to_chat(user, "<span class='notice'>You start securing [src]...</span>")
if(I.use_tool(src, user, 16, volume=50))
if(QDELETED(I))
return
if(anchored)
to_chat(user, "<span class='notice'>You unsecure [src].</span>")
else
to_chat(user, "<span class='notice'>You secure [src].</span>")
anchored = !anchored
return
else if(!open && user.a_intent == INTENT_HELP)
to_chat(user, "<span class='notice'>[src] must be open to move it.</span>")
return
/obj/structure/displaycase/forsale/emag_act(mob/user)
. = ..()
payments_acc = null
req_access = list()
to_chat(user, "<span class='warning'>[src]'s card reader fizzles and smokes, and the account owner is reset.</span>")
/obj/structure/displaycase/forsale/examine(mob/user)
. = ..()
if(showpiece && !open)
. += "<span class='notice'>[showpiece] is for sale for [sale_price] credits.</span>"
if(broken)
. += "<span class='notice'>[src] is sparking and the hover field generator seems to be overloaded. Use a multitool to fix it.</span>"
/obj/structure/displaycase/forsale/obj_break(damage_flag)
if(!broken && !(flags_1 & NODECONSTRUCT_1))
broken = TRUE
playsound(src, "shatter", 70, TRUE)
update_icon()
trigger_alarm() //In case it's given an alarm anyway.
/obj/structure/displaycase/forsale/kitchen
desc = "A display case with an ID-card swiper. Use your ID to purchase the contents. Meant for the bartender and chef."
req_one_access = list(ACCESS_KITCHEN, ACCESS_BAR)
*/
@@ -67,15 +67,14 @@
to_chat(user, "<span class='notice'>You put [I] in [src].</span>")
update_icon()
/obj/structure/tank_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, "TankDispenser", name, 275, 103, master_ui, state)
ui.open()
/obj/structure/tank_dispenser/ui_state(mob/user)
return GLOB.physical_state
/obj/structure/tank_dispenser/attack_robot(mob/user)
ui_interact(user)
/obj/structure/tank_dispenser/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TankDispenser", name)
ui.open()
/obj/structure/tank_dispenser/ui_data(mob/user)
var/list/data = list()
+3 -9
View File
@@ -9,8 +9,6 @@
icon_state = "bus"
density = TRUE
circuit = /obj/item/circuitboard/machine/ntnet_relay
ui_x = 400
ui_y = 300
var/datum/ntnet/NTNet = null // This is mostly for backwards reference and to allow varedit modifications from ingame.
var/enabled = 1 // Set to 0 if the relay was turned off
@@ -64,15 +62,12 @@
SSnetworks.station_network.add_log("Quantum relay switched from overload recovery mode to normal operation mode.")
..()
/obj/machinery/ntnet_relay/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/ntnet_relay/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "NtnetRelay", "NTNet Quantum Relay", ui_x, ui_y, master_ui, state)
ui = new(user, src, "NtnetRelay")
ui.open()
/obj/machinery/ntnet_relay/ui_data(mob/user)
var/list/data = list()
data["enabled"] = enabled
@@ -81,7 +76,6 @@
data["dos_crashed"] = dos_failure
return data
/obj/machinery/ntnet_relay/ui_act(action, params)
if(..())
return
+8 -3
View File
@@ -78,10 +78,15 @@
close_machine(target)
ui_interact(user)
/obj/machinery/vr_sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_contained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/vr_sleeper/ui_state(mob/user)
if(user == occupant)
return GLOB.contained_state
return GLOB.default_state
/obj/machinery/vr_sleeper/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "VrSleeper", "VR Sleeper", 475, 340, master_ui, state)
ui = new(user, src, "VrSleeper", "VR Sleeper")
ui.open()
/obj/machinery/vr_sleeper/ui_act(action, params)
@@ -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 //does not exist?
*/
/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"
@@ -23,99 +23,105 @@
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/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) && !HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
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_state(mob/user)
return GLOB.physical_state
/obj/machinery/abductor/console/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AbductorConsole", name)
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=helmet'>Agent Helmet (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=vest'>Agent Vest (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=silencer'>Radio Silencer (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=tool'>Science Tool (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=tongue'>Superlingual Matrix (1 Credit)</a><br>"
else
dat += "<span class='bad'>NO EXPERIMENT MACHINE DETECTED</span> <br>"
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/abductor/baton,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)
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)
@@ -156,7 +162,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
@@ -22,38 +22,44 @@
gland_colors[i] = random_color()
amounts[i] = rand(1,5)
/obj/machinery/abductor/gland_dispenser/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!isabductor(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_state(mob/user)
return GLOB.physical_state
/obj/machinery/abductor/gland_dispenser/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "GlandDispenser", name)
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
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))
@@ -65,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]--
@@ -15,16 +15,13 @@
var/breakout_time = 450
/obj/machinery/abductor/experiment/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target))
var/mob/living/L = user
if(user.stat || (isliving(user) && (!(L.mobility_flags & MOBILITY_STAND) || !(L.mobility_flags & MOBILITY_UI))) || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target))
return
if(isabductor(target))
return
close_machine(target)
/obj/machinery/abductor/experiment/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
experimentUI(user)
/obj/machinery/abductor/experiment/open_machine()
if(!state_open && !panel_open)
..()
@@ -46,7 +43,7 @@
/obj/machinery/abductor/experiment/container_resist(mob/living/user)
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a metallic creaking from [src].</span>")
"<span class='hear'>You hear a metallic creaking from [src].</span>")
if(do_after(user,(breakout_time), target = src))
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open)
return
@@ -54,122 +51,84 @@
"<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.dna.features["body_model"] == 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_state(mob/user)
return GLOB.physical_state
var/datum/sprite_accessory/S
S = GLOB.hair_styles_list[H.hair_style]
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)
/obj/machinery/abductor/experiment/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ProbingConsole", name)
ui.open()
S = GLOB.facial_hair_styles_list[H.facial_hair_style]
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>"
if(H.mind != null && (H.voluntary_ghosted || (H.ckey != null)))
return "No glands detected!"
if(H.mind != null && H.ckey != null)
LAZYINITLIST(abductee_minds)
LAZYADD(history, H)
LAZYADD(abductee_minds, H.mind)
@@ -191,22 +150,27 @@
point_reward++
if(point_reward > 0)
open_machine()
SendBack(H)
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
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, 1)
return "<span class='bad'>Experiment failed! No replacement organ detected.</span>"
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
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)
@@ -216,7 +180,6 @@
SSjob.SendToLateJoin(H, FALSE)
return
/obj/machinery/abductor/experiment/update_icon_state()
if(state_open)
icon_state = "experiment-open"
@@ -13,10 +13,13 @@
changeling = null
. = ..()
/datum/cellular_emporium/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/datum/cellular_emporium/ui_state(mob/user)
return GLOB.always_state
/datum/cellular_emporium/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "CellularEmporium", name, 900, 480, master_ui, state)
ui = new(user, src, "CellularEmporium", name)
ui.open()
/datum/cellular_emporium/ui_data(mob/user)
@@ -25,9 +25,6 @@
/datum/clockwork_scripture/ranged_ability/kindle, /datum/clockwork_scripture/ranged_ability/hateful_manacles) //quickbound scripture, accessed by index
var/maximum_quickbound = 5 //how many quickbound scriptures we can have
var/ui_x = 800
var/ui_z = 420
var/obj/structure/destructible/clockwork/trap/linking //If we're linking traps together, which ones we're doing
/obj/item/clockwork/slab/internal //an internal motor for mobs running scripture
@@ -39,6 +36,11 @@
speed_multiplier = 0
no_cost = TRUE
/obj/item/clockwork/slab/debug/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_servant_of_ratvar(user))
add_servant_of_ratvar(user)
return ..()
/obj/item/clockwork/slab/traitor
var/spent = FALSE
@@ -57,11 +59,6 @@
to_chat(user, "<span class='userdanger'>[src] falls dark. It appears you weren't worthy.</span>")
return ..()
/obj/item/clockwork/slab/debug/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_servant_of_ratvar(user))
add_servant_of_ratvar(user)
return ..()
/obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and fabricator
clockwork_desc = "A divine link to the Celestial Derelict, allowing for limited recital of scripture."
quickbound = list(/datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/ranged_ability/linked_vanguard, \
@@ -145,14 +142,15 @@
/obj/item/clockwork/slab/examine(mob/user)
. = ..()
if(is_servant_of_ratvar(user) || isobserver(user))
if(LAZYLEN(quickbound))
for(var/i in 1 to quickbound.len)
if(!quickbound[i])
continue
var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
. += "Quickbind button: <span class='[get_component_span(initial(quickbind_slot.primary_component))]'>[initial(quickbind_slot.name)]</span>."
. += "Available power: <span class='bold brass'>[DisplayPower(get_clockwork_power())].</span>"
if(!is_servant_of_ratvar(user) || !isobserver(user))
return
if(LAZYLEN(quickbound))
for(var/i in 1 to quickbound.len)
if(!quickbound[i])
continue
var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
. += "Quickbind button: <span class='[get_component_span(initial(quickbind_slot.primary_component))]'>[initial(quickbind_slot.name)]</span>."
. += "Available power: <span class='bold brass'>[DisplayPower(get_clockwork_power())].</span>"
//Slab actions; Hierophant, Quickbind
/obj/item/clockwork/slab/ui_action_click(mob/user, action)
@@ -198,12 +196,6 @@
ui_interact(user)
return TRUE
/obj/item/clockwork/slab/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ClockworkSlab", name, ui_x, ui_z, master_ui, state)
ui.open()
/obj/item/clockwork/slab/proc/recite_scripture(datum/clockwork_scripture/scripture, mob/living/user)
if(!scripture || !user || !user.canUseTopic(src) || (!no_cost && !can_recite_scripture(user)))
return FALSE
@@ -223,27 +215,62 @@
scripture_to_recite.run_scripture()
return TRUE
/*
* Gets text for a certain section. "Default" is used for when you first open Recollection.
* Current sections (make sure to update this if you add one:
* Basics
* Terminology
* Components
* Scripture
* Power
* Conversion
* * what - What section?
*/
/obj/item/clockwork/slab/proc/get_recollection(what) //Now DMDOC compliant!*
. = list()
switch(what) //need someone to rewrite info for this.
if("Default")
.["title"] = "Default"
.["info"] = "Hello servant! Currently these categories dosen't work!"
/*
if("Basics")
.["title"] = "Basics"
.["info"] = "# MARKDOWN WITH HTML?"
if("Terminology")
.["title"] = "Terminology"
.["info"] = "# MARKDOWN WITH HTML?"
if("Components")
.["title"] = "Default"
.["info"] = "# MARKDOWN WITH HTML?"
if("Scripture")
.["title"] = "Default"
.["info"] = "# MARKDOWN WITH HTML?"
if("Power")
.["title"] = "Power"
.["info"] = "# MARKDOWN WITH HTML?"
if("Conversion")
.["title"] = "Conversion"
.["info"] = "# MARKDOWN WITH HTML?"
*/
else
return null //error text handled tgui side. should not cause BSOD
//Gets text for a certain section. "Default" is used for when you first open Recollection.
//Current sections (make sure to update this if you add one:
//- Basics
//- Terminology
//- Components
//- Scripture
//- Power
//- Conversion
/obj/item/clockwork/slab/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ClockworkSlab", name)
ui.open()
/obj/item/clockwork/slab/ui_data(mob/user) //we display a lot of data via TGUI
. = list()
.["recollection"] = recollecting
.["power"] = DisplayPower(get_clockwork_power())
.["power_unformatted"] = get_clockwork_power()
// .["rec_text"] = recollection() handled TGUI side
.["HONOR_RATVAR"] = GLOB.ratvar_awakens
.["scripture"] = list()
for(var/s in GLOB.all_scripture)
for(var/s in GLOB.all_scripture) //don't block this, even when ratvar spawns for roundend griff.
var/datum/clockwork_scripture/S = GLOB.all_scripture[s]
if(S.tier == SCRIPTURE_PERIPHERAL) //yes, tiers are the tabs.
if(S.tier == SCRIPTURE_PERIPHERAL) // This tier is skiped because this contains basetype stuff
continue
var/list/data = list()
@@ -253,7 +280,7 @@
data["required"] = "([DisplayPower(S.power_cost)][S.special_power_text ? "+ [replacetext(S.special_power_text, "POWERCOST", "[DisplayPower(S.special_power_cost)]")]" : ""])"
data["required_unformatted"] = S.power_cost
data["type"] = "[S.type]"
data["quickbind"] = S.quickbind //this is if it cant quickbind
data["quickbind"] = S.quickbind //this is if it cant quickbind (bool)
data["fontcolor"] = get_component_color_bright(S.primary_component)
data["important"] = S.important //italic!
@@ -265,10 +292,8 @@
.["rec_binds"] = list()
for(var/i in 1 to maximum_quickbound)
if(GLOB.ratvar_awakens)
return
if(LAZYLEN(quickbound) < i || !quickbound[i])
.["rec_binds"] += list(list())
.["rec_binds"] += list(list()) //a blank json.
else
var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
.["rec_binds"] += list(list(
@@ -280,7 +305,11 @@
/obj/item/clockwork/slab/ui_static_data(mob/user)
. = list()
.["tier_infos"] = list()
.["tier_infos"] = list() //HEY!! WHEN ADDING NEW TIER, ADD IT HERE
.["tier_infos"][SCRIPTURE_PERIPHERAL] = list(
"requirement" = "Breaking the code DM side. Report to coggerbus if this appears!!",
"ready" = FALSE //just in case. Should NOT exist at all
)
.["tier_infos"][SCRIPTURE_DRIVER] = list(
"requirement" = "None, this is already unlocked",
"ready" = TRUE //to bold it on JS side, and to say "These scriptures are permanently unlocked."
@@ -297,10 +326,10 @@
"requirement" = "Unlock powerful equipment and structures by converting five servants or if [DisplayPower(JUDGEMENT_UNLOCK_THRESHOLD)] of power is reached..",
"ready" = SSticker.scripture_states[SCRIPTURE_JUDGEMENT]
)
// .["selected"] = selected_scripture
generate_all_scripture()
.["recollection_categories"] = GLOB.ratvar_awakens ? list() : list(
.["recollection_categories"] = list()
if(GLOB.ratvar_awakens)
return
.["recollection_categories"] = list(
list("name" = "Getting Started", "desc" = "First-time servant? Read this first."),
list("name" = "Basics", "desc" = "A primer on how to play as a servant."),
list("name" = "Terminology", "desc" = "Common acronyms, words, and terms."),
@@ -309,8 +338,9 @@
list("name" = "Power", "desc" = "The power system that certain objects use to function."),
list("name" = "Conversion", "desc" = "Converting the crew, cyborgs, and very walls to your cause.")
)
// .["rec_section"]["title"] //this is here if ever we decided to return these back.
// .["rec_section"]["info"]// wall of info for the thing
.["rec_section"] = get_recollection(recollection_category)
generate_all_scripture()
//needs a new place to live, preferably when clockcult unlocks/downgrades a tier. Smart enough to earlyreturn.
/obj/item/clockwork/slab/ui_act(action, params)
switch(action)
@@ -369,4 +399,4 @@
Q.button_icon_state = quickbind_slot.name
Q.UpdateButtonIcon()
if(isliving(loc))
Q.Grant(loc)
Q.Grant(loc)
@@ -7,17 +7,13 @@
density = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
ui_x = 350
ui_y = 442
var/timer_set = 90
var/default_timer_set = 90
var/minimum_timer_set = 90
var/maximum_timer_set = 3600
ui_style = "nanotrasen"
var/numeric_input = ""
var/ui_mode = NUKEUI_AWAIT_DISK
var/timing = FALSE
var/exploding = FALSE
var/exploded = FALSE
@@ -34,7 +30,6 @@
var/interior = ""
var/proper_bomb = TRUE //Please
var/obj/effect/countdown/nuclearbomb/countdown
var/nuclear_cooldown //used to stop global spam.
/obj/machinery/nuclearbomb/Initialize()
. = ..()
@@ -77,15 +72,16 @@
/obj/machinery/nuclearbomb/syndicate/get_cinematic_type(off_station)
var/datum/game_mode/nuclear/NM = SSticker.mode
switch(off_station)
if(FALSE)
if(0)
if(istype(NM) && !NM.nuke_team.syndies_escaped())
return CINEMATIC_ANNIHILATION
else
return CINEMATIC_NUKE_WIN
if(NUKE_MISS_STATION)
if(1)
return CINEMATIC_NUKE_MISS
else
if(2)
return CINEMATIC_NUKE_FAR
return CINEMATIC_NUKE_FAR
/obj/machinery/nuclearbomb/proc/disk_check(obj/item/disk/nuclear/D)
if(D.fake)
@@ -194,7 +190,7 @@
icon_state = "nuclearbomb_exploding"
/obj/machinery/nuclearbomb/update_overlays()
. = ..()
. += ..()
update_icon_interior()
update_icon_lights()
@@ -236,7 +232,7 @@
explode()
else
var/volume = (get_time_left() <= 20 ? 30 : 5)
playsound(loc, 'sound/items/timer.ogg', volume, 0)
playsound(loc, 'sound/items/timer.ogg', volume, FALSE)
/obj/machinery/nuclearbomb/proc/update_ui_mode()
if(exploded)
@@ -261,17 +257,18 @@
ui_mode = NUKEUI_AWAIT_TIMER
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state=GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/nuclearbomb/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "NuclearBomb", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "NuclearBomb", name)
ui.open()
/obj/machinery/nuclearbomb/ui_data(mob/user)
var/list/data = list()
data["disk_present"] = auth
var/hidden_code = (ui_mode == NUKEUI_AWAIT_CODE && numeric_input != "ERROR")
var/current_code = ""
if(hidden_code)
while(length(current_code) < length(numeric_input))
@@ -388,14 +385,13 @@
if("anchor")
if(auth && yes_code)
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
set_anchor(usr)
set_anchor()
else
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
/obj/machinery/nuclearbomb/proc/set_anchor(mob/user)
if((istype(get_area(src), /area/space) || isinspace()) && !anchored)
to_chat(user, "<span class='warning'>This is not a suitable platform for anchoring [src]!</span>")
/obj/machinery/nuclearbomb/proc/set_anchor()
if(isinspace() && !anchored)
to_chat(usr, "<span class='warning'>There is nothing to anchor to!</span>")
else
anchored = !anchored
@@ -416,9 +412,6 @@
if(safety)
to_chat(usr, "<span class='danger'>The safety is still on.</span>")
return
if(!timing && nuclear_cooldown > world.time)
to_chat(usr, "<span class='danger'>[src]'s timer protocols are currently on cooldown, please stand by.</span>")
return
timing = !timing
if(timing)
previous_level = NUM2SECLEVEL(GLOB.security_level)
@@ -427,12 +420,6 @@
S.switch_mode_to(TRACK_INFILTRATOR)
countdown.start()
set_security_level("delta")
nuclear_cooldown = world.time + 15 SECONDS
if(GLOB.war_declared)
var/area/A = get_area(src)
priority_announce("Alert: Unexpected increase in radiation levels near [A.name] ([src.x],[src.y],[src.z]). Please send an authorized radiation specialist to investigate.", "Sensory Nuclear Indexer Telemetry Calculation Helper")
else
detonation_timer = null
set_security_level(previous_level)
@@ -483,12 +470,19 @@
var/off_station = FALSE
var/turf/bomb_location = get_turf(src)
if(!bomb_location || !is_station_level(bomb_location.z))
off_station = NUKE_MISS_STATION
var/area/A = get_area(bomb_location)
if(bomb_location && is_station_level(bomb_location.z))
if(istype(A, /area/space))
off_station = NUKE_NEAR_MISS
if((bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)))
off_station = NUKE_NEAR_MISS
else if(bomb_location.onSyndieBase())
off_station = NUKE_SYNDICATE_BASE
else
off_station = NUKE_MISS_STATION
if(!off_station)
if(off_station < 2) //can only launch when nuke is on syndie base or space
SSshuttle.registerHostileEnvironment(src)
SSshuttle.lockdown = TRUE
@@ -502,13 +496,13 @@
INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnZLevel, z)
/obj/machinery/nuclearbomb/proc/get_cinematic_type(off_station)
if(!off_station)
if(off_station < 2)
return CINEMATIC_SELFDESTRUCT
else
return CINEMATIC_SELFDESTRUCT_MISS
/obj/machinery/nuclearbomb/beer
name = "Nanotrasen-brand nuclear fission explosive"
name = "\improper Nanotrasen-brand nuclear fission explosive"
desc = "One of the more successful achievements of the Nanotrasen Corporate Warfare Division, their nuclear fission explosives are renowned for being cheap to produce and devastatingly effective. Signs explain that though this particular device has been decommissioned, every Nanotrasen station is equipped with an equivalent one, just in case. All Captains carefully guard the disk needed to detonate them - at least, the sign says they do. There seems to be a tap on the back."
proper_bomb = FALSE
var/obj/structure/reagent_dispensers/beerkeg/keg
@@ -521,9 +515,9 @@
/obj/machinery/nuclearbomb/beer/examine(mob/user)
. = ..()
if(keg.reagents.total_volume)
. += "<span class='notice'>It has [keg.reagents.total_volume] unit\s left.</span>"
to_chat(user, "<span class='notice'>It has [keg.reagents.total_volume] unit\s left.</span>")
else
. += "<span class='danger'>It's empty.</span>"
to_chat(user, "<span class='danger'>It's empty.</span>")
/obj/machinery/nuclearbomb/beer/attackby(obj/item/W, mob/user, params)
if(W.is_refillable())
@@ -535,6 +529,8 @@
return ..()
/obj/machinery/nuclearbomb/beer/actually_explode()
//Unblock roundend, we're not actually exploding.
SSticker.roundend_check_paused = FALSE
var/turf/bomb_location = get_turf(src)
if(!bomb_location)
disarm()
@@ -583,7 +579,7 @@
This is here to make the tiles around the station mininuke change when it's armed.
*/
/obj/machinery/nuclearbomb/selfdestruct/set_anchor(mob/user)
/obj/machinery/nuclearbomb/selfdestruct/set_anchor()
return
/obj/machinery/nuclearbomb/selfdestruct/set_active()
@@ -641,18 +637,19 @@ This is here to make the tiles around the station mininuke change when it's arme
if(newturf && lastlocation == newturf)
if(last_disk_move < world.time - 5000 && prob((world.time - 5000 - last_disk_move)*0.0001))
var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control
if(istype(loneop))
if(istype(loneop) && loneop.occurrences < loneop.max_occurrences)
loneop.weight += 1
if(loneop.weight % 5 == 0)
if(loneop.weight % 5 == 0 && SSticker.totalPlayers > 1) //players count now
message_admins("[src] is stationary in [ADMIN_VERBOSEJMP(newturf)]. The weight of Lone Operative is now [loneop.weight].")
log_game("[src] is stationary for too long in [loc_name(newturf)], and has increased the weight of the Lone Operative event to [loneop.weight].")
else
lastlocation = newturf
last_disk_move = world.time
var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control
if(istype(loneop) && prob(loneop.weight))
if(istype(loneop) && loneop.occurrences < loneop.max_occurrences && prob(loneop.weight))
loneop.weight = max(loneop.weight - 1, 0)
if(loneop.weight % 5 == 0)
if(loneop.weight % 5 == 0 && SSticker.totalPlayers > 1)
message_admins("[src] is on the move (currently in [ADMIN_VERBOSEJMP(newturf)]). The weight of Lone Operative is now [loneop.weight].")
log_game("[src] being on the move has reduced the weight of the Lone Operative event to [loneop.weight].")
@@ -661,9 +658,19 @@ This is here to make the tiles around the station mininuke change when it's arme
if(!fake)
return
if(isobserver(user) || HAS_TRAIT(user, TRAIT_DISK_VERIFIER) || (user.mind && HAS_TRAIT(user.mind, TRAIT_DISK_VERIFIER)))
if(isobserver(user) || HAS_TRAIT(user.mind, TRAIT_DISK_VERIFIER))
. += "<span class='warning'>The serial numbers on [src] are incorrect.</span>"
/*
* You can't accidentally eat the nuke disk, bro
*/
/*
/obj/item/disk/nuclear/on_accidental_consumption(mob/living/carbon/M, mob/living/carbon/user, obj/item/source_item, discover_after = TRUE)
M.visible_message("<span class='warning'>[M] looks like [M.p_theyve()] just bitten into something important.</span>", \
"<span class='warning'>Wait, is this the nuke disk?</span>")
return discover_after
*/
/obj/item/disk/nuclear/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/claymore/highlander) && !fake)
var/obj/item/claymore/highlander/H = I
@@ -686,7 +693,7 @@ This is here to make the tiles around the station mininuke change when it's arme
/obj/item/disk/nuclear/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is going delta! It looks like [user.p_theyre()] trying to commit suicide!</span>")
playsound(src, 'sound/machines/alarm.ogg', 50, -1, 1)
playsound(src, 'sound/machines/alarm.ogg', 50, -1, TRUE)
for(var/i in 1 to 100)
addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#00FF00" : "#FF0000", ADMIN_COLOUR_PRIORITY), i)
addtimer(CALLBACK(src, .proc/manual_suicide, user), 101)
@@ -694,7 +701,7 @@ This is here to make the tiles around the station mininuke change when it's arme
/obj/item/disk/nuclear/proc/manual_suicide(mob/living/user)
user.remove_atom_colour(ADMIN_COLOUR_PRIORITY)
user.visible_message("<span class='suicide'>[user] was destroyed by the nuclear blast!</span>")
user.visible_message("<span class='suicide'>[user] is destroyed by the nuclear blast!</span>")
user.adjustOxyLoss(200)
user.death(0)
+4 -7
View File
@@ -4,8 +4,6 @@
icon_state = "infrared"
custom_materials = list(/datum/material/iron=1000, /datum/material/glass=500)
is_position_sensitive = TRUE
var/ui_x = 225
var/ui_y = 110
var/on = FALSE
var/visible = FALSE
var/maxlength = 8
@@ -134,7 +132,7 @@
. = ..()
setDir(t)
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE)
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE, quickstart = TRUE)
. = ..()
olddir = dir
@@ -186,11 +184,10 @@
return ..()
return UI_CLOSE
/obj/item/assembly/infra/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/assembly/infra/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "InfraredEmitter", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "InfraredEmitter", name)
ui.open()
/obj/item/assembly/infra/ui_data(mob/user)
+3 -6
View File
@@ -4,8 +4,6 @@
icon_state = "prox"
custom_materials = list(/datum/material/iron=800, /datum/material/glass=200)
attachable = TRUE
var/ui_x = 250
var/ui_y = 185
var/scanning = FALSE
var/timing = FALSE
var/time = 10
@@ -113,11 +111,10 @@
return ..()
return UI_CLOSE
/obj/item/assembly/prox_sensor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/assembly/prox_sensor/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "ProximitySensor", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "ProximitySensor", name)
ui.open()
/obj/item/assembly/prox_sensor/ui_data(mob/user)
+28 -80
View File
@@ -8,33 +8,46 @@
custom_materials = list(/datum/material/iron=400, /datum/material/glass=120)
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
attachable = TRUE
var/ui_x = 280
var/ui_y = 132
var/code = DEFAULT_SIGNALER_CODE
var/frequency = FREQ_SIGNALER
var/datum/radio_frequency/radio_connection
var/suicider = null
///Holds the mind that commited suicide.
var/datum/mind/suicider
///Holds a reference string to the mob, decides how much of a gamer you are.
var/suicide_mob
var/hearing_range = 1
/obj/item/assembly/signaler/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] eats \the [src]! If it is signaled, [user.p_they()] will die!</span>")
playsound(src, 'sound/items/eatfood.ogg', 50, TRUE)
user.transferItemToLoc(src, user, TRUE)
suicider = user
moveToNullspace()
suicider = user.mind
suicide_mob = REF(user)
return MANUAL_SUICIDE
/obj/item/assembly/signaler/proc/manual_suicide(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user]'s \the [src] receives a signal, killing [user.p_them()] instantly!</span>")
/obj/item/assembly/signaler/proc/manual_suicide(datum/mind/suicidee)
var/mob/living/user = suicidee.current
if(!istype(user))
return
if(suicide_mob == REF(user))
user.visible_message("<span class='suicide'>[user]'s [src] receives a signal, killing [user.p_them()] instantly!</span>")
else
user.visible_message("<span class='suicide'>[user]'s [src] receives a signal and [user.p_they()] die[user.p_s()] like a gamer!</span>")
user.adjustOxyLoss(200)//it sends an electrical pulse to their heart, killing them. or something.
user.death(0)
//user.set_suicide(TRUE)
user.suicide_log()
playsound(user, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
qdel(src)
/obj/item/assembly/signaler/Initialize()
. = ..()
set_frequency(frequency)
/obj/item/assembly/signaler/Destroy()
SSradio.remove_object(src,frequency)
suicider = null
. = ..()
/obj/item/assembly/signaler/activate()
@@ -53,11 +66,10 @@
return ..()
return UI_CLOSE
/obj/item/assembly/signaler/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/assembly/signaler/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Signaler", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "Signaler", name)
ui.open()
/obj/item/assembly/signaler/ui_data(mob/user)
@@ -66,12 +78,12 @@
data["code"] = code
data["minFrequency"] = MIN_FREE_FREQ
data["maxFrequency"] = MAX_FREE_FREQ
return data
/obj/item/assembly/signaler/ui_act(action, params)
if(..())
return
switch(action)
if("signal")
INVOKE_ASYNC(src, .proc/signal)
@@ -115,9 +127,6 @@
if(usr)
GLOB.lastsignalers.Add("[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]")
return
/obj/item/assembly/signaler/receive_signal(datum/signal/signal)
. = FALSE
if(!signal)
@@ -128,6 +137,7 @@
return
if(suicider)
manual_suicide(suicider)
return
pulse(TRUE)
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
for(var/CHM in get_hearers_in_view(hearing_range, src))
@@ -136,7 +146,6 @@
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
return TRUE
/obj/item/assembly/signaler/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
@@ -165,69 +174,8 @@
return
return ..(signal)
// Embedded signaller used in anomalies.
/obj/item/assembly/signaler/anomaly
name = "anomaly core"
desc = "The neutralized core of an anomaly. It'd probably be valuable for research."
icon_state = "anomaly core"
item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
resistance_flags = FIRE_PROOF
var/anomaly_type = /obj/effect/anomaly
/obj/item/assembly/signaler/anomaly/receive_signal(datum/signal/signal)
if(!signal)
return FALSE
if(signal.data["code"] != code)
return FALSE
if(suicider)
manual_suicide(suicider)
for(var/obj/effect/anomaly/A in get_turf(src))
A.anomalyNeutralize()
return TRUE
/obj/item/assembly/signaler/anomaly/manual_suicide(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user]'s [src] is reacting to the radio signal, warping [user.p_their()] body!</span>")
user.suiciding = TRUE
user.suicide_log()
user.gib()
/obj/item/assembly/signaler/anomaly/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_ANALYZER)
to_chat(user, "<span class='notice'>Analyzing... [src]'s stabilized field is fluctuating along frequency [format_frequency(frequency)], code [code].</span>")
..()
//Anomaly cores
/obj/item/assembly/signaler/anomaly/pyro
name = "\improper pyroclastic anomaly core"
desc = "The neutralized core of a pyroclastic anomaly. It feels warm to the touch. It'd probably be valuable for research."
icon_state = "pyro core"
anomaly_type = /obj/effect/anomaly/pyro
/obj/item/assembly/signaler/anomaly/grav
name = "\improper gravitational anomaly core"
desc = "The neutralized core of a gravitational anomaly. It feels much heavier than it looks. It'd probably be valuable for research."
icon_state = "grav core"
anomaly_type = /obj/effect/anomaly/grav
/obj/item/assembly/signaler/anomaly/flux
name = "\improper flux anomaly core"
desc = "The neutralized core of a flux anomaly. Touching it makes your skin tingle. It'd probably be valuable for research."
icon_state = "flux core"
anomaly_type = /obj/effect/anomaly/flux
/obj/item/assembly/signaler/anomaly/bluespace
name = "\improper bluespace anomaly core"
desc = "The neutralized core of a bluespace anomaly. It keeps phasing in and out of view. It'd probably be valuable for research."
icon_state = "anomaly core"
anomaly_type = /obj/effect/anomaly/bluespace
/obj/item/assembly/signaler/anomaly/vortex
name = "\improper vortex anomaly core"
desc = "The neutralized core of a vortex anomaly. It won't sit still, as if some invisible force is acting on it. It'd probably be valuable for research."
icon_state = "vortex core"
anomaly_type = /obj/effect/anomaly/bhole
/obj/item/assembly/signaler/anomaly/attack_self()
return
/obj/item/assembly/signaler/cyborg
+4 -6
View File
@@ -4,8 +4,7 @@
icon_state = "timer"
custom_materials = list(/datum/material/iron=500, /datum/material/glass=50)
attachable = TRUE
var/ui_x = 275
var/ui_y = 115
var/timing = FALSE
var/time = 5
var/saved_time = 5
@@ -88,11 +87,10 @@
return ..()
return UI_CLOSE
/obj/item/assembly/timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/assembly/timer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Timer", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "Timer", name)
ui.open()
/obj/item/assembly/timer/ui_data(mob/user)
+7
View File
@@ -94,6 +94,13 @@ Note: If your code uses output() with assets you will need to call asset_flush o
var/list/stacktrace = gib_stack_trace()
log_asset("WARNING: dupe asset added to the asset cache: [asset_name] existing asset md5: [OACI.md5] new asset md5:[ACI.md5]\n[stacktrace.Join("\n")]")
SSassets.cache[asset_name] = ACI
return ACI
/// Returns the url of the asset, currently this is just its name, here to allow further work cdn'ing assets.
/// Can be given an asset as well, this is just a work around for buggy edge cases where two assets may have the same name, doesn't matter now, but it will when the cdn comes.
/proc/get_asset_url(asset_name, asset = null)
var/datum/asset_cache_item/ACI = SSassets.cache[asset_name]
return ACI?.url
//Generated names do not include file extention.
//Used mainly for code that deals with assets in a generic way
@@ -5,6 +5,7 @@
**/
/datum/asset_cache_item
var/name
var/url
var/md5
var/resource
@@ -18,4 +19,5 @@
CRASH("invalid asset sent to asset cache")
debug_world_log("asset cache unexpected success of second fcopy_rsc")
src.name = name
url = name
resource = file
+34 -8
View File
@@ -16,6 +16,9 @@ GLOBAL_LIST_EMPTY(asset_datums)
GLOB.asset_datums[type] = src
register()
/datum/asset/proc/get_url_mappings()
return list()
/datum/asset/proc/register()
return
@@ -30,11 +33,19 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/simple/register()
for(var/asset_name in assets)
register_asset(asset_name, assets[asset_name])
assets[asset_name] = register_asset(asset_name, assets[asset_name])
/datum/asset/simple/send(client)
. = send_asset_list(client, assets)
/datum/asset/simple/get_url_mappings()
. = list()
for (var/asset_name in assets)
var/datum/asset_cache_item/ACI = assets[asset_name]
if (!ACI)
continue
.[asset_name] = ACI.url
// For registering or sending multiple others at once
/datum/asset/group
@@ -50,6 +61,11 @@ GLOBAL_LIST_EMPTY(asset_datums)
var/datum/asset/A = get_asset_datum(type)
. = A.send(C) || .
/datum/asset/group/get_url_mappings()
. = list()
for(var/type in children)
var/datum/asset/A = get_asset_datum(type)
. += A.get_url_mappings()
// spritesheet implementation - coalesces various icons into a single .png file
// and uses CSS to select icons out of that file - saves on transferring some
@@ -70,7 +86,9 @@ GLOBAL_LIST_EMPTY(asset_datums)
if (!name)
CRASH("spritesheet [type] cannot register without a name")
ensure_stripped()
for(var/size_id in sizes)
var/size = sizes[size_id]
register_asset("[name]_[size_id].png", size[SPRSZ_STRIPPED])
var/res_name = "spritesheet_[name].css"
var/fname = "data/spritesheets/[res_name]"
fdel(fname)
@@ -78,10 +96,6 @@ GLOBAL_LIST_EMPTY(asset_datums)
register_asset(res_name, fcopy_rsc(fname))
fdel(fname)
for(var/size_id in sizes)
var/size = sizes[size_id]
register_asset("[name]_[size_id].png", size[SPRSZ_STRIPPED])
/datum/asset/spritesheet/send(client/C)
if (!name)
return
@@ -90,6 +104,15 @@ GLOBAL_LIST_EMPTY(asset_datums)
all += "[name]_[size_id].png"
. = send_asset_list(C, all)
/datum/asset/spritesheet/get_url_mappings()
if (!name)
return
. = list("spritesheet_[name].css" = get_asset_url("spritesheet_[name].css"))
for(var/size_id in sizes)
.["[name]_[size_id].png"] = get_asset_url("[name]_[size_id].png")
/datum/asset/spritesheet/proc/ensure_stripped(sizes_to_strip = sizes)
for(var/size_id in sizes_to_strip)
var/size = sizes[size_id]
@@ -111,7 +134,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
for (var/size_id in sizes)
var/size = sizes[size_id]
var/icon/tiny = size[SPRSZ_ICON]
out += ".[name][size_id]{display:inline-block;width:[tiny.Width()]px;height:[tiny.Height()]px;background:url('[name]_[size_id].png') no-repeat;}"
out += ".[name][size_id]{display:inline-block;width:[tiny.Width()]px;height:[tiny.Height()]px;background:url('[get_asset_url("[name]_[size_id].png")]') no-repeat;}"
for (var/sprite_id in sprites)
var/sprite = sprites[sprite_id]
@@ -162,7 +185,10 @@ GLOBAL_LIST_EMPTY(asset_datums)
Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction)
/datum/asset/spritesheet/proc/css_tag()
return {"<link rel="stylesheet" href="spritesheet_[name].css" />"}
return {"<link rel="stylesheet" href="[css_filename()]" />"}
/datum/asset/spritesheet/proc/css_filename()
return get_asset_url("spritesheet_[name].css")
/datum/asset/spritesheet/proc/icon_tag(sprite_name)
var/sprite = sprites[sprite_name]
+17 -8
View File
@@ -6,12 +6,6 @@
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css',
)
/datum/asset/group/tgui
children = list(
/datum/asset/simple/tgui,
/datum/asset/simple/fontawesome
)
/datum/asset/simple/headers
assets = list(
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
@@ -78,6 +72,7 @@
"refresh" = 'icons/pda_icons/pda_refresh.png',
"scanner" = 'icons/pda_icons/pda_scanner.png',
"signaler" = 'icons/pda_icons/pda_signaler.png',
// "skills" = 'icons/pda_icons/pda_skills.png',
"status" = 'icons/pda_icons/pda_status.png',
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
"emoji" = 'icons/pda_icons/pda_emoji.png'
@@ -97,6 +92,10 @@
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png'
// "stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png'
// "stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png',
// "stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png',
// "stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png'
)
@@ -147,7 +146,6 @@
"jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js',
)
/datum/asset/simple/goonchat
assets = list(
"json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
@@ -375,7 +373,18 @@
"ghost.png" = 'html/ghost.png'
)
/datum/asset/simple/vv
assets = list(
"ghost.png" = 'html/ghost.png'
"view_variables.css" = 'html/admin/view_variables.css'
)
/datum/asset/spritesheet/sheetmaterials
name = "sheetmaterials"
/datum/asset/spritesheet/sheetmaterials/register()
InsertAll("", 'icons/obj/stack_objects.dmi')
// Special case to handle Bluespace Crystals
Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")
..()
@@ -237,11 +237,10 @@
return ..()
return UI_CLOSE
/obj/machinery/airalarm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/airalarm/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AirAlarm", name, 440, 650, master_ui, state)
ui = new(user, src, "AirAlarm", name)
ui.open()
/obj/machinery/airalarm/ui_data(mob/user)
@@ -26,9 +26,6 @@ Passive gate is similar to the regular pump except:
construction_type = /obj/item/pipe/directional
pipe_state = "passivegate"
ui_x = 335
ui_y = 115
/obj/machinery/atmospherics/components/binary/passive_gate/CtrlClick(mob/user)
if(can_interact(user))
on = !on
@@ -102,11 +99,10 @@ Passive gate is similar to the regular pump except:
))
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AtmosPump", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "AtmosPump", name)
ui.open()
/obj/machinery/atmospherics/components/binary/passive_gate/ui_data()
@@ -107,11 +107,10 @@
))
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "AtmosPump", name, 335, 115, master_ui, state)
ui = new(user, src, "AtmosPump", name)
ui.open()
/obj/machinery/atmospherics/components/binary/pump/ui_data()
@@ -60,15 +60,14 @@
else if(!opened && our_pressure >= open_pressure)
open()
/obj/machinery/atmospherics/components/binary/relief_valve/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/atmospherics/components/binary/relief_valve/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "atmos_relief", name, 335, 115, master_ui, state)
ui = new(user, src, "AtmosRelief", name)
ui.open()
/obj/machinery/atmospherics/components/binary/relief_valve/ui_data()
var/data = list()
var/list/data = list()
data["open_pressure"] = round(open_pressure)
data["close_pressure"] = round(close_pressure)
data["max_pressure"] = round(50*ONE_ATMOSPHERE)
@@ -79,11 +78,11 @@
return
switch(action)
if("open_pressure")
var/pressure = params["open_pressure"]
var/pressure = params["pressure"]
if(pressure == "max")
pressure = 50*ONE_ATMOSPHERE
. = TRUE
else if(pressure == "input")
else if(pressure == "input") // The manual expirience.
pressure = input("New output pressure ([close_pressure]-[50*ONE_ATMOSPHERE] kPa):", name, open_pressure) as num|null
if(!isnull(pressure) && !..())
. = TRUE
@@ -94,7 +93,7 @@
open_pressure = clamp(pressure, close_pressure, 50*ONE_ATMOSPHERE)
investigate_log("open pressure was set to [open_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
if("close_pressure")
var/pressure = params["close_pressure"]
var/pressure = params["pressure"]
if(pressure == "max")
pressure = open_pressure
. = TRUE

Some files were not shown because too many files have changed in this diff Show More