mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-20 19:44:09 +01:00
Adds CentComm only features to the Comms Console (#22096)
* here we go * add some logging * more buttons + no tgui fail * now requires R_ADMIN and R_EVENT * review * rebuild * prettier * lewc review * tgui * sirryan review * oops * prettier changes * tgui * OOPS * tgui * okay there we go
This commit is contained in:
@@ -76,3 +76,7 @@
|
||||
#define AIR_ALARM_FRAME 0
|
||||
#define AIR_ALARM_UNWIRED 1
|
||||
#define AIR_ALARM_READY 2
|
||||
|
||||
#define NUKE_STATUS_INTACT 0
|
||||
#define NUKE_CORE_MISSING 1
|
||||
#define NUKE_MISSING 2
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#define NUKE_INTACT 0
|
||||
#define NUKE_CORE_MISSING 1
|
||||
#define NUKE_MISSING 2
|
||||
/*
|
||||
* GAMEMODES (by Rastaf0)
|
||||
*
|
||||
@@ -404,7 +401,7 @@
|
||||
if(is_station_level(bomb.z))
|
||||
nuke_status = NUKE_CORE_MISSING
|
||||
if(bomb.core)
|
||||
nuke_status = NUKE_INTACT
|
||||
nuke_status = NUKE_STATUS_INTACT
|
||||
return nuke_status
|
||||
|
||||
/datum/game_mode/proc/replace_jobbanned_player(mob/living/M, role_type)
|
||||
@@ -508,7 +505,3 @@
|
||||
var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_EVENTMISC]
|
||||
antaghud.leave_hud(mob_mind.current)
|
||||
set_antag_hud(mob_mind.current, null)
|
||||
|
||||
#undef NUKE_INTACT
|
||||
#undef NUKE_CORE_MISSING
|
||||
#undef NUKE_MISSING
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
#define COMM_SCREEN_MAIN 1
|
||||
#define COMM_SCREEN_STAT 2
|
||||
#define COMM_SCREEN_MESSAGES 3
|
||||
#define COMM_SCREEN_ANNOUNCER 4
|
||||
|
||||
#define COMM_AUTHENTICATION_NONE 0
|
||||
#define COMM_AUTHENTICATION_HEAD 1
|
||||
#define COMM_AUTHENTICATION_CAPT 2
|
||||
#define COMM_AUTHENTICATION_AGHOST 3
|
||||
#define COMM_AUTHENTICATION_CENTCOM 3 // Admin-only access
|
||||
#define COMM_AUTHENTICATION_AGHOST 4
|
||||
|
||||
#define COMM_MSGLEN_MINIMUM 6
|
||||
#define COMM_CCMSGLEN_MINIMUM 20
|
||||
|
||||
#define ADMIN_CHECK(user) ((check_rights_all(R_ADMIN|R_EVENT, FALSE, user) && authenticated >= COMM_AUTHENTICATION_CENTCOM) || user.can_admin_interact())
|
||||
|
||||
// The communications computer
|
||||
/obj/machinery/computer/communications
|
||||
name = "communications console"
|
||||
@@ -30,7 +34,6 @@
|
||||
var/message_cooldown
|
||||
var/centcomm_message_cooldown
|
||||
var/alert_level_cooldown = 0
|
||||
var/tmp_alertlevel = 0
|
||||
|
||||
var/stat_msg1
|
||||
var/stat_msg2
|
||||
@@ -41,6 +44,10 @@
|
||||
|
||||
light_color = LIGHT_COLOR_LIGHTBLUE
|
||||
|
||||
var/list/cc_announcement_sounds = list("Beep" = 'sound/misc/notice2.ogg',
|
||||
"Enemy Communications Intercepted" = 'sound/AI/intercept.ogg',
|
||||
"New Command Report Created" = 'sound/AI/commandreport.ogg')
|
||||
|
||||
/obj/machinery/computer/communications/New()
|
||||
GLOB.shuttle_caller_list += src
|
||||
..()
|
||||
@@ -51,6 +58,8 @@
|
||||
/obj/machinery/computer/communications/proc/is_authenticated(mob/user, message = 1)
|
||||
if(user.can_admin_interact())
|
||||
return COMM_AUTHENTICATION_AGHOST
|
||||
if(ADMIN_CHECK(user))
|
||||
return COMM_AUTHENTICATION_CENTCOM
|
||||
if(authenticated == COMM_AUTHENTICATION_CAPT)
|
||||
return COMM_AUTHENTICATION_CAPT
|
||||
if(authenticated)
|
||||
@@ -59,147 +68,155 @@
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return COMM_AUTHENTICATION_NONE
|
||||
|
||||
/obj/machinery/computer/communications/proc/change_security_level(new_level)
|
||||
tmp_alertlevel = new_level
|
||||
/obj/machinery/computer/communications/proc/change_security_level(new_level, force)
|
||||
var/old_level = SSsecurity_level.get_current_level_as_number()
|
||||
if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN
|
||||
if(tmp_alertlevel < SEC_LEVEL_GREEN) tmp_alertlevel = SEC_LEVEL_GREEN
|
||||
if(tmp_alertlevel > SEC_LEVEL_BLUE) tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this
|
||||
SSsecurity_level.set_level(tmp_alertlevel)
|
||||
if(!force)
|
||||
new_level = clamp(new_level, SEC_LEVEL_GREEN, SEC_LEVEL_BLUE)
|
||||
SSsecurity_level.set_level(new_level)
|
||||
if(SSsecurity_level.get_current_level_as_number() != old_level)
|
||||
//Only notify the admins if an actual change happened
|
||||
log_game("[key_name(usr)] has changed the security level to [SSsecurity_level.get_current_level_as_text()].")
|
||||
message_admins("[key_name_admin(usr)] has changed the security level to [SSsecurity_level.get_current_level_as_text()].")
|
||||
tmp_alertlevel = 0
|
||||
if(new_level == SEC_LEVEL_EPSILON)
|
||||
// episilon is delayed... but we still want to log it
|
||||
log_game("[key_name(usr)] has changed the security level to epsilon.")
|
||||
message_admins("[key_name_admin(usr)] has changed the security level to epsilon.")
|
||||
|
||||
/obj/machinery/computer/communications/ui_act(action, params)
|
||||
/obj/machinery/computer/communications/ui_act(action, params, datum/tgui/ui)
|
||||
if(..())
|
||||
return
|
||||
if(!is_secure_level(z))
|
||||
to_chat(usr, "<span class='warning'>Unable to establish a connection: You're too far away from the station!</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Unable to establish a connection: You're too far away from the station!</span>")
|
||||
return
|
||||
|
||||
. = TRUE
|
||||
|
||||
if(action == "auth")
|
||||
if(!ishuman(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied, no humanoid lifesign detected.</span>")
|
||||
if(!ishuman(ui.user))
|
||||
to_chat(ui.user, "<span class='warning'>Access denied, no humanoid lifesign detected.</span>")
|
||||
return FALSE
|
||||
// Logout function.
|
||||
if(authenticated != COMM_AUTHENTICATION_NONE)
|
||||
authenticated = COMM_AUTHENTICATION_NONE
|
||||
announcer.author = null
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
return
|
||||
// Login function.
|
||||
var/list/access = usr.get_access()
|
||||
if(allowed(usr))
|
||||
var/list/access = ui.user.get_access()
|
||||
if(allowed(ui.user))
|
||||
authenticated = COMM_AUTHENTICATION_HEAD
|
||||
if(ACCESS_CAPTAIN in access)
|
||||
authenticated = COMM_AUTHENTICATION_CAPT
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(ACCESS_CENT_COMMANDER in access)
|
||||
if(!check_rights_all(R_ADMIN|R_EVENT, FALSE, ui.user))
|
||||
to_chat(ui.user, "<span class='warning'>[src] buzzes, invalid central command clearance.</span>")
|
||||
return
|
||||
authenticated = COMM_AUTHENTICATION_CENTCOM
|
||||
|
||||
if(authenticated >= COMM_AUTHENTICATION_CAPT)
|
||||
var/mob/living/carbon/human/H = ui.user
|
||||
if(!istype(H))
|
||||
return
|
||||
var/obj/item/card/id = H.get_idcard(TRUE)
|
||||
if(istype(id))
|
||||
announcer.author = GetNameAndAssignmentFromId(id)
|
||||
if(authenticated == COMM_AUTHENTICATION_NONE)
|
||||
to_chat(usr, "<span class='warning'>You need to wear a command or Captain-level ID.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>You need to wear a command or Captain-level ID.</span>")
|
||||
return
|
||||
|
||||
// All functions below this point require authentication.
|
||||
if(!is_authenticated(usr))
|
||||
if(!is_authenticated(ui.user))
|
||||
return FALSE
|
||||
|
||||
switch(action)
|
||||
if("main")
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
|
||||
if("newalertlevel")
|
||||
if(isAI(usr) || isrobot(usr))
|
||||
to_chat(usr, "<span class='warning'>Firewalls prevent you from changing the alert level.</span>")
|
||||
if(isAI(ui.user) || isrobot(ui.user))
|
||||
to_chat(ui.user, "<span class='warning'>Firewalls prevent you from changing the alert level.</span>")
|
||||
return
|
||||
else if(usr.can_admin_interact())
|
||||
change_security_level(text2num(params["level"]))
|
||||
else if(ADMIN_CHECK(ui.user))
|
||||
change_security_level(text2num(params["level"]), force = TRUE)
|
||||
return
|
||||
else if(!ishuman(usr))
|
||||
to_chat(usr, "<span class='warning'>Security measures prevent you from changing the alert level.</span>")
|
||||
else if(!ishuman(ui.user))
|
||||
to_chat(ui.user, "<span class='warning'>Security measures prevent you from changing the alert level.</span>")
|
||||
return
|
||||
else if(alert_level_cooldown > world.time)
|
||||
to_chat(usr, "<span class='warning'>Please allow at least one minute between manual changes to the alert level.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Please allow at least one minute between manual changes to the alert level.</span>")
|
||||
return
|
||||
|
||||
alert_level_cooldown = world.time + 60 SECONDS
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/mob/living/carbon/human/H = ui.user
|
||||
var/obj/item/card/id/I = H.get_idcard(TRUE)
|
||||
if(istype(I))
|
||||
// You must have captain access and it must be red alert or lower (no getting off delta/epsilon)
|
||||
if((ACCESS_CAPTAIN in I.access) && SSsecurity_level.get_current_level_as_number() <= SEC_LEVEL_RED)
|
||||
change_security_level(text2num(params["level"]))
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You are not authorized to do this.</span>")
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
to_chat(ui.user, "<span class='warning'>You are not authorized to do this.</span>")
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You need to wear your ID.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>You need to wear your ID.</span>")
|
||||
|
||||
if("announce")
|
||||
if(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT)
|
||||
if(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT)
|
||||
if(message_cooldown > world.time)
|
||||
to_chat(usr, "<span class='warning'>Please allow at least one minute to pass between announcements.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Please allow at least one minute to pass between announcements.</span>")
|
||||
return
|
||||
var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") as null|message
|
||||
if(!input || message_cooldown > world.time || ..() || !(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT))
|
||||
var/input = input(ui.user, "Please write a message to announce to the station crew.", "Priority Announcement") as null|message
|
||||
if(!input || message_cooldown > world.time || ..() || !(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT))
|
||||
return
|
||||
if(length(input) < COMM_MSGLEN_MINIMUM)
|
||||
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_MSGLEN_MINIMUM] character minimum.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Message '[input]' is too short. [COMM_MSGLEN_MINIMUM] character minimum.</span>")
|
||||
return
|
||||
announcer.Announce(input)
|
||||
message_cooldown = world.time + 600 //One minute
|
||||
|
||||
if("callshuttle")
|
||||
var/input = input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.") as null|message
|
||||
if(!input || ..() || !is_authenticated(usr))
|
||||
if(!input || ..() || !is_authenticated(ui.user))
|
||||
return
|
||||
call_shuttle_proc(usr, input)
|
||||
call_shuttle_proc(ui.user, input)
|
||||
if(SSshuttle.emergency.timer)
|
||||
post_status(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME)
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
|
||||
if("cancelshuttle")
|
||||
if(isAI(usr) || isrobot(usr))
|
||||
to_chat(usr, "<span class='warning'>Firewalls prevent you from recalling the shuttle.</span>")
|
||||
if(isAI(ui.user) || isrobot(ui.user))
|
||||
to_chat(ui.user, "<span class='warning'>Firewalls prevent you from recalling the shuttle.</span>")
|
||||
return
|
||||
var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No")
|
||||
if(response == "Yes")
|
||||
cancel_call_proc(usr)
|
||||
cancel_call_proc(ui.user)
|
||||
if(SSshuttle.emergency.timer)
|
||||
post_status(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME)
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
|
||||
if("messagelist")
|
||||
currmsg = null
|
||||
aicurrmsg = null
|
||||
if(params["msgid"])
|
||||
setCurrentMessage(usr, text2num(params["msgid"]))
|
||||
setMenuState(usr, COMM_SCREEN_MESSAGES)
|
||||
setCurrentMessage(ui.user, text2num(params["msgid"]))
|
||||
setMenuState(ui.user, COMM_SCREEN_MESSAGES)
|
||||
|
||||
if("delmessage")
|
||||
if(params["msgid"])
|
||||
currmsg = text2num(params["msgid"])
|
||||
var/response = alert("Are you sure you wish to delete this message?", "Confirm", "Yes", "No")
|
||||
if(response == "Yes")
|
||||
if(currmsg)
|
||||
var/id = getCurrentMessage()
|
||||
var/title = messagetitle[id]
|
||||
var/text = messagetext[id]
|
||||
messagetitle.Remove(title)
|
||||
messagetext.Remove(text)
|
||||
if(currmsg == id)
|
||||
currmsg = null
|
||||
if(aicurrmsg == id)
|
||||
aicurrmsg = null
|
||||
setMenuState(usr, COMM_SCREEN_MESSAGES)
|
||||
if(currmsg)
|
||||
var/id = getCurrentMessage()
|
||||
var/title = messagetitle[id]
|
||||
var/text = messagetext[id]
|
||||
messagetitle.Remove(title)
|
||||
messagetext.Remove(text)
|
||||
if(currmsg == id)
|
||||
currmsg = null
|
||||
if(aicurrmsg == id)
|
||||
aicurrmsg = null
|
||||
setMenuState(ui.user, COMM_SCREEN_MESSAGES)
|
||||
|
||||
if("status")
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
setMenuState(ui.user, COMM_SCREEN_STAT)
|
||||
|
||||
// Status display stuff
|
||||
if("setstat")
|
||||
@@ -214,74 +231,74 @@
|
||||
else
|
||||
display_icon = null
|
||||
post_status(display_type)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
setMenuState(ui.user, COMM_SCREEN_STAT)
|
||||
|
||||
if("setmsg1")
|
||||
stat_msg1 = clean_input("Line 1", "Enter Message Text", stat_msg1)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
setMenuState(ui.user, COMM_SCREEN_STAT)
|
||||
|
||||
if("setmsg2")
|
||||
stat_msg2 = clean_input("Line 2", "Enter Message Text", stat_msg2)
|
||||
setMenuState(usr, COMM_SCREEN_STAT)
|
||||
setMenuState(ui.user, COMM_SCREEN_STAT)
|
||||
|
||||
if("nukerequest")
|
||||
if(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT)
|
||||
if(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT)
|
||||
if(centcomm_message_cooldown > world.time)
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
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 || ..() || !(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT))
|
||||
var/input = stripped_input(ui.user, "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 || ..() || !(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT))
|
||||
return
|
||||
if(length(input) < COMM_CCMSGLEN_MINIMUM)
|
||||
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
return
|
||||
Nuke_request(input, usr)
|
||||
to_chat(usr, "<span class='notice'>Request sent.</span>")
|
||||
log_game("[key_name(usr)] has requested the nuclear codes from Centcomm")
|
||||
GLOB.major_announcement.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')
|
||||
Nuke_request(input, ui.user)
|
||||
to_chat(ui.user, "<span class='notice'>Request sent.</span>")
|
||||
log_game("[key_name(ui.user)] has requested the nuclear codes from Centcomm")
|
||||
GLOB.major_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [ui.user]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg')
|
||||
centcomm_message_cooldown = world.time + 6000 // 10 minutes
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
|
||||
if("MessageCentcomm")
|
||||
if(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT)
|
||||
if(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT)
|
||||
if(centcomm_message_cooldown > world.time)
|
||||
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||
return
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || ..() || !(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT))
|
||||
var/input = stripped_input(ui.user, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || ..() || !(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT))
|
||||
return
|
||||
if(length(input) < COMM_CCMSGLEN_MINIMUM)
|
||||
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
return
|
||||
Centcomm_announce(input, usr)
|
||||
Centcomm_announce(input, ui.user)
|
||||
print_centcom_report(input, station_time_timestamp() + " Captain's Message")
|
||||
to_chat(usr, "Message transmitted.")
|
||||
log_game("[key_name(usr)] has made a Centcomm announcement: [input]")
|
||||
to_chat(ui.user, "Message transmitted.")
|
||||
log_game("[key_name(ui.user)] has made a Centcomm announcement: [input]")
|
||||
centcomm_message_cooldown = world.time + 6000 // 10 minutes
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
|
||||
// OMG SYNDICATE ...LETTERHEAD
|
||||
if("MessageSyndicate")
|
||||
if((is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT) && (src.emagged))
|
||||
if((is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT) && (src.emagged))
|
||||
if(centcomm_message_cooldown > world.time)
|
||||
to_chat(usr, "Arrays recycling. Please stand by.")
|
||||
to_chat(ui.user, "Arrays recycling. Please stand by.")
|
||||
return
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || ..() || !(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT))
|
||||
var/input = stripped_input(ui.user, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || ..() || !(is_authenticated(ui.user) >= COMM_AUTHENTICATION_CAPT))
|
||||
return
|
||||
if(length(input) < COMM_CCMSGLEN_MINIMUM)
|
||||
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||
return
|
||||
Syndicate_announce(input, usr)
|
||||
to_chat(usr, "Message transmitted.")
|
||||
log_game("[key_name(usr)] has made a Syndicate announcement: [input]")
|
||||
Syndicate_announce(input, ui.user)
|
||||
to_chat(ui.user, "Message transmitted.")
|
||||
log_game("[key_name(ui.user)] has made a Syndicate announcement: [input]")
|
||||
centcomm_message_cooldown = world.time + 6000 // 10 minutes
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
|
||||
if("RestoreBackup")
|
||||
to_chat(usr, "Backup routing data restored!")
|
||||
to_chat(ui.user, "Backup routing data restored!")
|
||||
emagged = FALSE
|
||||
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||
setMenuState(ui.user, COMM_SCREEN_MAIN)
|
||||
|
||||
if("RestartNanoMob")
|
||||
if(SSmob_hunt)
|
||||
@@ -289,12 +306,94 @@
|
||||
var/loading_msg = pick("Respawning spawns", "Reticulating splines", "Flipping hat",
|
||||
"Capturing all of them", "Fixing minor text issues", "Being the very best",
|
||||
"Nerfing this", "Not communicating with playerbase", "Coding a ripoff in a 2D spaceman game")
|
||||
to_chat(usr, "<span class='notice'>Restarting Nano-Mob Hunter GO! game server. [loading_msg]...</span>")
|
||||
to_chat(ui.user, "<span class='notice'>Restarting Nano-Mob Hunter GO! game server. [loading_msg]...</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Nano-Mob Hunter GO! game server reboot failed due to recent restart. Please wait before re-attempting.</span>")
|
||||
to_chat(ui.user, "<span class='warning'>Nano-Mob Hunter GO! game server reboot failed due to recent restart. Please wait before re-attempting.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='danger'>Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.</span>")
|
||||
to_chat(ui.user, "<span class='danger'>Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.</span>")
|
||||
|
||||
// ADMIN CENTCOMM ONLY STUFF
|
||||
|
||||
if("send_to_cc_announcement_page")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
setMenuState(ui.user, COMM_SCREEN_ANNOUNCER)
|
||||
|
||||
if("make_other_announcement")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
ui.user.client.cmd_admin_create_centcom_report()
|
||||
|
||||
if("dispatch_ert")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
ui.user.client.response_team() // check_rights is handled on the other side, if someone does get ahold of this
|
||||
|
||||
if("send_nuke_codes")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
print_nuke_codes()
|
||||
|
||||
if("move_gamma_armory")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
SSblackbox.record_feedback("tally", "admin_comms_console", 1, "Send Gamma Armory")
|
||||
log_and_message_admins("moved the gamma armory")
|
||||
move_gamma_ship()
|
||||
|
||||
if("test_sound")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
SEND_SOUND(ui.user, sound(cc_announcement_sounds[params["sound"]]))
|
||||
|
||||
if("toggle_ert_allowed")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
ui.user.client.toggle_ert_calling()
|
||||
|
||||
if("view_econ")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
ui.user.client.economy_manager()
|
||||
|
||||
if("view_fax")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
ui.user.client.fax_panel()
|
||||
|
||||
if("make_cc_announcement")
|
||||
if(!ADMIN_CHECK(ui.user))
|
||||
return
|
||||
if(!text2bool(params["classified"]))
|
||||
GLOB.major_announcement.Announce(
|
||||
params["text"],
|
||||
new_title = "Central Command Report",
|
||||
new_subtitle = params["subtitle"],
|
||||
new_sound = cc_announcement_sounds[params["beepsound"]]
|
||||
)
|
||||
print_command_report(params["text"], params["subtitle"])
|
||||
else
|
||||
GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles.")
|
||||
print_command_report(params["text"], "Classified: [params["subtitle"]]")
|
||||
|
||||
log_and_message_admins("has created a communications report: [params["text"]]")
|
||||
// Okay but this is just an IC way of accessing the same verb
|
||||
SSblackbox.record_feedback("tally", "admin_comms_console", 1, "Create CC Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/obj/machinery/computer/communications/proc/print_nuke_codes()
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, TRUE)
|
||||
var/obj/item/paper/P = new /obj/item/paper(get_turf(src))
|
||||
P.name = "'CONFIDENTIAL' - [station_name()] Nuclear Codes"
|
||||
P.info = "<center>​<img src='ntlogo.png'><br><b>CONFIDENTIAL</b></center><br><hr>"
|
||||
|
||||
P.info += "The nuclear codes to [station_name()]'s nuclear device are [get_nuke_code()].<br>"
|
||||
switch(get_nuke_status())
|
||||
if(NUKE_MISSING)
|
||||
P.info += "Long-range scanners cannot detect the nuclear device on-station."
|
||||
if(NUKE_CORE_MISSING)
|
||||
P.info += "Long-range scanners detect no radioactive signatures from inside the device."
|
||||
|
||||
P.info += "<br><hr><font size=\"1\">Failure to comply with company regulatory confidential guidelines may result in immediate termination, at the jurisdiction of Central Command staff.</font>"
|
||||
|
||||
|
||||
/obj/machinery/computer/communications/emag_act(user as mob)
|
||||
@@ -334,6 +433,10 @@
|
||||
data["authenticated"] = is_authenticated(user, 0)
|
||||
data["authhead"] = data["authenticated"] >= COMM_AUTHENTICATION_HEAD && (data["authenticated"] == COMM_AUTHENTICATION_AGHOST || !isobserver(user))
|
||||
data["authcapt"] = data["authenticated"] >= COMM_AUTHENTICATION_CAPT && (data["authenticated"] == COMM_AUTHENTICATION_AGHOST || !isobserver(user))
|
||||
data["is_admin"] = data["authenticated"] >= COMM_AUTHENTICATION_CENTCOM && (data["authenticated"] == COMM_AUTHENTICATION_AGHOST || !isobserver(user))
|
||||
|
||||
data["gamma_armory_location"] = GLOB.gamma_ship_location
|
||||
data["ert_allowed"] = !SSticker.mode.ert_disabled
|
||||
|
||||
data["stat_display"] = list(
|
||||
"type" = display_type,
|
||||
@@ -366,10 +469,6 @@
|
||||
else
|
||||
data["security_level_color"] = "purple";
|
||||
data["str_security_level"] = capitalize(SSsecurity_level.get_current_level_as_text())
|
||||
data["levels"] = list(
|
||||
list("id" = SEC_LEVEL_GREEN, "name" = "Green", "icon" = "dove"),
|
||||
list("id" = SEC_LEVEL_BLUE, "name" = "Blue", "icon" = "eye"),
|
||||
)
|
||||
|
||||
var/list/msg_data = list()
|
||||
for(var/i = 1; i <= messagetext.len; i++)
|
||||
@@ -400,6 +499,29 @@
|
||||
data["esc_section"] = data["esc_status"] || data["esc_callable"] || data["esc_recallable"] || data["lastCallLoc"]
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/communications/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["levels"] = list(
|
||||
list("id" = SEC_LEVEL_GREEN, "name" = "Green", "icon" = "dove"),
|
||||
list("id" = SEC_LEVEL_BLUE, "name" = "Blue", "icon" = "eye"),
|
||||
)
|
||||
|
||||
data["admin_levels"] = list(
|
||||
list("id" = SEC_LEVEL_RED, "name" = "Red", "icon" = "exclamation"),
|
||||
list("id" = SEC_LEVEL_GAMMA, "name" = "Gamma", "icon" = "biohazard"),
|
||||
list("id" = SEC_LEVEL_EPSILON, "name" = "Epsilon", "icon" = "skull", "tooltip" = "Epsilon Alert will only activate after 15 or so seconds."),
|
||||
list("id" = SEC_LEVEL_DELTA, "name" = "Delta", "icon" = "bomb"),
|
||||
)
|
||||
|
||||
var/list/keys = list()
|
||||
for(var/sound_name in cc_announcement_sounds)
|
||||
keys += sound_name
|
||||
|
||||
data["possible_cc_sounds"] = keys
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/communications/proc/setCurrentMessage(mob/user, value)
|
||||
if(isAI(user) || isrobot(user))
|
||||
aicurrmsg = value
|
||||
@@ -521,4 +643,4 @@
|
||||
C.messagetitle.Add("[title]")
|
||||
C.messagetext.Add(text)
|
||||
|
||||
|
||||
#undef ADMIN_CHECK
|
||||
|
||||
@@ -145,6 +145,29 @@ you will have to do something like if(client.holder.rights & R_ADMIN) yourself.
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/**
|
||||
* Requires the holder to have all the rights specified
|
||||
*
|
||||
* rights_required = R_ADMIN|R_EVENT means they must have both flags, or it will return false
|
||||
*/
|
||||
/proc/check_rights_all(rights_required, show_msg = TRUE, mob/user = usr)
|
||||
if(!user?.client)
|
||||
return FALSE
|
||||
if(!rights_required)
|
||||
if(user.client.holder)
|
||||
return TRUE
|
||||
if(show_msg)
|
||||
to_chat(user, "<font color='red'>Error: You are not an admin.</font>")
|
||||
return FALSE
|
||||
|
||||
if(!user.client.holder)
|
||||
return FALSE
|
||||
if((user.client.holder.rights & rights_required) == rights_required)
|
||||
return TRUE
|
||||
if(show_msg)
|
||||
to_chat(user, "<font color='red'>Error: You do not have sufficient rights to do that. You require all of the following flags:[rights2text(rights_required, " ")].</font>")
|
||||
return FALSE
|
||||
|
||||
/datum/admins/vv_edit_var(var_name, var_value)
|
||||
return FALSE // no admin abuse
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
#define NUKE_INTACT 0
|
||||
#define NUKE_CORE_MISSING 1
|
||||
#define NUKE_MISSING 2
|
||||
|
||||
/mob/living/verb/pray(msg as text)
|
||||
set category = "IC"
|
||||
set name = "Pray"
|
||||
@@ -97,6 +93,3 @@
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
SEND_SOUND(X, sound('sound/effects/adminhelp.ogg'))
|
||||
|
||||
#undef NUKE_INTACT
|
||||
#undef NUKE_CORE_MISSING
|
||||
#undef NUKE_MISSING
|
||||
|
||||
@@ -1,42 +1,93 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, LabeledList, Box, Section } from '../components';
|
||||
import { useBackend, useLocalState } from '../backend';
|
||||
import {
|
||||
Button,
|
||||
LabeledList,
|
||||
Box,
|
||||
Section,
|
||||
Collapsible,
|
||||
Input,
|
||||
Flex,
|
||||
Dropdown,
|
||||
} from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
const PickWindow = (index) => {
|
||||
switch (index) {
|
||||
case 1:
|
||||
return <MainPage />;
|
||||
case 2:
|
||||
return <StatusScreens />;
|
||||
case 3:
|
||||
return <MessageView />;
|
||||
case 4:
|
||||
return <AdminAnnouncePage />;
|
||||
default:
|
||||
return 'ERROR. Unknown menu_state. Please contact NT Technical Support.';
|
||||
}
|
||||
};
|
||||
|
||||
export const CommunicationsComputer = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const { menu_state } = data;
|
||||
|
||||
return (
|
||||
<Window resizable>
|
||||
<Window.Content scrollable>
|
||||
<AuthBlock />
|
||||
{PickWindow(menu_state)}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const AuthBlock = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
authenticated,
|
||||
noauthbutton,
|
||||
esc_section,
|
||||
esc_callable,
|
||||
esc_recallable,
|
||||
esc_status,
|
||||
authhead,
|
||||
is_ai,
|
||||
lastCallLoc,
|
||||
} = data;
|
||||
|
||||
let hideLogButton = false;
|
||||
let authReadable;
|
||||
let authSpecial = false;
|
||||
if (!data.authenticated) {
|
||||
if (!authenticated) {
|
||||
authReadable = 'Not Logged In';
|
||||
} else if (data.authenticated === 1) {
|
||||
} else if (authenticated === 1) {
|
||||
authReadable = 'Command';
|
||||
} else if (data.authenticated === 2) {
|
||||
} else if (authenticated === 2) {
|
||||
authReadable = 'Captain';
|
||||
} else if (data.authenticated === 3) {
|
||||
} else if (authenticated === 3) {
|
||||
authReadable = 'CentComm Officer';
|
||||
} else if (authenticated === 4) {
|
||||
authReadable = 'CentComm Secure Connection';
|
||||
authSpecial = true;
|
||||
hideLogButton = true;
|
||||
} else {
|
||||
authReadable = 'ERROR: Report This Bug!';
|
||||
}
|
||||
let reportText = 'View (' + data.messages.length + ')';
|
||||
let authBlock = (
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Section title="Authentication">
|
||||
<LabeledList>
|
||||
{(authSpecial && (
|
||||
{(hideLogButton && (
|
||||
<LabeledList.Item label="Access">{authReadable}</LabeledList.Item>
|
||||
)) || (
|
||||
<LabeledList.Item label="Actions">
|
||||
<Button
|
||||
icon={data.authenticated ? 'sign-out-alt' : 'id-card'}
|
||||
selected={data.authenticated}
|
||||
disabled={data.noauthbutton}
|
||||
icon={authenticated ? 'sign-out-alt' : 'id-card'}
|
||||
selected={authenticated}
|
||||
disabled={noauthbutton}
|
||||
content={
|
||||
data.authenticated
|
||||
? 'Log Out (' + authReadable + ')'
|
||||
: 'Log In'
|
||||
authenticated ? 'Log Out (' + authReadable + ')' : 'Log In'
|
||||
}
|
||||
onClick={() => act('auth')}
|
||||
/>
|
||||
@@ -44,37 +95,35 @@ export const CommunicationsComputer = (props, context) => {
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
{!!data.esc_section && (
|
||||
{!!esc_section && (
|
||||
<Section title="Escape Shuttle">
|
||||
<LabeledList>
|
||||
{!!data.esc_status && (
|
||||
<LabeledList.Item label="Status">
|
||||
{data.esc_status}
|
||||
</LabeledList.Item>
|
||||
{!!esc_status && (
|
||||
<LabeledList.Item label="Status">{esc_status}</LabeledList.Item>
|
||||
)}
|
||||
{!!data.esc_callable && (
|
||||
{!!esc_callable && (
|
||||
<LabeledList.Item label="Options">
|
||||
<Button
|
||||
icon="rocket"
|
||||
content="Call Shuttle"
|
||||
disabled={!data.authhead}
|
||||
disabled={!authhead}
|
||||
onClick={() => act('callshuttle')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
{!!data.esc_recallable && (
|
||||
{!!esc_recallable && (
|
||||
<LabeledList.Item label="Options">
|
||||
<Button
|
||||
icon="times"
|
||||
content="Recall Shuttle"
|
||||
disabled={!data.authhead || data.is_ai}
|
||||
disabled={!authhead || is_ai}
|
||||
onClick={() => act('cancelshuttle')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
{!!data.lastCallLoc && (
|
||||
{!!lastCallLoc && (
|
||||
<LabeledList.Item label="Last Call/Recall From">
|
||||
{data.lastCallLoc}
|
||||
{lastCallLoc}
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
</LabeledList>
|
||||
@@ -82,81 +131,342 @@ export const CommunicationsComputer = (props, context) => {
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const MainPage = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const { is_admin } = data;
|
||||
|
||||
if (is_admin) {
|
||||
return <AdminPage />;
|
||||
}
|
||||
return <PlayerPage />;
|
||||
};
|
||||
|
||||
const AdminPage = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
is_admin,
|
||||
gamma_armory_location,
|
||||
admin_levels,
|
||||
authenticated,
|
||||
ert_allowed,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Section title="CentComm Actions">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Change Alert">
|
||||
<MappedAlertLevelButtons
|
||||
levels={admin_levels}
|
||||
required_access={is_admin}
|
||||
use_confirm={1}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Announcement">
|
||||
<Button
|
||||
icon="bullhorn"
|
||||
content="Make Central Announcement"
|
||||
disabled={!is_admin}
|
||||
onClick={() => act('send_to_cc_announcement_page')}
|
||||
/>
|
||||
{authenticated === 4 && (
|
||||
<Button
|
||||
icon="plus"
|
||||
content="Make Other Announcement"
|
||||
disabled={!is_admin}
|
||||
onClick={() => act('make_other_announcement')}
|
||||
/>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Response Team">
|
||||
<Button
|
||||
icon="ambulance"
|
||||
content="Dispatch ERT"
|
||||
disabled={!is_admin}
|
||||
onClick={() => act('dispatch_ert')}
|
||||
/>
|
||||
<Button.Checkbox
|
||||
checked={ert_allowed}
|
||||
content={
|
||||
ert_allowed ? 'ERT calling enabled' : 'ERT calling disabled'
|
||||
}
|
||||
tooltip={
|
||||
ert_allowed
|
||||
? 'Command can request an ERT'
|
||||
: 'ERTs cannot be requested'
|
||||
}
|
||||
disabled={!is_admin}
|
||||
onClick={() => act('toggle_ert_allowed')}
|
||||
selected={null}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Nuclear Device">
|
||||
<Button.Confirm
|
||||
icon="bomb"
|
||||
content="Get Authentication Codes"
|
||||
disabled={!is_admin}
|
||||
onClick={() => act('send_nuke_codes')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Gamma Armory">
|
||||
<Button.Confirm
|
||||
icon="biohazard"
|
||||
content={
|
||||
gamma_armory_location
|
||||
? 'Send Gamma Armory'
|
||||
: 'Recall Gamma Armory'
|
||||
}
|
||||
disabled={!is_admin}
|
||||
onClick={() => act('move_gamma_armory')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Other">
|
||||
<Button
|
||||
icon="coins"
|
||||
content="View Economy"
|
||||
disabled={!is_admin}
|
||||
onClick={() => act('view_econ')}
|
||||
/>
|
||||
<Button
|
||||
icon="fax"
|
||||
content="Fax Manager"
|
||||
disabled={!is_admin}
|
||||
onClick={() => act('view_fax')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Collapsible title="View Command accessible controls">
|
||||
<PlayerPage />
|
||||
</Collapsible>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const PlayerPage = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
msg_cooldown,
|
||||
emagged,
|
||||
cc_cooldown,
|
||||
security_level_color,
|
||||
str_security_level,
|
||||
levels,
|
||||
authcapt,
|
||||
authhead,
|
||||
messages,
|
||||
} = data;
|
||||
|
||||
let announceText = 'Make Priority Announcement';
|
||||
if (data.msg_cooldown > 0) {
|
||||
announceText += ' (' + data.msg_cooldown + 's)';
|
||||
if (msg_cooldown > 0) {
|
||||
announceText += ' (' + msg_cooldown + 's)';
|
||||
}
|
||||
let ccMessageText = data.emagged ? 'Message [UNKNOWN]' : 'Message CentComm';
|
||||
|
||||
let ccMessageText = emagged ? 'Message [UNKNOWN]' : 'Message CentComm';
|
||||
let nukeRequestText = 'Request Authentication Codes';
|
||||
if (data.cc_cooldown > 0) {
|
||||
ccMessageText += ' (' + data.cc_cooldown + 's)';
|
||||
nukeRequestText += ' (' + data.cc_cooldown + 's)';
|
||||
if (cc_cooldown > 0) {
|
||||
ccMessageText += ' (' + cc_cooldown + 's)';
|
||||
nukeRequestText += ' (' + cc_cooldown + 's)';
|
||||
}
|
||||
let alertLevelText = data.str_security_level;
|
||||
let alertLevelButtons = data.levels.map((slevel) => {
|
||||
return (
|
||||
<Button
|
||||
key={slevel.name}
|
||||
icon={slevel.icon}
|
||||
content={slevel.name}
|
||||
disabled={!data.authcapt || slevel.id === data.security_level}
|
||||
onClick={() => act('newalertlevel', { level: slevel.id })}
|
||||
/>
|
||||
);
|
||||
});
|
||||
let presetButtons = data.stat_display['presets'].map((pb) => {
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Section title="Captain-Only Actions">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Current Alert" color={security_level_color}>
|
||||
{str_security_level}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Change Alert">
|
||||
<MappedAlertLevelButtons
|
||||
levels={levels}
|
||||
required_access={authcapt}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Announcement">
|
||||
<Button
|
||||
icon="bullhorn"
|
||||
content={announceText}
|
||||
disabled={!authcapt || msg_cooldown > 0}
|
||||
onClick={() => act('announce')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
{(!!emagged && (
|
||||
<LabeledList.Item label="Transmit">
|
||||
<Button
|
||||
icon="broadcast-tower"
|
||||
color="red"
|
||||
content={ccMessageText}
|
||||
disabled={!authcapt || cc_cooldown > 0}
|
||||
onClick={() => act('MessageSyndicate')}
|
||||
/>
|
||||
<Button
|
||||
icon="sync-alt"
|
||||
content="Reset Relays"
|
||||
disabled={!authcapt}
|
||||
onClick={() => act('RestoreBackup')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
)) || (
|
||||
<LabeledList.Item label="Transmit">
|
||||
<Button
|
||||
icon="broadcast-tower"
|
||||
content={ccMessageText}
|
||||
disabled={!authcapt || cc_cooldown > 0}
|
||||
onClick={() => act('MessageCentcomm')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item label="Nuclear Device">
|
||||
<Button
|
||||
icon="bomb"
|
||||
content={nukeRequestText}
|
||||
disabled={!authcapt || cc_cooldown > 0}
|
||||
onClick={() => act('nukerequest')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Command Staff Actions">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Displays">
|
||||
<Button
|
||||
icon="tv"
|
||||
content="Change Status Displays"
|
||||
disabled={!authhead}
|
||||
onClick={() => act('status')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Incoming Messages">
|
||||
<Button
|
||||
icon="folder-open"
|
||||
content={'View (' + messages.length + ')'}
|
||||
disabled={!authhead}
|
||||
onClick={() => act('messagelist')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Misc">
|
||||
<Button
|
||||
icon="sync-alt"
|
||||
content="Restart Nano-Mob Hunter GO! Server"
|
||||
disabled={!authhead}
|
||||
onClick={() => act('RestartNanoMob')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const StatusScreens = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const { stat_display, authhead, current_message_title } = data;
|
||||
|
||||
let presetButtons = stat_display['presets'].map((pb) => {
|
||||
return (
|
||||
<Button
|
||||
key={pb.name}
|
||||
content={pb.label}
|
||||
selected={pb.name === data.stat_display.type}
|
||||
disabled={!data.authhead}
|
||||
selected={pb.name === stat_display.type}
|
||||
disabled={!authhead}
|
||||
onClick={() => act('setstat', { statdisp: pb.name })}
|
||||
/>
|
||||
);
|
||||
});
|
||||
let iconButtons = data.stat_display['alerts'].map((ib) => {
|
||||
let iconButtons = stat_display['alerts'].map((ib) => {
|
||||
return (
|
||||
<Button
|
||||
key={ib.alert}
|
||||
content={ib.label}
|
||||
selected={ib.alert === data.stat_display.icon}
|
||||
disabled={!data.authhead}
|
||||
selected={ib.alert === stat_display.icon}
|
||||
disabled={!authhead}
|
||||
onClick={() => act('setstat', { statdisp: 3, alert: ib.alert })}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Modify Status Screens"
|
||||
buttons={
|
||||
<Button
|
||||
icon="arrow-circle-left"
|
||||
content="Back To Main Menu"
|
||||
onClick={() => act('main')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Presets">{presetButtons}</LabeledList.Item>
|
||||
<LabeledList.Item label="Alerts">{iconButtons}</LabeledList.Item>
|
||||
<LabeledList.Item label="Message Line 1">
|
||||
<Button
|
||||
icon="pencil-alt"
|
||||
content={stat_display.line_1}
|
||||
disabled={!authhead}
|
||||
onClick={() => act('setmsg1')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Message Line 2">
|
||||
<Button
|
||||
icon="pencil-alt"
|
||||
content={stat_display.line_2}
|
||||
disabled={!authhead}
|
||||
onClick={() => act('setmsg2')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const MessageView = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
authhead,
|
||||
current_message_title,
|
||||
current_message,
|
||||
messages,
|
||||
security_level,
|
||||
} = data;
|
||||
|
||||
let messageView;
|
||||
if (data.current_message_title) {
|
||||
if (current_message_title) {
|
||||
messageView = (
|
||||
<Section
|
||||
title={data.current_message_title}
|
||||
title={current_message_title}
|
||||
buttons={
|
||||
<Button
|
||||
icon="times"
|
||||
content="Return To Message List"
|
||||
disabled={!data.authhead}
|
||||
disabled={!authhead}
|
||||
onClick={() => act('messagelist')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Box>{data.current_message}</Box>
|
||||
<Box>{current_message}</Box>
|
||||
</Section>
|
||||
);
|
||||
} else {
|
||||
let messageRows = data.messages.map((m) => {
|
||||
let messageRows = messages.map((m) => {
|
||||
return (
|
||||
<LabeledList.Item key={m.id} label={m.title}>
|
||||
<Button
|
||||
icon="eye"
|
||||
content="View"
|
||||
disabled={!data.authhead || data.current_message_title === m.title}
|
||||
disabled={!authhead || current_message_title === m.title}
|
||||
onClick={() => act('messagelist', { msgid: m.id })}
|
||||
/>
|
||||
<Button
|
||||
<Button.Confirm
|
||||
icon="times"
|
||||
content="Delete"
|
||||
disabled={!data.authhead}
|
||||
disabled={!authhead}
|
||||
onClick={() => act('delmessage', { msgid: m.id })}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
@@ -177,165 +487,134 @@ export const CommunicationsComputer = (props, context) => {
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
switch (data.menu_state) {
|
||||
// 1 = main screen
|
||||
case 1:
|
||||
return (
|
||||
<Window resizable>
|
||||
<Window.Content scrollable>
|
||||
{authBlock}
|
||||
<Section title="Captain-Only Actions">
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Current Alert"
|
||||
color={data.security_level_color}
|
||||
>
|
||||
{alertLevelText}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Change Alert">
|
||||
{alertLevelButtons}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Announcement">
|
||||
<Button
|
||||
icon="bullhorn"
|
||||
content={announceText}
|
||||
disabled={!data.authcapt || data.msg_cooldown > 0}
|
||||
onClick={() => act('announce')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
{(!!data.emagged && (
|
||||
<LabeledList.Item label="Transmit">
|
||||
<Button
|
||||
icon="broadcast-tower"
|
||||
color="red"
|
||||
content={ccMessageText}
|
||||
disabled={!data.authcapt || data.cc_cooldown > 0}
|
||||
onClick={() => act('MessageSyndicate')}
|
||||
/>
|
||||
<Button
|
||||
icon="sync-alt"
|
||||
content="Reset Relays"
|
||||
disabled={!data.authcapt}
|
||||
onClick={() => act('RestoreBackup')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
)) || (
|
||||
<LabeledList.Item label="Transmit">
|
||||
<Button
|
||||
icon="broadcast-tower"
|
||||
content={ccMessageText}
|
||||
disabled={!data.authcapt || data.cc_cooldown > 0}
|
||||
onClick={() => act('MessageCentcomm')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item label="Nuclear Device">
|
||||
<Button
|
||||
icon="bomb"
|
||||
content={nukeRequestText}
|
||||
disabled={!data.authcapt || data.cc_cooldown > 0}
|
||||
onClick={() => act('nukerequest')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Command Staff Actions">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Displays">
|
||||
<Button
|
||||
icon="tv"
|
||||
content="Change Status Displays"
|
||||
disabled={!data.authhead}
|
||||
onClick={() => act('status')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Incoming Messages">
|
||||
<Button
|
||||
icon="folder-open"
|
||||
content={reportText}
|
||||
disabled={!data.authhead}
|
||||
onClick={() => act('messagelist')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Misc">
|
||||
<Button
|
||||
icon="sync-alt"
|
||||
content="Restart Nano-Mob Hunter GO! Server"
|
||||
disabled={!data.authhead}
|
||||
onClick={() => act('RestartNanoMob')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
|
||||
// 2 = status screen
|
||||
case 2:
|
||||
return (
|
||||
<Window>
|
||||
<Window.Content>
|
||||
{authBlock}
|
||||
<Section
|
||||
title="Modify Status Screens"
|
||||
buttons={
|
||||
<Button
|
||||
icon="arrow-circle-left"
|
||||
content="Back To Main Menu"
|
||||
onClick={() => act('main')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Presets">
|
||||
{presetButtons}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Alerts">
|
||||
{iconButtons}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Message Line 1">
|
||||
<Button
|
||||
icon="pencil-alt"
|
||||
content={data.stat_display.line_1}
|
||||
disabled={!data.authhead}
|
||||
onClick={() => act('setmsg1')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Message Line 2">
|
||||
<Button
|
||||
icon="pencil-alt"
|
||||
content={data.stat_display.line_2}
|
||||
disabled={!data.authhead}
|
||||
onClick={() => act('setmsg2')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
|
||||
// 3 = messages screen
|
||||
case 3:
|
||||
return (
|
||||
<Window>
|
||||
<Window.Content>
|
||||
{authBlock}
|
||||
{messageView}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
|
||||
default:
|
||||
return (
|
||||
<Window>
|
||||
<Window.Content>
|
||||
{authBlock}
|
||||
ERRROR. Unknown menu_state: {data.menu_state}
|
||||
Please report this to NT Technical Support.
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
}
|
||||
return <Box>{messageView}</Box>;
|
||||
};
|
||||
|
||||
const MappedAlertLevelButtons = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const { levels, required_access, use_confirm } = props;
|
||||
const { security_level } = data;
|
||||
|
||||
if (use_confirm) {
|
||||
return levels.map((slevel) => {
|
||||
return (
|
||||
<Button.Confirm
|
||||
key={slevel.name}
|
||||
icon={slevel.icon}
|
||||
content={slevel.name}
|
||||
disabled={!required_access || slevel.id === security_level}
|
||||
tooltip={slevel.tooltip}
|
||||
onClick={() => act('newalertlevel', { level: slevel.id })}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return levels.map((slevel) => {
|
||||
return (
|
||||
<Button
|
||||
key={slevel.name}
|
||||
icon={slevel.icon}
|
||||
content={slevel.name}
|
||||
disabled={!required_access || slevel.id === security_level}
|
||||
tooltip={slevel.tooltip}
|
||||
onClick={() => act('newalertlevel', { level: slevel.id })}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const AdminAnnouncePage = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const { is_admin, possible_cc_sounds } = data;
|
||||
|
||||
if (!is_admin) {
|
||||
return act('main');
|
||||
}
|
||||
|
||||
const [subtitle, setSubtitle] = useLocalState(context, 'subtitle', '');
|
||||
const [text, setText] = useLocalState(context, 'text', '');
|
||||
const [classified, setClassified] = useLocalState(context, 'classified', 0);
|
||||
const [beepsound, setBeepsound] = useLocalState(context, 'beepsound', 'Beep');
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Central Command Report"
|
||||
buttons={
|
||||
<Button
|
||||
icon="arrow-circle-left"
|
||||
content="Back To Main Menu"
|
||||
onClick={() => act('main')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Input
|
||||
placeholder="Enter Subtitle here."
|
||||
fluid
|
||||
value={subtitle}
|
||||
onChange={(e, value) => setSubtitle(value)}
|
||||
mb="5px"
|
||||
/>
|
||||
<Input
|
||||
placeholder="Enter Announcement here,\nMultiline input is accepted."
|
||||
rows={10}
|
||||
fluid
|
||||
multiline={1}
|
||||
value={text}
|
||||
onChange={(e, value) => setText(value)}
|
||||
/>
|
||||
<Button.Confirm
|
||||
content="Send Announcement"
|
||||
fluid
|
||||
icon="paper-plane"
|
||||
center
|
||||
mt="5px"
|
||||
textAlign="center"
|
||||
onClick={() =>
|
||||
act('make_cc_announcement', {
|
||||
subtitle: subtitle,
|
||||
text: text,
|
||||
classified: classified,
|
||||
beepsound: beepsound,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Flex mt="5px">
|
||||
<Flex.Item>
|
||||
<Dropdown
|
||||
width="260px"
|
||||
height="20px"
|
||||
options={possible_cc_sounds}
|
||||
selected={beepsound}
|
||||
onSelected={(val) => setBeepsound(val)}
|
||||
disabled={classified}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="volume-up"
|
||||
mx="5px"
|
||||
disabled={classified}
|
||||
tooltip="Test sound"
|
||||
onClick={() => act('test_sound', { sound: beepsound })}
|
||||
/>
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button.Checkbox
|
||||
checked={classified}
|
||||
content="Classified"
|
||||
fluid
|
||||
tooltip={
|
||||
classified
|
||||
? 'Sent to station communications consoles'
|
||||
: 'Publically announced'
|
||||
}
|
||||
onClick={() => setClassified(!classified)}
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -41,45 +41,50 @@ export const Smartfridge = (props, context) => {
|
||||
{!contents && <Box color="average"> No products loaded. </Box>}
|
||||
{!!contents &&
|
||||
contents
|
||||
.slice()
|
||||
.sort((a, b) => a.display_name.localeCompare(b.display_name))
|
||||
.map((item) => {
|
||||
return (
|
||||
<Flex direction="row" key={item}>
|
||||
<Flex.Item width="45%">{item.display_name}</Flex.Item>
|
||||
<Flex.Item width="25%">({item.quantity} in stock)</Flex.Item>
|
||||
<Flex.Item width="30%">
|
||||
<Button
|
||||
icon="arrow-down"
|
||||
tooltip="Dispense one."
|
||||
content="1"
|
||||
onClick={() =>
|
||||
act('vend', { index: item.vend, amount: 1 })
|
||||
}
|
||||
/>
|
||||
<NumberInput
|
||||
width="40px"
|
||||
minValue={0}
|
||||
value={0}
|
||||
maxValue={item.quantity}
|
||||
step={1}
|
||||
stepPixelSize={3}
|
||||
onChange={(e, value) =>
|
||||
act('vend', { index: item.vend, amount: value })
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
icon="arrow-down"
|
||||
content="All"
|
||||
tooltip="Dispense all. "
|
||||
onClick={() =>
|
||||
act('vend', { index: item.vend, amount: item.quantity })
|
||||
}
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
.slice()
|
||||
.sort((a, b) => a.display_name.localeCompare(b.display_name))
|
||||
.map((item) => {
|
||||
return (
|
||||
<Flex direction="row" key={item}>
|
||||
<Flex.Item width="45%">{item.display_name}</Flex.Item>
|
||||
<Flex.Item width="25%">
|
||||
({item.quantity} in stock)
|
||||
</Flex.Item>
|
||||
<Flex.Item width="30%">
|
||||
<Button
|
||||
icon="arrow-down"
|
||||
tooltip="Dispense one."
|
||||
content="1"
|
||||
onClick={() =>
|
||||
act('vend', { index: item.vend, amount: 1 })
|
||||
}
|
||||
/>
|
||||
<NumberInput
|
||||
width="40px"
|
||||
minValue={0}
|
||||
value={0}
|
||||
maxValue={item.quantity}
|
||||
step={1}
|
||||
stepPixelSize={3}
|
||||
onChange={(e, value) =>
|
||||
act('vend', { index: item.vend, amount: value })
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
icon="arrow-down"
|
||||
content="All"
|
||||
tooltip="Dispense all. "
|
||||
onClick={() =>
|
||||
act('vend', {
|
||||
index: item.vend,
|
||||
amount: item.quantity,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user