From 8a0c932d554f95b83ef133ab22b32e3dbadb9e82 Mon Sep 17 00:00:00 2001
From: Letter N <24603524+LetterN@users.noreply.github.com>
Date: Fri, 12 Feb 2021 11:07:58 +0800
Subject: [PATCH] oops! All Refactors!
---
.../configuration/entries/comms.dm | 10 +-
code/datums/shuttles.dm | 211 +-
code/datums/view.dm | 2 -
code/datums/world_topic.dm | 4 +-
code/game/gamemodes/meteor/meteors.dm | 2 +-
code/game/machinery/computer/arcade.dm | 2 +-
.../game/machinery/computer/communications.dm | 1169 +++++------
.../items/circuitboards/circuitboard.dm | 40 +-
.../circuitboards/computer_circuitboards.dm | 700 ++++---
.../circuitboards/machine_circuitboards.dm | 1763 +++++++++--------
code/game/objects/items/storage/boxes.dm | 4 +-
code/modules/admin/verbs/adminhelp.dm | 48 +-
code/modules/admin/verbs/pray.dm | 43 +-
code/modules/cargo/console.dm | 37 +-
code/modules/client/client_procs.dm | 2 +-
code/modules/client/preferences.dm | 19 +-
.../kitchen_machinery/smartfridge.dm | 67 +-
code/modules/mapping/map_template.dm | 3 +
code/modules/mapping/verify.dm | 2 +-
.../modules/research/machinery/_production.dm | 5 +-
.../research/machinery/circuit_imprinter.dm | 9 -
code/modules/research/machinery/protolathe.dm | 9 -
config/comms.txt | 12 +-
tgui/packages/tgui/interfaces/Cargo.js | 123 +-
24 files changed, 2304 insertions(+), 1982 deletions(-)
diff --git a/code/controllers/configuration/entries/comms.dm b/code/controllers/configuration/entries/comms.dm
index e56ff3f0d1..254622d8ae 100644
--- a/code/controllers/configuration/entries/comms.dm
+++ b/code/controllers/configuration/entries/comms.dm
@@ -22,11 +22,10 @@
/datum/config_entry/string/cross_comms_name
-/datum/config_entry/string/medal_hub_address
-
-/datum/config_entry/string/medal_hub_password
- protection = CONFIG_ENTRY_HIDDEN
+/datum/config_entry/string/cross_comms_network
+ protection = CONFIG_ENTRY_LOCKED
+/// cit config
/datum/config_entry/keyed_list/cross_server_bunker_override
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_TEXT
@@ -42,6 +41,3 @@
/datum/config_entry/keyed_list/cross_server_bunker_override/ValidateListEntry(key_name, key_value)
return key_value != "byond:\\address:port" && ..()
-
-/datum/config_entry/flag/allow_cross_server_bunker_override
- protection = CONFIG_ENTRY_LOCKED
diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm
index e2e6a05b08..17116b922b 100644
--- a/code/datums/shuttles.dm
+++ b/code/datums/shuttles.dm
@@ -8,12 +8,16 @@
var/description
var/prerequisites
var/admin_notes
-
+ /// How much does this shuttle cost the cargo budget to purchase? Put in terms of CARGO_CRATE_VALUE to properly scale the cost with the current balance of cargo's income.
var/credit_cost = INFINITY
+ /// Can the be legitimately purchased by the station? Used by hardcoded or pre-mapped shuttles like the lavaland or cargo shuttle.
var/can_be_bought = TRUE
+ /// If set, overrides default movement_force on shuttle
+ var/list/movement_force
var/port_x_offset
var/port_y_offset
+ var/extra_desc = ""
/datum/map_template/shuttle/proc/prerequisites_met()
return TRUE
@@ -23,7 +27,7 @@
mappath = "[prefix][shuttle_id].dmm"
. = ..()
-/datum/map_template/shuttle/preload_size(path = mappath, force_cache = FALSE)
+/datum/map_template/shuttle/preload_size(path, force_cache)
. = ..(path, TRUE) // Done this way because we still want to know if someone actualy wanted to cache the map
if(!cached_map)
return
@@ -64,6 +68,9 @@
continue
if(length(place.baseturfs) < 2) // Some snowflake shuttle shit
continue
+ // var/list/sanity = place.baseturfs.Copy() // we do not have new baseturfs yet
+ // sanity.Insert(3, /turf/baseturf_skipover/shuttle)
+ // place.baseturfs = baseturfs_string_list(sanity, place)
place.baseturfs.Insert(3, /turf/baseturf_skipover/shuttle)
for(var/obj/docking_port/mobile/port in place)
@@ -93,6 +100,7 @@
port.dwidth = port_y_offset - 1
port.dheight = width - port_x_offset
+ // these three for loops are cit specific.
for(var/obj/structure/closet/closet in place)
if(closet.anchorable)
closet.anchored = TRUE
@@ -104,11 +112,10 @@
rack.AddComponent(/datum/component/magnetic_catch)
//Whatever special stuff you want
-/datum/map_template/shuttle/proc/post_load(obj/docking_port/mobile/M)
- return
-
-/datum/map_template/shuttle/proc/on_bought()
- return
+/datum/map_template/shuttle/post_load(obj/docking_port/mobile/M)
+ if(movement_force)
+ M.movement_force = movement_force.Copy()
+ M.linkup()
/datum/map_template/shuttle/emergency
port_id = "emergency"
@@ -117,6 +124,7 @@
/datum/map_template/shuttle/cargo
port_id = "cargo"
name = "Base Shuttle Template (Cargo)"
+ can_be_bought = FALSE
/datum/map_template/shuttle/ferry
port_id = "ferry"
@@ -137,10 +145,6 @@
port_id = "mining_common"
can_be_bought = FALSE
-/datum/map_template/shuttle/cargo
- port_id = "cargo"
- can_be_bought = FALSE
-
/datum/map_template/shuttle/arrival
port_id = "arrival"
can_be_bought = FALSE
@@ -189,21 +193,23 @@
name = "Backup Shuttle"
can_be_bought = FALSE
-/datum/map_template/shuttle/emergency/airless
- suffix = "airless"
+/datum/map_template/shuttle/emergency/construction
+ suffix = "construction"
name = "Build your own shuttle kit"
- description = "Save money by building your own shuttle! The chassis will dock upon purchase, but launch will have to be authorized as usual via shuttle call. Interior and lighting not included."
+ description = "For the enterprising shuttle engineer! The chassis will dock upon purchase, but launch will have to be authorized as usual via shuttle call. Comes stocked with construction materials. Unlocks the ability to buy shuttle engine crates from cargo."
admin_notes = "No brig, no medical facilities, just an empty box."
credit_cost = -7500
-/datum/map_template/shuttle/emergency/airless/prerequisites_met()
+/datum/map_template/shuttle/emergency/construction/prerequisites_met()
// first 10 minutes only
return world.time - SSticker.round_start_time < 6000
-/datum/map_template/shuttle/emergency/airless/on_bought()
- //enable buying engines from cargo
- var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
- P.special_enabled = TRUE
+// this is broken and does not work. Thanks TG
+// /datum/map_template/shuttle/emergency/airless/post_load()
+// . = ..()
+// //enable buying engines from cargo
+// var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
+// P.special_enabled = TRUE
/datum/map_template/shuttle/emergency/asteroid
@@ -220,6 +226,13 @@
Has medical facilities."
credit_cost = 5000
+// /datum/map_template/shuttle/emergency/pod
+// suffix = "pod"
+// name = "Emergency Pods"
+// description = "We did not expect an evacuation this quickly. All we have available is two escape pods."
+// admin_notes = "For player punishment."
+// can_be_bought = FALSE
+
/datum/map_template/shuttle/emergency/russiafightpit
suffix = "russiafightpit"
name = "Mother Russia Bleeds"
@@ -230,9 +243,10 @@
/datum/map_template/shuttle/emergency/meteor
suffix = "meteor"
name = "Asteroid With Engines Strapped To It"
- description = "A hollowed out asteroid with engines strapped to it. Due to its size and difficulty in steering it, this shuttle may damage the docking area."
+ description = "A hollowed out asteroid with engines strapped to it, the hollowing procedure makes it very difficult to hijack but is very expensive. Due to its size and difficulty in steering it, this shuttle may damage the docking area."
admin_notes = "This shuttle will likely crush escape, killing anyone there."
credit_cost = -5000
+ movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
/datum/map_template/shuttle/emergency/luxury
suffix = "luxury"
@@ -247,6 +261,7 @@
description = "The glorious results of centuries of plasma research done by Nanotrasen employees. This is the reason why you are here. Get on and dance like you're on fire, burn baby burn!"
admin_notes = "Flaming hot. The main area has a dance machine as well as plasma floor tiles that will be ignited by players every single time."
credit_cost = 10000
+ // can_be_bought = FALSE
/datum/map_template/shuttle/emergency/arena
suffix = "arena"
@@ -254,11 +269,22 @@
description = "The crew must pass through an otherworldy arena to board this shuttle. Expect massive casualties. The source of the Bloody Signal must be tracked down and eliminated to unlock this shuttle."
admin_notes = "RIP AND TEAR."
credit_cost = 10000
+ /// Whether the arena z-level has been created
+ var/arena_loaded = FALSE
/datum/map_template/shuttle/emergency/arena/prerequisites_met()
- if("bubblegum" in SSshuttle.shuttle_purchase_requirements_met)
- return TRUE
- return FALSE
+ return SSshuttle.shuttle_purchase_requirements_met["bubblegum"]
+
+/datum/map_template/shuttle/emergency/arena/post_load(obj/docking_port/mobile/M)
+ . = ..()
+ if(!arena_loaded)
+ arena_loaded = TRUE
+ var/datum/map_template/arena/arena_template = new()
+ arena_template.load_new_z()
+
+/datum/map_template/arena
+ name = "The Arena"
+ mappath = "_maps/templates/the_arena.dmm"
/datum/map_template/shuttle/emergency/birdboat
suffix = "birdboat"
@@ -272,6 +298,13 @@
credit_cost = 2000
description = "The gold standard in emergency exfiltration, this tried and true design is equipped with everything the crew needs for a safe flight home."
+// /datum/map_template/shuttle/emergency/donut
+// suffix = "donut"
+// name = "Donutstation Emergency Shuttle"
+// description = "The perfect spearhead for any crude joke involving the station's shape, this shuttle supports a separate containment cell for prisoners and a compact medical wing."
+// admin_notes = "Has airlocks on both sides of the shuttle and will probably intersect near the front on some stations that build past departures."
+// credit_cost = 2500
+
/datum/map_template/shuttle/emergency/clown
suffix = "clown"
name = "Snappop(tm)!"
@@ -316,7 +349,9 @@
credit_cost = -1000
description = "Due to a lack of functional emergency shuttles, we bought this second hand from a scrapyard and pressed it into service. Please do not lean too heavily on the exterior windows, they are fragile."
admin_notes = "An abomination with no functional medbay, sections missing, and some very fragile windows. Surprisingly airtight."
+ movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
+// CIT SPECIFIC
/datum/map_template/shuttle/emergency/syndicate
suffix = "syndicate"
name = "Syndicate GM Battlecruiser"
@@ -325,9 +360,7 @@
admin_notes = "An emag exclusive, stocked with syndicate equipment and turrets that will target any simplemob."
/datum/map_template/shuttle/emergency/syndicate/prerequisites_met()
- if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
- return TRUE
- return FALSE
+ return SSshuttle.shuttle_purchase_requirements_met["emagged"]
/datum/map_template/shuttle/emergency/narnar
suffix = "narnar"
@@ -335,6 +368,10 @@
description = "Looks like this shuttle may have wandered into the darkness between the stars on route to the station. Let's not think too hard about where all the bodies came from."
admin_notes = "Contains real cult ruins, mob eyeballs, and inactive constructs. Cult mobs will automatically be sentienced by fun balloon. \
Cloning pods in 'medbay' area are showcases and nonfunctional."
+ credit_cost = 6667 ///The joke is the number so no defines
+
+/datum/map_template/shuttle/emergency/narnar/prerequisites_met()
+ return SSshuttle.shuttle_purchase_requirements_met["narsie"]
/datum/map_template/shuttle/emergency/pubby
suffix = "pubby"
@@ -354,7 +391,7 @@
/datum/map_template/shuttle/emergency/supermatter
suffix = "supermatter"
name = "Hyperfractal Gigashuttle"
- description = "(Emag only) \"I dunno, this seems kinda needlessly complicated.\"\n\
+ description = "\"I dunno, this seems kinda needlessly complicated.\"\n\
\"This shuttle has very a very high safety record, according to CentCom Officer Cadet Yins.\"\n\
\"Are you sure?\"\n\
\"Yes, it has a safety record of N-A-N, which is apparently larger than 100%.\""
@@ -363,19 +400,19 @@
It does, however, still dust anything on contact, emits high levels of radiation, and induce hallucinations in anyone looking at it without protective goggles. \
Emitters spawn powered on, expect admin notices, they are harmless."
credit_cost = 15000
+ movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
/datum/map_template/shuttle/emergency/supermatter/prerequisites_met()
- if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
- return TRUE
- return FALSE
-
+ return SSshuttle.shuttle_purchase_requirements_met["emagged"]
/datum/map_template/shuttle/emergency/imfedupwiththisworld
suffix = "imfedupwiththisworld"
name = "Oh, Hi Daniel"
description = "How was space work today? Oh, pretty good. We got a new space station and the company will make a lot of money. What space station? I cannot tell you; it's space confidential. \
Aw, come space on. Why not? No, I can't. Anyway, how is your space roleplay life?"
admin_notes = "Tiny, with a single airlock and wooden walls. What could go wrong?"
+ // can_be_bought = FALSE
credit_cost = -5000
+ movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
/datum/map_template/shuttle/emergency/goon
suffix = "goon"
@@ -383,6 +420,14 @@
description = "The Nanotrasen Emergency Shuttle Port(NES Port for short) is a shuttle used at other less known Nanotrasen facilities and has a more open inside for larger crowds, but fewer onboard shuttle facilities."
credit_cost = 500
+// /datum/map_template/shuttle/emergency/rollerdome
+// suffix = "rollerdome"
+// name = "Uncle Pete's Rollerdome"
+// description = "Developed by a member of Nanotrasen's R&D crew that claims to have travelled from the year 2028.
+// He says this shuttle is based off an old entertainment complex from the 1990s, though our database has no records on anything pertaining to that decade."
+// admin_notes = "ONLY NINETIES KIDS REMEMBER. Uses the fun balloon and drone from the Emergency Bar."
+// credit_cost = 500 * 5
+
/datum/map_template/shuttle/emergency/wabbajack
suffix = "wabbajack"
name = "NT Lepton Violet"
@@ -398,6 +443,7 @@
description = "On the smaller size with a modern design, this shuttle is for the crew who like the cosier things, while still being able to stretch their legs."
credit_cost = 1000
+// CIT SPECIFIC
/datum/map_template/shuttle/emergency/gorilla
suffix = "gorilla"
name = "Gorilla Cargo Freighter"
@@ -405,11 +451,17 @@
credit_cost = 2000
/datum/map_template/shuttle/emergency/gorilla/prerequisites_met()
- if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
- return TRUE
- return FALSE
+ return SSshuttle.shuttle_purchase_requirements_met["emagged"]
+
/datum/map_template/shuttle/emergency/cruise
+ suffix = "cruise"
+ name = "The NTSS Independence"
+ description = "Ordinarily reserved for special functions and events, the Cruise Shuttle Independence can bring a summery cheer to your next station evacuation for a 'modest' fee!"
+ admin_notes = "This motherfucker is BIG. You might need to force dock it."
+ credit_cost = 8000
+
+/datum/map_template/shuttle/emergency/monkey
suffix = "nature"
name = "Dynamic Environmental Interaction Shuttle"
description = "A large shuttle with a center biodome that is flourishing with life. Frolick with the monkeys! (Extra monkeys are stored on the bridge.)"
@@ -441,7 +493,7 @@
/datum/map_template/shuttle/ferry/fancy
suffix = "fancy"
name = "fancy transport ferry"
- description = "At some point, someone upgraded the ferry to have fancier flooring... and less seats."
+ description = "At some point, someone upgraded the ferry to have fancier flooring... and fewer seats."
/datum/map_template/shuttle/ferry/kilo
suffix = "kilo"
@@ -464,6 +516,14 @@
suffix = "cere"
name = "NT Construction Vessel"
+// /datum/map_template/shuttle/whiteship/kilo
+// suffix = "kilo"
+// name = "NT Mining Shuttle"
+
+// /datum/map_template/shuttle/whiteship/donut
+// suffix = "donut"
+// name = "NT Long-Distance Bluespace Jumper"
+
/datum/map_template/shuttle/whiteship/delta
suffix = "delta"
name = "NT Frigate"
@@ -476,10 +536,6 @@
suffix = "cog"
name = "NT Prisoner Transport"
-/datum/map_template/shuttle/cargo/box
- suffix = "box"
- name = "supply shuttle (Box)"
-
/datum/map_template/shuttle/cargo/kilo
suffix = "kilo"
name = "supply shuttle (Kilo)"
@@ -488,6 +544,14 @@
suffix = "birdboat"
name = "supply shuttle (Birdboat)"
+// /datum/map_template/shuttle/cargo/donut
+// suffix = "donut"
+// name = "supply shuttle (Donut)"
+
+// /datum/map_template/shuttle/cargo/pubby
+// suffix = "pubby"
+// name = "supply shuttle (Pubby)"
+
/datum/map_template/shuttle/emergency/delta
suffix = "delta"
name = "Delta Station Emergency Shuttle"
@@ -497,11 +561,24 @@
/datum/map_template/shuttle/emergency/raven
suffix = "raven"
- name = "CentCom Raven Battlecruiser"
- description = "The CentCom Raven Battlecruiser is currently docked at the CentCom ship bay awaiting a mission, this Battlecruiser has been reassigned as an emergency escape shuttle for currently unknown reasons. The CentCom Raven Battlecruiser should comfortably fit a medium to large crew size crew and is complete with all required facitlities including a top of the range CentCom Medical Bay."
- admin_notes = "Comes with turrets that will target any simplemob."
+ name = "CentCom Raven Cruiser"
+ description = "The CentCom Raven Cruiser is a former high-risk salvage vessel, now repurposed into an emergency escape shuttle. \
+ Once first to the scene to pick through warzones for valuable remains, it now serves as an excellent escape option for stations under heavy fire from outside forces. \
+ This escape shuttle boasts shields and numerous anti-personnel turrets guarding its perimeter to fend off meteors and enemy boarding attempts."
+ admin_notes = "Comes with turrets that will target anything without the neutral faction (nuke ops, xenos etc, but not pets)."
credit_cost = 12500
+// /datum/map_template/shuttle/emergency/zeta
+// suffix = "zeta"
+// name = "Tr%nPo2r& Z3TA"
+// description = "A glitch appears on your monitor, flickering in and out of the options laid before you.
+// It seems strange and alien, you may need a special technology to access the signal.."
+// admin_notes = "Has alien surgery tools, and a void core that provides unlimited power."
+// credit_cost = CARGO_CRATE_VALUE * 16
+
+// /datum/map_template/shuttle/emergency/zeta/prerequisites_met()
+// return SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_ALIENTECH]
+
/datum/map_template/shuttle/emergency/cog
suffix = "cog"
name = "NES Classic"
@@ -524,18 +601,22 @@
suffix = "box"
name = "labour shuttle (Box)"
-/datum/map_template/shuttle/labour/kilo
- suffix = "kilo"
- name = "labour shuttle (Kilo)"
-
/datum/map_template/shuttle/labour/cog
suffix = "cog"
name = "labour shuttle (Cog)"
+// /datum/map_template/shuttle/arrival/donut
+// suffix = "donut"
+// name = "arrival shuttle (Donut)"
+
/datum/map_template/shuttle/infiltrator/basic
suffix = "basic"
name = "basic syndicate infiltrator"
+// /datum/map_template/shuttle/infiltrator/advanced
+// suffix = "advanced"
+// name = "advanced syndicate infiltrator"
+
/datum/map_template/shuttle/cargo/delta
suffix = "delta"
name = "cargo ferry (Delta)"
@@ -548,17 +629,25 @@
suffix = "kilo"
name = "mining shuttle (Kilo)"
+// /datum/map_template/shuttle/mining/large
+// suffix = "large"
+// name = "mining shuttle (Large)"
+
/datum/map_template/shuttle/labour/delta
suffix = "delta"
name = "labour shuttle (Delta)"
+/datum/map_template/shuttle/labour/kilo
+ suffix = "kilo"
+ name = "labour shuttle (Kilo)"
+
/datum/map_template/shuttle/mining_common/meta
suffix = "meta"
name = "lavaland shuttle (Meta)"
-/datum/map_template/shuttle/labour/kilo
- suffix = "kilo"
- name = "labour shuttle (Kilo)"
+// /datum/map_template/shuttle/mining_common/kilo
+// suffix = "kilo"
+// name = "lavaland shuttle (Kilo)"
/datum/map_template/shuttle/arrival/delta
suffix = "delta"
@@ -608,6 +697,18 @@
suffix = "default"
name = "pirate ship (Default)"
+/datum/map_template/shuttle/hunter/space_cop
+ suffix = "space_cop"
+ name = "Police Spacevan"
+
+/datum/map_template/shuttle/hunter/russian
+ suffix = "russian"
+ name = "Russian Cargo Ship"
+
+/datum/map_template/shuttle/hunter/bounty
+ suffix = "bounty"
+ name = "Bounty Hunter Ship"
+
/datum/map_template/shuttle/ruin/caravan_victim
suffix = "caravan_victim"
name = "Small Freighter"
@@ -631,15 +732,3 @@
/datum/map_template/shuttle/snowdin/excavation
suffix = "excavation"
name = "Snowdin Excavation Elevator"
-
-/datum/map_template/shuttle/hunter/space_cop
- suffix = "space_cop"
- name = "Police Spacevan"
-
-/datum/map_template/shuttle/hunter/russian
- suffix = "russian"
- name = "Russian Cargo Ship"
-
-/datum/map_template/shuttle/hunter/bounty
- suffix = "bounty"
- name = "Bounty Hunter Ship"
diff --git a/code/datums/view.dm b/code/datums/view.dm
index 8eb06c2bd2..5610fb040e 100644
--- a/code/datums/view.dm
+++ b/code/datums/view.dm
@@ -83,8 +83,6 @@
/datum/viewData/proc/apply()
chief.change_view(getView())
safeApplyFormat()
- if(chief.prefs.auto_fit_viewport)
- chief.fit_viewport()
/datum/viewData/proc/supress()
is_suppressed = TRUE
diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm
index 7a1f0f6980..415a616c90 100644
--- a/code/datums/world_topic.dm
+++ b/code/datums/world_topic.dm
@@ -106,8 +106,8 @@
/datum/world_topic/comms_console/Run(list/input, addr)
minor_announce(input["message"], "Incoming message from [input["message_sender"]]")
- for(var/obj/machinery/computer/communications/CM in GLOB.machines)
- CM.overrideCooldown()
+ for(var/obj/machinery/computer/communications/console in GLOB.machines)
+ console.override_cooldown()
/datum/world_topic/news_report
keyword = "News_Report"
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 19e6768d71..9953b593d9 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -149,7 +149,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
if(isliving(thing))
var/mob/living/living_thing = thing
living_thing.visible_message("[src] slams into [living_thing].", "[src] slams into you!.")
- A.ex_act(hitpwr)
+ living_thing.ex_act(hitpwr)
//then, ram the turf if it still exists
if(T)
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 82dd78eecc..dd2ebf287f 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -96,7 +96,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
/obj/machinery/computer/arcade/proc/prizevend(mob/user, prizes = 1)
// if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD))
- // visible_message("[user] inputs an intense cheat code!",\
+ // visible_message("[user] inputs an intense cheat code!",
// "You hear a flurry of buttons being pressed.")
// say("CODE ACTIVATED: EXTRA PRIZES.")
// prizes *= 2
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 3ef887b156..83fae86ad6 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -1,14 +1,10 @@
-#define STATE_DEFAULT 1
-#define STATE_CALLSHUTTLE 2
-#define STATE_CANCELSHUTTLE 3
-#define STATE_MESSAGELIST 4
-#define STATE_VIEWMESSAGE 5
-#define STATE_DELMESSAGE 6
-#define STATE_STATUSDISPLAY 7
-#define STATE_ALERT_LEVEL 8
-#define STATE_CONFIRM_LEVEL 9
-#define STATE_TOGGLE_EMERGENCY 10
-#define STATE_PURCHASE 11
+#define IMPORTANT_ACTION_COOLDOWN (60 SECONDS)
+#define MAX_STATUS_LINE_LENGTH 40
+
+#define STATE_BUYING_SHUTTLE "buying_shuttle"
+#define STATE_CHANGING_STATUS "changing_status"
+#define STATE_MAIN "main"
+#define STATE_MESSAGES "messages"
// The communications computer
/obj/machinery/computer/communications
@@ -19,423 +15,53 @@
req_access = list(ACCESS_HEADS)
circuit = /obj/item/circuitboard/computer/communications
light_color = LIGHT_COLOR_BLUE
- var/auth_id = "Unknown" //Who is currently logged in?
- var/list/datum/comm_message/messages = list()
- var/datum/comm_message/currmsg
- var/datum/comm_message/aicurrmsg
- var/state = STATE_DEFAULT
- var/aistate = STATE_DEFAULT
- var/message_cooldown = 0
- var/ai_message_cooldown = 0
- var/tmp_alertlevel = 0
- var/static/security_level_cd // used to stop mass spam.
- var/stat_msg1
- var/stat_msg2
+ /// Cooldown for important actions, such as messaging CentCom or other sectors
+ COOLDOWN_DECLARE(static/important_action_cooldown)
+ /// The current state of the UI
+ var/state = STATE_MAIN
-/obj/machinery/computer/communications/proc/checkCCcooldown()
- var/obj/item/circuitboard/computer/communications/CM = circuit
- if(CM.lastTimeUsed + 600 > world.time)
- return FALSE
- return TRUE
+ /// The current state of the UI for AIs
+ var/cyborg_state = STATE_MAIN
+
+ /// The name of the user who logged in
+ var/authorize_name
+
+ /// The access that the card had on login
+ var/list/authorize_access
+
+ /// The messages this console has been sent
+ var/list/datum/comm_message/messages
+
+ /// How many times the alert level has been changed
+ /// Used to clear the modal to change alert level
+ var/alert_level_tick = 0
+
+ /// The last lines used for changing the status display
+ var/static/last_status_display
/obj/machinery/computer/communications/Initialize()
. = ..()
GLOB.shuttle_caller_list += src
-/obj/machinery/computer/communications/Topic(href, href_list)
- if(..())
- return
- if(!usr.canUseTopic(src, !issilicon(usr)))
- return
- if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13
- to_chat(usr, "Unable to establish a connection: \black You're too far away from the station!")
- return
- usr.set_machine(src)
+/// Are we NOT a silicon, AND we're logged in as the captain?
+/obj/machinery/computer/communications/proc/authenticated_as_non_silicon_captain(mob/user)
+ if (issilicon(user))
+ return FALSE
+ return ACCESS_CAPTAIN in authorize_access
+/// Are we a silicon, OR we're logged in as the captain?
+/obj/machinery/computer/communications/proc/authenticated_as_silicon_or_captain(mob/user)
+ if (issilicon(user))
+ return TRUE
+ return ACCESS_CAPTAIN in authorize_access
- if(!href_list["operation"])
- return
- var/obj/item/circuitboard/computer/communications/CM = circuit
- switch(href_list["operation"])
- // main interface
- if("main")
- state = STATE_DEFAULT
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
- if("login")
- var/mob/M = usr
-
- var/obj/item/card/id/I = M.get_idcard(TRUE)
-
- if(I && istype(I))
- if(check_access(I))
- authenticated = 1
- auth_id = "[I.registered_name] ([I.assignment])"
- if((ACCESS_CAPTAIN in I.access))
- authenticated = 2
- playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
- if(obj_flags & EMAGGED)
- authenticated = 2
- auth_id = "Unknown"
- to_chat(M, "[src] lets out a quiet alarm as its login is overridden.")
- playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
- playsound(src, 'sound/machines/terminal_alert.ogg', 25, FALSE)
- if(prob(25))
- for(var/mob/living/silicon/ai/AI in active_ais())
- SEND_SOUND(AI, sound('sound/machines/terminal_alert.ogg', volume = 10)) //Very quiet for balance reasons
- if("logout")
- authenticated = 0
- playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
-
- if("swipeidseclevel")
- var/mob/M = usr
- var/obj/item/card/id/I = M.get_active_held_item()
- if (istype(I, /obj/item/pda))
- var/obj/item/pda/pda = I
- I = pda.id
- if (I && istype(I))
- if(ACCESS_CAPTAIN in I.access)
- if(security_level_cd > world.time)
- to_chat(usr, "Security level protocols are currently on cooldown. Please stand by.")
- return
- var/old_level = GLOB.security_level
- if(!tmp_alertlevel)
- tmp_alertlevel = SEC_LEVEL_GREEN
- if(tmp_alertlevel < SEC_LEVEL_GREEN)
- tmp_alertlevel = SEC_LEVEL_GREEN
- if(tmp_alertlevel > SEC_LEVEL_AMBER)
- tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this
- set_security_level(tmp_alertlevel)
- security_level_cd = world.time + 15 SECONDS
- if(GLOB.security_level != old_level)
- to_chat(usr, "Authorization confirmed. Modifying security level.")
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- //Only notify people if an actual change happened
- var/security_level = NUM2SECLEVEL(GLOB.security_level)
- log_game("[key_name(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].")
- message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].")
- deadchat_broadcast("[usr.real_name] has changed the security level to [security_level] with [src] at [get_area_name(usr, TRUE)].", usr)
- tmp_alertlevel = 0
- else
- to_chat(usr, "You are not authorized to do this!")
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
- tmp_alertlevel = 0
- state = STATE_DEFAULT
- else
- to_chat(usr, "You need to swipe your ID!")
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
-
- if("announce")
- if(authenticated==2)
- playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
- make_announcement(usr)
-
- if("crossserver")
- if(authenticated==2)
- var/dest = href_list["cross_dest"]
- if(!checkCCcooldown())
- to_chat(usr, "Arrays recycling. Please stand by.")
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
- return
- var/warning = dest == "all" ? "Please choose a message to transmit to allied stations." : "Please choose a message to transmit to [dest] sector station."
- var/input = stripped_multiline_input(usr, "[warning] Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "")
- if(!input || !(usr in view(1,src)) || !checkCCcooldown())
- return
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- if(dest == "all")
- send2otherserver("[station_name()]", input,"Comms_Console")
- else
- send2otherserver("[station_name()]", input,"Comms_Console", list(dest))
- minor_announce(input, title = "Outgoing message to allied station")
- usr.log_talk(input, LOG_SAY, tag="message to the other server")
- message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server.")
- deadchat_broadcast("[usr.real_name] has sent an outgoing message to the other station(s).", usr)
- CM.lastTimeUsed = world.time
-
- if("purchase_menu")
- state = STATE_PURCHASE
-
- if("buyshuttle")
- if(authenticated==2)
- var/list/shuttles = flatten_list(SSmapping.shuttle_templates)
- var/datum/map_template/shuttle/S = locate(href_list["chosen_shuttle"]) in shuttles
- if(S && istype(S))
- if(SSshuttle.emergency.mode != SHUTTLE_RECALL && SSshuttle.emergency.mode != SHUTTLE_IDLE)
- to_chat(usr, "It's a bit late to buy a new shuttle, don't you think?")
- return
- if(SSshuttle.shuttle_purchased)
- to_chat(usr, "A replacement shuttle has already been purchased.")
- else if(!S.prerequisites_met())
- to_chat(usr, "You have not met the requirements for purchasing this shuttle.")
- else
- var/points_to_check
- var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
- if(D)
- points_to_check = D.account_balance
- if(points_to_check >= S.credit_cost)
- SSshuttle.shuttle_purchased = TRUE
- SSshuttle.unload_preview()
- SSshuttle.load_template(S)
- SSshuttle.existing_shuttle = SSshuttle.emergency
- SSshuttle.action_load(S)
- D.adjust_money(-S.credit_cost)
- minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase")
- message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].")
- log_shuttle("[key_name(usr)] has purchased [S.name].")
- SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]")
- else
- to_chat(usr, "Insufficient credits.")
-
- if("callshuttle")
- state = STATE_DEFAULT
- if(authenticated && SSshuttle.canEvac(usr))
- state = STATE_CALLSHUTTLE
- if("callshuttle2")
- if(authenticated)
- SSshuttle.requestEvac(usr, href_list["call"])
- if(SSshuttle.emergency.timer)
- post_status("shuttle")
- state = STATE_DEFAULT
- if("cancelshuttle")
- state = STATE_DEFAULT
- if(authenticated)
- state = STATE_CANCELSHUTTLE
- if("cancelshuttle2")
- if(authenticated)
- if(SSshuttle.endvote_passed) //Citadel Edit - endvote passing = no recalls
- say("Warning: Emergency shuttle recalls have been blocked by Central Command due to ongoing crew transfer procedures.")
- else
- SSshuttle.cancelEvac(usr)
- state = STATE_DEFAULT
- if("messagelist")
- currmsg = 0
- state = STATE_MESSAGELIST
- if("viewmessage")
- state = STATE_VIEWMESSAGE
- if (!currmsg)
- if(href_list["message-num"])
- var/msgnum = text2num(href_list["message-num"])
- currmsg = messages[msgnum]
- else
- state = STATE_MESSAGELIST
- if("delmessage")
- state = currmsg ? STATE_DELMESSAGE : STATE_MESSAGELIST
- if("delmessage2")
- if(authenticated)
- if(currmsg)
- if(aicurrmsg == currmsg)
- aicurrmsg = null
- messages -= currmsg
- currmsg = null
- state = STATE_MESSAGELIST
- else
- state = STATE_VIEWMESSAGE
- if("respond")
- var/answer = text2num(href_list["answer"])
- if(!currmsg || !answer || currmsg.possible_answers.len < answer)
- state = STATE_MESSAGELIST
- else
- if(!currmsg.answered)
- currmsg.answered = answer
- log_game("[key_name(usr)] answered [currmsg.title] comm message. Answer : [currmsg.answered]")
- if(currmsg)
- currmsg.answer_callback.InvokeAsync()
- state = STATE_VIEWMESSAGE
- updateDialog()
- if("status")
- state = STATE_STATUSDISPLAY
- if("securitylevel")
- tmp_alertlevel = text2num( href_list["newalertlevel"] )
- if(!tmp_alertlevel)
- tmp_alertlevel = 0
- state = STATE_CONFIRM_LEVEL
- if("changeseclevel")
- state = STATE_ALERT_LEVEL
-
- if("emergencyaccess")
- state = STATE_TOGGLE_EMERGENCY
- if("enableemergency")
- make_maint_all_access()
- log_game("[key_name(usr)] enabled emergency maintenance access.")
- message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.")
- deadchat_broadcast("[usr.real_name] enabled emergency maintenance access at [get_area_name(usr, TRUE)].", usr)
- state = STATE_DEFAULT
- if("disableemergency")
- revoke_maint_all_access()
- log_game("[key_name(usr)] disabled emergency maintenance access.")
- message_admins("[ADMIN_LOOKUPFLW(usr)] disabled emergency maintenance access.")
- deadchat_broadcast("[usr.real_name] disabled emergency maintenance access at [get_area_name(usr, TRUE)].", usr)
- state = STATE_DEFAULT
-
- // Status display stuff
- if("setstat")
- playsound(src, "terminal_type", 50, FALSE)
- switch(href_list["statdisp"])
- if("message")
- post_status("message", stat_msg1, stat_msg2)
- if("alert")
- post_status("alert", href_list["alert"])
- else
- post_status(href_list["statdisp"])
-
- if("setmsg1")
- stat_msg1 = reject_bad_text(input("Line 1", "Enter Message Text", stat_msg1) as text|null, 40)
- updateDialog()
- if("setmsg2")
- stat_msg2 = reject_bad_text(input("Line 2", "Enter Message Text", stat_msg2) as text|null, 40)
- updateDialog()
-
- // OMG CENTCOM LETTERHEAD
- if("MessageCentCom")
- if(authenticated)
- if(!checkCCcooldown())
- to_chat(usr, "Arrays recycling. Please stand by.")
- return
- var/input = stripped_input(usr, "Please choose a message to transmit to CentCom via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to CentCom.", "")
- if(!input || !(usr in view(1,src)) || !checkCCcooldown())
- return
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- CentCom_announce(input, usr)
- to_chat(usr, "Message transmitted to Central Command.")
- for(var/client/X in GLOB.admins)
- if(X.prefs.toggles & SOUND_ADMINHELP)
- SEND_SOUND(X, sound('sound/effects/printer.ogg'))
- window_flash(X, ignorepref = FALSE)
- usr.log_talk(input, LOG_SAY, tag="CentCom announcement")
- deadchat_broadcast("[usr.real_name] has messaged CentCom, \"[input]\" at [get_area_name(usr, TRUE)].", usr)
- CM.lastTimeUsed = world.time
-
- // OMG SYNDICATE ...LETTERHEAD
- if("MessageSyndicate")
- if((authenticated) && (obj_flags & EMAGGED))
- if(!checkCCcooldown())
- to_chat(usr, "Arrays recycling. Please stand by.")
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
- return
- var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING COORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to /??????/.", "")
- if(!input || !(usr in view(1,src)) || !checkCCcooldown())
- return
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- Syndicate_announce(input, usr)
- to_chat(usr, "SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.")
- for(var/client/X in GLOB.admins)
- if(X.prefs.toggles & SOUND_ADMINHELP)
- SEND_SOUND(X, sound('sound/effects/printer.ogg'))
- window_flash(X, ignorepref = FALSE)
- usr.log_talk(input, LOG_SAY, tag="Syndicate announcement")
- deadchat_broadcast("[usr.real_name] has messaged the Syndicate, \"[input]\" at [get_area_name(usr, TRUE)].", usr)
- CM.lastTimeUsed = world.time
-
- if("RestoreBackup")
- to_chat(usr, "Backup routing data restored!")
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- obj_flags &= ~EMAGGED
- updateDialog()
-
- if("nukerequest") //When there's no other way
- if(authenticated==2)
- if(!checkCCcooldown())
- to_chat(usr, "Arrays recycling. Please stand by.")
- return
- var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self-Destruct Code Request.","")
- if(!input || !(usr in view(1,src)) || !checkCCcooldown())
- return
- Nuke_request(input, usr)
- to_chat(usr, "Request sent.")
- usr.log_message("has requested the nuclear codes from CentCom with reason \"[input]\"", LOG_SAY)
- priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport")
- CM.lastTimeUsed = world.time
-
-
- // AI interface
- if("ai-main")
- aicurrmsg = null
- aistate = STATE_DEFAULT
- if("ai-callshuttle")
- aistate = STATE_DEFAULT
- if(SSshuttle.canEvac(usr))
- aistate = STATE_CALLSHUTTLE
- if("ai-callshuttle2")
- SSshuttle.requestEvac(usr, href_list["call"])
- aistate = STATE_DEFAULT
- if("ai-messagelist")
- aicurrmsg = null
- aistate = STATE_MESSAGELIST
- if("ai-viewmessage")
- aistate = STATE_VIEWMESSAGE
- if (!aicurrmsg)
- if(href_list["message-num"])
- var/msgnum = text2num(href_list["message-num"])
- aicurrmsg = messages[msgnum]
- else
- aistate = STATE_MESSAGELIST
- if("ai-delmessage")
- aistate = aicurrmsg ? STATE_DELMESSAGE : STATE_MESSAGELIST
- if("ai-delmessage2")
- if(aicurrmsg)
- if(currmsg == aicurrmsg)
- currmsg = null
- messages -= aicurrmsg
- aicurrmsg = null
- aistate = STATE_MESSAGELIST
- if("ai-respond")
- var/answer = text2num(href_list["answer"])
- if(!aicurrmsg || !answer || aicurrmsg.possible_answers.len < answer)
- aistate = STATE_MESSAGELIST
- else
- if(!aicurrmsg.answered)
- aicurrmsg.answered = answer
- log_game("[key_name(usr)] answered [aicurrmsg.title] comm message. Answer : [aicurrmsg.answered]")
- if(aicurrmsg.answer_callback)
- aicurrmsg.answer_callback.InvokeAsync()
- aistate = STATE_VIEWMESSAGE
- if("ai-status")
- aistate = STATE_STATUSDISPLAY
- if("ai-announce")
- make_announcement(usr, 1)
- if("ai-securitylevel")
- if(security_level_cd > world.time)
- to_chat(usr, "Security level protocols are currently on cooldown. Please stand by.")
- return
- tmp_alertlevel = text2num( href_list["newalertlevel"] )
- if(!tmp_alertlevel)
- tmp_alertlevel = SEC_LEVEL_GREEN
- var/old_level = GLOB.security_level
- if(!tmp_alertlevel)
- tmp_alertlevel = SEC_LEVEL_GREEN
- if(tmp_alertlevel < SEC_LEVEL_GREEN)
- tmp_alertlevel = SEC_LEVEL_GREEN
- if(tmp_alertlevel > SEC_LEVEL_AMBER)
- tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this
- set_security_level(tmp_alertlevel)
- security_level_cd = world.time + 15 SECONDS
- if(GLOB.security_level != old_level)
- //Only notify people if an actual change happened
- var/security_level = NUM2SECLEVEL(GLOB.security_level)
- log_game("[key_name(usr)] has changed the security level to [security_level] from [src] at [AREACOORD(usr)].")
- message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [security_level] from [src] at [AREACOORD(usr)].")
- deadchat_broadcast("[usr.real_name] has changed the security level to [security_level] from [src] at [get_area_name(usr, TRUE)].", usr)
- tmp_alertlevel = 0
- aistate = STATE_DEFAULT
- if("ai-changeseclevel")
- aistate = STATE_ALERT_LEVEL
- if("ai-emergencyaccess")
- aistate = STATE_TOGGLE_EMERGENCY
- if("ai-enableemergency")
- make_maint_all_access()
- log_game("[key_name(usr)] enabled emergency maintenance access.")
- message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.")
- deadchat_broadcast("[usr.real_name] enabled emergency maintenance access.", usr)
- aistate = STATE_DEFAULT
- if("ai-disableemergency")
- revoke_maint_all_access()
- log_game("[key_name(usr)] disabled emergency maintenance access.")
- message_admins("[ADMIN_LOOKUPFLW(usr)] disabled emergency maintenance access.")
- deadchat_broadcast("[usr.real_name] disabled emergency maintenance access.", usr)
- aistate = STATE_DEFAULT
-
- updateUsrDialog()
+/// Are we a silicon, OR logged in?
+/obj/machinery/computer/communications/proc/authenticated(mob/user)
+ if (issilicon(user))
+ return TRUE
+ return authenticated
/obj/machinery/computer/communications/attackby(obj/I, mob/user, params)
if(istype(I, /obj/item/card/id))
@@ -445,292 +71,414 @@
/obj/machinery/computer/communications/emag_act(mob/user)
. = ..()
- if(obj_flags & EMAGGED)
+ if (obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
- SSshuttle.shuttle_purchase_requirements_met |= "emagged"
- if(authenticated == 1)
- authenticated = 2
+ if (authenticated)
+ authorize_access = get_all_accesses()
to_chat(user, "You scramble the communication routing circuits!")
playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE)
+ return
+
+/obj/machinery/computer/communications/ui_act(action, list/params)
+ var/static/list/approved_states = list(STATE_BUYING_SHUTTLE, STATE_CHANGING_STATUS, STATE_MAIN, STATE_MESSAGES)
+ var/static/list/approved_status_pictures = list("biohazard", "blank", "default", "lockdown", "redalert", "shuttle")
+
+ . = ..()
+ if (.)
+ return
+
+ if (!has_communication())
+ return
+
+ . = TRUE
+
+ switch (action)
+ if ("answerMessage")
+ if (!authenticated(usr))
+ return
+ var/answer_index = text2num(params["answer"])
+ var/message_index = text2num(params["message"])
+ if (!answer_index || !message_index || answer_index < 1 || message_index < 1)
+ return
+ var/datum/comm_message/message = messages[message_index]
+ if (message.answered)
+ return
+ message.answered = answer_index
+ message.answer_callback.InvokeAsync()
+ if ("callShuttle")
+ if (!authenticated(usr))
+ return
+ var/reason = trim(params["reason"], MAX_MESSAGE_LEN)
+ if (length(reason) < CALL_SHUTTLE_REASON_LENGTH)
+ return
+ SSshuttle.requestEvac(usr, reason)
+ post_status("shuttle")
+ if ("changeSecurityLevel")
+ if (!authenticated_as_silicon_or_captain(usr))
+ return
+
+ // Check if they have
+ if (!issilicon(usr))
+ var/obj/item/held_item = usr.get_active_held_item()
+ var/obj/item/card/id/id_card = held_item?.GetID()
+ if (!istype(id_card))
+ to_chat(usr, "You need to swipe your ID!")
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
+ return
+ if (!(ACCESS_CAPTAIN in id_card.access))
+ to_chat(usr, "You are not authorized to do this!")
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
+ return
+
+ var/new_sec_level = SECLEVEL2NUM(params["newSecurityLevel"])
+ if (new_sec_level != SEC_LEVEL_GREEN && new_sec_level != SEC_LEVEL_BLUE
+ && new_sec_level != SEC_LEVEL_AMBER)
+ return
+ if (GLOB.security_level == new_sec_level)
+ return
+
+ set_security_level(new_sec_level)
+
+ to_chat(usr, "Authorization confirmed. Modifying security level.")
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
+
+ // Only notify people if an actual change happened
+ log_game("[key_name(usr)] has changed the security level to [params["newSecurityLevel"]] with [src] at [AREACOORD(usr)].")
+ message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [params["newSecurityLevel"]] with [src] at [AREACOORD(usr)].")
+ deadchat_broadcast(" has changed the security level to [params["newSecurityLevel"]] with [src] at [get_area_name(usr, TRUE)].", "[usr.real_name]", usr)
+
+ alert_level_tick += 1
+ if ("deleteMessage")
+ if (!authenticated(usr))
+ return
+ var/message_index = text2num(params["message"])
+ if (!message_index)
+ return
+ LAZYREMOVE(messages, LAZYACCESS(messages, message_index))
+ if ("makePriorityAnnouncement")
+ if (!authenticated_as_silicon_or_captain(usr))
+ return
+ make_announcement(usr)
+ if ("messageAssociates")
+ if (!authenticated_as_non_silicon_captain(usr))
+ return
+ if (!COOLDOWN_FINISHED(src, important_action_cooldown))
+ return
+
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
+ var/message = trim(html_encode(params["message"]), MAX_MESSAGE_LEN)
+
+ var/emagged = obj_flags & EMAGGED
+ if (emagged)
+ message_syndicate(message, usr)
+ to_chat(usr, "SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.")
+ else
+ message_centcom(message, usr)
+ to_chat(usr, "Message transmitted to Central Command.")
+
+ var/associates = emagged ? "the Syndicate": "CentCom"
+ usr.log_talk(message, LOG_SAY, tag = "message to [associates]")
+ deadchat_broadcast(" has messaged [associates], \"[message]\" at [get_area_name(usr, TRUE)].", "[usr.real_name]", usr)
+ COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN)
+ if ("purchaseShuttle")
+ var/can_buy_shuttles_or_fail_reason = can_buy_shuttles(usr)
+ if (can_buy_shuttles_or_fail_reason != TRUE)
+ if (can_buy_shuttles_or_fail_reason != FALSE)
+ to_chat(usr, "[can_buy_shuttles_or_fail_reason]")
+ return
+ var/list/shuttles = flatten_list(SSmapping.shuttle_templates)
+ var/datum/map_template/shuttle/shuttle = locate(params["shuttle"]) in shuttles
+ if (!istype(shuttle))
+ return
+ if (!shuttle.prerequisites_met())
+ to_chat(usr, "You have not met the requirements for purchasing this shuttle.")
+ return
+ var/datum/bank_account/bank_account = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ if (bank_account.account_balance < shuttle.credit_cost)
+ return
+ SSshuttle.shuttle_purchased = SHUTTLEPURCHASE_PURCHASED
+ SSshuttle.unload_preview()
+ SSshuttle.existing_shuttle = SSshuttle.emergency
+ SSshuttle.action_load(shuttle, replace = TRUE)
+ bank_account.adjust_money(-shuttle.credit_cost)
+ minor_announce("[usr.real_name] has purchased [shuttle.name] for [shuttle.credit_cost] credits.[shuttle.extra_desc ? " [shuttle.extra_desc]" : ""]" , "Shuttle Purchase")
+ message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [shuttle.name].")
+ log_shuttle("[key_name(usr)] has purchased [shuttle.name].")
+ SSblackbox.record_feedback("text", "shuttle_purchase", 1, shuttle.name)
+ state = STATE_MAIN
+ if ("recallShuttle")
+ // AIs cannot recall the shuttle
+ if (!authenticated(usr) || issilicon(usr))
+ return
+ SSshuttle.cancelEvac(usr)
+ if ("requestNukeCodes")
+ if (!authenticated_as_non_silicon_captain(usr))
+ return
+ if (!COOLDOWN_FINISHED(src, important_action_cooldown))
+ return
+ var/reason = trim(html_encode(params["reason"]), MAX_MESSAGE_LEN)
+ nuke_request(reason, usr)
+ to_chat(usr, "Request sent.")
+ usr.log_message("has requested the nuclear codes from CentCom with reason \"[reason]\"", LOG_SAY)
+ priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self-Destruct Codes Requested", 'sound/ai/commandreport.ogg')
+ playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
+ COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN)
+ if ("restoreBackupRoutingData")
+ if (!authenticated_as_non_silicon_captain(usr))
+ return
+ if (!(obj_flags & EMAGGED))
+ return
+ to_chat(usr, "Backup routing data restored.")
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
+ obj_flags &= ~EMAGGED
+ if ("sendToOtherSector")
+ if (!authenticated_as_non_silicon_captain(usr))
+ return
+ if (!can_send_messages_to_other_sectors(usr))
+ return
+ if (!COOLDOWN_FINISHED(src, important_action_cooldown))
+ return
+
+ var/message = trim(html_encode(params["message"]), MAX_MESSAGE_LEN)
+ if (!message)
+ return
+
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
+
+ var/destination = params["destination"]
+ var/list/payload = list()
+
+ var/network_name = CONFIG_GET(string/cross_comms_network)
+ if (network_name)
+ payload["network"] = network_name
+
+ send2otherserver(station_name(), message, "Comms_Console", destination == "all" ? null : list(destination), additional_data = payload)
+ minor_announce(message, title = "Outgoing message to allied station")
+ usr.log_talk(message, LOG_SAY, tag = "message to the other server")
+ message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server\[s].")
+ deadchat_broadcast(" has sent an outgoing message to the other station(s).", "[usr.real_name]", usr)
+
+ COOLDOWN_START(src, important_action_cooldown, IMPORTANT_ACTION_COOLDOWN)
+ if ("setState")
+ if (!authenticated(usr))
+ return
+ if (!(params["state"] in approved_states))
+ return
+ if (state == STATE_BUYING_SHUTTLE && can_buy_shuttles(usr) != TRUE)
+ return
+ set_state(usr, params["state"])
+ playsound(src, "terminal_type", 50, FALSE)
+ if ("setStatusMessage")
+ if (!authenticated(usr))
+ return
+ var/line_one = reject_bad_text(params["lineOne"] || "", MAX_STATUS_LINE_LENGTH)
+ var/line_two = reject_bad_text(params["lineTwo"] || "", MAX_STATUS_LINE_LENGTH)
+ post_status("alert", "blank")
+ post_status("message", line_one, line_two)
+ last_status_display = list(line_one, line_two)
+ playsound(src, "terminal_type", 50, FALSE)
+ if ("setStatusPicture")
+ if (!authenticated(usr))
+ return
+ var/picture = params["picture"]
+ if (!(picture in approved_status_pictures))
+ return
+ post_status("alert", picture)
+ playsound(src, "terminal_type", 50, FALSE)
+ if ("toggleAuthentication")
+ // Log out if we're logged in
+ if (authorize_name)
+ authenticated = FALSE
+ authorize_access = null
+ authorize_name = null
+ playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
+ return
+
+ if (obj_flags & EMAGGED)
+ authenticated = TRUE
+ authorize_access = get_all_accesses()
+ authorize_name = "Unknown"
+ to_chat(usr, "[src] lets out a quiet alarm as its login is overridden.")
+ playsound(src, 'sound/machines/terminal_alert.ogg', 25, FALSE)
+ else if(isliving(usr))
+ var/mob/living/L = usr
+ var/obj/item/card/id/id_card = L.get_idcard(hand_first = TRUE)
+ if (check_access(id_card))
+ authenticated = TRUE
+ authorize_access = id_card.access
+ authorize_name = "[id_card.registered_name] - [id_card.assignment]"
+
+ state = STATE_MAIN
+ playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
+ if ("toggleEmergencyAccess")
+ if (!authenticated_as_silicon_or_captain(usr))
+ return
+ if (GLOB.emergency_access)
+ revoke_maint_all_access()
+ log_game("[key_name(usr)] disabled emergency maintenance access.")
+ message_admins("[ADMIN_LOOKUPFLW(usr)] disabled emergency maintenance access.")
+ deadchat_broadcast(" disabled emergency maintenance access at [get_area_name(usr, TRUE)].", "[usr.real_name]", usr)
+ else
+ make_maint_all_access()
+ log_game("[key_name(usr)] enabled emergency maintenance access.")
+ message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.")
+ deadchat_broadcast(" enabled emergency maintenance access at [get_area_name(usr, TRUE)].", "[usr.real_name]", usr)
+
+/obj/machinery/computer/communications/ui_data(mob/user)
+ var/list/data = list(
+ "authenticated" = FALSE,
+ "emagged" = FALSE,
+ "hasConnection" = has_communication(),
+ )
+
+ var/ui_state = issilicon(user) ? cyborg_state : state
+
+ if (authenticated || issilicon(user))
+ data["authenticated"] = TRUE
+ data["canLogOut"] = !issilicon(user)
+ data["page"] = ui_state
+
+ if (obj_flags & EMAGGED)
+ data["emagged"] = TRUE
+
+ switch (ui_state)
+ if (STATE_MAIN)
+ data["canBuyShuttles"] = can_buy_shuttles(user)
+ data["canMakeAnnouncement"] = FALSE
+ data["canMessageAssociates"] = FALSE
+ data["canRecallShuttles"] = !issilicon(user)
+ data["canRequestNuke"] = FALSE
+ data["canSendToSectors"] = FALSE
+ data["canSetAlertLevel"] = FALSE
+ data["canToggleEmergencyAccess"] = FALSE
+ data["importantActionReady"] = COOLDOWN_FINISHED(src, important_action_cooldown)
+ data["shuttleCalled"] = FALSE
+ data["shuttleLastCalled"] = FALSE
+
+ data["alertLevel"] = GLOB.security_level
+ data["authorizeName"] = authorize_name
+ data["canLogOut"] = !issilicon(user)
+ data["shuttleCanEvacOrFailReason"] = SSshuttle.canEvac(user)
+
+ if (authenticated_as_non_silicon_captain(user))
+ data["canMessageAssociates"] = TRUE
+ data["canRequestNuke"] = TRUE
+
+ if (can_send_messages_to_other_sectors(user))
+ data["canSendToSectors"] = TRUE
+
+ var/list/sectors = list()
+ var/our_id = CONFIG_GET(string/cross_comms_name)
+
+ for (var/server in CONFIG_GET(keyed_list/cross_server))
+ if (server == our_id)
+ continue
+ sectors += server
+
+ data["sectors"] = sectors
+
+ if (authenticated_as_silicon_or_captain(user))
+ data["canToggleEmergencyAccess"] = TRUE
+ data["emergencyAccess"] = GLOB.emergency_access
+
+ data["alertLevelTick"] = alert_level_tick
+ data["canMakeAnnouncement"] = TRUE
+ data["canSetAlertLevel"] = issilicon(user) ? "NO_SWIPE_NEEDED" : "SWIPE_NEEDED"
+
+ if (SSshuttle.emergency.mode != SHUTTLE_IDLE && SSshuttle.emergency.mode != SHUTTLE_RECALL)
+ data["shuttleCalled"] = TRUE
+ data["shuttleRecallable"] = SSshuttle.canRecall()
+
+ if (SSshuttle.emergencyCallAmount)
+ data["shuttleCalledPreviously"] = TRUE
+ if (SSshuttle.emergencyLastCallLoc)
+ data["shuttleLastCalled"] = format_text(SSshuttle.emergencyLastCallLoc.name)
+ if (STATE_MESSAGES)
+ data["messages"] = list()
+
+ if (messages)
+ for (var/_message in messages)
+ var/datum/comm_message/message = _message
+ data["messages"] += list(list(
+ "answered" = message.answered,
+ "content" = message.content,
+ "title" = message.title,
+ "possibleAnswers" = message.possible_answers,
+ ))
+ if (STATE_BUYING_SHUTTLE)
+ var/datum/bank_account/bank_account = SSeconomy.get_dep_account(ACCOUNT_CAR)
+ var/list/shuttles = list()
+
+ for (var/shuttle_id in SSmapping.shuttle_templates)
+ var/datum/map_template/shuttle/shuttle_template = SSmapping.shuttle_templates[shuttle_id]
+ if (!shuttle_template.can_be_bought || shuttle_template.credit_cost == INFINITY)
+ continue
+ shuttles += list(list(
+ "name" = shuttle_template.name,
+ "description" = shuttle_template.description,
+ "creditCost" = shuttle_template.credit_cost,
+ "prerequisites" = shuttle_template.prerequisites,
+ "ref" = REF(shuttle_template),
+ ))
+
+ data["budget"] = bank_account.account_balance
+ data["shuttles"] = shuttles
+ if (STATE_CHANGING_STATUS)
+ data["lineOne"] = last_status_display ? last_status_display[1] : ""
+ data["lineTwo"] = last_status_display ? last_status_display[2] : ""
+
+ return data
+
+/obj/machinery/computer/communications/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if (!ui)
+ ui = new(user, src, "CommunicationsConsole")
+ ui.open()
+
+/obj/machinery/computer/communications/ui_static_data(mob/user)
+ return list(
+ "callShuttleReasonMinLength" = CALL_SHUTTLE_REASON_LENGTH,
+ "maxStatusLineLength" = MAX_STATUS_LINE_LENGTH,
+ "maxMessageLength" = MAX_MESSAGE_LEN,
+ )
+
+/// Returns whether or not the communications console can communicate with the station
+/obj/machinery/computer/communications/proc/has_communication()
+ var/turf/current_turf = get_turf(src)
+ var/z_level = current_turf.z
+ return is_station_level(z_level) || is_centcom_level(z_level)
+
+/obj/machinery/computer/communications/proc/set_state(mob/user, new_state)
+ if (issilicon(user))
+ cyborg_state = new_state
+ else
+ state = new_state
+
+/// Returns TRUE if the user can buy shuttles.
+/// If they cannot, returns FALSE or a string detailing why.
+/obj/machinery/computer/communications/proc/can_buy_shuttles(mob/user)
+ if (!SSmapping.config.allow_custom_shuttles)
+ return FALSE
+ if (!authenticated_as_non_silicon_captain(user))
+ return FALSE
+ if (SSshuttle.emergency.mode != SHUTTLE_RECALL && SSshuttle.emergency.mode != SHUTTLE_IDLE)
+ return "The shuttle is already in transit."
+ if (SSshuttle.shuttle_purchased == SHUTTLEPURCHASE_PURCHASED)
+ return "A replacement shuttle has already been purchased."
+ if (SSshuttle.shuttle_purchased == SHUTTLEPURCHASE_FORCED)
+ return "Due to unforseen circumstances, shuttle purchasing is no longer available."
return TRUE
-/obj/machinery/computer/communications/ui_interact(mob/user)
- . = ..()
- if (z > 6)
- to_chat(user, "Unable to establish a connection: \black You're too far away from the station!")
+/obj/machinery/computer/communications/proc/can_send_messages_to_other_sectors(mob/user)
+ if (!authenticated_as_non_silicon_captain(user))
return
- var/dat = ""
- if(SSshuttle.emergency.mode == SHUTTLE_CALL)
- var/timeleft = SSshuttle.emergency.timeLeft()
- dat += "Emergency shuttle\n
\nETA: [timeleft / 60 % 60]:[add_leading(num2text(timeleft % 60), 2, "0")]"
+ return length(CONFIG_GET(keyed_list/cross_server)) > 0
-
- var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500)
-
- if(issilicon(user))
- var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access
- if(dat2)
- dat += dat2
- popup.set_content(dat)
- popup.open()
- return
-
- switch(state)
- if(STATE_DEFAULT)
- if (authenticated)
- if(SSshuttle.emergencyCallAmount)
- if(SSshuttle.emergencyLastCallLoc)
- dat += "Most recent shuttle call/recall traced to: [format_text(SSshuttle.emergencyLastCallLoc.name)]
"
- else
- dat += "Unable to trace most recent shuttle call/recall signal.
"
- dat += "Logged in as: [auth_id]"
- dat += "
"
- dat += "
\[ Log Out \]
"
- dat += "
General Functions"
- dat += "
\[ Message List \]"
- switch(SSshuttle.emergency.mode)
- if(SHUTTLE_IDLE, SHUTTLE_RECALL)
- dat += "
\[ Call Emergency Shuttle \]"
- else
- dat += "
\[ Cancel Shuttle Call \]"
-
- dat += "
\[ Set Status Display \]"
- if (authenticated==2)
- dat += "
Captain Functions"
- dat += "
\[ Make a Captain's Announcement \]"
- var/list/cross_servers = CONFIG_GET(keyed_list/cross_server)
- var/our_id = CONFIG_GET(string/cross_comms_name)
- if(cross_servers.len)
- for(var/server in cross_servers)
- if(server == our_id)
- continue
- dat += "
\[ Send a message to station in [server] sector. \]"
- if(cross_servers.len > 2)
- dat += "
\[ Send a message to all allied stations \]"
- if(SSmapping.config.allow_custom_shuttles)
- dat += "
\[ Purchase Shuttle \]"
- dat += "
\[ Change Alert Level \]"
- dat += "
\[ Emergency Maintenance Access \]"
- dat += "
\[ Request Nuclear Authentication Codes \]"
- if(!(obj_flags & EMAGGED))
- dat += "
\[ Send Message to CentCom \]"
- else
- dat += "
\[ Send Message to \[UNKNOWN\] \]"
- dat += "
\[ Restore Backup Routing Data \]"
- else
- dat += "
\[ Log In \]"
- if(STATE_CALLSHUTTLE)
- dat += get_call_shuttle_form()
- playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
- if(STATE_CANCELSHUTTLE)
- dat += get_cancel_shuttle_form()
- playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
- if(STATE_MESSAGELIST)
- dat += "Messages:"
- for(var/i in 1 to messages.len)
- var/datum/comm_message/M = messages[i]
- dat += "
[M.title]"
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- if(STATE_VIEWMESSAGE)
- if (currmsg)
- dat += "[currmsg.title]
[currmsg.content]"
- if(!currmsg.answered && currmsg.possible_answers.len)
- for(var/i in 1 to currmsg.possible_answers.len)
- var/answer = currmsg.possible_answers[i]
- dat += "
\[ Answer : [answer] \]"
- else if(currmsg.answered)
- var/answered = currmsg.possible_answers[currmsg.answered]
- dat += "
Archived Answer : [answered]"
- dat += "
\[ Delete \]"
- else
- aistate = STATE_MESSAGELIST
- attack_hand(user)
- return
- if(STATE_DELMESSAGE)
- if (currmsg)
- dat += "Are you sure you want to delete this message? \[ OK | Cancel \]"
- else
- state = STATE_MESSAGELIST
- attack_hand(user)
- return
- if(STATE_STATUSDISPLAY)
- dat += "Set Status Displays
"
- dat += "\[ Clear \]
"
- dat += "\[ Shuttle ETA \]
"
- dat += "\[ Message \]"
- dat += "
"
- dat += "\[ Alert: None |"
- dat += " Red Alert |"
- dat += " Lockdown |"
- dat += " Biohazard \]
"
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- if(STATE_ALERT_LEVEL)
- dat += "Current alert level: [NUM2SECLEVEL(GLOB.security_level)]
"
- if(GLOB.security_level == SEC_LEVEL_DELTA)
- dat += "The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate."
- else
- dat += "Amber
"
- dat += "Blue
"
- dat += "Green"
- if(STATE_CONFIRM_LEVEL)
- dat += "Current alert level: [NUM2SECLEVEL(GLOB.security_level)]
"
- dat += "Confirm the change to: [NUM2SECLEVEL(tmp_alertlevel)]
"
- dat += "Swipe ID to confirm change.
"
- if(STATE_TOGGLE_EMERGENCY)
- playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
- if(GLOB.emergency_access == 1)
- dat += "Emergency Maintenance Access is currently ENABLED"
- dat += "
Restore maintenance access restrictions?
\[ OK | Cancel \]"
- else
- dat += "Emergency Maintenance Access is currently DISABLED"
- dat += "
Lift access restrictions on maintenance and external airlocks?
\[ OK | Cancel \]"
-
- if(STATE_PURCHASE)
- var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
- dat += "Budget: [D.account_balance] Credits.
"
- dat += "
"
- dat += "Caution: Purchasing dangerous shuttles may lead to mutiny and/or death.
"
- dat += "
"
- for(var/shuttle_id in SSmapping.shuttle_templates)
- var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id]
- if(S.can_be_bought && S.credit_cost < INFINITY)
- dat += "[S.name] | [S.credit_cost] Credits
"
- dat += "[S.description]
"
- if(S.prerequisites)
- dat += "Prerequisites: [S.prerequisites]
"
- dat += "(Purchase)
"
-
- dat += "
\[ [(state != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]"
-
- popup.set_content(dat)
- popup.open()
-
-/obj/machinery/computer/communications/proc/get_javascript_header(form_id)
- var/dat = {""}
- return dat
-
-/obj/machinery/computer/communications/proc/get_call_shuttle_form(ai_interface = 0)
- var/form_id = "callshuttle"
- var/dat = get_javascript_header(form_id)
- dat += "