diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index 3065cfa8476..276a0b31314 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -3881,7 +3881,7 @@
"bwG" = (/obj/machinery/power/apc{dir = 1; name = "Bridge Maintenance APC"; pixel_y = 24},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor/plating,/area/maintenance/maintcentral)
"bwH" = (/obj/effect/decal/cleanable/generic,/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/port)
"bwI" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/wall,/area/bridge/meeting_room)
-"bwJ" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1; level = 1},/obj/machinery/account_database{anchored = 1},/obj/machinery/camera{c_tag = "Head of Personnel's Office Back Room"; dir = 2; network = list("SS13")},/turf/simulated/floor,/area/bridge/meeting_room)
+"bwJ" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1; level = 1},/obj/machinery/computer/account_database{anchored = 1},/turf/simulated/floor,/area/bridge/meeting_room)
"bwK" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light{dir = 4; icon_state = "tube1"},/obj/structure/disposalpipe/segment,/turf/simulated/floor,/area/bridge/meeting_room)
"bwL" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/wall/r_wall,/area/bridge/meeting_room)
"bwM" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/lattice,/turf/space,/area/space)
@@ -3976,7 +3976,7 @@
"byx" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/structure/closet/wardrobe/black,/turf/simulated/floor/plating,/area/maintenance/maintcentral)
"byy" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall,/area/bridge/meeting_room)
"byz" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/item/device/radio/intercom{name = "Station Intercom (General)"; pixel_y = -29},/turf/simulated/floor,/area/bridge/meeting_room)
-"byA" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{level = 1},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor,/area/bridge/meeting_room)
+"byA" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{level = 1},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/obj/machinery/camera{c_tag = "Gravity Generator Room South"; dir = 8; network = list("SS13")},/turf/simulated/floor,/area/bridge/meeting_room)
"byB" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall/r_wall,/area/bridge/meeting_room)
"byC" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/obj/structure/lattice,/turf/space,/area/space)
"byD" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{req_access_txt = "0"},/turf/space,/area/space)
diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm
index bb812b44229..451d434bc4b 100644
--- a/_maps/map_files/cyberiad/z2.dmm
+++ b/_maps/map_files/cyberiad/z2.dmm
@@ -1128,7 +1128,7 @@
"vJ" = (/obj/machinery/embedded_controller/radio/simple_docking_controller{frequency = 1380; id_tag = "specops_centcom_dock"; pixel_y = -25; req_access_txt = "109"; tag_door = "specops_centcom_dock_inner"},/turf/unsimulated/floor{icon_state = "dark"},/area/centcom/specops)
"vK" = (/obj/structure/table/woodentable{dir = 10},/obj/machinery/door_control{desc = "A remote control switch to block view of the singularity."; icon_state = "doorctrl0"; id = "SPECOPS"; name = "Ready Room"; pixel_y = 16; req_access_txt = "114"},/obj/machinery/door_control{desc = "A remote control switch to block view of the singularity."; icon_state = "doorctrl0"; id = "ASSAULT"; name = "Assault Armor"; pixel_y = -4; req_access_txt = "114"},/obj/machinery/door_control{desc = "A remote control switch to block view of the singularity."; icon_state = "doorctrl0"; id = "specopsoffice"; name = "Privacy Shutters"; pixel_y = 6; req_access_txt = "114"},/turf/unsimulated/floor{dir = 8; icon_state = "carpetside"},/area/centcom/specops)
"vL" = (/obj/structure/stool/bed/chair/comfy/black{dir = 1},/turf/unsimulated/floor{icon_state = "carpet"; dir = 2},/area/centcom/specops)
-"vM" = (/obj/item/device/radio/intercom{broadcasting = 1; dir = 1; frequency = 1441; name = "Spec Ops Intercom"; pixel_y = 28},/obj/machinery/artillerycontrol{luminosity = 255},/turf/unsimulated/floor{dir = 4; icon_state = "carpetside"},/area/centcom/specops)
+"vM" = (/obj/item/device/radio/intercom{broadcasting = 1; dir = 1; frequency = 1441; name = "Spec Ops Intercom"; pixel_y = 28},/obj/machinery/computer/artillerycontrol{luminosity = 255},/turf/unsimulated/floor{dir = 4; icon_state = "carpetside"},/area/centcom/specops)
"vN" = (/obj/structure/stool/bed/chair{dir = 1},/turf/unsimulated/floor{icon_state = "grimy"},/area/centcom/specops)
"vO" = (/obj/machinery/telecomms/processor/preset_cent,/turf/unsimulated/floor{icon_state = "green"; dir = 8},/area/centcom/control)
"vP" = (/obj/machinery/door/airlock/external{frequency = 1380; icon_state = "door_locked"; id_tag = "specops_centcom_dock_inner"; locked = 1; name = "Shuttle Hatch"; req_access = null; req_access_txt = "109"},/turf/unsimulated/floor{icon_state = "vault"; dir = 5},/area/centcom/specops)
@@ -1666,7 +1666,7 @@
"Gb" = (/obj/structure/table/woodentable,/obj/item/toy/cards/deck/syndicate,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin)
"Gc" = (/obj/structure/table/woodentable,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/devilskiss,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin)
"Gd" = (/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/turf/unsimulated/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; dir = 8; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; name = "window"; opacity = 0; tag = "icon-window5_end (WEST)"},/area/admin)
-"Ge" = (/obj/machinery/artillerycontrol{luminosity = 255},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
+"Ge" = (/obj/machinery/computer/artillerycontrol{luminosity = 255},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Gf" = (/obj/structure/stool/bed/chair{dir = 8},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Gg" = (/obj/item/weapon/stool,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin)
"Gh" = (/obj/structure/table/woodentable,/obj/item/weapon/lighter/zippo/fluff/naples_1,/obj/item/weapon/storage/fancy/cigarettes/dromedaryco,/turf/unsimulated/floor{dir = 8; icon_state = "wood"},/area/admin)
@@ -1678,7 +1678,7 @@
"Gn" = (/obj/machinery/computer/message_monitor,/obj/item/weapon/paper/monitorkey,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Go" = (/obj/machinery/computer/atmos_alert,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Gp" = (/obj/machinery/computer/secure_data,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
-"Gq" = (/obj/machinery/account_database{name = "Admin Accounts Database"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
+"Gq" = (/obj/machinery/computer/account_database{name = "Admin Accounts Database"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Gr" = (/obj/structure/table,/obj/item/weapon/gun/projectile/automatic/pistol,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Gs" = (/obj/structure/table,/obj/machinery/door_control{desc = "A remote control switch to lock down external access to the admin room."; icon_state = "doorctrl0"; id = "ADMINLOCKDOWN"; name = "Lockdown"; pixel_y = 0; req_access_txt = "0"},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
"Gt" = (/obj/structure/table,/obj/item/weapon/storage/fancy/cigarettes/syndicate,/obj/item/weapon/reagent_containers/food/drinks/cans/adminbooze,/obj/item/weapon/reagent_containers/food/drinks/cans/badminbrew,/obj/item/weapon/reagent_containers/food/drinks/cans/madminmalt,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin)
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index e38a0bb9328..741bc4769bd 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -190,8 +190,8 @@ var/bomb_set
data["is_syndicate"] = is_syndicate
if(!src.opened)
data["hacking"] = 0
- data["auth"] = src.auth
- if (src.auth)
+ data["auth"] = is_auth(user)
+ if (is_auth(user))
if (src.yes_code)
data["authstatus"] = src.timing ? "Functional/Set" : "Functional"
else
@@ -208,7 +208,7 @@ var/bomb_set
data["anchored"] = src.anchored
data["yescode"] = src.yes_code
data["message"] = "AUTH"
- if (src.auth)
+ if (is_auth(user))
data["message"] = src.code
if (src.yes_code)
data["message"] = "*****"
@@ -233,6 +233,7 @@ var/bomb_set
ui = new(user, src, ui_key, "nuclear_bomb.tmpl", uititle, uiwidth, uiheight)
ui.set_initial_data(data)
ui.open()
+ ui.set_auto_update(1)
/obj/machinery/nuclearbomb/verb/make_deployable()
set category = "Object"
@@ -250,6 +251,14 @@ var/bomb_set
src.deployable = 1
return
+/obj/machinery/nuclearbomb/proc/is_auth(user as mob)
+ if(auth)
+ return 1
+ if(isobserver(user) && check_rights(R_ADMIN, 0, user))
+ return 1
+ else
+ return 0
+
/obj/machinery/nuclearbomb/Topic(href, href_list)
if(..())
return 1
@@ -307,7 +316,7 @@ var/bomb_set
usr.drop_item()
I.loc = src
src.auth = I
- if (src.auth)
+ if (is_auth(usr))
if (href_list["type"])
if (href_list["type"] == "E")
if (src.code == src.r_code)
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 5667a13a40d..17a2f1ebc12 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -695,7 +695,7 @@
data["danger"] = danger
return data
-/obj/machinery/alarm/proc/get_nano_data(mob/user)
+/obj/machinery/alarm/proc/get_nano_data(mob/user, href_list)
var/data[0]
data["name"] = sanitize(name)
data["air"] = ui_air_status()
@@ -705,7 +705,7 @@
// Locked when:
// Not sent from atmos console AND
// Not silicon AND locked.
- data["locked"] = (!(istype(user, /mob/living/silicon)) && locked)
+ data["locked"] = is_locked(user,href_list)
data["rcon"] = rcon_setting
data["target_temp"] = target_temperature - T0C
data["atmos_alarm"] = alarm_area.atmosalm
@@ -805,15 +805,15 @@
return thresholds
/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
- var/list/data = get_nano_data(user)
-
+ var/list/href = state.href_list(user)
var/remote_connection = 0
var/remote_access = 0
- if(state)
- var/list/href = state.href_list(user)
+ if(href)
remote_connection = href["remote_connection"] // Remote connection means we're non-adjacent/connecting from another computer
remote_access = href["remote_access"] // Remote access means we also have the privilege to alter the air alarm.
+ var/list/data = get_nano_data(user, href)
+
data["remote_connection"] = remote_connection
data["remote_access"] = remote_access
@@ -825,11 +825,23 @@
ui.set_auto_update(1)
/obj/machinery/alarm/proc/is_authenticated(mob/user as mob, href_list)
- if(isAI(user) || isrobot(user) || emagged || is_auth_rcon(href_list))
+ if(isobserver(user) && check_rights(R_ADMIN, 0, user))
+ return 1
+ else if(isAI(user) || isrobot(user) || emagged || is_auth_rcon(href_list))
return 1
else
return !locked
+/obj/machinery/alarm/proc/is_locked(mob/user as mob, href_list)
+ if(isobserver(user) && check_rights(R_ADMIN, 0, user))
+ return 0
+ else if(is_auth_rcon(href_list))
+ return 0
+ else if(isAI(user))
+ return 0
+ else
+ return locked
+
/obj/machinery/alarm/proc/is_auth_rcon(href_list)
if(href_list["remote_connection"] && href_list["remote_access"])
return 1
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index 62629ca59ec..f8e177a32d8 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -50,8 +50,12 @@ var/time_last_changed_position = 0
/obj/machinery/computer/card/proc/is_centcom()
return istype(src, /obj/machinery/computer/card/centcom)
-/obj/machinery/computer/card/proc/is_authenticated()
- return scan ? check_access(scan) : 0
+/obj/machinery/computer/card/proc/is_authenticated(user as mob)
+ if(isobserver(user) && check_rights(R_ADMIN, 0, user))
+ return 1
+ if(scan)
+ return check_access(scan)
+ return 0
/obj/machinery/computer/card/proc/get_target_rank()
return modify && modify.assignment ? modify.assignment : "Unassigned"
@@ -180,7 +184,7 @@ var/time_last_changed_position = 0
data["target_owner"] = modify && modify.registered_name ? modify.registered_name : "-----"
data["target_rank"] = get_target_rank()
data["scan_name"] = scan ? scan.name : "-----"
- data["authenticated"] = is_authenticated()
+ data["authenticated"] = is_authenticated(user)
data["has_modify"] = !!modify
data["account_number"] = modify ? modify.associated_account_number : null
data["centcom_access"] = is_centcom()
@@ -285,7 +289,7 @@ var/time_last_changed_position = 0
if("access")
if(href_list["allowed"])
- if(is_authenticated())
+ if(is_authenticated(usr))
var/access_type = text2num(href_list["access_target"])
var/access_allowed = text2num(href_list["allowed"])
if(access_type in (is_centcom() ? get_all_centcom_access() : get_all_accesses()))
@@ -295,11 +299,11 @@ var/time_last_changed_position = 0
if("skin")
var/skin = href_list["skin_target"]
- if(is_authenticated() && modify && ((skin in get_station_card_skins()) || ((skin in get_centcom_card_skins()) && is_centcom())))
+ if(is_authenticated(usr) && modify && ((skin in get_station_card_skins()) || ((skin in get_centcom_card_skins()) && is_centcom())))
modify.icon_state = href_list["skin_target"]
if ("assign")
- if (is_authenticated() && modify)
+ if (is_authenticated(usr) && modify)
var/t1 = href_list["assign_target"]
if(t1 == "Custom")
var/temp_t = sanitize(copytext(input("Enter a custom job assignment.","Assignment"),1,MAX_MESSAGE_LEN))
@@ -330,7 +334,7 @@ var/time_last_changed_position = 0
callHook("reassign_employee", list(modify))
if ("reg")
- if (is_authenticated())
+ if (is_authenticated(usr))
var/t2 = modify
if ((modify == t2 && (in_range(src, usr) || (istype(usr, /mob/living/silicon))) && istype(loc, /turf)))
var/temp_name = reject_bad_name(href_list["reg"])
@@ -341,7 +345,7 @@ var/time_last_changed_position = 0
nanomanager.update_uis(src)
if ("account")
- if (is_authenticated())
+ if (is_authenticated(usr))
var/t2 = modify
if ((modify == t2 && (in_range(src, usr) || (istype(usr, /mob/living/silicon))) && istype(loc, /turf)))
var/account_num = text2num(href_list["account"])
@@ -381,7 +385,7 @@ var/time_last_changed_position = 0
P.info += " [get_access_desc(A)]"
if ("terminate")
- if (is_authenticated())
+ if (is_authenticated(usr))
modify.assignment = "Terminated"
modify.access = list()
@@ -389,7 +393,7 @@ var/time_last_changed_position = 0
if("make_job_available")
// MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS
- if(is_authenticated())
+ if(is_authenticated(usr))
var/edit_job_target = href_list["job"]
var/datum/job/j = job_master.GetJob(edit_job_target)
if(!j)
@@ -404,7 +408,7 @@ var/time_last_changed_position = 0
if("make_job_unavailable")
// MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS
- if(is_authenticated())
+ if(is_authenticated(usr))
var/edit_job_target = href_list["job"]
var/datum/job/j = job_master.GetJob(edit_job_target)
if(!j)
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 5ebcb512d72..7bb074e03f4 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -174,7 +174,7 @@ var/list/turret_icons
user << "There seems to be a firewall preventing you from accessing this device."
return 1
- if(locked && !(isrobot(user) || isAI(user)))
+ if(locked && !(isrobot(user) || isAI(user) || isobserver(user)))
user << "Access denied."
return 1
@@ -185,6 +185,9 @@ var/list/turret_icons
return
ui_interact(user)
+
+/obj/machinery/porta_turret/attack_ghost(mob/user)
+ ui_interact(user)
/obj/machinery/porta_turret/attack_hand(mob/user)
if(isLocked(user))
diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm
index 03509d38ac3..41c2d08c22b 100644
--- a/code/modules/awaymissions/bluespaceartillery.dm
+++ b/code/modules/awaymissions/bluespaceartillery.dm
@@ -1,15 +1,59 @@
-
-/obj/machinery/artillerycontrol
- var/reload = 180
+/obj/machinery/computer/artillerycontrol
name = "bluespace artillery control"
- icon_state = "control_boxp1"
- icon = 'icons/obj/machines/particle_accelerator.dmi'
- density = 1
- anchored = 1
+ icon_screen = "accelerator"
+ icon_keyboard = "accelerator_key"
+ icon_state = "computer_wires"
+ req_access = list(access_cent_commander)
+ var/last_fire = 0
+ var/reload_cooldown = 180 // 3 minute cooldown
+
+ light_color = LIGHT_COLOR_LIGHTBLUE
-/obj/machinery/artillerycontrol/process()
- if(src.reload<180)
- src.reload++
+/obj/machinery/computer/artillerycontrol/attack_ai(user as mob)
+ user << "Access denied."
+ return
+
+/obj/machinery/computer/artillerycontrol/attack_hand(user as mob)
+ ui_interact(user)
+
+/obj/machinery/computer/artillerycontrol/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ var/data[0]
+ var/time_to_wait = round(reload_cooldown - ((world.time / 10) - last_fire), 1)
+ var/mins = round(time_to_wait / 60)
+ var/seconds = time_to_wait - (60*mins)
+ data["reloadtime_mins"] = mins
+ data["reloadtime_secs"] = (seconds < 10) ? "0[seconds]" : seconds
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+
+ if (!ui)
+ ui = new(user, src, ui_key, "bluespace_artillery.tmpl", "Bluespace Control", 400, 260)
+ ui.set_initial_data(data)
+ ui.open()
+ ui.set_auto_update(1)
+
+/obj/machinery/computer/artillerycontrol/Topic(href, href_list)
+ if(..())
+ return 1
+
+ var/A
+ A = input("Area to jump bombard", "Open Fire", A) in teleportlocs
+ var/area/thearea = teleportlocs[A]
+ if(..() || !istype(thearea))
+ return
+
+ var/delta = (world.time / 10) - last_fire
+ if(reload_cooldown > delta)
+ return 1
+
+ command_announcement.Announce("Bluespace artillery fire detected. Brace for impact.")
+ message_admins("[key_name_admin(usr)] has launched an artillery strike.", 1)
+ var/list/L = list()
+ for(var/turf/T in get_area_turfs(thearea.type))
+ L+=T
+ var/loc = pick(L)
+ explosion(loc,2,5,11)
+ last_fire = world.time / 10
/obj/structure/artilleryplaceholder
name = "artillery"
@@ -19,47 +63,3 @@
/obj/structure/artilleryplaceholder/decorative
density = 0
-
-/obj/machinery/artillerycontrol/attack_hand(mob/user as mob)
- user.set_machine(src)
- var/dat = "Bluespace Artillery Control:
"
- dat += "Locked on
"
- dat += "Charge progress: [reload]/180:
"
- dat += "Open Fire
"
- dat += "Deployment of weapon authorized by
Nanotrasen Naval Command
Remember, friendly fire is grounds for termination of your contract and life.