mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-12 19:22:56 +00:00
Merge pull request #7275 from atlantiscze/substation-features
RCON System
This commit is contained in:
60
code/datums/wires/smes.dm
Normal file
60
code/datums/wires/smes.dm
Normal file
@@ -0,0 +1,60 @@
|
||||
/datum/wires/smes
|
||||
holder_type = /obj/machinery/power/smes/buildable
|
||||
wire_count = 5
|
||||
|
||||
var/const/SMES_WIRE_RCON = 1 // Remote control (AI and consoles), cut to disable
|
||||
var/const/SMES_WIRE_INPUT = 2 // Input wire, cut to disable input, pulse to disable for 60s
|
||||
var/const/SMES_WIRE_OUTPUT = 4 // Output wire, cut to disable output, pulse to disable for 60s
|
||||
var/const/SMES_WIRE_GROUNDING = 8 // Cut to quickly discharge causing sparks, pulse to only create few sparks
|
||||
var/const/SMES_WIRE_FAILSAFES = 16 // Cut to disable failsafes, mend to reenable
|
||||
|
||||
|
||||
/datum/wires/smes/CanUse(var/mob/living/L)
|
||||
var/obj/machinery/power/smes/buildable/S = holder
|
||||
if(S.open_hatch)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/datum/wires/smes/GetInteractWindow()
|
||||
var/obj/machinery/power/smes/buildable/S = holder
|
||||
. += ..()
|
||||
. += "The green light is [(S.input_cut || S.input_pulsed || S.output_cut || S.output_pulsed) ? "off" : "on"]<br>"
|
||||
. += "The red light is [(S.safeties_enabled || S.grounding) ? "off" : "blinking"]<br>"
|
||||
. += "The blue light is [S.RCon ? "on" : "off"]"
|
||||
|
||||
|
||||
/datum/wires/smes/UpdateCut(var/index, var/mended)
|
||||
var/obj/machinery/power/smes/buildable/S = holder
|
||||
switch(index)
|
||||
if(SMES_WIRE_RCON)
|
||||
S.RCon = mended
|
||||
if(SMES_WIRE_INPUT)
|
||||
S.input_cut = !mended
|
||||
if(SMES_WIRE_OUTPUT)
|
||||
S.output_cut = !mended
|
||||
if(SMES_WIRE_GROUNDING)
|
||||
S.grounding = mended
|
||||
if(SMES_WIRE_FAILSAFES)
|
||||
S.safeties_enabled = mended
|
||||
|
||||
|
||||
/datum/wires/smes/UpdatePulsed(var/index)
|
||||
var/obj/machinery/power/smes/buildable/S = holder
|
||||
switch(index)
|
||||
if(SMES_WIRE_RCON)
|
||||
if(S.RCon)
|
||||
S.RCon = 0
|
||||
spawn(10)
|
||||
S.RCon = 1
|
||||
if(SMES_WIRE_INPUT)
|
||||
S.toggle_input()
|
||||
if(SMES_WIRE_OUTPUT)
|
||||
S.toggle_output()
|
||||
if(SMES_WIRE_GROUNDING)
|
||||
S.grounding = 0
|
||||
if(SMES_WIRE_FAILSAFES)
|
||||
if(S.safeties_enabled)
|
||||
S.safeties_enabled = 0
|
||||
spawn(10)
|
||||
S.safeties_enabled = 1
|
||||
116
code/game/machinery/computer/RCON_Console.dm
Normal file
116
code/game/machinery/computer/RCON_Console.dm
Normal file
@@ -0,0 +1,116 @@
|
||||
/obj/item/weapon/circuitboard/rcon_console
|
||||
name = "\improper RCON Remote Control Console circuit board"
|
||||
build_path = /obj/machinery/computer/rcon
|
||||
origin_tech = "programming=4;engineering=3;powerstorage=5"
|
||||
|
||||
/obj/machinery/computer/rcon
|
||||
name = "RCON Console"
|
||||
desc = "Console used to remotely control machinery on the station."
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "ai-fixer"
|
||||
circuit = /obj/item/weapon/circuitboard/rcon_console
|
||||
req_one_access = list(access_engine)
|
||||
var/current_tag = null
|
||||
var/list/known_SMESs = null
|
||||
var/list/known_breakers = null
|
||||
|
||||
/obj/machinery/computer/rcon/attack_ai(var/mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/rcon/attack_hand(var/mob/user as mob)
|
||||
..()
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/rcon/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
FindDevices() // Update our devices list
|
||||
var/data[0]
|
||||
|
||||
// SMES DATA (simplified view)
|
||||
var/list/smeslist[0]
|
||||
for(var/obj/machinery/power/smes/buildable/SMES in known_SMESs)
|
||||
smeslist.Add(list(list(
|
||||
"charge" = round(SMES.Percentage()),
|
||||
"input_set" = SMES.input_attempt,
|
||||
"input_val" = round(SMES.input_level),
|
||||
"output_set" = SMES.output_attempt,
|
||||
"output_val" = round(SMES.output_level),
|
||||
"output_load" = round(SMES.output_used),
|
||||
"RCON_tag" = SMES.RCon_tag
|
||||
)))
|
||||
data["smes_info"] = smeslist
|
||||
|
||||
// BREAKER DATA (simplified view)
|
||||
var/list/breakerlist[0]
|
||||
for(var/obj/machinery/power/breakerbox/BR in known_breakers)
|
||||
breakerlist.Add(list(list(
|
||||
"RCON_tag" = BR.RCon_tag,
|
||||
"enabled" = BR.on
|
||||
)))
|
||||
data["breaker_info"] = breakerlist
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "rcon.tmpl", "RCON Control Console", 600, 400)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/computer/rcon/Topic(href, href_list)
|
||||
if(href_list["smes_in_toggle"])
|
||||
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_in_toggle"])
|
||||
if(SMES)
|
||||
SMES.toggle_input()
|
||||
if(href_list["smes_out_toggle"])
|
||||
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_out_toggle"])
|
||||
if(SMES)
|
||||
SMES.toggle_output()
|
||||
if(href_list["smes_in_set"])
|
||||
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_in_set"])
|
||||
if(SMES)
|
||||
var/inputset = input(usr, "Enter new input level (0-[SMES.input_level_max])", "SMES Input Power Control") as num
|
||||
SMES.set_input(inputset)
|
||||
if(href_list["smes_out_set"])
|
||||
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_out_set"])
|
||||
if(SMES)
|
||||
var/outputset = input(usr, "Enter new output level (0-[SMES.output_level_max])", "SMES Input Power Control") as num
|
||||
SMES.set_output(outputset)
|
||||
|
||||
if(href_list["toggle_breaker"])
|
||||
var/obj/machinery/power/breakerbox/toggle = null
|
||||
for(var/obj/machinery/power/breakerbox/breaker in known_breakers)
|
||||
if(breaker.RCon_tag == href_list["toggle_breaker"])
|
||||
toggle = breaker
|
||||
if(toggle)
|
||||
if(toggle.update_locked)
|
||||
usr << "The breaker box was recently toggled. Please wait before toggling it again."
|
||||
else
|
||||
toggle.auto_toggle()
|
||||
|
||||
/obj/machinery/computer/rcon/proc/GetSMESByTag(var/tag)
|
||||
if(!tag)
|
||||
return
|
||||
|
||||
for(var/obj/machinery/power/smes/buildable/S in known_SMESs)
|
||||
if(S.RCon_tag == tag)
|
||||
return S
|
||||
|
||||
/obj/machinery/computer/rcon/proc/FindDevices()
|
||||
known_SMESs = new /list()
|
||||
for(var/obj/machinery/power/smes/buildable/SMES in machines)
|
||||
if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon)
|
||||
known_SMESs.Add(SMES)
|
||||
|
||||
known_breakers = new /list()
|
||||
for(var/obj/machinery/power/breakerbox/breaker in machines)
|
||||
if(breaker.RCon_tag != "NO_TAG")
|
||||
known_breakers.Add(breaker)
|
||||
@@ -17,6 +17,8 @@
|
||||
var/on = 0
|
||||
var/busy = 0
|
||||
var/directions = list(1,2,4,8,5,6,9,10)
|
||||
var/RCon_tag = "NO_TAG"
|
||||
var/update_locked = 0
|
||||
|
||||
/obj/machinery/power/breakerbox/activated
|
||||
icon_state = "bbox_on"
|
||||
@@ -33,19 +35,29 @@
|
||||
user << "\red It seems to be offline"
|
||||
|
||||
/obj/machinery/power/breakerbox/attack_ai(mob/user)
|
||||
if(update_locked)
|
||||
user << "\red System locked. Please try again later."
|
||||
return
|
||||
|
||||
if(busy)
|
||||
user << "\red System is busy. Please wait until current operation is finished before changing power settings."
|
||||
return
|
||||
|
||||
busy = 1
|
||||
user << "\green Updating power settings.."
|
||||
if(do_after(user, 50)) //5s for AI as AIs can manipulate electronics much faster.
|
||||
if(do_after(user, 50))
|
||||
set_state(!on)
|
||||
user << "\green Update Completed. New setting:[on ? "on": "off"]"
|
||||
update_locked = 1
|
||||
spawn(600)
|
||||
update_locked = 0
|
||||
busy = 0
|
||||
|
||||
|
||||
/obj/machinery/power/breakerbox/attack_hand(mob/user)
|
||||
if(update_locked)
|
||||
user << "\red System locked. Please try again later."
|
||||
return
|
||||
|
||||
if(busy)
|
||||
user << "\red System is busy. Please wait until current operation is finished before changing power settings."
|
||||
@@ -55,13 +67,27 @@
|
||||
for(var/mob/O in viewers(user))
|
||||
O.show_message(text("\red [user] started reprogramming [src]!"), 1)
|
||||
|
||||
if(do_after(user, 300)) // 30s for non-AIs as humans have to manually reprogram it and rapid switching may cause some lag / powernet updates flood. If AIs spam it they can be easily traced.
|
||||
if(do_after(user, 50))
|
||||
set_state(!on)
|
||||
user.visible_message(\
|
||||
"<span class='notice'>[user.name] [on ? "enabled" : "disabled"] the breaker box!</span>",\
|
||||
"<span class='notice'>You [on ? "enabled" : "disabled"] the breaker box!</span>")
|
||||
update_locked = 1
|
||||
spawn(600)
|
||||
update_locked = 0
|
||||
busy = 0
|
||||
|
||||
/obj/machinery/power/breakerbox/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if(istype(W, /obj/item/device/multitool))
|
||||
var/newtag = input(user, "Enter new RCON tag. Use \"NO_TAG\" to disable RCON or leave empty to cancel.", "SMES RCON system") as text
|
||||
if(newtag)
|
||||
RCon_tag = newtag
|
||||
user << "<span class='notice'>You changed the RCON tag to: [newtag]</span>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/machinery/power/breakerbox/proc/set_state(var/state)
|
||||
on = state
|
||||
if(on)
|
||||
@@ -93,3 +119,14 @@
|
||||
icon_state = icon_state_off
|
||||
for(var/obj/structure/cable/C in src.loc)
|
||||
del(C)
|
||||
|
||||
// Used by RCON to toggle the breaker box.
|
||||
/obj/machinery/power/breakerbox/proc/auto_toggle()
|
||||
if(!update_locked)
|
||||
set_state(!on)
|
||||
update_locked = 1
|
||||
spawn(600)
|
||||
update_locked = 0
|
||||
|
||||
/obj/machinery/power/breakerbox/process()
|
||||
return 1
|
||||
@@ -32,6 +32,11 @@
|
||||
var/last_input_attempt = 0
|
||||
var/last_charge = 0
|
||||
|
||||
var/input_cut = 0
|
||||
var/input_pulsed = 0
|
||||
var/output_cut = 0
|
||||
var/output_pulsed = 0
|
||||
|
||||
var/open_hatch = 0
|
||||
var/name_tag = null
|
||||
var/building_terminal = 0 //Suggestions about how to avoid clickspam building several terminals accepted!
|
||||
@@ -120,7 +125,7 @@
|
||||
var/last_onln = outputting
|
||||
|
||||
//inputting
|
||||
if(input_attempt)
|
||||
if(input_attempt && (!input_pulsed && !input_cut))
|
||||
var/target_load = min((capacity-charge)/SMESRATE, input_level) // charge at set rate, limited to spare capacity
|
||||
var/actual_load = draw_power(target_load) // add the load to the terminal side network
|
||||
charge += actual_load * SMESRATE // increase the charge
|
||||
@@ -133,7 +138,7 @@
|
||||
inputting = 0
|
||||
|
||||
//outputting
|
||||
if(outputting)
|
||||
if(outputting && (!output_pulsed && !output_cut))
|
||||
output_used = min( charge/SMESRATE, output_level) //limit output to that stored
|
||||
|
||||
charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive)
|
||||
@@ -319,6 +324,8 @@
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/power/smes/proc/Percentage()
|
||||
return round(100.0*charge/capacity, 0.1)
|
||||
|
||||
/obj/machinery/power/smes/Topic(href, href_list)
|
||||
..()
|
||||
@@ -425,6 +432,4 @@
|
||||
|
||||
/obj/machinery/power/smes/magical/process()
|
||||
charge = 5000000
|
||||
..()
|
||||
|
||||
#undef SMESRATE
|
||||
..()
|
||||
@@ -31,13 +31,36 @@
|
||||
var/cur_coils = 1 // Current amount of installed coils
|
||||
var/safeties_enabled = 1 // If 0 modifications can be done without discharging the SMES, at risk of critical failure.
|
||||
var/failing = 0 // If 1 critical failure has occured and SMES explosion is imminent.
|
||||
var/datum/wires/smes/wires
|
||||
var/grounding = 1 // Cut to quickly discharge, at cost of "minor" electrical issues in output powernet.
|
||||
var/RCon = 1 // Cut to disable AI and remote control.
|
||||
var/RCon_tag = "NO_TAG" // RCON tag, change to show it on SMES Remote control console.
|
||||
charge = 0
|
||||
should_be_mapped = 1
|
||||
|
||||
/obj/machinery/power/smes/buildable/process()
|
||||
if(!grounding && (Percentage() > 5))
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
charge -= (output_level_max * SMESRATE)
|
||||
if(prob(1)) // Small chance of overload occuring since grounding is disabled.
|
||||
apcs_overload(5,10)
|
||||
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/power/smes/buildable/attack_ai()
|
||||
if(RCon)
|
||||
..()
|
||||
else // RCON wire cut
|
||||
usr << "<span class='warning'>Connection error: Destination Unreachable.</span>"
|
||||
|
||||
/obj/machinery/power/smes/buildable/New()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/stack/cable_coil(src,30)
|
||||
component_parts += new /obj/item/weapon/circuitboard/smes(src)
|
||||
src.wires = new /datum/wires/smes(src)
|
||||
|
||||
// Allows for mapped-in SMESs with larger capacity/IO
|
||||
for(var/i = 1, i <= cur_coils, i++)
|
||||
@@ -46,6 +69,11 @@
|
||||
recalc_coils()
|
||||
..()
|
||||
|
||||
/obj/machinery/power/smes/buildable/attack_hand()
|
||||
..()
|
||||
if(open_hatch)
|
||||
wires.Interact(usr)
|
||||
|
||||
/obj/machinery/power/smes/buildable/proc/recalc_coils()
|
||||
if ((cur_coils <= max_coils) && (cur_coils >= 1))
|
||||
capacity = 0
|
||||
@@ -205,8 +233,15 @@
|
||||
// - No action was taken in parent function (terminal de/construction atm).
|
||||
if (..())
|
||||
|
||||
// Multitool - change RCON tag
|
||||
if(istype(W, /obj/item/device/multitool))
|
||||
var/newtag = input(user, "Enter new RCON tag. Use \"NO_TAG\" to disable RCON or leave empty to cancel.", "SMES RCON system") as text
|
||||
if(newtag)
|
||||
RCon_tag = newtag
|
||||
user << "<span class='notice'>You changed the RCON tag to: [newtag]</span>"
|
||||
return
|
||||
// Charged above 1% and safeties are enabled.
|
||||
if((charge > (capacity/100)) && safeties_enabled && (!istype(W, /obj/item/device/multitool)))
|
||||
if((charge > (capacity/100)) && safeties_enabled)
|
||||
user << "<span class='warning'>Safety circuit of [src] is preventing modifications while it's charged!</span>"
|
||||
return
|
||||
|
||||
@@ -263,8 +298,18 @@
|
||||
else
|
||||
usr << "\red You can't insert more coils to this SMES unit!"
|
||||
|
||||
// Multitool - Toggle the safeties.
|
||||
else if(istype(W, /obj/item/device/multitool))
|
||||
safeties_enabled = !safeties_enabled
|
||||
user << "<span class='warning'>You [safeties_enabled ? "connected" : "disconnected"] the safety circuit.</span>"
|
||||
src.visible_message("\icon[src] <b>[src]</b> beeps: \"Caution. Safety circuit has been: [safeties_enabled ? "re-enabled" : "disabled. Please excercise caution."]\"")
|
||||
/obj/machinery/power/smes/buildable/proc/toggle_input()
|
||||
input_attempt = !input_attempt
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/power/smes/buildable/proc/toggle_output()
|
||||
output_attempt = !output_attempt
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/power/smes/buildable/proc/set_input(var/new_input = 0)
|
||||
input_level = new_input
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/power/smes/buildable/proc/set_output(var/new_output = 0)
|
||||
output_level = new_output
|
||||
update_icon()
|
||||
@@ -202,6 +202,15 @@ datum/design/air_management
|
||||
materials = list("$glass" = 2000, "sacid" = 20)
|
||||
build_path = /obj/item/weapon/circuitboard/air_management
|
||||
|
||||
datum/design/rcon_console
|
||||
name = "Circuit Design (RCON Console)"
|
||||
desc = "Allows for the construction of circuit boards used to build an RCON Remote Control Console."
|
||||
id = "rcon_console"
|
||||
req_tech = list("programming" = 4, "engineering" = 3, "powerstorage" = 5)
|
||||
build_type = IMPRINTER
|
||||
materials = list("$glass" = 2000, "sacid" = 20)
|
||||
build_path = /obj/item/weapon/circuitboard/rcon_console
|
||||
|
||||
/* Uncomment if someone makes these buildable
|
||||
datum/design/general_alert
|
||||
name = "Circuit Design (General Alert Console)"
|
||||
|
||||
Reference in New Issue
Block a user