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:
Contrabang
2023-10-20 15:10:59 -04:00
committed by GitHub
parent c0159d6f97
commit 75a02c1cd2
8 changed files with 794 additions and 375 deletions
+4
View File
@@ -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 -8
View File
@@ -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
+222 -100
View File
@@ -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>&ZeroWidthSpace;<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
+23
View File
@@ -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
-7
View File
@@ -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>
);
};
+44 -39
View File
@@ -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